| summaryrefslogtreecommitdiff | 
diff options
Diffstat (limited to 'src')
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); +   }  } | 


