mirror of
https://codeberg.org/ProgramSnail/truffle-lama.git
synced 2025-12-06 06:48:47 +00:00
most of node factory nodes (without grammar fixes), different scopes, function arguments, correct way to unreference (without grammar fix), captures (partially, only parsing)
This commit is contained in:
parent
587e733f52
commit
91505d247b
19 changed files with 438 additions and 105 deletions
|
|
@ -30,7 +30,7 @@ public final class GlobalScopeObject implements TruffleObject {
|
||||||
|
|
||||||
public boolean updateVariable(String name, Object value) {
|
public boolean updateVariable(String name, Object value) {
|
||||||
if (this.constants.contains(name)) {
|
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);
|
Object updatedValue = this.variables.computeIfPresent(name, (k, v) -> value);
|
||||||
return updatedValue != null;
|
return updatedValue != null;
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,14 @@ public abstract class FunctionDispatchNode extends Node {
|
||||||
protected static Object dispatchDirectly(FunctionObject function,
|
protected static Object dispatchDirectly(FunctionObject function,
|
||||||
Object[] arguments,
|
Object[] arguments,
|
||||||
@Cached("create(function.callTarget)") DirectCallNode directCallNode) {
|
@Cached("create(function.callTarget)") DirectCallNode directCallNode) {
|
||||||
return directCallNode.call(arguments); // TODO: check arguments count ??
|
return directCallNode.call(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Specialization(replaces = "dispatchDirectly")
|
@Specialization(replaces = "dispatchDirectly")
|
||||||
protected static Object dispatchIndirectly(FunctionObject function,
|
protected static Object dispatchIndirectly(FunctionObject function,
|
||||||
Object[] arguments,
|
Object[] arguments,
|
||||||
@Cached IndirectCallNode indirectCallNode) {
|
@Cached IndirectCallNode indirectCallNode) {
|
||||||
return indirectCallNode.call(function.callTarget, arguments); // TODO: check arguments count ??
|
return indirectCallNode.call(function.callTarget, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Fallback
|
@Fallback
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ public abstract class LamaExpressionNode extends Node {
|
||||||
return LamaContext.get(this);
|
return LamaContext.get(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public abstract Object executeGeneric(VirtualFrame frame);
|
public abstract Object executeGeneric(VirtualFrame frame);
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
package org.programsnail.truffle_lama.nodes.expression;
|
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.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
|
||||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||||
import org.programsnail.truffle_lama.runtime.LamaException;
|
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.LamaUnit;
|
||||||
import org.programsnail.truffle_lama.runtime.LamaGlobalVarRef;
|
|
||||||
|
|
||||||
public final class LamaAssignNode extends LamaExpressionNode {
|
public final class LamaAssignNode extends LamaExpressionNode {
|
||||||
@Child
|
@Child
|
||||||
|
|
@ -22,12 +19,12 @@ public final class LamaAssignNode extends LamaExpressionNode {
|
||||||
var leftValue = leftNode.executeGeneric(frame);
|
var leftValue = leftNode.executeGeneric(frame);
|
||||||
var rightValue = rightNode.executeGeneric(frame);
|
var rightValue = rightNode.executeGeneric(frame);
|
||||||
|
|
||||||
if (leftValue instanceof LamaGlobalVarRef varRef) {
|
if (leftValue instanceof LamaObjRef varRef) {
|
||||||
if (!varRef.assign(rightValue, frame)) {
|
if (!varRef.put(rightValue, frame)) {
|
||||||
throw new LamaException("Can't update variable by identifier '" + varRef.getName() + "'");
|
throw new LamaException("Can't update variable");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new LamaException("Can't assign not to ref", this);
|
throw new LamaException("Can't put not to ref", this);
|
||||||
}
|
}
|
||||||
return LamaUnit.INSTANCE;
|
return LamaUnit.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package org.programsnail.truffle_lama.nodes.expression;
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||||
import org.programsnail.truffle_lama.nodes.FunctionDispatchNode;
|
import org.programsnail.truffle_lama.nodes.FunctionDispatchNode;
|
||||||
|
import org.programsnail.truffle_lama.nodes.FunctionDispatchNodeGen;
|
||||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||||
|
|
||||||
public final class LamaCallNode extends LamaExpressionNode {
|
public final class LamaCallNode extends LamaExpressionNode {
|
||||||
|
|
@ -15,10 +16,10 @@ public final class LamaCallNode extends LamaExpressionNode {
|
||||||
@Child
|
@Child
|
||||||
private FunctionDispatchNode dispatchNode;
|
private FunctionDispatchNode dispatchNode;
|
||||||
|
|
||||||
public LamaCallNode(LamaExpressionNode targetFunction, LamaExpressionNode[] callArguments, FunctionDispatchNode dispatchNode) {
|
public LamaCallNode(LamaExpressionNode targetFunction, LamaExpressionNode[] callArguments) {
|
||||||
this.functionNode = targetFunction;
|
this.functionNode = targetFunction;
|
||||||
this.callArgumentNodes = callArguments;
|
this.callArgumentNodes = callArguments;
|
||||||
this.dispatchNode = dispatchNode;
|
this.dispatchNode = FunctionDispatchNodeGen.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
package org.programsnail.truffle_lama.nodes.expression;
|
package org.programsnail.truffle_lama.nodes.expression;
|
||||||
|
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
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.nodes.LamaExpressionNode;
|
||||||
import org.programsnail.truffle_lama.runtime.LamaGlobalVarRef;
|
import org.programsnail.truffle_lama.runtime.LamaGlobalVarRef;
|
||||||
|
|
||||||
public final class LamaGlobalRefNode extends LamaExpressionNode {
|
public final class LamaGlobalRefNode extends LamaExpressionNode {
|
||||||
String name;
|
private final String name;
|
||||||
|
|
||||||
public LamaGlobalRefNode(String name) {
|
public LamaGlobalRefNode(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
@ -14,6 +13,6 @@ public final class LamaGlobalRefNode extends LamaExpressionNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object executeGeneric(VirtualFrame frame) {
|
public Object executeGeneric(VirtualFrame frame) {
|
||||||
return new LamaGlobalVarRef(this.name, this.currentLanguageContext());
|
return new LamaGlobalVarRef(this.name, this.currentLanguageContext()).get(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ import org.programsnail.truffle_lama.runtime.LamaUnit;
|
||||||
public final class LamaGlobalVarNode extends LamaExpressionNode {
|
public final class LamaGlobalVarNode extends LamaExpressionNode {
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
|
public LamaGlobalVarNode(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object executeGeneric(VirtualFrame frame) {
|
public Object executeGeneric(VirtualFrame frame) {
|
||||||
this.currentLanguageContext().globalScopeObject.newVariable(name, LamaUnit.INSTANCE, false);
|
this.currentLanguageContext().globalScopeObject.newVariable(name, LamaUnit.INSTANCE, false);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package org.programsnail.truffle_lama.nodes.expression;
|
|
||||||
|
|
||||||
public final class LamaLeaveNode {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
@ -19,7 +19,8 @@ public final class LamaLocalVarNode extends LamaExpressionNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object executeGeneric(VirtualFrame frame) {
|
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;
|
return LamaUnit.INSTANCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -224,11 +224,11 @@ postfix returns [List<LamaExpressionNode> args, Optional<LamaExpressionNode> acc
|
||||||
|
|
||||||
primary returns [LamaExpressionNode result]:
|
primary returns [LamaExpressionNode result]:
|
||||||
DECIMAL_LITERAL { $result = factory.createConstNode($DECIMAL_LITERAL); } // minus - inside decimal literal definition
|
DECIMAL_LITERAL { $result = factory.createConstNode($DECIMAL_LITERAL); } // minus - inside decimal literal definition
|
||||||
| STRING_LITERAL { $result = factory.createStringNode(LamaStrings.convertStringLiteral($STRING_LITERAL)); }
|
| STRING_LITERAL { $result = factory.createStringNode($STRING_LITERAL); }
|
||||||
| CHAR_LITERAL { $result = factory.createConstNode(LamaStrings.convertCharLiteral($CHAR_LITERAL)); }
|
| CHAR_LITERAL { $result = factory.createCharConstNode($CHAR_LITERAL); }
|
||||||
| LIDENT { $result = factory.createRefNode($LIDENT); }
|
| LIDENT { $result = factory.createRefNode($LIDENT); }
|
||||||
| 'true' { $result = factory.createConstNode(1); }
|
| tok='true' { $result = factory.createValueConstNode($tok, 1); }
|
||||||
| 'false' { $result = factory.createConstNode(0); }
|
| tok='false' { $result = factory.createValueConstNode($tok, 0); }
|
||||||
| 'infix' any_infix { $result = factory.createRefNode($any_infix.result); }
|
| 'infix' any_infix { $result = factory.createRefNode($any_infix.result); }
|
||||||
| 'fun' '(' function_arguments ')' function_body
|
| 'fun' '(' function_arguments ')' function_body
|
||||||
{ $result = factory.createClosureNode($function_arguments.args, $function_body.result); } // TODO: scopes
|
{ $result = factory.createClosureNode($function_arguments.args, $function_body.result); } // TODO: scopes
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package org.programsnail.truffle_lama.parser;
|
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.FrameDescriptor;
|
||||||
|
import com.oracle.truffle.api.frame.FrameSlotKind;
|
||||||
import com.oracle.truffle.api.source.Source;
|
import com.oracle.truffle.api.source.Source;
|
||||||
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;
|
||||||
|
|
@ -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.controlflow.LamaWhileNode;
|
||||||
import org.programsnail.truffle_lama.nodes.expression.*;
|
import org.programsnail.truffle_lama.nodes.expression.*;
|
||||||
import org.programsnail.truffle_lama.nodes.pattern.*;
|
import org.programsnail.truffle_lama.nodes.pattern.*;
|
||||||
|
import org.programsnail.truffle_lama.runtime.LamaException;
|
||||||
|
|
||||||
import javax.print.attribute.standard.PresentationDirection;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class LamaNodeFactory {
|
public class LamaNodeFactory {
|
||||||
static class LexicalScope {
|
|
||||||
protected final LexicalScope outer;
|
|
||||||
protected final Map<TruffleString, Integer> locals;
|
|
||||||
|
|
||||||
LexicalScope(LexicalScope outer) {
|
static class FunctionData {
|
||||||
this.outer = outer;
|
protected FrameDescriptor.Builder frameDescriptorBuilder;
|
||||||
this.locals = new HashMap<>();
|
protected Map<Integer, Integer> captureList;
|
||||||
|
protected Map<String, Integer> arguments;
|
||||||
|
|
||||||
|
public FunctionData() {
|
||||||
|
this.frameDescriptorBuilder = FrameDescriptor.newBuilder();
|
||||||
|
this.captureList = Map.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer find(TruffleString name) {
|
public FrameDescriptor.Builder getFrameDescriptorBuilder() {
|
||||||
|
return frameDescriptorBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer, Integer> getCaptureList() {
|
||||||
|
return captureList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Integer> 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<String, Integer> 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);
|
Integer result = locals.get(name);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
} else if (outer != null) {
|
} else if (outer != null && !isTop && (!isFramed() || throughFrame)) {
|
||||||
return outer.find(name);
|
return outer.find(name);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
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. */
|
/* State while parsing a source unit. */
|
||||||
private final Source source;
|
private final Source source;
|
||||||
private final TruffleString sourceString;
|
private final TruffleString sourceString;
|
||||||
// private final Map<TruffleString, RootCallTarget> 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. */
|
/* State while parsing an expr. */
|
||||||
private LexicalScope lexicalScope;
|
private LexicalScope lexicalScope;
|
||||||
|
|
@ -64,24 +268,38 @@ public class LamaNodeFactory {
|
||||||
this.language = language;
|
this.language = language;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.sourceString = LamaStrings.fromJavaString(source.getCharacters().toString());
|
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() {
|
public void enterScope(LexicalScope.Kind kind) {
|
||||||
// TODO
|
lexicalScope = new LexicalScope(lexicalScope, kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exitScope() {
|
public void exitScope() {
|
||||||
// TODO
|
lexicalScope = lexicalScope.getOuter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
public LamaExpressionNode defineFunction(String name, LamaExpressionNode[] args, LamaExpressionNode body) {
|
// TODO: add to parser
|
||||||
// TODO: set correct frame descriptor, scope, etc.
|
public void AddFunctionArguments(Token[] args) {
|
||||||
return null; // TODO
|
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
|
// 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
|
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);
|
return addSrcFromToken(new LamaConstNode(Long.parseLong(token.getText())), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LamaExpressionNode createVarNode(String name, LamaExpressionNode value) {
|
public LamaExpressionNode createValueConstNode(Token token, long value) {
|
||||||
// TODO: register id in current frame descriptor
|
return addSrcFromToken(new LamaConstNode(value), token);
|
||||||
return null; // TODO
|
}
|
||||||
|
|
||||||
|
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) {
|
public LamaExpressionNode createSeqNode(LamaExpressionNode left, LamaExpressionNode right) {
|
||||||
|
|
@ -115,25 +353,41 @@ public class LamaNodeFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: decide Elem or ElemRef
|
// TODO: decide Elem or ElemRef
|
||||||
public LamaExpressionNode createElemNode(LamaExpressionNode array, LamaExpressionNode index) {
|
public LamaExpressionNode createElemRefOrValueNode(LamaExpressionNode array, LamaExpressionNode index, boolean doUnref) {
|
||||||
return addSrcFromNodes(LamaElemNodeGen.create(array, index), array, index);
|
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) {
|
public LamaExpressionNode createCallNode(LamaExpressionNode func, LamaExpressionNode[] args) {
|
||||||
// TODO: find function in local / global vars
|
return addSrcFromNodes(new LamaCallNode(func, args), func, args.length > 0 ? args[args.length - 1] : func);
|
||||||
return null; // TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LamaExpressionNode createRefNode(String name) {
|
public LamaExpressionNode createRefOrValueNode(Token token, boolean doUnref) {
|
||||||
// TODO: find var in local / global vars
|
return addUnref(createRefNode(token), doUnref);
|
||||||
return null; // TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LamaExpressionNode createClosureNode(LamaExpressionNode[] args, LamaExpressionNode body) {
|
public LamaExpressionNode createRefNode(Token token) {
|
||||||
// TODO: build frame descriptor from body
|
String name = token.getText();
|
||||||
// TODO: set correct frame descriptor, scope, etc.
|
|
||||||
// return new LamaLambdaNode(body, "", /**/, args);
|
Integer slot = lexicalScope.find(name); // globals => null, check inside
|
||||||
return null; // TODO
|
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) {
|
public LamaExpressionNode createSkipNode(Token token) {
|
||||||
|
|
@ -200,11 +454,10 @@ public class LamaNodeFactory {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix name pattern: add possibility of associated pattern
|
public LamaPattern createNamedPattern(Token token, LamaPattern pattern) {
|
||||||
public LamaPattern createNamedPattern(TruffleString name, LamaPattern pattern) {
|
String name = token.getText();
|
||||||
// TODO: register frame descriptor id
|
int frameSlot = lexicalScope.add(name);
|
||||||
// return new LamaNamedPattern(/*id*/, pattern);
|
return new LamaNamedPattern(frameSlot, pattern);
|
||||||
return null; // TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LamaPattern createConstPattern(Token token) {
|
public LamaPattern createConstPattern(Token token) {
|
||||||
|
|
@ -250,12 +503,35 @@ public class LamaNodeFactory {
|
||||||
return node;
|
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) {
|
private static LamaExpressionNode addSrcFromNodes(LamaExpressionNode node, LamaExpressionNode begin, LamaExpressionNode end) {
|
||||||
int beginIndex = begin.getSourceCharIndex();
|
int beginIndex = begin.getSourceCharIndex();
|
||||||
node.setSourceSection(beginIndex, end.getSourceEndIndex() - beginIndex);
|
node.setSourceSection(beginIndex, end.getSourceEndIndex() - beginIndex);
|
||||||
return node;
|
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() {
|
public LamaExpressionNode getRootExpr() {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,12 @@ public class LamaElemRef extends LamaObjRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
return array.assignAt(id, object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,12 @@ public final class LamaGlobalVarRef extends LamaObjRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
return this.context.globalScopeObject.updateVariable(name, object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,12 @@ public final class LamaLocalVarRef extends LamaObjRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
frame.setObject(id, object);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,7 @@ package org.programsnail.truffle_lama.runtime;
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
|
||||||
public abstract class LamaObjRef {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue