| summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src/core')
3 files changed, 448 insertions, 2 deletions
diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java index 1473c6c..2587769 100644 --- a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java +++ b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java @@ -2854,6 +2854,96 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor ); } + private void visit_merge_with_defaults + ( + final tonkadur.fate.v1.lang.computation.MergeComputation n + ) + throws Throwable + { + final List<Computation> params; + final ComputationCompiler lambda_cc, default_a_cc, default_b_cc; + final ComputationCompiler in_collection_a_cc, in_collection_b_cc; + final Register result; + + result = reserve(TypeCompiler.compile(compiler, n.get_type())); + + result_as_address = result.get_address(); + result_as_computation = result.get_value(); + + params = new ArrayList<Computation>(); + + for + ( + final tonkadur.fate.v1.lang.meta.Computation p: + n.get_extra_parameters() + ) + { + final ComputationCompiler param_cc; + + param_cc = new ComputationCompiler(compiler); + + p.get_visited_by(param_cc); + + /* Let's not re-compute the parameters on every iteration. */ + param_cc.generate_address(); + + assimilate(param_cc); + + params.add(param_cc.get_computation()); + } + + lambda_cc = new ComputationCompiler(compiler); + + n.get_lambda_function().get_visited_by(lambda_cc); + + assimilate(lambda_cc); + + default_a_cc = new ComputationCompiler(compiler); + + n.get_default_a().get_visited_by(default_a_cc); + + default_a_cc.generate_address(); + + assimilate(default_a_cc); + + default_b_cc = new ComputationCompiler(compiler); + + n.get_default_b().get_visited_by(default_b_cc); + + default_b_cc.generate_address(); + + assimilate(default_b_cc); + + in_collection_a_cc = new ComputationCompiler(compiler); + + n.get_collection_in_a().get_visited_by(in_collection_a_cc); + + assimilate(in_collection_a_cc); + + in_collection_b_cc = new ComputationCompiler(compiler); + + n.get_collection_in_b().get_visited_by(in_collection_b_cc); + + assimilate(in_collection_b_cc); + + init_instructions.add + ( + MergeLambda.generate + ( + compiler.registers(), + compiler.assembler(), + lambda_cc.get_computation(), + default_a_cc.get_computation(), + in_collection_a_cc.get_address(), + default_b_cc.get_computation(), + in_collection_b_cc.get_address(), + result_as_address, + n.to_set(), + params + ) + ); + } + @Override public void visit_merge ( @@ -2861,7 +2951,13 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor ) throws Throwable { - /* TODO: handle the default values if there are any. */ + if (n.get_default_a() == null) + { + visit_merge_with_defaults(n); + + return; + } + final List<Computation> params; final ComputationCompiler lambda_cc; final ComputationCompiler in_collection_a_cc, in_collection_b_cc; diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java index 438dde7..147f2f1 100644 --- a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java +++ b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java @@ -613,6 +613,16 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor result.add ( + Clear.generate + ( + compiler.registers(), + compiler.assembler(), + collection_cc.get_address() + ) + ); + + result.add + ( MapLambda.generate ( compiler.registers(), @@ -732,6 +742,147 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor } } + private void visit_merge_with_defaults + ( + final tonkadur.fate.v1.lang.instruction.Merge n + ) + throws Throwable + { + final Register holder; + final ComputationCompiler lambda_cc, default_a_cc, default_b_cc; + final List<Computation> params; + final List<ComputationCompiler> param_cc_list; + final ComputationCompiler collection_cc, in_collection_b_cc; + + params = new ArrayList<Computation>(); + param_cc_list = new ArrayList<ComputationCompiler>(); + + lambda_cc = new ComputationCompiler(compiler); + default_a_cc = new ComputationCompiler(compiler); + default_b_cc = new ComputationCompiler(compiler); + + n.get_lambda_function().get_visited_by(lambda_cc); + + if (lambda_cc.has_init()) + { + result.add(lambda_cc.get_init()); + } + + collection_cc = new ComputationCompiler(compiler); + + n.get_collection().get_visited_by(collection_cc); + + if (collection_cc.has_init()) + { + result.add(collection_cc.get_init()); + } + + n.get_default_a().get_visited_by(default_a_cc); + + default_a_cc.generate_address(); + + if (default_a_cc.has_init()) + { + result.add(default_a_cc.get_init()); + } + + n.get_default_b().get_visited_by(default_b_cc); + + default_b_cc.generate_address(); + + if (default_b_cc.has_init()) + { + result.add(default_b_cc.get_init()); + } + + holder = + compiler.registers().reserve + ( + collection_cc.get_computation().get_type(), + result + ); + + result.add + ( + new SetValue(holder.get_address(), collection_cc.get_computation()) + ); + + result.add + ( + Clear.generate + ( + compiler.registers(), + compiler.assembler(), + collection_cc.get_address() + ) + ); + + in_collection_b_cc = new ComputationCompiler(compiler); + + n.get_collection_in_b().get_visited_by(in_collection_b_cc); + + if (in_collection_b_cc.has_init()) + { + result.add(in_collection_b_cc.get_init()); + } + + for + ( + final tonkadur.fate.v1.lang.meta.Computation p: + n.get_extra_parameters() + ) + { + final ComputationCompiler param_cc; + + param_cc = new ComputationCompiler(compiler); + + p.get_visited_by(param_cc); + + /* Let's not re-compute the parameters on every iteration. */ + param_cc.generate_address(); + + if (param_cc.has_init()) + { + result.add(param_cc.get_init()); + } + + param_cc_list.add(param_cc); + + params.add(param_cc.get_computation()); + } + + result.add + ( + MergeLambda.generate + ( + compiler.registers(), + compiler.assembler(), + lambda_cc.get_computation(), + default_a_cc.get_computation(), + holder.get_address(), + default_b_cc.get_computation(), + in_collection_b_cc.get_address(), + collection_cc.get_address(), + ( + (tonkadur.fate.v1.lang.type.CollectionType) + n.get_collection().get_type() + ).is_set(), + params + ) + ); + + collection_cc.release_registers(result); + in_collection_b_cc.release_registers(result); + default_a_cc.release_registers(result); + default_b_cc.release_registers(result); + compiler.registers().release(holder, result); + + for (final ComputationCompiler cc: param_cc_list) + { + cc.release_registers(result); + } + } + @Override public void visit_merge ( @@ -741,6 +892,13 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor { /* TODO: handle default values. */ /* This is one dangerous operation to do in-place, so we don't. */ + + if (n.get_default_a() == null) + { + visit_merge_with_defaults(n); + return; + } + final Register holder; final ComputationCompiler lambda_cc; final List<Computation> params; @@ -1547,6 +1705,16 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor result.add ( + Clear.generate + ( + compiler.registers(), + compiler.assembler(), + collection_cc.get_address() + ) + ); + + result.add + ( IndexedMapLambda.generate ( compiler.registers(), diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/MergeLambda.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/MergeLambda.java index d09f05f..3cbed3d 100644 --- a/src/core/src/tonkadur/wyrd/v1/compiler/util/MergeLambda.java +++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/MergeLambda.java @@ -30,7 +30,6 @@ public class MergeLambda /* Utility Class */ private MergeLambda () {} - /* Uses Durstenfeld's shuffling algorithm */ public static Instruction generate ( final RegisterManager registers, @@ -184,4 +183,187 @@ public class MergeLambda return assembler.merge(result); } + + public static Instruction generate + ( + final RegisterManager registers, + final InstructionManager assembler, + final Computation lambda, + final Computation default_a, + final Address collection_in_a, + final Computation default_b, + final Address collection_in_b, + final Address collection_out, + final boolean to_set, + final List<Computation> extra_params + ) + { + final List<Instruction> result, while_body; + final Register iterator_a, iterator_b; + final Register collection_a_size, collection_b_size; + final Register storage; + + result = new ArrayList<Instruction>(); + while_body = new ArrayList<Instruction>(); + + iterator_a = registers.reserve(Type.INT, result); + iterator_b = registers.reserve(Type.INT, result); + + collection_a_size = registers.reserve(Type.INT, result); + collection_b_size = registers.reserve(Type.INT, result); + + storage = + registers.reserve + ( + ((MapType) collection_out.get_target_type()).get_member_type(), + result + ); + + result.add(new SetValue(iterator_a.get_address(), Constant.ZERO)); + result.add(new SetValue(iterator_b.get_address(), Constant.ZERO)); + + result.add + ( + new SetValue + ( + collection_a_size.get_address(), + new Size(collection_in_a) + ) + ); + + result.add + ( + new SetValue + ( + collection_b_size.get_address(), + new Size(collection_in_b) + ) + ); + + extra_params.add + ( + 0, + new IfElseComputation + ( + Operation.less_than + ( + iterator_b.get_value(), + collection_b_size.get_value() + ), + new ValueOf + ( + new RelativeAddress + ( + collection_in_b, + new Cast(iterator_b.get_value(), Type.STRING), + ( + (MapType) collection_in_b.get_target_type() + ).get_member_type() + ) + ), + default_b + ) + ); + + extra_params.add + ( + 0, + new IfElseComputation + ( + Operation.less_than + ( + iterator_a.get_value(), + collection_a_size.get_value() + ), + new ValueOf + ( + new RelativeAddress + ( + collection_in_a, + new Cast(iterator_a.get_value(), Type.STRING), + ( + (MapType) collection_in_a.get_target_type() + ).get_member_type() + ) + ), + default_a + ) + ); + + while_body.add + ( + LambdaEvaluation.generate + ( + registers, + assembler, + lambda, + /* Can't put it in the target collection directly, since that may + * be a set. + */ + storage.get_address(), + extra_params + ) + ); + + while_body.add + ( + AddElement.generate + ( + registers, + assembler, + storage.get_value(), + collection_out, + to_set + ) + ); + + while_body.add + ( + new SetValue + ( + iterator_a.get_address(), + Operation.plus(iterator_a.get_value(), Constant.ONE) + ) + ); + + while_body.add + ( + new SetValue + ( + iterator_b.get_address(), + Operation.plus(iterator_b.get_value(), Constant.ONE) + ) + ); + + result.add + ( + While.generate + ( + registers, + assembler, + Operation.or + ( + Operation.less_than + ( + iterator_a.get_value(), + collection_a_size.get_value() + ), + Operation.less_than + ( + iterator_b.get_value(), + collection_b_size.get_value() + ) + ), + assembler.merge(while_body) + ) + ); + + registers.release(iterator_a, result); + registers.release(iterator_b, result); + registers.release(collection_a_size, result); + registers.release(collection_b_size, result); + registers.release(storage, result); + + return assembler.merge(result); + } } |


