[tlox] global vars
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package xyz.ctsk.lox;
|
package xyz.ctsk.lox;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||||
import xyz.ctsk.lox.nodes.LoxRootNode;
|
import xyz.ctsk.lox.nodes.LoxRootNode;
|
||||||
import xyz.ctsk.lox.parser.LoxParser;
|
import xyz.ctsk.lox.parser.LoxParser;
|
||||||
|
|
||||||
@@ -22,13 +23,10 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void run(String program) {
|
public static void run(String program) {
|
||||||
var parsed = LoxParser.parseLox(program);
|
var parseResult = LoxParser.parseLox(program);
|
||||||
|
var root = new LoxRootNode(parseResult.rootNode(), parseResult.frame());
|
||||||
if (parsed instanceof LoxParser.ExpressionContext expr) {
|
var callTarget = root.getCallTarget();
|
||||||
var root = new LoxRootNode(expr.result);
|
System.out.println(callTarget.call());
|
||||||
var callTarget = root.getCallTarget();
|
|
||||||
System.out.println(callTarget.call());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package xyz.ctsk.lox.nodes;
|
package xyz.ctsk.lox.nodes;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.RootNode;
|
import com.oracle.truffle.api.nodes.RootNode;
|
||||||
|
|
||||||
@@ -8,8 +9,8 @@ public class LoxRootNode extends RootNode {
|
|||||||
@Child
|
@Child
|
||||||
private LoxExpressionNode exprNode;
|
private LoxExpressionNode exprNode;
|
||||||
|
|
||||||
public LoxRootNode(LoxExpressionNode exprNode) {
|
public LoxRootNode(LoxExpressionNode exprNode, FrameDescriptor frameDescriptor) {
|
||||||
super(null);
|
super(null, frameDescriptor);
|
||||||
this.exprNode = exprNode;
|
this.exprNode = exprNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package xyz.ctsk.lox.nodes.expr;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.NodeField;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
@NodeField(name = "slot", type = int.class)
|
||||||
|
public abstract class LoxReadVariableNode extends LoxExpressionNode {
|
||||||
|
protected abstract int getSlot();
|
||||||
|
|
||||||
|
@Specialization(guards = "frame.isDouble(getSlot())")
|
||||||
|
protected double readDouble(VirtualFrame frame) {
|
||||||
|
return frame.getLong(getSlot());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "frame.isBoolean(getSlot())")
|
||||||
|
protected boolean readBoolean(VirtualFrame frame) {
|
||||||
|
return frame.getBoolean(getSlot());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(replaces = { "readDouble", "readBoolean"})
|
||||||
|
protected Object readObject(VirtualFrame frame) {
|
||||||
|
return frame.getObject(getSlot());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package xyz.ctsk.lox.nodes.expr;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.NodeChild;
|
||||||
|
import com.oracle.truffle.api.dsl.NodeField;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.frame.FrameSlotKind;
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
@NodeChild("valueNode")
|
||||||
|
@NodeField(name = "slot", type = int.class)
|
||||||
|
public abstract class LoxWriteVariableNode extends LoxExpressionNode {
|
||||||
|
protected abstract int getSlot();
|
||||||
|
|
||||||
|
@Specialization(guards = "isDoubleOrIllegal(frame)")
|
||||||
|
protected double writeDouble(VirtualFrame frame, double value) {
|
||||||
|
frame.getFrameDescriptor().setSlotKind(getSlot(), FrameSlotKind.Double);
|
||||||
|
frame.setDouble(getSlot(), value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "isBooleanOrIllegal(frame)")
|
||||||
|
protected boolean writeBoolean(VirtualFrame frame, boolean value) {
|
||||||
|
frame.getFrameDescriptor().setSlotKind(getSlot(), FrameSlotKind.Boolean);
|
||||||
|
frame.setBoolean(getSlot(), value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(replaces = { "writeDouble", "writeBoolean"})
|
||||||
|
protected Object write(VirtualFrame frame, Object value) {
|
||||||
|
frame.getFrameDescriptor().setSlotKind(getSlot(), FrameSlotKind.Object);
|
||||||
|
frame.setObject(getSlot(), value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isDoubleOrIllegal(VirtualFrame frame) {
|
||||||
|
final FrameSlotKind kind = frame.getFrameDescriptor().getSlotKind(getSlot());
|
||||||
|
return kind == FrameSlotKind.Double || kind == FrameSlotKind.Illegal;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isBooleanOrIllegal(VirtualFrame frame) {
|
||||||
|
final FrameSlotKind kind = frame.getFrameDescriptor().getSlotKind(getSlot());
|
||||||
|
return kind == FrameSlotKind.Boolean || kind == FrameSlotKind.Illegal;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +1,61 @@
|
|||||||
package xyz.ctsk.lox.parser;
|
package xyz.ctsk.lox.parser;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||||
|
import com.oracle.truffle.api.frame.FrameSlotKind;
|
||||||
import com.oracle.truffle.api.strings.TruffleString;
|
import com.oracle.truffle.api.strings.TruffleString;
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
import xyz.ctsk.lox.nodes.expr.*;
|
import xyz.ctsk.lox.nodes.expr.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class LoxNodeFactory {
|
public class LoxNodeFactory {
|
||||||
public static LoxNumberLiteralNode createNumberLiteral(Token literalToken) {
|
private static class GlobalScope {
|
||||||
|
private final Map<TruffleString, Integer> values = new HashMap<>();
|
||||||
|
private final FrameDescriptor.Builder builder = FrameDescriptor.newBuilder();
|
||||||
|
|
||||||
|
Integer find(TruffleString name) {
|
||||||
|
return values.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int add(TruffleString name) {
|
||||||
|
var slot = builder.addSlot(FrameSlotKind.Illegal, name, null);
|
||||||
|
values.put(name, slot);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer findOrAdd(TruffleString name) {
|
||||||
|
return Optional.ofNullable(find(name)).orElseGet(() -> add(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameDescriptor getFrame() {
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final GlobalScope globalScope = new GlobalScope();
|
||||||
|
public LoxNumberLiteralNode createNumberLiteral(Token literalToken) {
|
||||||
var value = Double.parseDouble(literalToken.getText());
|
var value = Double.parseDouble(literalToken.getText());
|
||||||
return new LoxNumberLiteralNode(value);
|
return new LoxNumberLiteralNode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoxStringLiteralNode createStringLiteral(Token literalToken) {
|
public LoxStringLiteralNode createStringLiteral(Token literalToken) {
|
||||||
var value = TruffleString.fromJavaStringUncached(literalToken.getText(), TruffleString.Encoding.UTF_16);
|
var value = TruffleString.fromJavaStringUncached(literalToken.getText(), TruffleString.Encoding.UTF_16);
|
||||||
return new LoxStringLiteralNode(value);
|
return new LoxStringLiteralNode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoxBooleanLiteralNode createBooleanLiteral(Token literalToken) {
|
public LoxBooleanLiteralNode createBooleanLiteral(Token literalToken) {
|
||||||
var value = Boolean.parseBoolean(literalToken.getText());
|
var value = Boolean.parseBoolean(literalToken.getText());
|
||||||
return new LoxBooleanLiteralNode(value);
|
return new LoxBooleanLiteralNode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoxNilLiteralNode createNilLiteral() {
|
public LoxNilLiteralNode createNilLiteral() {
|
||||||
return new LoxNilLiteralNode();
|
return new LoxNilLiteralNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoxExpressionNode createUnary(Token op, LoxExpressionNode value) {
|
public LoxExpressionNode createUnary(Token op, LoxExpressionNode value) {
|
||||||
return switch (op.getText()) {
|
return switch (op.getText()) {
|
||||||
case "-" -> LoxNegNodeGen.create(value);
|
case "-" -> LoxNegNodeGen.create(value);
|
||||||
case "!" -> LoxLogicalNotNodeGen.create(value);
|
case "!" -> LoxLogicalNotNodeGen.create(value);
|
||||||
@@ -33,7 +63,7 @@ public class LoxNodeFactory {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoxExpressionNode createBinary(Token op, LoxExpressionNode left, LoxExpressionNode right) {
|
public LoxExpressionNode createBinary(Token op, LoxExpressionNode left, LoxExpressionNode right) {
|
||||||
return switch (op.getText()) {
|
return switch (op.getText()) {
|
||||||
case "+" -> LoxAddNodeGen.create(left, right);
|
case "+" -> LoxAddNodeGen.create(left, right);
|
||||||
case "-" -> LoxSubNodeGen.create(left, right);
|
case "-" -> LoxSubNodeGen.create(left, right);
|
||||||
@@ -48,4 +78,20 @@ public class LoxNodeFactory {
|
|||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoxWriteVariableNode createAssignment(Token identifier, LoxExpressionNode value) {
|
||||||
|
var name = TruffleString.fromJavaStringUncached(identifier.getText(), TruffleString.Encoding.US_ASCII);
|
||||||
|
var slot = globalScope.findOrAdd(name);
|
||||||
|
return LoxWriteVariableNodeGen.create(value, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoxReadVariableNode createRead(Token identifier) {
|
||||||
|
var name = TruffleString.fromJavaStringUncached(identifier.getText(), TruffleString.Encoding.US_ASCII);
|
||||||
|
var slot = globalScope.find(name);
|
||||||
|
return LoxReadVariableNodeGen.create(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameDescriptor getFrameDescriptor() {
|
||||||
|
return globalScope.getFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package xyz.ctsk.lox.parser;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||||
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
|
|
||||||
|
public record ParseResult(LoxExpressionNode rootNode, FrameDescriptor frame) { }
|
||||||
@@ -3,6 +3,7 @@ grammar Lox;
|
|||||||
|
|
||||||
@parser::header {
|
@parser::header {
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||||
import com.oracle.truffle.api.source.Source;
|
import com.oracle.truffle.api.source.Source;
|
||||||
|
|
||||||
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
import xyz.ctsk.lox.nodes.LoxExpressionNode;
|
||||||
@@ -11,16 +12,18 @@ import xyz.ctsk.lox.parser.*;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@parser::members {
|
@parser::members {
|
||||||
private LoxNodeFactory factory;
|
|
||||||
|
|
||||||
public static Object parseLox(String source) {
|
private LoxNodeFactory factory;
|
||||||
LoxLexer lexer = new LoxLexer(CharStreams.fromString(source));
|
|
||||||
LoxParser parser = new LoxParser(new CommonTokenStream(lexer));
|
|
||||||
|
|
||||||
parser.factory = new LoxNodeFactory();
|
public static ParseResult parseLox(String source) {
|
||||||
|
LoxLexer lexer = new LoxLexer(CharStreams.fromString(source));
|
||||||
|
LoxParser parser = new LoxParser(new CommonTokenStream(lexer));
|
||||||
|
|
||||||
|
parser.factory = new LoxNodeFactory();
|
||||||
|
var root = parser.expression().result;
|
||||||
|
return new ParseResult(root, parser.factory.getFrameDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
return parser.expression();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file returns [LoxExpressionNode result]
|
file returns [LoxExpressionNode result]
|
||||||
@@ -41,14 +44,17 @@ expression returns [LoxExpressionNode result]
|
|||||||
{ $result = factory.createBinary($op, $left.result, $right.result); }
|
{ $result = factory.createBinary($op, $left.result, $right.result); }
|
||||||
| left=expression op=( EQUAL_EQUAL | BANG_EQUAL ) right=expression
|
| left=expression op=( EQUAL_EQUAL | BANG_EQUAL ) right=expression
|
||||||
{ $result = factory.createBinary($op, $left.result, $right.result); }
|
{ $result = factory.createBinary($op, $left.result, $right.result); }
|
||||||
|
| IDENTIFIER EQUAL expression
|
||||||
|
{ $result = factory.createAssignment($IDENTIFIER, $expression.result); }
|
||||||
;
|
;
|
||||||
|
|
||||||
literal returns [LoxExpressionNode result]
|
literal returns [LoxExpressionNode result]
|
||||||
: NUMBER { $result = factory.createNumberLiteral($NUMBER); }
|
: NUMBER { $result = factory.createNumberLiteral($NUMBER); }
|
||||||
| STRING { $result = factory.createStringLiteral($STRING); }
|
| STRING { $result = factory.createStringLiteral($STRING); }
|
||||||
| TRUE { $result = factory.createBooleanLiteral($TRUE); }
|
| TRUE { $result = factory.createBooleanLiteral($TRUE); }
|
||||||
| FALSE { $result = factory.createBooleanLiteral($FALSE); }
|
| FALSE { $result = factory.createBooleanLiteral($FALSE); }
|
||||||
| NIL { $result = factory.createNilLiteral(); }
|
| NIL { $result = factory.createNilLiteral(); }
|
||||||
|
| IDENTIFIER { $result = factory.createRead($IDENTIFIER); }
|
||||||
;
|
;
|
||||||
|
|
||||||
AND: 'and' ;
|
AND: 'and' ;
|
||||||
|
|||||||
Reference in New Issue
Block a user