From 16a20ee8b08df919e93ea1b878013f9a2ad709fa Mon Sep 17 00:00:00 2001 From: Uko Kokņevičs Date: Sat, 24 Aug 2024 03:54:25 +0800 Subject: Added fancier tuple argument specs. Made ArgSpec use visitor pattern to avoid problems the best way. Merged empty tuple and non-empty tuple classes. --- .../java/lv/enes/orang/evaluator/EmptyTuple.java | 21 ---------- .../java/lv/enes/orang/evaluator/Evaluator.java | 8 +--- .../lv/enes/orang/evaluator/PartialFunction.java | 45 +++++++++++++++++----- .../main/java/lv/enes/orang/evaluator/Tuple.java | 12 +++++- .../main/java/lv/enes/orang/evaluator/Value.java | 2 +- 5 files changed, 48 insertions(+), 40 deletions(-) delete mode 100644 evaluator/src/main/java/lv/enes/orang/evaluator/EmptyTuple.java (limited to 'evaluator/src/main/java') diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/EmptyTuple.java b/evaluator/src/main/java/lv/enes/orang/evaluator/EmptyTuple.java deleted file mode 100644 index f8e043b..0000000 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/EmptyTuple.java +++ /dev/null @@ -1,21 +0,0 @@ -package lv.enes.orang.evaluator; - -import lombok.EqualsAndHashCode; - -@EqualsAndHashCode -public final class EmptyTuple implements Value { - public static final EmptyTuple INSTANCE = new EmptyTuple(); - - private EmptyTuple() { - } - - @Override - public String typeName() { - return "Nothing"; - } - - @Override - public String stringify() { - return "()"; - } -} diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java b/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java index f0299b4..1f51b9d 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/Evaluator.java @@ -2,7 +2,6 @@ package lv.enes.orang.evaluator; import lv.enes.orang.ast.*; import lv.enes.orang.core.OrangRuntimeException; -import lv.enes.orang.utils.NonEmptyList; import java.util.ArrayList; import java.util.Collections; @@ -71,11 +70,6 @@ public record Evaluator(Map scope, Value lastResult) implements E return value; } - @Override - public Value visitEmptyTupleExpression() { - return EmptyTuple.INSTANCE; - } - @Override public Evaluator visitExpression(ExpressionStatement expr) throws OrangRuntimeException { return new Evaluator(this.scope(), visit(expr.expr())); @@ -148,7 +142,7 @@ public record Evaluator(Map scope, Value lastResult) implements E for (var tailExpr : expr.children()) { values.add(visit(tailExpr)); } - return new Tuple(new NonEmptyList<>(values)); + return new Tuple(values); } @Override diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/PartialFunction.java b/evaluator/src/main/java/lv/enes/orang/evaluator/PartialFunction.java index 7c0ca20..bea3d02 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/PartialFunction.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/PartialFunction.java @@ -1,7 +1,6 @@ package lv.enes.orang.evaluator; -import lv.enes.orang.ast.ArgSpec; -import lv.enes.orang.ast.Expression; +import lv.enes.orang.ast.*; import lv.enes.orang.core.OrangRuntimeException; import lv.enes.orang.utils.NonEmptyList; @@ -10,17 +9,45 @@ import java.util.Map; public record PartialFunction(Map scope, NonEmptyList remainingArgs, Expression body) implements Value { public static Value of(Map scope, NonEmptyList remainingArgs, Expression body, Value param) throws OrangRuntimeException { - var spec = remainingArgs.getFirst(); - var newScope = new HashMap<>(scope); - switch (spec.getType()) { - case NAMED -> newScope.put(((ArgSpec.Named)spec).name(), param); - case NOTHING -> { - if (!(param instanceof EmptyTuple)) { - throw new OrangRuntimeException(STR."Expected () as a parameter but got \{param.typeName()}"); + class Helper implements ArgSpecVisitor { + private final HashMap newScope; + private final Value param; + + public Helper(HashMap newScope, Value param) { + this.newScope = newScope; + this.param = param; + } + + @Override + public Void visitIgnored() { + // Do nothing :3 + return null; + } + + @Override + public Void visitNamed(ArgSpecNamed named) { + newScope.put(named.name(), param); + return null; + } + + @Override + public Void visitTuple(ArgSpecTuple tuple) throws OrangRuntimeException { + if (param instanceof Tuple(var children)) { + if (children.size() == tuple.children().size()) { + for (var i = 0; i < children.size(); i++) { + new Helper(newScope, children.get(i)).visit(tuple.children().get(i)); + } + return null; + } } + throw new OrangRuntimeException(STR."Expected a tuple with \{tuple.children().size()} members as a parameter but got \{param.typeName()}"); } } + var spec = remainingArgs.getFirst(); + var newScope = new HashMap<>(scope); + new Helper(newScope, param).visit(spec); + if (remainingArgs.size() == 1) { return new Evaluator(newScope).visit(body); } else { diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/Tuple.java b/evaluator/src/main/java/lv/enes/orang/evaluator/Tuple.java index d5a1df5..fb607db 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/Tuple.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/Tuple.java @@ -1,10 +1,14 @@ package lv.enes.orang.evaluator; -import lv.enes.orang.utils.NonEmptyList; +import java.util.List; -public record Tuple(NonEmptyList contents) implements Value { +public record Tuple(List contents) implements Value { @Override public String typeName() { + if (contents.isEmpty()) { + return "()"; + } + var sb = new StringBuilder("("); sb.append(contents.getFirst().typeName()); for (var i = 1; i < contents.size(); i++) { @@ -15,6 +19,10 @@ public record Tuple(NonEmptyList contents) implements Value { @Override public String stringify() { + if (contents.isEmpty()) { + return "()"; + } + var sb = new StringBuilder("("); sb.append(contents.getFirst().stringify()); for (var i = 1; i < contents.size(); i++) { diff --git a/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java b/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java index 2ef5136..1a1aad6 100644 --- a/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java +++ b/evaluator/src/main/java/lv/enes/orang/evaluator/Value.java @@ -3,7 +3,7 @@ package lv.enes.orang.evaluator; import lv.enes.orang.core.OrangRuntimeException; public sealed interface Value - permits Array, BuiltinFunction, EmptyTuple, Function, OrangBoolean, OrangInteger, OrangString, + permits Array, BuiltinFunction, Function, OrangBoolean, OrangInteger, OrangString, PartialBuiltinFunction, PartialFunction, Tuple, Undefined { String typeName(); String stringify(); -- cgit v1.2.3