diff --git a/src/main/java/org/programsnail/truffle_lama/GlobalScopeObject.java b/src/main/java/org/programsnail/truffle_lama/GlobalScopeObject.java index b499be0..3ae2d76 100644 --- a/src/main/java/org/programsnail/truffle_lama/GlobalScopeObject.java +++ b/src/main/java/org/programsnail/truffle_lama/GlobalScopeObject.java @@ -30,7 +30,7 @@ public final class GlobalScopeObject implements TruffleObject { public boolean updateVariable(String name, Object value) { if (this.constants.contains(name)) { - throw new LamaException("Can't assign to const var '" + name + "'."); + throw new LamaException("Can't put to const var '" + name + "'."); } Object updatedValue = this.variables.computeIfPresent(name, (k, v) -> value); return updatedValue != null; diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/FunctionDispatchNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/FunctionDispatchNode.java index 6933b15..e2d559a 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/FunctionDispatchNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/FunctionDispatchNode.java @@ -16,14 +16,14 @@ public abstract class FunctionDispatchNode extends Node { protected static Object dispatchDirectly(FunctionObject function, Object[] arguments, @Cached("create(function.callTarget)") DirectCallNode directCallNode) { - return directCallNode.call(arguments); // TODO: check arguments count ?? + return directCallNode.call(arguments); } @Specialization(replaces = "dispatchDirectly") protected static Object dispatchIndirectly(FunctionObject function, Object[] arguments, @Cached IndirectCallNode indirectCallNode) { - return indirectCallNode.call(function.callTarget, arguments); // TODO: check arguments count ?? + return indirectCallNode.call(function.callTarget, arguments); } @Fallback diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/LamaExpressionNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/LamaExpressionNode.java index fb57137..46dbca4 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/LamaExpressionNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/LamaExpressionNode.java @@ -24,8 +24,7 @@ public abstract class LamaExpressionNode extends Node { protected final LamaContext currentLanguageContext() { return LamaContext.get(this); } - - + public abstract Object executeGeneric(VirtualFrame frame); // --- diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaArgumentRefNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaArgumentRefNode.java new file mode 100644 index 0000000..dc58a8f --- /dev/null +++ b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaArgumentRefNode.java @@ -0,0 +1,18 @@ +package org.programsnail.truffle_lama.nodes.expression; + +import com.oracle.truffle.api.frame.VirtualFrame; +import org.programsnail.truffle_lama.nodes.LamaExpressionNode; +import org.programsnail.truffle_lama.runtime.LamaArgumentRef; + +public final class LamaArgumentRefNode extends LamaExpressionNode { + private final int index; + + public LamaArgumentRefNode(int index) { + this.index = index; + } + + @Override + public Object executeGeneric(VirtualFrame frame) { + return new LamaArgumentRef(this.index); + } +} diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaAssignNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaAssignNode.java index 55a0dce..8256054 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaAssignNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaAssignNode.java @@ -1,13 +1,10 @@ package org.programsnail.truffle_lama.nodes.expression; -import com.oracle.truffle.api.dsl.NodeChild; -import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.UnexpectedResultException; import org.programsnail.truffle_lama.nodes.LamaExpressionNode; import org.programsnail.truffle_lama.runtime.LamaException; +import org.programsnail.truffle_lama.runtime.LamaObjRef; import org.programsnail.truffle_lama.runtime.LamaUnit; -import org.programsnail.truffle_lama.runtime.LamaGlobalVarRef; public final class LamaAssignNode extends LamaExpressionNode { @Child @@ -22,12 +19,12 @@ public final class LamaAssignNode extends LamaExpressionNode { var leftValue = leftNode.executeGeneric(frame); var rightValue = rightNode.executeGeneric(frame); - if (leftValue instanceof LamaGlobalVarRef varRef) { - if (!varRef.assign(rightValue, frame)) { - throw new LamaException("Can't update variable by identifier '" + varRef.getName() + "'"); + if (leftValue instanceof LamaObjRef varRef) { + if (!varRef.put(rightValue, frame)) { + throw new LamaException("Can't update variable"); } } else { - throw new LamaException("Can't assign not to ref", this); + throw new LamaException("Can't put not to ref", this); } return LamaUnit.INSTANCE; } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaCallNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaCallNode.java index f123770..fd97ce5 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaCallNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaCallNode.java @@ -3,6 +3,7 @@ package org.programsnail.truffle_lama.nodes.expression; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; import org.programsnail.truffle_lama.nodes.FunctionDispatchNode; +import org.programsnail.truffle_lama.nodes.FunctionDispatchNodeGen; import org.programsnail.truffle_lama.nodes.LamaExpressionNode; public final class LamaCallNode extends LamaExpressionNode { @@ -15,10 +16,10 @@ public final class LamaCallNode extends LamaExpressionNode { @Child private FunctionDispatchNode dispatchNode; - public LamaCallNode(LamaExpressionNode targetFunction, LamaExpressionNode[] callArguments, FunctionDispatchNode dispatchNode) { + public LamaCallNode(LamaExpressionNode targetFunction, LamaExpressionNode[] callArguments) { this.functionNode = targetFunction; this.callArgumentNodes = callArguments; - this.dispatchNode = dispatchNode; + this.dispatchNode = FunctionDispatchNodeGen.create(); } @Override diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaElemNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaElemNode.java deleted file mode 100644 index ad6e65e..0000000 --- a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaElemNode.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.programsnail.truffle_lama.nodes.expression; - -import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.NodeChild; -import com.oracle.truffle.api.dsl.Specialization; -import org.programsnail.truffle_lama.nodes.LamaExpressionNode; -import org.programsnail.truffle_lama.runtime.LamaArrayLike; -import org.programsnail.truffle_lama.runtime.LamaException; - -@NodeChild("leftNode") -@NodeChild("rightNode") -public abstract class LamaElemNode extends LamaExpressionNode { - @Specialization - public Object accessAt(LamaArrayLike array, int id) { - return array.readAt(id); - } - - @Fallback - public Object accessFailed(Object array, Object id) { - throw new LamaException("Elem: wrong types", this); - } -} diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalRefNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalRefNode.java index b2942fc..d548936 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalRefNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalRefNode.java @@ -1,12 +1,11 @@ package org.programsnail.truffle_lama.nodes.expression; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.UnexpectedResultException; import org.programsnail.truffle_lama.nodes.LamaExpressionNode; import org.programsnail.truffle_lama.runtime.LamaGlobalVarRef; public final class LamaGlobalRefNode extends LamaExpressionNode { - String name; + private final String name; public LamaGlobalRefNode(String name) { this.name = name; @@ -14,6 +13,6 @@ public final class LamaGlobalRefNode extends LamaExpressionNode { @Override public Object executeGeneric(VirtualFrame frame) { - return new LamaGlobalVarRef(this.name, this.currentLanguageContext()); + return new LamaGlobalVarRef(this.name, this.currentLanguageContext()).get(frame); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalVarNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalVarNode.java index 00800f2..7c1827e 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalVarNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaGlobalVarNode.java @@ -8,6 +8,10 @@ import org.programsnail.truffle_lama.runtime.LamaUnit; public final class LamaGlobalVarNode extends LamaExpressionNode { String name; + public LamaGlobalVarNode(String name) { + this.name = name; + } + @Override public Object executeGeneric(VirtualFrame frame) { this.currentLanguageContext().globalScopeObject.newVariable(name, LamaUnit.INSTANCE, false); diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaLeaveNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaLeaveNode.java deleted file mode 100644 index 9fb42eb..0000000 --- a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaLeaveNode.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.programsnail.truffle_lama.nodes.expression; - -public final class LamaLeaveNode { - // TODO -} diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaLocalVarNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaLocalVarNode.java index 0898448..e77eabf 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaLocalVarNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaLocalVarNode.java @@ -19,7 +19,8 @@ public final class LamaLocalVarNode extends LamaExpressionNode { @Override public Object executeGeneric(VirtualFrame frame) { - frame.getFrameDescriptor().setSlotKind(this.frameSlot, FrameSlotKind.Object); + // NOTE: slot is already created in parser.NodeFactory + // frame.getFrameDescriptor().setSlotKind(this.frameSlot, FrameSlotKind.Object); return LamaUnit.INSTANCE; } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaUnrefNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaUnrefNode.java new file mode 100644 index 0000000..44ee653 --- /dev/null +++ b/src/main/java/org/programsnail/truffle_lama/nodes/expression/LamaUnrefNode.java @@ -0,0 +1,26 @@ +package org.programsnail.truffle_lama.nodes.expression; + +import com.oracle.truffle.api.frame.VirtualFrame; +import org.programsnail.truffle_lama.nodes.LamaExpressionNode; +import org.programsnail.truffle_lama.runtime.LamaException; +import org.programsnail.truffle_lama.runtime.LamaObjRef; +import org.programsnail.truffle_lama.runtime.LamaUnit; + +public final class LamaUnrefNode extends LamaExpressionNode { + @Child + private LamaExpressionNode refNode; + + public LamaUnrefNode(LamaExpressionNode refNode) { + this.refNode = refNode; + } + + public Object executeGeneric(VirtualFrame frame) { + var refValue = refNode.executeGeneric(frame); + + if (refValue instanceof LamaObjRef varRef) { + return varRef.get(frame); + } + + throw new LamaException("Can't put not to ref", this); + } +} diff --git a/src/main/java/org/programsnail/truffle_lama/parser/Lama.g4 b/src/main/java/org/programsnail/truffle_lama/parser/Lama.g4 index 3a00436..ea6a454 100644 --- a/src/main/java/org/programsnail/truffle_lama/parser/Lama.g4 +++ b/src/main/java/org/programsnail/truffle_lama/parser/Lama.g4 @@ -224,11 +224,11 @@ postfix returns [List args, Optional acc primary returns [LamaExpressionNode result]: DECIMAL_LITERAL { $result = factory.createConstNode($DECIMAL_LITERAL); } // minus - inside decimal literal definition - | STRING_LITERAL { $result = factory.createStringNode(LamaStrings.convertStringLiteral($STRING_LITERAL)); } - | CHAR_LITERAL { $result = factory.createConstNode(LamaStrings.convertCharLiteral($CHAR_LITERAL)); } + | STRING_LITERAL { $result = factory.createStringNode($STRING_LITERAL); } + | CHAR_LITERAL { $result = factory.createCharConstNode($CHAR_LITERAL); } | LIDENT { $result = factory.createRefNode($LIDENT); } - | 'true' { $result = factory.createConstNode(1); } - | 'false' { $result = factory.createConstNode(0); } + | tok='true' { $result = factory.createValueConstNode($tok, 1); } + | tok='false' { $result = factory.createValueConstNode($tok, 0); } | 'infix' any_infix { $result = factory.createRefNode($any_infix.result); } | 'fun' '(' function_arguments ')' function_body { $result = factory.createClosureNode($function_arguments.args, $function_body.result); } // TODO: scopes diff --git a/src/main/java/org/programsnail/truffle_lama/parser/LamaNodeFactory.java b/src/main/java/org/programsnail/truffle_lama/parser/LamaNodeFactory.java index 35a47f1..ad9a369 100644 --- a/src/main/java/org/programsnail/truffle_lama/parser/LamaNodeFactory.java +++ b/src/main/java/org/programsnail/truffle_lama/parser/LamaNodeFactory.java @@ -1,7 +1,7 @@ package org.programsnail.truffle_lama.parser; -import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.strings.TruffleString; import org.antlr.v4.runtime.Token; @@ -14,47 +14,251 @@ import org.programsnail.truffle_lama.nodes.controlflow.LamaIfNode; import org.programsnail.truffle_lama.nodes.controlflow.LamaWhileNode; import org.programsnail.truffle_lama.nodes.expression.*; import org.programsnail.truffle_lama.nodes.pattern.*; +import org.programsnail.truffle_lama.runtime.LamaException; -import javax.print.attribute.standard.PresentationDirection; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class LamaNodeFactory { - static class LexicalScope { - protected final LexicalScope outer; - protected final Map locals; - LexicalScope(LexicalScope outer) { - this.outer = outer; - this.locals = new HashMap<>(); + static class FunctionData { + protected FrameDescriptor.Builder frameDescriptorBuilder; + protected Map captureList; + protected Map arguments; + + public FunctionData() { + this.frameDescriptorBuilder = FrameDescriptor.newBuilder(); + this.captureList = Map.of(); } - public Integer find(TruffleString name) { + public FrameDescriptor.Builder getFrameDescriptorBuilder() { + return frameDescriptorBuilder; + } + + public Map getCaptureList() { + return captureList; + } + + public Map getArguments() { + return arguments; + } + + public FrameDescriptor buildFrameDescriptor() { + return this.frameDescriptorBuilder.build(); + } + + public Integer addArgument(String name) { + if (arguments.get(name) != null) { + throw new LamaException("Can't bind argument " + name + " more then once in one function"); + } + int index = arguments.size(); + return arguments.put(name, index); + } + + public int findArgument(String name) { + return arguments.get(name); + } + + public int getArgumentsCount() { + return arguments.size(); + } + } + + static class LexicalScope { + protected final LexicalScope outer; + protected final LexicalScope global; + protected final LexicalScope top; + protected final LexicalScope frame; + protected final boolean isTop; + + protected final Map locals; + + FunctionData functionData; + + public enum Kind { + INNER_SCOPE, + INNER_CLOSURE, + FUNCTION, + } + + // outer scope == null -> global scope + // isTop - for independent lexical scopes separation (functions) + // isFramed - to separate scopes with capture possibility + public LexicalScope(LexicalScope outer, Kind kind) { + boolean isTop = kind == Kind.FUNCTION; + boolean isFramed = kind == Kind.INNER_CLOSURE || kind == Kind.FUNCTION; + // assert !isTop || isFramed; + + this.outer = outer; + this.isTop = isTop; + this.locals = new HashMap<>(); + + this.global = outer == null ? this : outer; + this.top = isTop ? this : (outer == null ? null : outer.top); + this.frame = isFramed ? this : (outer == null ? null : outer.frame); + + if (isFramed) { + functionData = new FunctionData(); + } + } + + public LexicalScope getOuter() { + return outer; + } + + public LexicalScope getGlobal() { + return global; + } + + public LexicalScope getTop() { + return top; + } + + public LexicalScope getFrame() { + return frame; + } + + public int getArgumentsCount() { + return frame.functionData.getArgumentsCount(); + } + + + // --- + + public FrameDescriptor buildFrameDescriptor() { + return functionData.buildFrameDescriptor(); + } + + // --- + + public boolean isGlobal() { + return outer == null; + } + + public boolean isFramed() { + return functionData != null; + } + + // --- + + public int addArgument(String name) { + if (!isFramed()) { + throw new LamaException("Can't add argument " + name + ": not in the function primary scope"); + } + return frame.functionData.addArgument(name); + } + + public int add(String name) { + int frameSlot = addSlot(name); + if (locals.get(name) != null) { + throw new LamaException("Can't bind name " + name + " more then once in one scope"); + } + locals.put(name, frameSlot); + return frameSlot; + } + + public int addToGlobal(String name) { + return global.add(name); + } + + // NOTE: only for frame + protected int addWithCapture(String name, Integer capturedSlot) { + int frameSlot = add(name); + if (capturedSlot != null) { + functionData.getCaptureList().put(frameSlot, capturedSlot); + } + return frameSlot; + } + + protected int addToFrameWithCapture(String name, Integer capturedSlot) { + if (frame == null) { + throw new LamaException("Can't bind name " + name + " at top scope: no frame scope available"); + } + return frame.addWithCapture(name, capturedSlot); + } + + public int addToFrame(String name) { + return addToFrameWithCapture(name, null); + } + + public Integer capture(String name) { + if (isGlobal()) { // can't capture in global context + return null; + } + if (find(name) != null) { + throw new LamaException("Can't capture name " + name + ": name already is in function scope"); + } + return captureNoCheck(name); + } + + public Integer captureNoCheck(String name) { + Integer capturedSlot = frame.findNoCheck(name, true); + if (capturedSlot == null) { + return null; + } + return addToFrameWithCapture(name, capturedSlot); + } + + // --- + + public Integer findArgument(String name) { + return frame.functionData.findArgument(name); + } + + public Integer findGlobal(String name) { + return global.findNoCheck(name, false); + } + + public Integer find(String name) { + if (isGlobal()) { // global variables are not part of the local scope + return null; + } + return findNoCheck(name, false); + } + + protected Integer findNoCheck(String name, boolean throughFrame) { Integer result = locals.get(name); if (result != null) { return result; - } else if (outer != null) { + } else if (outer != null && !isTop && (!isFramed() || throughFrame)) { return outer.find(name); } else { return null; } } + + public Integer findOrCapture(String name) { + if (isGlobal()) { // global variables are not part of the local scope + return null; + } + Integer result = findNoCheck(name, false); + if (result == null) { + return captureNoCheck(name); + } + return result; + } + + // --- + + protected int addSlot(String name) { + if (isGlobal()) { + return 0; // no slots + } + + if (frame == null) { + throw new LamaException("Can't add slot for name " + name + ": no frame scope available"); + } + + if (isFramed()) { + return outer.addSlot(name); + } + + return functionData.getFrameDescriptorBuilder().addSlot(FrameSlotKind.Object, name, null); + } } /* State while parsing a source unit. */ private final Source source; private final TruffleString sourceString; -// private final Map allFunctions; // defined in scope - - /* State while parsing a function. */ - private int functionStartPos; - private TruffleString functionName; - private int functionBodyStartPos; // includes parameter list - private int argumentsCount; - private FrameDescriptor.Builder frameDescriptorBuilder; - private LamaExpressionNode functionBody; /* State while parsing an expr. */ private LexicalScope lexicalScope; @@ -64,24 +268,38 @@ public class LamaNodeFactory { this.language = language; this.source = source; this.sourceString = LamaStrings.fromJavaString(source.getCharacters().toString()); -// this.allFunctions = new HashMap<>(); + lexicalScope = new LexicalScope(null, LexicalScope.Kind.FUNCTION); // same to top level } // --- - public void enterScope() { - // TODO + public void enterScope(LexicalScope.Kind kind) { + lexicalScope = new LexicalScope(lexicalScope, kind); } public void exitScope() { - // TODO + lexicalScope = lexicalScope.getOuter(); } // --- - public LamaExpressionNode defineFunction(String name, LamaExpressionNode[] args, LamaExpressionNode body) { - // TODO: set correct frame descriptor, scope, etc. - return null; // TODO + // TODO: add to parser + public void AddFunctionArguments(Token[] args) { + for (Token arg : args) { + lexicalScope.addArgument(arg.getText()); + } + } + + // TODO: FIXME: save captures into function + public LamaExpressionNode createClosureNode(Token beginToken, LamaExpressionNode body, int argsCount) { + return addSrcFromTokenAndNode( + new LamaLambdaNode( + body, + "", + lexicalScope.buildFrameDescriptor(), + lexicalScope.getArgumentsCount()), + beginToken, + body); } // --- @@ -93,7 +311,7 @@ public class LamaNodeFactory { } // TODO: use in grammar - public LamaExpressionNode createConstCharNode(Token token) { + public LamaExpressionNode createCharConstNode(Token token) { return addSrcFromToken(new LamaConstNode(token.getText().charAt(1)), token); // TODO: special chars } @@ -101,9 +319,29 @@ public class LamaNodeFactory { return addSrcFromToken(new LamaConstNode(Long.parseLong(token.getText())), token); } - public LamaExpressionNode createVarNode(String name, LamaExpressionNode value) { - // TODO: register id in current frame descriptor - return null; // TODO + public LamaExpressionNode createValueConstNode(Token token, long value) { + return addSrcFromToken(new LamaConstNode(value), token); + } + + public LamaExpressionNode createVarNode(Token token) { + String name = token.getText(); + + int slot = lexicalScope.add(name); // TODO: check if not arg ?? + return addSrcFromToken(lexicalScope.isGlobal() /*global scope*/ + ? new LamaGlobalVarNode(name) + : new LamaLocalVarNode(slot), token); + } + + public LamaExpressionNode createAssignNode(LamaExpressionNode left, LamaExpressionNode right) { + return addSrcFromNodes(new LamaAssignNode(left, right), left, right); + } + + // TODO: fix assignment in parser (var + ref + put ??) + public LamaExpressionNode createAssignVarNode(Token token, LamaExpressionNode value) { + var definition = createVarNode(token); + var reference = createRefNode(token); + var assignment = createAssignNode(reference, value); + return createSeqNode(definition, assignment); } public LamaExpressionNode createSeqNode(LamaExpressionNode left, LamaExpressionNode right) { @@ -115,25 +353,41 @@ public class LamaNodeFactory { } // TODO: decide Elem or ElemRef - public LamaExpressionNode createElemNode(LamaExpressionNode array, LamaExpressionNode index) { - return addSrcFromNodes(LamaElemNodeGen.create(array, index), array, index); + public LamaExpressionNode createElemRefOrValueNode(LamaExpressionNode array, LamaExpressionNode index, boolean doUnref) { + return addUnref(createElemRefNode(array, index), doUnref); + } + + public LamaExpressionNode createElemRefNode(LamaExpressionNode array, LamaExpressionNode index) { + return addSrcFromNodes(LamaElemRefNodeGen.create(array, index), array, index); } public LamaExpressionNode createCallNode(LamaExpressionNode func, LamaExpressionNode[] args) { - // TODO: find function in local / global vars - return null; // TODO + return addSrcFromNodes(new LamaCallNode(func, args), func, args.length > 0 ? args[args.length - 1] : func); } - public LamaExpressionNode createRefNode(String name) { - // TODO: find var in local / global vars - return null; // TODO + public LamaExpressionNode createRefOrValueNode(Token token, boolean doUnref) { + return addUnref(createRefNode(token), doUnref); } - public LamaExpressionNode createClosureNode(LamaExpressionNode[] args, LamaExpressionNode body) { - // TODO: build frame descriptor from body - // TODO: set correct frame descriptor, scope, etc. - // return new LamaLambdaNode(body, "", /**/, args); - return null; // TODO + public LamaExpressionNode createRefNode(Token token) { + String name = token.getText(); + + Integer slot = lexicalScope.find(name); // globals => null, check inside + if (slot != null) { + return addSrcFromToken(new LamaLocalRefNode(slot), token); + } + + slot = lexicalScope.findArgument(name); + if (slot != null) { + return addSrcFromToken(new LamaArgumentRefNode(slot), token); + } + + slot = lexicalScope.captureNoCheck(name); + if (slot != null) { + return addSrcFromToken(new LamaLocalRefNode(slot), token); + } + + return addSrcFromToken(new LamaGlobalRefNode(name), token); } public LamaExpressionNode createSkipNode(Token token) { @@ -200,11 +454,10 @@ public class LamaNodeFactory { return result; } - // TODO: fix name pattern: add possibility of associated pattern - public LamaPattern createNamedPattern(TruffleString name, LamaPattern pattern) { - // TODO: register frame descriptor id - // return new LamaNamedPattern(/*id*/, pattern); - return null; // TODO + public LamaPattern createNamedPattern(Token token, LamaPattern pattern) { + String name = token.getText(); + int frameSlot = lexicalScope.add(name); + return new LamaNamedPattern(frameSlot, pattern); } public LamaPattern createConstPattern(Token token) { @@ -250,12 +503,35 @@ public class LamaNodeFactory { return node; } + private static LamaExpressionNode addSrcFromTokenAndNode(LamaExpressionNode node, Token begin, LamaExpressionNode end) { + int beginIndex = begin.getStartIndex(); + node.setSourceSection(beginIndex, end.getSourceEndIndex() - beginIndex); + return node; + } + + private static LamaExpressionNode addSrcFromNodeAndToken(LamaExpressionNode node, LamaExpressionNode begin, Token end) { + int beginIndex = begin.getSourceCharIndex(); + node.setSourceSection(beginIndex, end.getStopIndex() - beginIndex); + return node; + } + private static LamaExpressionNode addSrcFromNodes(LamaExpressionNode node, LamaExpressionNode begin, LamaExpressionNode end) { int beginIndex = begin.getSourceCharIndex(); node.setSourceSection(beginIndex, end.getSourceEndIndex() - beginIndex); return node; } + private static LamaExpressionNode addSrcFromNode(LamaExpressionNode node, LamaExpressionNode other) { + node.setSourceSection(other.getSourceCharIndex(), other.getSourceLength()); + return node; + } + + // --- + + private static LamaExpressionNode addUnref(LamaExpressionNode node, boolean doUnref) { + return doUnref ? addSrcFromNode(new LamaUnrefNode(node), node) : node; + } + // --- public LamaExpressionNode getRootExpr() { diff --git a/src/main/java/org/programsnail/truffle_lama/runtime/LamaArgumentRef.java b/src/main/java/org/programsnail/truffle_lama/runtime/LamaArgumentRef.java new file mode 100644 index 0000000..38a7abb --- /dev/null +++ b/src/main/java/org/programsnail/truffle_lama/runtime/LamaArgumentRef.java @@ -0,0 +1,22 @@ +package org.programsnail.truffle_lama.runtime; + +import com.oracle.truffle.api.frame.VirtualFrame; + +public final class LamaArgumentRef extends LamaObjRef { + private int index; + + public LamaArgumentRef(int id) { + this.index = id; + } + + @Override + public Object get(VirtualFrame frame) { + return frame.getArguments()[index]; + } + + @Override + public boolean put(Object object, VirtualFrame frame) { + frame.getArguments()[index] = object; + return true; + } +} diff --git a/src/main/java/org/programsnail/truffle_lama/runtime/LamaElemRef.java b/src/main/java/org/programsnail/truffle_lama/runtime/LamaElemRef.java index 49dd8a8..fdcdc3e 100644 --- a/src/main/java/org/programsnail/truffle_lama/runtime/LamaElemRef.java +++ b/src/main/java/org/programsnail/truffle_lama/runtime/LamaElemRef.java @@ -12,7 +12,12 @@ public class LamaElemRef extends LamaObjRef { } @Override - public boolean assign(Object object, VirtualFrame frame) { + public Object get(VirtualFrame frame) { + return array.readAt(id); + } + + @Override + public boolean put(Object object, VirtualFrame frame) { return array.assignAt(id, object); } } diff --git a/src/main/java/org/programsnail/truffle_lama/runtime/LamaGlobalVarRef.java b/src/main/java/org/programsnail/truffle_lama/runtime/LamaGlobalVarRef.java index 67786b1..13be7a9 100644 --- a/src/main/java/org/programsnail/truffle_lama/runtime/LamaGlobalVarRef.java +++ b/src/main/java/org/programsnail/truffle_lama/runtime/LamaGlobalVarRef.java @@ -17,7 +17,12 @@ public final class LamaGlobalVarRef extends LamaObjRef { } @Override - public boolean assign(Object object, VirtualFrame frame) { + public Object get(VirtualFrame frame) { + return this.context.globalScopeObject.getVariable(name); + } + + @Override + public boolean put(Object object, VirtualFrame frame) { return this.context.globalScopeObject.updateVariable(name, object); } } diff --git a/src/main/java/org/programsnail/truffle_lama/runtime/LamaLocalVarRef.java b/src/main/java/org/programsnail/truffle_lama/runtime/LamaLocalVarRef.java index 8f08339..c9d3043 100644 --- a/src/main/java/org/programsnail/truffle_lama/runtime/LamaLocalVarRef.java +++ b/src/main/java/org/programsnail/truffle_lama/runtime/LamaLocalVarRef.java @@ -10,7 +10,12 @@ public final class LamaLocalVarRef extends LamaObjRef { } @Override - public boolean assign(Object object, VirtualFrame frame) { + public Object get(VirtualFrame frame) { + return frame.getObject(id); + } + + @Override + public boolean put(Object object, VirtualFrame frame) { frame.setObject(id, object); return true; } diff --git a/src/main/java/org/programsnail/truffle_lama/runtime/LamaObjRef.java b/src/main/java/org/programsnail/truffle_lama/runtime/LamaObjRef.java index 1654c35..06a84bc 100644 --- a/src/main/java/org/programsnail/truffle_lama/runtime/LamaObjRef.java +++ b/src/main/java/org/programsnail/truffle_lama/runtime/LamaObjRef.java @@ -3,5 +3,7 @@ package org.programsnail.truffle_lama.runtime; import com.oracle.truffle.api.frame.VirtualFrame; public abstract class LamaObjRef { - public abstract boolean assign(Object object, VirtualFrame frame); + public abstract Object get(VirtualFrame frame); + + public abstract boolean put(Object object, VirtualFrame frame); }