summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/computation/IndexedMergeComputation.java68
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/instruction/IndexedMerge.java64
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g4169
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/ComputationCompiler.java97
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/InstructionCompiler.java147
-rw-r--r--src/core/src/tonkadur/wyrd/v1/compiler/util/IndexedMergeLambda.java188
6 files changed, 728 insertions, 5 deletions
diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/IndexedMergeComputation.java b/src/core/src/tonkadur/fate/v1/lang/computation/IndexedMergeComputation.java
index 3a81b53..f9f8ae4 100644
--- a/src/core/src/tonkadur/fate/v1/lang/computation/IndexedMergeComputation.java
+++ b/src/core/src/tonkadur/fate/v1/lang/computation/IndexedMergeComputation.java
@@ -23,7 +23,9 @@ public class IndexedMergeComputation extends Computation
protected final List<Computation> extra_params;
protected final Computation lambda_function;
protected final Computation collection_in_a;
+ protected final Computation default_a;
protected final Computation collection_in_b;
+ protected final Computation default_b;
protected final boolean to_set;
/***************************************************************************/
@@ -35,7 +37,9 @@ public class IndexedMergeComputation extends Computation
final Origin origin,
final Computation lambda_function,
final Computation collection_in_a,
+ final Computation default_a,
final Computation collection_in_b,
+ final Computation default_b,
final boolean to_set,
final List<Computation> extra_params,
final Type output_type
@@ -45,7 +49,9 @@ public class IndexedMergeComputation extends Computation
this.lambda_function = lambda_function;
this.collection_in_a = collection_in_a;
+ this.default_a = default_a;
this.collection_in_b = collection_in_b;
+ this.default_b = default_b;
this.to_set = to_set;
this.extra_params = extra_params;
}
@@ -59,7 +65,9 @@ public class IndexedMergeComputation extends Computation
final Origin origin,
final Computation lambda_function,
final Computation collection_in_a,
+ final Computation default_a,
final Computation collection_in_b,
+ final Computation default_b,
final boolean to_set,
final List<Computation> extra_params
)
@@ -69,8 +77,23 @@ public class IndexedMergeComputation extends Computation
types_in = new ArrayList<Type>();
- RecurrentChecks.assert_is_a_collection(collection_in_a);
- RecurrentChecks.assert_is_a_collection(collection_in_b);
+ if (default_a == null)
+ {
+ RecurrentChecks.assert_is_a_collection(collection_in_a);
+ }
+ else
+ {
+ RecurrentChecks.assert_is_a_collection_of(collection_in_a, default_a);
+ }
+
+ if (default_b == null)
+ {
+ RecurrentChecks.assert_is_a_collection(collection_in_b);
+ }
+ else
+ {
+ RecurrentChecks.assert_is_a_collection_of(collection_in_b, default_b);
+ }
types_in.add(Type.INT);
@@ -79,6 +102,15 @@ public class IndexedMergeComputation extends Computation
((CollectionType) collection_in_a.get_type()).get_content_type()
);
+ if (default_b != null)
+ {
+ /*
+ * Safe-Mode: two indices.
+ * Unsafe-Mode: only one index, since out-of-bound means stopping.
+ */
+ types_in.add(Type.INT);
+ }
+
types_in.add
(
((CollectionType) collection_in_b.get_type()).get_content_type()
@@ -97,7 +129,9 @@ public class IndexedMergeComputation extends Computation
origin,
lambda_function,
collection_in_a,
+ default_a,
collection_in_b,
+ default_b,
to_set,
extra_params,
CollectionType.build
@@ -128,11 +162,21 @@ public class IndexedMergeComputation extends Computation
return collection_in_a;
}
+ public Computation get_default_a ()
+ {
+ return default_a;
+ }
+
public Computation get_collection_in_b ()
{
return collection_in_b;
}
+ public Computation get_default_b ()
+ {
+ return default_b;
+ }
+
public List<Computation> get_extra_parameters ()
{
return extra_params;
@@ -163,7 +207,27 @@ public class IndexedMergeComputation extends Computation
sb.append(collection_in_a.toString());
sb.append(" ");
+ if (default_a == null)
+ {
+ sb.append("null");
+ }
+ else
+ {
+ sb.append(default_a.toString());
+ }
+
+ sb.append(" ");
sb.append(collection_in_b.toString());
+ sb.append(" ");
+
+ if (default_b == null)
+ {
+ sb.append("null");
+ }
+ else
+ {
+ sb.append(default_b.toString());
+ }
for (final Computation c: extra_params)
{
diff --git a/src/core/src/tonkadur/fate/v1/lang/instruction/IndexedMerge.java b/src/core/src/tonkadur/fate/v1/lang/instruction/IndexedMerge.java
index 5fd86ec..96cfefc 100644
--- a/src/core/src/tonkadur/fate/v1/lang/instruction/IndexedMerge.java
+++ b/src/core/src/tonkadur/fate/v1/lang/instruction/IndexedMerge.java
@@ -23,7 +23,9 @@ public class IndexedMerge extends Instruction
protected final List<Computation> extra_params;
protected final Computation lambda_function;
protected final Reference collection;
+ protected final Computation default_a;
protected final Computation collection_in_b;
+ protected final Computation default_b;
/***************************************************************************/
/**** PROTECTED ************************************************************/
@@ -34,7 +36,9 @@ public class IndexedMerge extends Instruction
final Origin origin,
final Computation lambda_function,
final Reference collection,
+ final Computation default_a,
final Computation collection_in_b,
+ final Computation default_b,
final List<Computation> extra_params
)
{
@@ -42,7 +46,9 @@ public class IndexedMerge extends Instruction
this.lambda_function = lambda_function;
this.collection = collection;
+ this.default_a = default_a;
this.collection_in_b = collection_in_b;
+ this.default_b = default_b;
this.extra_params = extra_params;
}
@@ -55,7 +61,9 @@ public class IndexedMerge extends Instruction
final Origin origin,
final Computation lambda_function,
final Reference collection,
+ final Computation default_a,
final Computation collection_in_b,
+ final Computation default_b,
final List<Computation> extra_params
)
throws Throwable
@@ -64,8 +72,23 @@ public class IndexedMerge extends Instruction
types_in = new ArrayList<Type>();
- RecurrentChecks.assert_is_a_collection(collection);
- RecurrentChecks.assert_is_a_collection(collection_in_b);
+ if (default_a == null)
+ {
+ RecurrentChecks.assert_is_a_collection(collection);
+ }
+ else
+ {
+ RecurrentChecks.assert_is_a_collection_of(collection, default_a);
+ }
+
+ if (default_b == null)
+ {
+ RecurrentChecks.assert_is_a_collection(collection_in_b);
+ }
+ else
+ {
+ RecurrentChecks.assert_is_a_collection_of(collection_in_b, default_b);
+ }
types_in.add(Type.INT);
types_in.add
@@ -73,6 +96,11 @@ public class IndexedMerge extends Instruction
((CollectionType) collection.get_type()).get_content_type()
);
+ if (default_b != null)
+ {
+ types_in.add(Type.INT);
+ }
+
types_in.add
(
((CollectionType) collection_in_b.get_type()).get_content_type()
@@ -96,7 +124,9 @@ public class IndexedMerge extends Instruction
origin,
lambda_function,
collection,
+ default_a,
collection_in_b,
+ default_b,
extra_params
);
}
@@ -114,11 +144,21 @@ public class IndexedMerge extends Instruction
return lambda_function;
}
+ public Computation get_default_a ()
+ {
+ return default_a;
+ }
+
public Computation get_collection_in_b ()
{
return collection_in_b;
}
+ public Computation get_default_b ()
+ {
+ return default_b;
+ }
+
public Reference get_collection ()
{
return collection;
@@ -139,9 +179,29 @@ public class IndexedMerge extends Instruction
sb.append(lambda_function.toString());
sb.append(" ");
sb.append(collection.toString());
+ sb.append(" ");
+
+ if (default_a == null)
+ {
+ sb.append("null");
+ }
+ else
+ {
+ sb.append(default_a.toString());
+ }
sb.append(" ");
sb.append(collection_in_b.toString());
+ sb.append(" ");
+
+ if (default_b == null)
+ {
+ sb.append("null");
+ }
+ else
+ {
+ sb.append(default_b.toString());
+ }
for (final Computation c: extra_params)
{
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
index 4d791e3..6f84490 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
@@ -1017,7 +1017,9 @@ returns [Instruction result]
),
($fun.result),
($value_reference.result),
+ null,
($inv1.result),
+ null,
new ArrayList()
);
}
@@ -1039,7 +1041,9 @@ returns [Instruction result]
),
($fun.result),
($value_reference.result),
+ null,
($inv1.result),
+ null,
($value_list.result)
);
}
@@ -1095,6 +1099,57 @@ returns [Instruction result]
);
}
+ | SAFE_IMP_INDEXED_MERGE_KW
+ fun=non_text_value WS+
+ def0=value WS+
+ value_reference WS+
+ def1=value WS+
+ inv1=non_text_value WS*
+ R_PAREN
+ {
+ $result =
+ IndexedMerge.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($SAFE_IMP_INDEXED_MERGE_KW.getLine()),
+ ($SAFE_IMP_INDEXED_MERGE_KW.getCharPositionInLine())
+ ),
+ ($fun.result),
+ ($value_reference.result),
+ ($def0.result),
+ ($inv1.result),
+ ($def1.result),
+ new ArrayList()
+ );
+ }
+
+ | SAFE_IMP_INDEXED_MERGE_KW
+ fun=non_text_value WS+
+ def0=value WS+
+ value_reference WS+
+ def1=value WS+
+ inv1=non_text_value WS+
+ value_list WS*
+ R_PAREN
+ {
+ $result =
+ IndexedMerge.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($SAFE_IMP_INDEXED_MERGE_KW.getLine()),
+ ($SAFE_IMP_INDEXED_MERGE_KW.getCharPositionInLine())
+ ),
+ ($fun.result),
+ ($value_reference.result),
+ ($def0.result),
+ ($inv1.result),
+ ($def1.result),
+ ($value_list.result)
+ );
+ }
+
| IMP_SUB_LIST_KW
vstart=non_text_value WS+
vend=non_text_value WS+
@@ -4314,7 +4369,9 @@ returns [Computation result]
),
($fun.result),
($inv0.result),
+ null,
($inv1.result),
+ null,
false,
new ArrayList()
);
@@ -4337,7 +4394,62 @@ returns [Computation result]
),
($fun.result),
($inv0.result),
+ null,
($inv1.result),
+ null,
+ false,
+ ($value_list.result)
+ );
+ }
+
+ | SAFE_INDEXED_MERGE_TO_LIST_KW
+ fun=non_text_value WS+
+ def0=value WS+
+ inv0=non_text_value WS+
+ def1=value WS+
+ inv1=non_text_value WS*
+ R_PAREN
+ {
+ $result =
+ IndexedMergeComputation.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($SAFE_INDEXED_MERGE_TO_LIST_KW.getLine()),
+ ($SAFE_INDEXED_MERGE_TO_LIST_KW.getCharPositionInLine())
+ ),
+ ($fun.result),
+ ($inv0.result),
+ ($def0.result),
+ ($inv1.result),
+ ($def1.result),
+ false,
+ new ArrayList()
+ );
+ }
+
+ | SAFE_INDEXED_MERGE_TO_LIST_KW
+ fun=non_text_value WS+
+ def0=value WS+
+ inv0=non_text_value WS+
+ def1=value WS+
+ inv1=non_text_value WS+
+ value_list WS*
+ R_PAREN
+ {
+ $result =
+ IndexedMergeComputation.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($SAFE_INDEXED_MERGE_TO_LIST_KW.getLine()),
+ ($SAFE_INDEXED_MERGE_TO_LIST_KW.getCharPositionInLine())
+ ),
+ ($fun.result),
+ ($inv0.result),
+ ($def0.result),
+ ($inv1.result),
+ ($def1.result),
false,
($value_list.result)
);
@@ -4461,7 +4573,9 @@ returns [Computation result]
),
($fun.result),
($inv0.result),
+ null,
($inv1.result),
+ null,
true,
new ArrayList()
);
@@ -4484,7 +4598,62 @@ returns [Computation result]
),
($fun.result),
($inv0.result),
+ null,
($inv1.result),
+ null,
+ true,
+ ($value_list.result)
+ );
+ }
+
+ | SAFE_INDEXED_MERGE_TO_SET_KW
+ fun=non_text_value WS+
+ def0=value WS+
+ inv0=non_text_value WS+
+ def1=value WS+
+ inv1=non_text_value WS*
+ R_PAREN
+ {
+ $result =
+ IndexedMergeComputation.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($SAFE_INDEXED_MERGE_TO_SET_KW.getLine()),
+ ($SAFE_INDEXED_MERGE_TO_SET_KW.getCharPositionInLine())
+ ),
+ ($fun.result),
+ ($inv0.result),
+ ($def0.result),
+ ($inv1.result),
+ ($def1.result),
+ true,
+ new ArrayList()
+ );
+ }
+
+ | SAFE_INDEXED_MERGE_TO_SET_KW
+ fun=non_text_value WS+
+ def0=value WS+
+ inv0=non_text_value WS+
+ def1=value WS+
+ inv1=non_text_value WS+
+ value_list WS*
+ R_PAREN
+ {
+ $result =
+ IndexedMergeComputation.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($SAFE_INDEXED_MERGE_TO_SET_KW.getLine()),
+ ($SAFE_INDEXED_MERGE_TO_SET_KW.getCharPositionInLine())
+ ),
+ ($fun.result),
+ ($inv0.result),
+ ($def0.result),
+ ($inv1.result),
+ ($def1.result),
true,
($value_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 9fb288d..2df0868 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
@@ -3024,6 +3024,96 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor
);
}
+ private void visit_indexed_merge_with_defaults
+ (
+ final tonkadur.fate.v1.lang.computation.IndexedMergeComputation 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
+ (
+ IndexedMergeLambda.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_indexed_merge
(
@@ -3031,6 +3121,13 @@ implements tonkadur.fate.v1.lang.meta.ComputationVisitor
)
throws Throwable
{
+ if (n.get_default_a() != null)
+ {
+ visit_indexed_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 2f82d3c..36e7b66 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
@@ -1010,6 +1010,147 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
}
}
+ private void visit_indexed_merge_with_defaults
+ (
+ final tonkadur.fate.v1.lang.instruction.IndexedMerge 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
+ (
+ IndexedMergeLambda.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_indexed_merge
(
@@ -1017,6 +1158,12 @@ implements tonkadur.fate.v1.lang.meta.InstructionVisitor
)
throws Throwable
{
+ if (n.get_default_a() != null)
+ {
+ visit_indexed_merge_with_defaults(n);
+ return;
+ }
+
/* This is one dangerous operation to do in-place, so we don't. */
final Register holder;
final ComputationCompiler lambda_cc;
diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/util/IndexedMergeLambda.java b/src/core/src/tonkadur/wyrd/v1/compiler/util/IndexedMergeLambda.java
index 3a501e2..e1e4e4f 100644
--- a/src/core/src/tonkadur/wyrd/v1/compiler/util/IndexedMergeLambda.java
+++ b/src/core/src/tonkadur/wyrd/v1/compiler/util/IndexedMergeLambda.java
@@ -30,7 +30,6 @@ public class IndexedMergeLambda
/* Utility Class */
private IndexedMergeLambda () {}
- /* Uses Durstenfeld's shuffling algorithm */
public static Instruction generate
(
final RegisterManager registers,
@@ -187,4 +186,191 @@ public class IndexedMergeLambda
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, iterator_b.get_value());
+
+ 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
+ )
+ );
+
+ extra_params.add(0, iterator_a.get_value());
+
+ 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);
+ }
}