| summaryrefslogtreecommitdiff |
diff options
5 files changed, 437 insertions, 21 deletions
diff --git a/data/examples/blackjack/cards.fate b/data/examples/blackjack/cards.fate index 16d0bf7..f41163c 100644 --- a/data/examples/blackjack/cards.fate +++ b/data/examples/blackjack/cards.fate @@ -16,22 +16,22 @@ (int number) (string family) ) - ) - (set_fields (default card) - (number (var number)) - (name - (text - (switch (var number) - (1 Ace) - (11 Jack) - (12 Queen) - (13 Kind) - (cast string (var number)) + (set_fields (default card) + (number (var number)) + (name + (text + (switch (var number) + (1 Ace) + (11 Jack) + (12 Queen) + (13 Kind) + (cast string (var number)) + ) + of (var family) ) - of (var name) ) + (score (max 10 number)) ) - (score (max 10 number)) ) (range 1 13 1) (var family) @@ -54,7 +54,7 @@ (foreach (at deck) card (set (at result) (+ card.score (at result))) - (if (= card.number 1) + (if (= (var card.number) 1) (set aces_count (+ aces_count 1)) ) ) diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index f4a3d12..1289a9e 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -1784,7 +1784,6 @@ returns [List<Cons<Computation, Instruction>> result] @init { $result = new ArrayList<Cons<Computation, Instruction>>(); - /* TODO: resolve grammar collisions */ } : ( @@ -1929,7 +1928,7 @@ returns [Instruction result] } | FOR_EACH_KW - value_reference WS+ new_reference_name + non_text_value WS+ new_reference_name { final Map<String, Variable> variable_map; final Variable new_variable; @@ -1938,7 +1937,7 @@ returns [Instruction result] elem_type = Type.ANY; - collection_type = ($value_reference.result).get_type(); + collection_type = ($non_text_value.result).get_type(); if (collection_type instanceof CollectionType) { @@ -2016,7 +2015,7 @@ returns [Instruction result] ($FOR_EACH_KW.getLine()), ($FOR_EACH_KW.getCharPositionInLine()) ), - ($value_reference.result), + ($non_text_value.result), ($new_reference_name.result), ($player_choice_list.result) ); 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 487554e..767724a 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 @@ -35,6 +35,7 @@ import tonkadur.wyrd.v1.compiler.util.RemoveElementsOf; import tonkadur.wyrd.v1.compiler.util.InsertAt; import tonkadur.wyrd.v1.compiler.util.RemoveAllOf; import tonkadur.wyrd.v1.compiler.util.IndexedMapLambda; +import tonkadur.wyrd.v1.compiler.util.PartitionLambda; import tonkadur.wyrd.v1.compiler.util.MapLambda; import tonkadur.wyrd.v1.compiler.util.MergeLambda; import tonkadur.wyrd.v1.compiler.util.RemoveOneOf; @@ -2804,7 +2805,98 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor ) throws Throwable { - /* TODO */ + final List<Computation> params; + final ComputationCompiler lambda_cc, in_collection_cc; + final Address car_addr, cdr_addr; + final Register result; + + result = reserve(DictType.WILD); + + 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); + + in_collection_cc = new ComputationCompiler(compiler); + + n.get_collection().get_visited_by(in_collection_cc); + + if (in_collection_cc.has_init()) + { + init_instructions.add(in_collection_cc.get_init()); + } + + car_addr = + new RelativeAddress + ( + result_as_address, + new Constant(Type.STRING, "0"), + in_collection_cc.get_computation().get_type() + ); + + init_instructions.add + ( + new SetValue + ( + car_addr, + in_collection_cc.get_computation() + ) + ); + + cdr_addr = + new RelativeAddress + ( + result_as_address, + new Constant(Type.STRING, "1"), + in_collection_cc.get_computation().get_type() + ); + + in_collection_cc.release_registers(init_instructions); + + init_instructions.add(new Initialize(cdr_addr)); + + init_instructions.add + ( + PartitionLambda.generate + ( + compiler.registers(), + compiler.assembler(), + lambda_cc.get_computation(), + car_addr, + cdr_addr, + ( + (tonkadur.fate.v1.lang.type.CollectionType) + n.get_collection().get_type() + ).is_set(), + params + ) + ); } @Override @@ -2870,6 +2962,11 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor init_instructions.add(in_collection_cc.get_init()); } + init_instructions.add + ( + new SetValue(result_as_address, in_collection_cc.get_computation()) + ); + in_collection_cc.release_registers(init_instructions); init_instructions.add 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 a0a5810..9cd5d43 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 @@ -55,6 +55,7 @@ import tonkadur.wyrd.v1.compiler.util.Shuffle; import tonkadur.wyrd.v1.compiler.util.Clear; import tonkadur.wyrd.v1.compiler.util.MapLambda; import tonkadur.wyrd.v1.compiler.util.MergeLambda; +import tonkadur.wyrd.v1.compiler.util.PartitionLambda; import tonkadur.wyrd.v1.compiler.util.IndexedMapLambda; import tonkadur.wyrd.v1.compiler.util.IterativeSearch; import tonkadur.wyrd.v1.compiler.util.RemoveAllOf; @@ -749,7 +750,90 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor ) throws Throwable { - /* TODO */ + final List<Computation> params; + final List<ComputationCompiler> param_cc_list; + final ComputationCompiler lambda_cc, collection_in_cc, collection_out_cc; + + params = new ArrayList<Computation>(); + param_cc_list = new ArrayList<ComputationCompiler>(); + + 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()); + } + + lambda_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_in_cc = new ComputationCompiler(compiler); + + n.get_collection_in().get_visited_by(collection_in_cc); + + if (collection_in_cc.has_init()) + { + result.add(collection_in_cc.get_init()); + } + + collection_out_cc = new ComputationCompiler(compiler); + + n.get_collection_out().get_visited_by(collection_out_cc); + + if (collection_out_cc.has_init()) + { + result.add(collection_out_cc.get_init()); + } + + result.add + ( + PartitionLambda.generate + ( + compiler.registers(), + compiler.assembler(), + lambda_cc.get_computation(), + collection_in_cc.get_address(), + collection_out_cc.get_address(), + ( + (tonkadur.fate.v1.lang.type.CollectionType) + n.get_collection_out().get_type() + ).is_set(), + params + ) + ); + + lambda_cc.release_registers(result); + collection_in_cc.release_registers(result); + collection_out_cc.release_registers(result); + + for (final ComputationCompiler cc: param_cc_list) + { + cc.release_registers(result); + } } @Override @@ -769,7 +853,67 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor ) throws Throwable { - /* TODO */ + final ComputationCompiler address_compiler, element_compiler; + final Register collection_size, index; + + address_compiler = new ComputationCompiler(compiler); + element_compiler = new ComputationCompiler(compiler); + + n.get_collection().get_visited_by(address_compiler); + + if (address_compiler.has_init()) + { + result.add(address_compiler.get_init()); + } + + address_compiler.release_registers(result); + + n.get_element().get_visited_by(element_compiler); + + if (element_compiler.has_init()) + { + result.add(element_compiler.get_init()); + } + + collection_size = compiler.registers().reserve(Type.INT, result); + index = compiler.registers().reserve(Type.INT, result); + + result.add + ( + new SetValue + ( + collection_size.get_address(), + new Size(address_compiler.get_address()) + ) + ); + + result.add + ( + new SetValue + ( + index.get_address(), + (n.is_from_left() ? Constant.ZERO : collection_size.get_value()) + ) + ); + + result.add + ( + InsertAt.generate + ( + compiler.registers(), + compiler.assembler(), + index.get_address(), + element_compiler.get_computation(), + collection_size.get_value(), + address_compiler.get_address() + ) + ); + + address_compiler.release_registers(result); + element_compiler.release_registers(result); + + compiler.registers().release(collection_size, result); + compiler.registers().release(index, result); } @Override diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/PartitionLambda.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/PartitionLambda.java new file mode 100644 index 0000000..706aee2 --- /dev/null +++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/PartitionLambda.java @@ -0,0 +1,176 @@ +package tonkadur.wyrd.v1.compiler.util; + +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; + +import tonkadur.wyrd.v1.lang.Register; + +import tonkadur.wyrd.v1.lang.type.Type; +import tonkadur.wyrd.v1.lang.type.MapType; + +import tonkadur.wyrd.v1.lang.meta.Instruction; +import tonkadur.wyrd.v1.lang.meta.Computation; + +import tonkadur.wyrd.v1.lang.computation.Cast; +import tonkadur.wyrd.v1.lang.computation.Constant; +import tonkadur.wyrd.v1.lang.computation.Operation; +import tonkadur.wyrd.v1.lang.computation.Address; +import tonkadur.wyrd.v1.lang.computation.RelativeAddress; +import tonkadur.wyrd.v1.lang.computation.ValueOf; +import tonkadur.wyrd.v1.lang.computation.Size; + +import tonkadur.wyrd.v1.lang.instruction.SetValue; + +import tonkadur.wyrd.v1.compiler.util.registers.RegisterManager; + +public class PartitionLambda +{ + /* Utility Class */ + private PartitionLambda () {} + + /* Uses Durstenfeld's shuffling algorithm */ + public static Instruction generate + ( + final RegisterManager registers, + final InstructionManager assembler, + final Computation lambda, + final Address collection_in, + final Address collection_out, + final boolean to_set, + final List<Computation> extra_params + ) + { + final List<Instruction> result, while_body, remove_instructions; + final Register iterator, index_storage, collection_size, storage; + final Computation iterator_target; + + result = new ArrayList<Instruction>(); + while_body = new ArrayList<Instruction>(); + remove_instructions = new ArrayList<Instruction>(); + + iterator = registers.reserve(Type.INT, result); + index_storage = registers.reserve(Type.INT, result); + collection_size = registers.reserve(Type.INT, result); + storage = registers.reserve(Type.BOOL, result); + + iterator_target = + new ValueOf + ( + new RelativeAddress + ( + collection_in, + new Cast(iterator.get_value(), Type.STRING), + ((MapType) collection_in.get_target_type()).get_member_type() + ) + ); + + result.add(new SetValue(iterator.get_address(), Constant.ZERO)); + result.add + ( + new SetValue(collection_size.get_address(), new Size(collection_in)) + ); + + extra_params.add(0, iterator_target); + + remove_instructions.add + ( + AddElement.generate + ( + registers, + assembler, + iterator_target, + collection_out, + to_set + ) + ); + + remove_instructions.add + ( + new SetValue(index_storage.get_address(), iterator.get_value()) + ); + + remove_instructions.add + ( + RemoveAt.generate + ( + registers, + assembler, + index_storage.get_address(), + collection_size.get_value(), + collection_in + ) + ); + + remove_instructions.add + ( + new SetValue + ( + collection_size.get_address(), + Operation.minus(collection_size.get_value(), Constant.ONE) + ) + ); + + 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 + ( + IfElse.generate + ( + registers, + assembler, + Operation.not(storage.get_value()), + assembler.merge(remove_instructions), + new SetValue + ( + iterator.get_address(), + Operation.plus(iterator.get_value(), Constant.ONE) + ) + ) + ); + + while_body.add + ( + new SetValue + ( + iterator.get_address(), + Operation.plus(iterator.get_value(), Constant.ONE) + ) + ); + + result.add + ( + While.generate + ( + registers, + assembler, + Operation.less_than + ( + iterator.get_value(), + collection_size.get_value() + ), + assembler.merge(while_body) + ) + ); + + registers.release(iterator, result); + registers.release(index_storage, result); + registers.release(collection_size, result); + registers.release(storage, result); + + return assembler.merge(result); + } +} |


