| summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/ataxic_optimize.erl')
| -rw-r--r-- | src/ataxic_optimize.erl | 178 |
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. |


