From ed8f945f7f2d932a06182d82466e33a6a0045a37 Mon Sep 17 00:00:00 2001 From: ctsk <9384305+ctsk@users.noreply.github.com> Date: Tue, 13 Sep 2022 19:05:17 +0200 Subject: [PATCH] [tlox] Add support for comparisons --- .../xyz/ctsk/lox/nodes/LoxExpressionNode.java | 12 +++++++++++- .../java/xyz/ctsk/lox/nodes/LoxRootNode.java | 2 +- .../main/java/xyz/ctsk/lox/nodes/LoxTypes.java | 7 +++++++ .../ctsk/lox/nodes/expr/LoxGreaterNode.java | 18 ++++++++++++++++++ .../lox/nodes/expr/LoxGreaterOrEqualNode.java | 18 ++++++++++++++++++ .../xyz/ctsk/lox/nodes/expr/LoxLessNode.java | 18 ++++++++++++++++++ .../lox/nodes/expr/LoxLessOrEqualNode.java | 18 ++++++++++++++++++ .../lox/nodes/expr/LoxNumberLiteralNode.java | 4 ---- .../xyz/ctsk/lox/parser/LoxNodeFactory.java | 4 ++++ .../main/resources/xyz/ctsk/lox/parser/Lox.g4 | 11 ++++++++--- 10 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxTypes.java create mode 100644 jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterNode.java create mode 100644 jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterOrEqualNode.java create mode 100644 jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessNode.java create mode 100644 jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessOrEqualNode.java diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxExpressionNode.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxExpressionNode.java index 6b9e800..d22d0af 100644 --- a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxExpressionNode.java +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxExpressionNode.java @@ -1,9 +1,19 @@ package xyz.ctsk.lox.nodes; +import com.oracle.truffle.api.dsl.TypeSystem; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.UnexpectedResultException; +@TypeSystemReference(LoxTypes.class) public abstract class LoxExpressionNode extends LoxNode { - public abstract double executeDouble(VirtualFrame frame); + public double executeDouble(VirtualFrame frame) throws UnexpectedResultException { + return LoxTypesGen.expectDouble(executeGeneric(frame)); + } + + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + return LoxTypesGen.expectBoolean(executeGeneric(frame)); + } public abstract Object executeGeneric(VirtualFrame frame); } diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxRootNode.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxRootNode.java index c83bcd9..e9c395f 100644 --- a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxRootNode.java +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxRootNode.java @@ -15,6 +15,6 @@ public class LoxRootNode extends RootNode { @Override public Object execute(VirtualFrame frame) { - return this.exprNode.executeDouble(frame); + return this.exprNode.executeGeneric(frame); } } diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxTypes.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxTypes.java new file mode 100644 index 0000000..d3fbe32 --- /dev/null +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/LoxTypes.java @@ -0,0 +1,7 @@ +package xyz.ctsk.lox.nodes; + +import com.oracle.truffle.api.dsl.TypeSystem; + +@TypeSystem({double.class, boolean.class}) +public abstract class LoxTypes { +} diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterNode.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterNode.java new file mode 100644 index 0000000..aecdcbf --- /dev/null +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterNode.java @@ -0,0 +1,18 @@ +package xyz.ctsk.lox.nodes.expr; + +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import xyz.ctsk.lox.LoxException; + +public abstract class LoxGreaterNode extends LoxBinaryNode { + @Specialization + public boolean greater(double left, double right) { + return left > right; + } + + @Fallback + protected Object typeError(Object left, Object right) { + throw LoxException.typeError(this, left, right); + } + +} diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterOrEqualNode.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterOrEqualNode.java new file mode 100644 index 0000000..6ca04a3 --- /dev/null +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxGreaterOrEqualNode.java @@ -0,0 +1,18 @@ +package xyz.ctsk.lox.nodes.expr; + +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import xyz.ctsk.lox.LoxException; + +public abstract class LoxGreaterOrEqualNode extends LoxBinaryNode { + @Specialization + public boolean greaterOrEqual(double left, double right) { + return left >= right; + } + + @Fallback + protected Object typeError(Object left, Object right) { + throw LoxException.typeError(this, left, right); + } + +} diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessNode.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessNode.java new file mode 100644 index 0000000..7e4050c --- /dev/null +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessNode.java @@ -0,0 +1,18 @@ +package xyz.ctsk.lox.nodes.expr; + +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import xyz.ctsk.lox.LoxException; + +public abstract class LoxLessNode extends LoxBinaryNode { + @Specialization + public boolean less(double left, double right) { + return left < right; + } + + @Fallback + protected Object typeError(Object left, Object right) { + throw LoxException.typeError(this, left, right); + } + +} diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessOrEqualNode.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessOrEqualNode.java new file mode 100644 index 0000000..58b1726 --- /dev/null +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxLessOrEqualNode.java @@ -0,0 +1,18 @@ +package xyz.ctsk.lox.nodes.expr; + +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import xyz.ctsk.lox.LoxException; + +public abstract class LoxLessOrEqualNode extends LoxBinaryNode { + @Specialization + public boolean lessOrEqual(double left, double right) { + return left <= right; + } + + @Fallback + protected Object typeError(Object left, Object right) { + throw LoxException.typeError(this, left, right); + } + +} diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxNumberLiteralNode.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxNumberLiteralNode.java index a29a898..f0b3d55 100644 --- a/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxNumberLiteralNode.java +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/nodes/expr/LoxNumberLiteralNode.java @@ -10,10 +10,6 @@ public class LoxNumberLiteralNode extends LoxExpressionNode { this.value = value; } - public double executeDouble(VirtualFrame frame) { - return this.value; - } - @Override public Object executeGeneric(VirtualFrame frame) { return this.value; diff --git a/jlox/tlox/src/main/java/xyz/ctsk/lox/parser/LoxNodeFactory.java b/jlox/tlox/src/main/java/xyz/ctsk/lox/parser/LoxNodeFactory.java index 54644b4..fd0dd58 100644 --- a/jlox/tlox/src/main/java/xyz/ctsk/lox/parser/LoxNodeFactory.java +++ b/jlox/tlox/src/main/java/xyz/ctsk/lox/parser/LoxNodeFactory.java @@ -16,6 +16,10 @@ public class LoxNodeFactory { case "-" -> LoxSubNodeGen.create(left, right); case "*" -> LoxMulNodeGen.create(left, right); case "/" -> LoxDivNodeGen.create(left, right); + case "<" -> LoxLessNodeGen.create(left, right); + case "<=" -> LoxLessOrEqualNodeGen.create(left, right); + case ">" -> LoxGreaterNodeGen.create(left, right); + case ">=" -> LoxGreaterOrEqualNodeGen.create(left, right); default -> null; }; } diff --git a/jlox/tlox/src/main/resources/xyz/ctsk/lox/parser/Lox.g4 b/jlox/tlox/src/main/resources/xyz/ctsk/lox/parser/Lox.g4 index 722b77f..dced7d2 100644 --- a/jlox/tlox/src/main/resources/xyz/ctsk/lox/parser/Lox.g4 +++ b/jlox/tlox/src/main/resources/xyz/ctsk/lox/parser/Lox.g4 @@ -28,9 +28,14 @@ file returns [LoxExpressionNode result] ; expression returns [LoxExpressionNode result] - : literal { $result = $literal.result; } - | left=expression op=( '*' | '/' ) right=expression { $result = factory.createBinaryNode($op, $left.result, $right.result); } - | left=expression op=( '+' | '-' ) right=expression { $result = factory.createBinaryNode($op, $left.result, $right.result); } + : literal + { $result = $literal.result; } + | left=expression op=( '*' | '/' ) right=expression + { $result = factory.createBinaryNode($op, $left.result, $right.result); } + | left=expression op=( '+' | '-' ) right=expression + { $result = factory.createBinaryNode($op, $left.result, $right.result); } + | left=expression op=( LESS | LESS_EQUAL | GREATER | GREATER_EQUAL) right=expression + { $result = factory.createBinaryNode($op, $left.result, $right.result); } ; literal returns [LoxExpressionNode result]