summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/ataxic_optimize.erl')
-rw-r--r--src/ataxic_optimize.erl178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/ataxic_optimize.erl b/src/ataxic_optimize.erl
new file mode 100644
index 0000000..2fc269e
--- /dev/null
+++ b/src/ataxic_optimize.erl
@@ -0,0 +1,178 @@
+-module(ataxic_optimize).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-include("ataxia/ataxic.hrl").
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-export([aggressive/1, light/1]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec optimize_update_field_sequence
+ (
+ list(ataxic:basic()),
+ list(ataxic:basic())
+ )
+ -> ataxic:basic().
+optimize_update_field_sequence ([], Result) ->
+ case Result of
+ [A] -> A;
+ _ -> ataxic:sequence(Result)
+ end;
+optimize_update_field_sequence (UnsortedOPs, CurrentResults) ->
+ {FieldUpdates, PotentiallyImportantOPs} =
+ lists:splitwith(fun (E) -> is_record(E, upfield) end, UnsortedOPs),
+
+ SortedFieldUpdates =
+ lists:sort
+ (
+ fun (A, B) ->
+ ((A#upfield.ix) =< (B#upfield.ix))
+ end,
+ FieldUpdates
+ ),
+
+ {LastIX, LastUpdateOPs, OtherMergedFieldUpdates} =
+ lists:foldl
+ (
+ fun (Update, {CurrentIX, CurrentOPs, CurrentResult}) ->
+ case (Update#upfield.ix == CurrentIX) of
+ true ->
+ {CurrentIX, [Update#upfield.op|CurrentOPs], CurrentResult};
+
+ _ ->
+ {
+ Update#upfield.ix,
+ [Update#upfield.op],
+ (
+ case CurrentOPs of
+ [] -> CurrentResult;
+ [OP] ->
+ [
+ ataxic:update_field(CurrentIX, OP)
+ |CurrentResult
+ ];
+ _ ->
+ [
+ ataxic:update_field
+ (
+ CurrentIX,
+ ataxic:sequence(CurrentOPs)
+ )
+ |CurrentResult
+ ]
+ end
+ )
+ }
+ end
+ end,
+ {-1, [], []},
+ SortedFieldUpdates
+ ),
+
+ MergedFieldUpdates =
+ (
+ case LastUpdateOPs of
+ [] -> OtherMergedFieldUpdates;
+ [OP] ->
+ [
+ ataxic:update_field(LastIX, OP)
+ |OtherMergedFieldUpdates
+ ];
+ _ ->
+ [
+ ataxic:update_field(LastIX, ataxic:sequence(LastUpdateOPs))
+ |OtherMergedFieldUpdates
+ ]
+ end
+ ),
+ {ImportantOPs, PotentialFieldUpdates} =
+ lists:splitwith
+ (
+ fun (E) -> not is_record(E, upfield) end,
+ PotentiallyImportantOPs
+ ),
+
+ optimize_update_field_sequence
+ (
+ PotentialFieldUpdates,
+ (CurrentResults ++ MergedFieldUpdates ++ ImportantOPs)
+ ).
+
+-spec flatten_sequence (list(ataxic:basic())) -> list(ataxic:basic()).
+flatten_sequence (OPs) ->
+ lists:foldl
+ (
+ fun (E, CurrentOPs) ->
+ case is_record(E, seq) of
+ true -> (E#seq.ops ++ CurrentOPs);
+ _ -> [E|CurrentOPs]
+ end
+ end,
+ [],
+ OPs
+ ).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec aggressive
+ (ataxic:basic()) -> ataxic:basic();
+ (ataxic:meta()) -> ataxic:meta().
+aggressive (In = #field{ op = OP }) ->
+ In#field{ op = aggressive(OP) };
+aggressive (In = #upfield{ op = S0OP}) ->
+ S1OP = aggressive(S0OP),
+
+ case S1OP of
+ #current{} -> S1OP;
+ _ -> In#upfield{ op = S1OP }
+ end;
+aggressive (#seq{ ops = S0OPs }) ->
+ S1OPs = lists:map(fun aggressive/1, S0OPs),
+ S2OPs = flatten_sequence(S1OPs),
+ S3OPs = lists:filter(fun (E) -> (not is_record(E, current)) end, S2OPs),
+ Result = optimize_update_field_sequence(S3OPs, []),
+
+ case Result#seq.ops of
+ [] -> #current{};
+ _ -> Result
+ end;
+aggressive (In = #apply_fun{ params = OPs }) ->
+ In#apply_fun
+ {
+ params = lists:map(fun aggressive/1, OPs)
+ };
+aggressive (In = #list_cons{ param = OP }) ->
+ In#list_cons{ param = lists:map(fun aggressive/1, OP) };
+aggressive (In = #read_perm{ op = OP }) ->
+ In#read_perm{ op = aggressive(OP) };
+aggressive (In = #write_perm{ op = OP }) ->
+ In#write_perm{ op = aggressive(OP) };
+aggressive (In = #lock{ op = OP }) ->
+ In#lock{ op = aggressive(OP) };
+aggressive (In = #value{ op = OP }) ->
+ In#value{ op = aggressive(OP) };
+aggressive (In = #mseq{ ops = OPs }) ->
+ In#mseq{ ops = lists:map(fun aggressive/1, OPs) };
+aggressive (Other) ->
+ Other.
+
+-spec light
+ (ataxic:basic()) -> ataxic:basic();
+ (ataxic:meta()) -> ataxic:meta().
+light (#seq{ ops = S0OPs }) ->
+ S1OPs = flatten_sequence(S0OPs),
+ S2OPs = lists:filter(fun (E) -> (not is_record(E, current)) end, S1OPs),
+ Result = optimize_update_field_sequence(S2OPs, []),
+
+ case Result#seq.ops of
+ [] -> #current{};
+ _ -> Result
+ end;
+light (OP) -> OP.