| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-08-21 21:48:47 +0200 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-08-21 21:48:47 +0200 |
| commit | 248a0bffd1d96548402c70a5b181e67de59d1e14 (patch) | |
| tree | fe34cc397e12590abcabc3f19f2e00bceac3d17d | |
| parent | c44f60829dc93687fe7d904b60d154de58f0492d (diff) | |
Adds some missing generic computations.
4 files changed, 426 insertions, 0 deletions
diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/generic/IfElseValue.java b/src/core/src/tonkadur/fate/v1/lang/computation/generic/IfElseValue.java new file mode 100644 index 0000000..7555849 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/computation/generic/IfElseValue.java @@ -0,0 +1,187 @@ +package tonkadur.fate.v1.lang.computation.generic; + +import java.util.Collection; +import java.util.List; +import java.util.ArrayList; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +import tonkadur.fate.v1.lang.type.Type; +import tonkadur.fate.v1.lang.type.FutureType; + +import tonkadur.fate.v1.lang.meta.ComputationVisitor; +import tonkadur.fate.v1.lang.meta.Computation; +import tonkadur.fate.v1.lang.meta.RecurrentChecks; + +import tonkadur.fate.v1.lang.computation.GenericComputation; + +public class IfElseValue extends GenericComputation +{ + public static Collection<String> get_aliases () + { + final Collection<String> aliases; + + aliases = new ArrayList<String>(); + + aliases.add("ifelse"); + aliases.add("if_else"); + aliases.add("ifElse"); + + return aliases; + } + + public static GenericComputation build + ( + final Origin origin, + final String alias, + final List<Computation> call_parameters + ) + throws Throwable + { + if (call_parameters.size() != 3) + { + // TODO: Error. + System.err.println("Wrong number of params at " + origin.toString()); + + return null; + } + + return + build + ( + origin, + call_parameters.get(0), + call_parameters.get(1), + call_parameters.get(2) + ); + } + + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Computation condition; + protected final Computation if_true; + protected final Computation if_false; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected IfElseValue + ( + final Origin origin, + final Type return_type, + final Computation condition, + final Computation if_true, + final Computation if_false + ) + { + super(origin, return_type); + + this.condition = condition; + this.if_true = if_true; + this.if_false = if_false; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static IfElseValue build + ( + final Origin origin, + final Computation condition, + final Computation if_true, + final Computation if_false + ) + throws ParsingError + { + condition.expect_non_string(); + + RecurrentChecks.assert_can_be_used_as(condition, Type.BOOL); + + return + new IfElseValue + ( + origin, + new FutureType(origin), + condition, + if_true, + if_false + ); + } + + /**** Accessors ************************************************************/ + @Override + public void expect_non_string () + throws ParsingError + { + if_true.expect_non_string(); + if_false.expect_non_string(); + + ((FutureType) get_type()).resolve_to + ( + RecurrentChecks.assert_can_be_used_as(if_false, if_true.get_type()) + ); + } + + @Override + public void expect_string () + throws ParsingError + { + if_true.expect_string(); + if_false.expect_string(); + + ((FutureType) get_type()).resolve_to + ( + RecurrentChecks.assert_can_be_used_as(if_false, if_true.get_type()) + ); + } + + public Computation get_condition () + { + return condition; + } + + public Computation get_if_true () + { + return if_true; + } + + public Computation get_if_false () + { + return if_false; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(IfElseValue"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("Condition:"); + sb.append(System.lineSeparator()); + sb.append(condition.toString()); + + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + sb.append("If true:"); + sb.append(System.lineSeparator()); + sb.append(if_true.toString()); + + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + sb.append("If false:"); + sb.append(System.lineSeparator()); + sb.append(if_false.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/generic/Newline.java b/src/core/src/tonkadur/fate/v1/lang/computation/generic/Newline.java new file mode 100644 index 0000000..664b864 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/computation/generic/Newline.java @@ -0,0 +1,64 @@ +package tonkadur.fate.v1.lang.computation.generic; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.ComputationVisitor; +import tonkadur.fate.v1.lang.meta.Computation; + +import tonkadur.fate.v1.lang.type.Type; + +import tonkadur.fate.v1.lang.computation.GenericComputation; + +public class Newline extends GenericComputation +{ + public static Collection<String> get_aliases () + { + final Collection<String> aliases; + + aliases = new ArrayList<String>(); + + aliases.add("newline"); + + return aliases; + } + + public static GenericComputation build + ( + final Origin origin, + final String alias, + final List<Computation> call_parameters + ) + throws Throwable + { + if (call_parameters.size() != 0) + { + // TODO: Error. + System.err.println("Wrong number of params at " + origin.toString()); + + return null; + } + + return new Newline(origin); + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public Newline (final Origin origin) + { + super(origin, Type.TEXT); + } + + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + return "(Newline)"; + } +} diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/computation/generic/IfElseValueCompiler.java b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/computation/generic/IfElseValueCompiler.java new file mode 100644 index 0000000..c6d6d2e --- /dev/null +++ b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/computation/generic/IfElseValueCompiler.java @@ -0,0 +1,144 @@ +package tonkadur.wyrd.v1.compiler.fate.v1.computation.generic; + +import java.util.List; +import java.util.ArrayList; + +import tonkadur.fate.v1.lang.computation.generic.IfElseValue; + +import tonkadur.wyrd.v1.compiler.fate.v1.Compiler; +import tonkadur.wyrd.v1.compiler.fate.v1.ComputationCompiler; + +import tonkadur.wyrd.v1.compiler.fate.v1.computation.GenericComputationCompiler; + +import tonkadur.wyrd.v1.lang.computation.IfElseComputation; + +import tonkadur.wyrd.v1.lang.Register; + +import tonkadur.wyrd.v1.lang.meta.Instruction; + +import tonkadur.wyrd.v1.lang.instruction.SetValue; + +public class IfElseValueCompiler +extends GenericComputationCompiler +{ + public static Class get_target_class () + { + return IfElseValue.class; + } + + public IfElseValueCompiler (final Compiler compiler) + { + super(compiler); + } + + public void compile + ( + final tonkadur.fate.v1.lang.computation.GenericComputation computation + ) + throws Throwable + { + final IfElseValue source; + final ComputationCompiler cond_cc, if_true_cc, if_false_cc; + + source = (IfElseValue) computation; + + cond_cc = new ComputationCompiler(compiler); + if_true_cc = new ComputationCompiler(compiler); + if_false_cc = new ComputationCompiler(compiler); + + source.get_condition().get_visited_by(cond_cc); + source.get_if_true().get_visited_by(if_true_cc); + source.get_if_false().get_visited_by(if_false_cc); + + if (if_true_cc.has_init() || if_false_cc.has_init()) + { + /* + * Unsafe ifelse computation: at least one of the branches needs to + * use instructions with values *before* the condition has been + * checked. This results in non-lazy evaluation, and is dangerous: + * the condition might be a test to ensure that the computations of the + * chosen branch are legal. In such cases, performing the potentially + * illegal branch's instructions is likely to result in a runtime error + * on the interpreter. + * + * Instead, we just convert the ifelse into an instruction-based + * equivalent and store the result in an anonymous register to be used + * here. + */ + final Register if_else_result; + final List<Instruction> if_true_branch; + final List<Instruction> if_false_branch; + + if_else_result = reserve(if_true_cc.get_computation().get_type()); + + if_true_branch = new ArrayList<Instruction>(); + if_false_branch = new ArrayList<Instruction>(); + + if (if_true_cc.has_init()) + { + if_true_branch.add(if_true_cc.get_init()); + } + + if (if_false_cc.has_init()) + { + if_false_branch.add(if_false_cc.get_init()); + } + + if_true_branch.add + ( + new SetValue + ( + if_else_result.get_address(), + if_true_cc.get_computation() + ) + ); + + if_false_branch.add + ( + new SetValue + ( + if_else_result.get_address(), + if_false_cc.get_computation() + ) + ); + + if (cond_cc.has_init()) + { + init_instructions.add(cond_cc.get_init()); + } + + init_instructions.add + ( + tonkadur.wyrd.v1.compiler.util.IfElse.generate + ( + compiler.registers(), + compiler.assembler(), + cond_cc.get_computation(), + compiler.assembler().merge(if_true_branch), + compiler.assembler().merge(if_false_branch) + ) + ); + + assimilate_reserved_registers(cond_cc); + assimilate_reserved_registers(if_true_cc); + assimilate_reserved_registers(if_false_cc); + + result_as_computation = if_else_result.get_value(); + result_as_address = if_else_result.get_address(); + } + else + { + assimilate(cond_cc); + assimilate(if_true_cc); + assimilate(if_false_cc); + + result_as_computation = + new IfElseComputation + ( + cond_cc.get_computation(), + if_true_cc.get_computation(), + if_false_cc.get_computation() + ); + } + } +} diff --git a/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/computation/generic/NewlineCompiler.java b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/computation/generic/NewlineCompiler.java new file mode 100644 index 0000000..d5ce82d --- /dev/null +++ b/src/core/src/tonkadur/wyrd/v1/compiler/fate/v1/computation/generic/NewlineCompiler.java @@ -0,0 +1,31 @@ +package tonkadur.wyrd.v1.compiler.fate.v1.computation.generic; + +import tonkadur.fate.v1.lang.computation.generic.Newline; + +import tonkadur.wyrd.v1.compiler.fate.v1.Compiler; +import tonkadur.wyrd.v1.compiler.fate.v1.ComputationCompiler; + +import tonkadur.wyrd.v1.compiler.fate.v1.computation.GenericComputationCompiler; + +public class NewlineCompiler +extends GenericComputationCompiler +{ + public static Class get_target_class () + { + return Newline.class; + } + + public NewlineCompiler (final Compiler compiler) + { + super(compiler); + } + + public void compile + ( + final tonkadur.fate.v1.lang.computation.GenericComputation _computation + ) + throws Throwable + { + result_as_computation = new tonkadur.wyrd.v1.lang.computation.Newline(); + } +} |


