mirror of
https://codeberg.org/ProgramSnail/truffle-lama.git
synced 2025-12-05 22:38:43 +00:00
init nodes, some basic nodes implementations
This commit is contained in:
parent
a149766007
commit
07b80ce5cb
46 changed files with 906 additions and 256 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -35,4 +35,6 @@ build/
|
|||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
gen/
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
This is an attempt to implement the LaMa language (https://github.com/PLTools/Lama) with GraalVM and Truffle.
|
||||
|
||||
Code is based on:
|
||||
|
||||
- https://github.com/graalvm/simplelanguage
|
||||
- https://github.com/cesquivias/mumbler
|
||||
- https://github.com/skinny85/graalvm-truffle-tutorial
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package org.programsnail.truffle_lama;
|
||||
|
||||
import com.oracle.truffle.api.CallTarget;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.library.ExportLibrary;
|
||||
import com.oracle.truffle.api.library.ExportMessage;
|
||||
import org.programsnail.truffle_lama.nodes.FunctionDispatchNode;
|
||||
import org.programsnail.truffle_lama.runtime.LamaException;
|
||||
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
public final class FunctionObject implements TruffleObject {
|
||||
public final CallTarget callTarget;
|
||||
public final int argumentCount;
|
||||
public final FunctionDispatchNode functionDispatchNode;
|
||||
|
||||
public FunctionObject(CallTarget callTarget, int argumentCount, FunctionDispatchNode functionDispatchNode) {
|
||||
this.callTarget = callTarget;
|
||||
this.argumentCount = argumentCount;
|
||||
this.functionDispatchNode = functionDispatchNode;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isExecutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
Object execute(Object[] arguments) {
|
||||
if (arguments.length != argumentCount) {
|
||||
throw new LamaException("Wrong amount of function arguments: " + arguments.length + " instead of " + argumentCount);
|
||||
}
|
||||
// TODO: check values of arguments ??
|
||||
return this.functionDispatchNode.executeDispatch(this, arguments);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
package org.programsnail.truffle_lama;
|
||||
|
||||
import com.oracle.truffle.api.TruffleLanguage;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
import com.oracle.truffle.api.interop.UnknownIdentifierException;
|
||||
import com.oracle.truffle.api.library.ExportLibrary;
|
||||
import com.oracle.truffle.api.library.ExportMessage;
|
||||
import org.programsnail.truffle_lama.runtime.LamaException;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
public final class GlobalScopeObject implements TruffleObject {
|
||||
private final Map<String, Object> variables = new HashMap<>();
|
||||
private final Set<String> constants = new HashSet<>();
|
||||
|
||||
public boolean newVariable(String name, Object value, boolean isConst) {
|
||||
Object previousValue = variables.put(name, value);
|
||||
if (isConst) {
|
||||
constants.add(name);
|
||||
}
|
||||
return previousValue == null;
|
||||
}
|
||||
|
||||
public void newFunction(String name, FunctionObject fun) {
|
||||
variables.put(name, fun);
|
||||
}
|
||||
|
||||
public boolean updateVariable(String name, Object value) {
|
||||
if (this.constants.contains(name)) {
|
||||
throw new LamaException("Can't assign to const var '" + name + "'.");
|
||||
}
|
||||
Object updatedValue = this.variables.computeIfPresent(name, (k, v) -> value);
|
||||
return updatedValue != null;
|
||||
}
|
||||
|
||||
public Object getVariable(String name) {
|
||||
return this.variables.get(name);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
@ExportMessage
|
||||
boolean isScope() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean hasMembers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
Object getMembers(@SuppressWarnings("unused") boolean includeInternal) {
|
||||
return new GlobalVariableNamesObject(this.variables.keySet());
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isMemberReadable(String member) {
|
||||
return this.variables.containsKey(member);
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
Object readMember(String member) throws UnknownIdentifierException {
|
||||
Object value = this.variables.get(member);
|
||||
if (null == value) {
|
||||
throw UnknownIdentifierException.create(member);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
Object toDisplayString(@SuppressWarnings("unused") boolean allowSideEffects) {
|
||||
return "global";
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean hasLanguage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
Class<? extends TruffleLanguage<?>> getLanguage() {
|
||||
return LamaLanguage.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
final class GlobalVariablesNamesObject implements TruffleObject {
|
||||
private final List<String> names;
|
||||
|
||||
GlobalVariablesNamesObject(List<String> names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean hasArrayElements() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
long getArraySize() {
|
||||
return this.names.size();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean isArrayElementReadable(long index) {
|
||||
return index >= 0 && index < this.names.size();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
Object readArrayElement(long index) throws InvalidArrayIndexException {
|
||||
if (!this.isArrayElementReadable(index)) {
|
||||
throw InvalidArrayIndexException.create(index);
|
||||
}
|
||||
return this.names.get((int) index);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,47 +1,59 @@
|
|||
package org.programsnail.truffle_lama;
|
||||
|
||||
import com.oracle.truffle.api.Truffle;
|
||||
import com.oracle.truffle.api.TruffleLanguage;
|
||||
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||
import com.oracle.truffle.api.frame.MaterializedFrame;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
// TODO
|
||||
public class LamaContext {
|
||||
private final FrameDescriptor globalFrameDescriptor;
|
||||
private final Namespace globalNamespace;
|
||||
private final MaterializedFrame globalFrame;
|
||||
private final LamaLanguage language;
|
||||
public final class LamaContext {
|
||||
private static final TruffleLanguage.ContextReference<LamaContext> REF = TruffleLanguage.ContextReference.create(LamaLanguage.class);
|
||||
|
||||
public LamaContext() { this(null); }
|
||||
|
||||
public LamaContext(LamaLanguage language) {
|
||||
this.globalFrameDescriptor = new FrameDescriptor();
|
||||
this.globalNamespace = new Namespace(this.globalFrameDescriptor);
|
||||
this.globalFrame = this.initGlobalFrame(language);
|
||||
this.language = language;
|
||||
public static LamaContext get(Node node) {
|
||||
return REF.get(node);
|
||||
}
|
||||
|
||||
private MaterializedFrame initGlobalFrame(LamaLanguage language) {
|
||||
VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(null, this.globalFrameDescriptor);
|
||||
addGlobalFunctions(language, frame);
|
||||
return frame.materialize();
|
||||
}
|
||||
public final GlobalScopeObject globalScopeObject;
|
||||
|
||||
private static void addGlobalFunctions(LamaLanguage language, VirtualFrame virtualFrame) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link MaterializedFrame} on the heap that contains all global
|
||||
* values.
|
||||
*/
|
||||
public MaterializedFrame getGlobalFrame() {
|
||||
return this.globalFrame;
|
||||
}
|
||||
|
||||
public Namespace getGlobalNamespace() {
|
||||
return this.globalNamespace;
|
||||
public LamaContext() {
|
||||
this.globalScopeObject = new GlobalScopeObject();
|
||||
}
|
||||
// private final FrameDescriptor globalFrameDescriptor;
|
||||
// private final Namespace globalNamespace;
|
||||
// private final MaterializedFrame globalFrame;
|
||||
// private final LamaLanguage language;
|
||||
//
|
||||
// public LamaContext() { this(null); }
|
||||
//
|
||||
// public LamaContext(LamaLanguage language) {
|
||||
// this.globalFrameDescriptor = new FrameDescriptor();
|
||||
// this.globalNamespace = new Namespace(this.globalFrameDescriptor);
|
||||
// this.globalFrame = this.initGlobalFrame(language);
|
||||
// this.language = language;
|
||||
// }
|
||||
//
|
||||
// private MaterializedFrame initGlobalFrame(LamaLanguage language) {
|
||||
// VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(null, this.globalFrameDescriptor);
|
||||
// addGlobalFunctions(language, frame);
|
||||
// return frame.materialize();
|
||||
// }
|
||||
//
|
||||
// private static void addGlobalFunctions(LamaLanguage language, VirtualFrame virtualFrame) {
|
||||
// // TODO
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return A {@link MaterializedFrame} on the heap that contains all global
|
||||
// * values.
|
||||
// */
|
||||
// public MaterializedFrame getGlobalFrame() {
|
||||
// return this.globalFrame;
|
||||
// }
|
||||
//
|
||||
// public Namespace getGlobalNamespace() {
|
||||
// return this.globalNamespace;
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ import com.oracle.truffle.api.nodes.RootNode;
|
|||
import com.oracle.truffle.api.object.Shape;
|
||||
import com.oracle.truffle.api.source.Source;
|
||||
import com.oracle.truffle.api.strings.TruffleString;
|
||||
import org.programsnail.truffle_lama.builtins.LamaBuiltinNode;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.nodes.LamaRootNode;
|
||||
import org.programsnail.truffle_lama.parser.LamaParser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -23,204 +26,185 @@ import java.util.Map;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@TruffleLanguage.Registration(id = LamaLanguage.ID, name = "Lama", defaultMimeType = LamaLanguage.MIME_TYPE, characterMimeTypes = LamaLanguage.MIME_TYPE, contextPolicy = TruffleLanguage.ContextPolicy.SHARED, fileTypeDetectors = LamaFileDetector.class)
|
||||
@ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, StandardTags.RootBodyTag.class, StandardTags.ExpressionTag.class, DebuggerTags.AlwaysHalt.class,
|
||||
StandardTags.ReadVariableTag.class, StandardTags.WriteVariableTag.class})
|
||||
//@ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, StandardTags.RootBodyTag.class, StandardTags.ExpressionTag.class, DebuggerTags.AlwaysHalt.class,
|
||||
// StandardTags.ReadVariableTag.class, StandardTags.WriteVariableTag.class})
|
||||
public class LamaLanguage extends TruffleLanguage<LamaContext> {
|
||||
public static volatile int counter; // count class instances
|
||||
// public static volatile int counter; // count class instances
|
||||
|
||||
public static final String ID = "lama";
|
||||
public static final String MIME_TYPE = "application/x-lama";
|
||||
|
||||
private static final Source BUILTIN_SOURCE = Source.newBuilder(ID, "", "LaMa builtin").build();
|
||||
private static final LanguageReference<LamaLanguage> REFERENCE = LanguageReference.create(LamaLanguage.class);
|
||||
private static final List<NodeFactory<? extends LamaBuiltinNode>> EXTERNAL_BUILTINS = Collections.synchronizedList(new ArrayList<>());
|
||||
// private static final Source BUILTIN_SOURCE = Source.newBuilder(ID, "", "LaMa builtin").build();
|
||||
// private static final LanguageReference<LamaLanguage> REFERENCE = LanguageReference.create(LamaLanguage.class);
|
||||
// private static final List<NodeFactory<? extends LamaBuiltinNode>> EXTERNAL_BUILTINS = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
public static final TruffleString.Encoding STRING_ENCODING = TruffleString.Encoding.UTF_16;
|
||||
// public static final TruffleString.Encoding STRING_ENCODING = TruffleString.Encoding.UTF_16;
|
||||
|
||||
private final Assumption singleContext = Truffle.getRuntime().createAssumption("Single Lama context.");
|
||||
|
||||
private final Map<NodeFactory<? extends LamaBuiltinNode>, RootCallTarget> builtinTargets = new ConcurrentHashMap<>();
|
||||
private final Map<TruffleString, RootCallTarget> undefinedFunctions = new ConcurrentHashMap<>();
|
||||
|
||||
private final Shape rootShape;
|
||||
|
||||
//
|
||||
|
||||
public LamaLanguage() {
|
||||
counter++;
|
||||
this.rootShape = Shape.newBuilder().layout(LamaObject.class).build();
|
||||
@Override
|
||||
protected CallTarget parse(ParsingRequest request) throws Exception {
|
||||
var exprNode = LamaParser.parseLama(this, request.getSource());
|
||||
var rootNode = new LamaRootNode(exprNode);
|
||||
return rootNode.getCallTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LamaContext createContext(Env env) {
|
||||
return new LamaContext(this, env, new ArrayList<>(EXTERNAL_BUILTINS));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean patchContext(LamaContext context, Env newEnv) {
|
||||
context.patchContext(newEnv);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public RootCallTarget getOrCreateUndefinedFunction(TruffleString name) {
|
||||
RootCallTarget target = undefinedFunctions.get(name);
|
||||
if (target == null) {
|
||||
target = new LamaUndefinedFunctionRootNode(this, name).getCallTarget();
|
||||
RootCallTarget other = undefinedFunctions.putIfAbsent(name, target);
|
||||
if (other != null) {
|
||||
target = other;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public RootCallTarget lookupBuiltin(NodeFactory<? extends LamaBuiltinNode> factory) {
|
||||
RootCallTarget target = builtinTargets.get(factory);
|
||||
if (target != null) {
|
||||
return target;
|
||||
}
|
||||
|
||||
/*
|
||||
* The builtin node factory is a class that is automatically generated by the Truffle DSL.
|
||||
* The signature returned by the factory reflects the signature of the @Specialization
|
||||
*
|
||||
* methods in the builtin classes.
|
||||
*/
|
||||
int argumentCount = factory.getExecutionSignature().size();
|
||||
LamaExpressionNode[] argumentNodes = new LamaExpressionNode[argumentCount];
|
||||
/*
|
||||
* Builtin functions are like normal functions, i.e., the arguments are passed in as an
|
||||
* Object[] array encapsulated in SLArguments. A SLReadArgumentNode extracts a parameter
|
||||
* from this array.
|
||||
*/
|
||||
for (int i = 0; i < argumentCount; i++) {
|
||||
argumentNodes[i] = new LamaReadArgumentNode(i);
|
||||
}
|
||||
/* Instantiate the builtin node. This node performs the actual functionality. */
|
||||
LamaBuiltinNode builtinBodyNode = factory.createNode((Object) argumentNodes);
|
||||
builtinBodyNode.addRootTag();
|
||||
/* The name of the builtin function is specified via an annotation on the node class. */
|
||||
TruffleString name = LamaStrings.fromJavaString(lookupNodeInfo(builtinBodyNode.getClass()).shortName());
|
||||
builtinBodyNode.setUnavailableSourceSection();
|
||||
|
||||
/* Wrap the builtin in a RootNode. Truffle requires all AST to start with a RootNode. */
|
||||
LamamRootNode rootNode = new LammaRootNode(this, new FrameDescriptor(), builtinBodyNode, BUILTIN_SOURCE.createUnavailableSection(), name);
|
||||
|
||||
/*
|
||||
* Register the builtin function in the builtin registry. Call targets for builtins may be
|
||||
* reused across multiple contexts.
|
||||
*/
|
||||
RootCallTarget newTarget = rootNode.getCallTarget();
|
||||
RootCallTarget oldTarget = builtinTargets.putIfAbsent(factory, newTarget);
|
||||
if (oldTarget != null) {
|
||||
return oldTarget;
|
||||
}
|
||||
return newTarget;
|
||||
}
|
||||
|
||||
public static NodeInfo lookupNodeInfo(Class<?> c) {
|
||||
if (c == null) {
|
||||
return null;
|
||||
}
|
||||
NodeInfo info = c.getAnnotation(NodeInfo.class);
|
||||
if (info != null) {
|
||||
return info;
|
||||
} else {
|
||||
return lookupNodeInfo(c.getSuperclass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CallTarget parse(ParsingRequest request) throws Exception {
|
||||
Source source = request.getSource();
|
||||
Map<TruffleString, RootCallTarget> functions;
|
||||
/*
|
||||
* Parse the provided source. At this point, we do not have a SLContext yet. Registration of
|
||||
* the functions with the SLContext happens lazily in SLEvalRootNode.
|
||||
*/
|
||||
if (request.getArgumentNames().isEmpty()) {
|
||||
functions = LamaParser.parseLama(this, source);
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("function main(");
|
||||
String sep = "";
|
||||
for (String argumentName : request.getArgumentNames()) {
|
||||
sb.append(sep);
|
||||
sb.append(argumentName);
|
||||
sep = ",";
|
||||
}
|
||||
sb.append(") { return ");
|
||||
sb.append(source.getCharacters());
|
||||
sb.append(";}");
|
||||
String language = source.getLanguage() == null ? ID : source.getLanguage();
|
||||
Source decoratedSource = Source.newBuilder(language, sb.toString(), source.getName()).build();
|
||||
functions = LamaParser.parseLama(this, decoratedSource);
|
||||
}
|
||||
|
||||
// TODO: execute source itself, not main function
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeMultipleContexts() {
|
||||
singleContext.invalidate();
|
||||
}
|
||||
|
||||
public boolean isSingleContext() {
|
||||
return singleContext.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getLanguageView(LamaContext context, Object value) {
|
||||
return LamaLanguageView.create(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisible(LamaContext context, Object value) {
|
||||
return !InteropLibrary.getFactory().getUncached(value).isNull(value);
|
||||
return new LamaContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getScope(LamaContext context) {
|
||||
return context.getFunctionRegistry().getFunctionsObject();
|
||||
}
|
||||
|
||||
public Shape getRootShape() {
|
||||
return rootShape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate an empty object. All new objects initially have no properties. Properties are added
|
||||
* when they are first stored, i.e., the store triggers a shape change of the object.
|
||||
*/
|
||||
public LamaObject createObject(AllocationReporter reporter) {
|
||||
reporter.onEnter(null, 0, AllocationReporter.SIZE_UNKNOWN);
|
||||
LamaObject object = new LamaObject(rootShape);
|
||||
reporter.onReturnValue(object, 0, AllocationReporter.SIZE_UNKNOWN);
|
||||
return object;
|
||||
return context.globalScopeObject;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public static LamaLanguage get(Node node) {
|
||||
return REFERENCE.get(node);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public static void installBuiltin(NodeFactory<? extends LamaBuiltinNode> builtin) {
|
||||
EXTERNAL_BUILTINS.add(builtin);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exitContext(LamaContext context, ExitMode exitMode, int exitCode) {
|
||||
/*
|
||||
* Runs shutdown hooks during explicit exit triggered by TruffleContext#closeExit(Node, int)
|
||||
* or natural exit triggered during natural context close.
|
||||
*/
|
||||
context.runShutdownHooks();
|
||||
}
|
||||
// //
|
||||
//
|
||||
// public LamaLanguage() {
|
||||
//// counter++;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected LamaContext createContext(Env env) {
|
||||
// return new LamaContext(this, env, new ArrayList<>(EXTERNAL_BUILTINS));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected boolean patchContext(LamaContext context, Env newEnv) {
|
||||
// context.patchContext(newEnv);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// //
|
||||
//
|
||||
// public RootCallTarget getOrCreateUndefinedFunction(TruffleString name) {
|
||||
// RootCallTarget target = undefinedFunctions.get(name);
|
||||
// if (target == null) {
|
||||
// target = new LamaUndefinedFunctionRootNode(this, name).getCallTarget();
|
||||
// RootCallTarget other = undefinedFunctions.putIfAbsent(name, target);
|
||||
// if (other != null) {
|
||||
// target = other;
|
||||
// }
|
||||
// }
|
||||
// return target;
|
||||
// }
|
||||
//
|
||||
// public RootCallTarget lookupBuiltin(NodeFactory<? extends LamaBuiltinNode> factory) {
|
||||
// RootCallTarget target = builtinTargets.get(factory);
|
||||
// if (target != null) {
|
||||
// return target;
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * The builtin node factory is a class that is automatically generated by the Truffle DSL.
|
||||
// * The signature returned by the factory reflects the signature of the @Specialization
|
||||
// *
|
||||
// * methods in the builtin classes.
|
||||
// */
|
||||
// int argumentCount = factory.getExecutionSignature().size();
|
||||
// LamaExpressionNode[] argumentNodes = new LamaExpressionNode[argumentCount];
|
||||
// /*
|
||||
// * Builtin functions are like normal functions, i.e., the arguments are passed in as an
|
||||
// * Object[] array encapsulated in SLArguments. A SLReadArgumentNode extracts a parameter
|
||||
// * from this array.
|
||||
// */
|
||||
// for (int i = 0; i < argumentCount; i++) {
|
||||
// argumentNodes[i] = new LamaReadArgumentNode(i);
|
||||
// }
|
||||
// /* Instantiate the builtin node. This node performs the actual functionality. */
|
||||
// LamaBuiltinNode builtinBodyNode = factory.createNode((Object) argumentNodes);
|
||||
// builtinBodyNode.addRootTag();
|
||||
// /* The name of the builtin function is specified via an annotation on the node class. */
|
||||
// TruffleString name = LamaStrings.fromJavaString(lookupNodeInfo(builtinBodyNode.getClass()).shortName());
|
||||
// builtinBodyNode.setUnavailableSourceSection();
|
||||
//
|
||||
// /* Wrap the builtin in a RootNode. Truffle requires all AST to start with a RootNode. */
|
||||
// LamaRootNode rootNode = new LamaRootNode(this, new FrameDescriptor(), builtinBodyNode, BUILTIN_SOURCE.createUnavailableSection(), name);
|
||||
//
|
||||
// /*
|
||||
// * Register the builtin function in the builtin registry. Call targets for builtins may be
|
||||
// * reused across multiple contexts.
|
||||
// */
|
||||
// RootCallTarget newTarget = rootNode.getCallTarget();
|
||||
// RootCallTarget oldTarget = builtinTargets.putIfAbsent(factory, newTarget);
|
||||
// if (oldTarget != null) {
|
||||
// return oldTarget;
|
||||
// }
|
||||
// return newTarget;
|
||||
// }
|
||||
//
|
||||
// public static NodeInfo lookupNodeInfo(Class<?> c) {
|
||||
// if (c == null) {
|
||||
// return null;
|
||||
// }
|
||||
// NodeInfo info = c.getAnnotation(NodeInfo.class);
|
||||
// if (info != null) {
|
||||
// return info;
|
||||
// } else {
|
||||
// return lookupNodeInfo(c.getSuperclass());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// protected void initializeMultipleContexts() {
|
||||
// singleContext.invalidate();
|
||||
// }
|
||||
//
|
||||
// public boolean isSingleContext() {
|
||||
// return singleContext.isValid();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Object getLanguageView(LamaContext context, Object value) {
|
||||
// return LamaLanguageView.create(value);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected boolean isVisible(LamaContext context, Object value) {
|
||||
// return !InteropLibrary.getFactory().getUncached(value).isNull(value);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Object getScope(LamaContext context) {
|
||||
// return context.getFunctionRegistry().getFunctionsObject();
|
||||
// }
|
||||
//
|
||||
// public Shape getRootShape() {
|
||||
// return rootShape;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Allocate an empty object. All new objects initially have no properties. Properties are added
|
||||
// * when they are first stored, i.e., the store triggers a shape change of the object.
|
||||
// */
|
||||
// public LamaObject createObject(AllocationReporter reporter) {
|
||||
// reporter.onEnter(null, 0, AllocationReporter.SIZE_UNKNOWN);
|
||||
// LamaObject object = new LamaObject(rootShape);
|
||||
// reporter.onReturnValue(object, 0, AllocationReporter.SIZE_UNKNOWN);
|
||||
// return object;
|
||||
// }
|
||||
//
|
||||
// //
|
||||
//
|
||||
// public static LamaLanguage get(Node node) {
|
||||
// return REFERENCE.get(node);
|
||||
// }
|
||||
//
|
||||
// //
|
||||
//
|
||||
// public static void installBuiltin(NodeFactory<? extends LamaBuiltinNode> builtin) {
|
||||
// EXTERNAL_BUILTINS.add(builtin);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void exitContext(LamaContext context, ExitMode exitMode, int exitCode) {
|
||||
// /*
|
||||
// * Runs shutdown hooks during explicit exit triggered by TruffleContext#closeExit(Node, int)
|
||||
// * or natural exit triggered during natural context close.
|
||||
// */
|
||||
// context.runShutdownHooks();
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
package org.programsnail.truffle_lama;
|
||||
|
||||
import com.oracle.truffle.api.dsl.ImplicitCast;
|
||||
import com.oracle.truffle.api.dsl.TypeSystem;
|
||||
|
||||
@TypeSystem({long.class, boolean.class, String.class})
|
||||
public class LamaTypes {}
|
||||
|
|
@ -6,6 +6,9 @@ import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
|
|||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
|
||||
|
||||
@NodeChild(value = "arguments", type = LamaExpressionNode[].class)
|
||||
@GenerateNodeFactory
|
||||
public abstract class LamaBuiltinNode extends LamaExpressionNode {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package org.programsnail.truffle_lama.nodes;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.DirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.IndirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.programsnail.truffle_lama.FunctionObject;
|
||||
import org.programsnail.truffle_lama.runtime.LamaException;
|
||||
|
||||
public abstract class FunctionDispatchNode extends Node {
|
||||
public abstract Object executeDispatch(Object function, Object[] arguments);
|
||||
|
||||
@Specialization(guards = "function.callTarget == directCallNode.getCallTarget()", limit = "2")
|
||||
protected static Object dispatchDirectly(FunctionObject function,
|
||||
Object[] arguments,
|
||||
@Cached("create(function.callTarget)")
|
||||
DirectCallNode directCallNode) {
|
||||
return directCallNode.call(arguments); // TODO: check arguments count ??
|
||||
}
|
||||
|
||||
@Specialization(replaces = "dispatchDirectly")
|
||||
protected static Object dispatchIndirectly(FunctionObject function,
|
||||
Object[] arguments,
|
||||
IndirectCallNode indirectCallNode) {
|
||||
return indirectCallNode.call(function.callTarget, arguments); // TODO: check arguments count ??
|
||||
}
|
||||
|
||||
@Fallback
|
||||
protected static Object targetIsNotAFunction(Object object, Object[] arguments) {
|
||||
throw new LamaException("Called '" + object + "' is not a function");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes;
|
||||
|
||||
public class LamaDeclNode {
|
||||
}
|
||||
|
|
@ -3,13 +3,13 @@ package org.programsnail.truffle_lama.nodes;
|
|||
import com.oracle.truffle.api.dsl.TypeSystemReference;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.instrumentation.*;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
|
||||
@TypeSystemReference(SLTypes.class)
|
||||
@TypeSystemReference(LamaTypes.class)
|
||||
@NodeInfo(description = "The abstract base node for all expressions")
|
||||
@GenerateWrapper
|
||||
public abstract class LamaExpressionNode extends LamaStatementNode {
|
||||
public abstract class LamaExpressionNode extends Node {
|
||||
|
||||
private boolean hasExpressionTag;
|
||||
|
||||
|
|
@ -17,29 +17,21 @@ public abstract class LamaExpressionNode extends LamaStatementNode {
|
|||
* The execute method when no specialization is possible. This is the most general case,
|
||||
* therefore it must be provided by all subclasses.
|
||||
*/
|
||||
public abstract Object executeGeneric(VirtualFrame frame);
|
||||
public abstract Object executeGeneric(VirtualFrame frame) throws UnexpectedResultException;
|
||||
|
||||
/**
|
||||
* When we use an expression at places where a {@link LamaStatementNode statement} is already
|
||||
* sufficient, the return value is just discarded.
|
||||
* The return value is just discarded.
|
||||
*/
|
||||
@Override
|
||||
public void executeVoid(VirtualFrame frame) {
|
||||
executeGeneric(frame);
|
||||
}
|
||||
|
||||
// LamaExpressionNodeWrapper is generated (?)
|
||||
@Override
|
||||
public InstrumentableNode.WrapperNode createWrapper(ProbeNode probe) {
|
||||
return new LamaExpressionNodeWrapper(this, probe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTag(Class<? extends Tag> tag) {
|
||||
if (tag == StandardTags.ExpressionTag.class) {
|
||||
return hasExpressionTag;
|
||||
}
|
||||
return super.hasTag(tag);
|
||||
return false; // no super tags
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,6 +49,7 @@ public abstract class LamaExpressionNode extends LamaStatementNode {
|
|||
|
||||
// LamaTypesGen is generated from LamaTypes
|
||||
|
||||
// TODO
|
||||
public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
|
||||
return LamaTypesGen.expectLong(executeGeneric(frame));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package org.programsnail.truffle_lama.nodes;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.RootNode;
|
||||
|
||||
public class LamaRootNode extends RootNode {
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
@Child
|
||||
private LamaExpressionNode exprNode;
|
||||
|
||||
public LamaRootNode(LamaExpressionNode exprNode) {
|
||||
super(null);
|
||||
|
||||
this.exprNode = exprNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(VirtualFrame frame) {
|
||||
return this.exprNode.executeGeneric(frame);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package org.programsnail.truffle_lama.nodes;
|
||||
|
||||
import com.oracle.truffle.api.dsl.TypeSystem;
|
||||
|
||||
@TypeSystem({long.class, boolean.class, String.class})
|
||||
public abstract class LamaTypes {}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.controlflow;
|
||||
|
||||
public class LamaCaseNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.controlflow;
|
||||
|
||||
public class LamaControlNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.programsnail.truffle_lama.nodes.controlflow;
|
||||
|
||||
import com.oracle.truffle.api.Truffle;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.LoopNode;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.nodes.RepeatingNode;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.runtime.LamaUnit;
|
||||
|
||||
public final class LamaDoWhileNode extends LamaExpressionNode {
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
@Child
|
||||
private LoopNode loopNode;
|
||||
|
||||
public LamaDoWhileNode(LamaExpressionNode conditionExpr, LamaExpressionNode bodyExpr) {
|
||||
this.loopNode = Truffle.getRuntime().createLoopNode(
|
||||
new WhileRepeatingNode(conditionExpr, bodyExpr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) throws UnexpectedResultException {
|
||||
this.loopNode.execute(frame);
|
||||
return LamaUnit.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class WhileRepeatingNode extends Node implements RepeatingNode {
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
@Child
|
||||
private LamaExpressionNode conditionExpr, bodyExpr;
|
||||
|
||||
public WhileRepeatingNode(LamaExpressionNode conditionExpr, LamaExpressionNode bodyExpr) {
|
||||
this.conditionExpr = conditionExpr;
|
||||
this.bodyExpr = bodyExpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeRepeating(VirtualFrame frame) {
|
||||
try {
|
||||
this.bodyExpr.executeGeneric(frame);
|
||||
// NOTE: try/catch for break/continue
|
||||
if (!this.conditionExpr.executeBoolean(frame)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
} catch (UnexpectedResultException e) { // TODO: handle in proper way
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package org.programsnail.truffle_lama.nodes.controlflow;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
|
||||
public final class LamaIfNode extends LamaExpressionNode {
|
||||
@Child
|
||||
private LamaExpressionNode conditionExpr;
|
||||
|
||||
@Child
|
||||
private LamaExpressionNode thenExpr;
|
||||
|
||||
@Child
|
||||
private LamaExpressionNode elseExpr;
|
||||
|
||||
private final ConditionProfile condition = ConditionProfile.create();
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) throws UnexpectedResultException {
|
||||
if (this.condition.profile(this.conditionExpr.executeBoolean(frame))) {
|
||||
return this.thenExpr.executeGeneric(frame);
|
||||
}
|
||||
return this.elseExpr; // TODO: cases with no else
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.programsnail.truffle_lama.nodes.controlflow;
|
||||
|
||||
import com.oracle.truffle.api.Truffle;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.LoopNode;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.nodes.RepeatingNode;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.runtime.LamaUnit;
|
||||
|
||||
public final class LamaWhileNode extends LamaExpressionNode {
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
@Child
|
||||
private LoopNode loopNode;
|
||||
|
||||
public LamaWhileNode(LamaExpressionNode conditionExpr, LamaExpressionNode bodyExpr) {
|
||||
this.loopNode = Truffle.getRuntime().createLoopNode(
|
||||
new WhileRepeatingNode(conditionExpr, bodyExpr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) throws UnexpectedResultException {
|
||||
this.loopNode.execute(frame);
|
||||
return LamaUnit.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class WhileRepeatingNode extends Node implements RepeatingNode {
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
@Child
|
||||
private LamaExpressionNode conditionExpr, bodyExpr;
|
||||
|
||||
public WhileRepeatingNode(LamaExpressionNode conditionExpr, LamaExpressionNode bodyExpr) {
|
||||
this.conditionExpr = conditionExpr;
|
||||
this.bodyExpr = bodyExpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeRepeating(VirtualFrame frame) {
|
||||
try {
|
||||
if (!this.conditionExpr.executeBoolean(frame)) {
|
||||
return false;
|
||||
}
|
||||
this.bodyExpr.executeGeneric(frame);
|
||||
// NOTE: try/catch for break/continue
|
||||
return false;
|
||||
} catch (UnexpectedResultException e) { // TODO: handle in proper way
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaArrayNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaAssignNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
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.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
|
||||
@NodeChild("leftNode")
|
||||
@NodeChild("rightNode")
|
||||
@NodeField(name = "op", type = String.class)
|
||||
public abstract class LamaBinopNode extends LamaExpressionNode {
|
||||
@Child
|
||||
LamaExpressionNode leftNode, rightNode;
|
||||
|
||||
@Specialization(rewriteOn = IllegalStateException.class)
|
||||
protected long numOp(long leftValue, long rightValue) {
|
||||
return switch (op) {
|
||||
case "+" -> leftValue + rightValue;
|
||||
case "-" -> leftValue - rightValue;
|
||||
case "/" -> leftValue / rightValue;
|
||||
case "%" -> leftValue % rightValue;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
}
|
||||
|
||||
@Specialization(replaces = "numOp")
|
||||
protected boolean compOp(long leftValue, long rightValue) {
|
||||
return switch (op) {
|
||||
case "<" -> leftValue < rightValue;
|
||||
case "<=" -> leftValue <= rightValue;
|
||||
case ">" -> leftValue > rightValue;
|
||||
case ">=" -> leftValue >= rightValue;
|
||||
case "==" -> leftValue == rightValue;
|
||||
case "!=" -> leftValue != rightValue;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected boolean boolOp(boolean leftValue, boolean rightValue) {
|
||||
return switch (op) {
|
||||
case "&&" -> leftValue && rightValue;
|
||||
case "!!" -> leftValue || rightValue;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
}
|
||||
|
||||
String op;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaCallNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
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;
|
||||
|
||||
public final class LamaConstNode extends LamaExpressionNode {
|
||||
private final int value;
|
||||
|
||||
public LamaConstNode(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) {
|
||||
return this.executeLong(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long executeLong(VirtualFrame frame) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeBoolean(VirtualFrame frame) {
|
||||
return value != 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaElemNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaElemRefNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
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.LamaUnit;
|
||||
|
||||
public final class LamaIgnoreNode extends LamaExpressionNode {
|
||||
@Child
|
||||
LamaExpressionNode node;
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) throws UnexpectedResultException {
|
||||
return LamaUnit.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaIntrinsicNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaLambdaNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaLeaveNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaRefNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaScopeNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaSeqNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaSexpNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaSkipNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaStringNode {
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
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.LamaUnit;
|
||||
|
||||
public final class LamaUnitNode extends LamaExpressionNode {
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) throws UnexpectedResultException {
|
||||
return LamaUnit.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package org.programsnail.truffle_lama.nodes.expression;
|
||||
|
||||
public class LamaVarNode {
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* The parser and lexer need to be generated using "mx create-sl-parser".
|
||||
* The parser and lexer need to be generated using "mx create-lama-parser". ???
|
||||
*/
|
||||
|
||||
grammar Lama;
|
||||
|
|
@ -58,7 +58,6 @@ import com.oracle.truffle.api.source.Source;
|
|||
import com.oracle.truffle.api.strings.TruffleString;
|
||||
import org.programsnail.truffle_lama.LamaLanguage;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.nodes.LamaStatementNode;
|
||||
}
|
||||
|
||||
@lexer::header
|
||||
|
|
@ -91,11 +90,11 @@ private static void throwParseError(Source source, int line, int charPositionInL
|
|||
int col = charPositionInLine + 1;
|
||||
String location = "-- line " + line + " col " + col + ": ";
|
||||
int length = token == null ? 1 : Math.max(token.getStopIndex() - token.getStartIndex(), 0);
|
||||
throw new SLParseError(source, line, col, length, String.format("Error(s) parsing script:%n" + location + message));
|
||||
throw new LamaParseError(source, line, col, length, String.format("Error(s) parsing script:%n" + location + message));
|
||||
}
|
||||
|
||||
public static Map<TruffleString, RootCallTarget> parseLama(LamaLanguage language, Source source) {
|
||||
LamaLexer lexer = new LamamLexer(CharStreams.fromString(source.getCharacters().toString()));
|
||||
public static LamaExpressionNode parseLama(LamaLanguage language, Source source) {
|
||||
LamaLexer lexer = new LamaLexer(CharStreams.fromString(source.getCharacters().toString()));
|
||||
LamaParser parser = new LamaParser(new CommonTokenStream(lexer));
|
||||
lexer.removeErrorListeners();
|
||||
parser.removeErrorListeners();
|
||||
|
|
@ -105,7 +104,7 @@ public static Map<TruffleString, RootCallTarget> parseLama(LamaLanguage language
|
|||
parser.factory = new LamaNodeFactory(language, source);
|
||||
parser.source = source;
|
||||
parser.lama();
|
||||
return parser.factory.getAllFunctions();
|
||||
return parser.factory.getRootExpr();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,15 +141,15 @@ level : ('at' | 'before' | 'after') INFIX;
|
|||
|
||||
//
|
||||
|
||||
expression returns [SLExpressionNode result]: basic_expression (';' expression)?;
|
||||
basic_expression returns [SLExpressionNode result]: binary_expression;
|
||||
binary_expression returns [SLExpressionNode result]: postfix_expression (INFIX postfix_expression)*;
|
||||
postfix_expression returns [SLExpressionNode result]: ('-')? primary (postfix)*;
|
||||
expression returns [LamaExpressionNode result]: basic_expression (';' expression)?;
|
||||
basic_expression returns [LamaExpressionNode result]: binary_expression;
|
||||
binary_expression returns [LamaExpressionNode result]: postfix_expression (INFIX postfix_expression)*;
|
||||
postfix_expression returns [LamaExpressionNode result]: ('-')? primary (postfix)*;
|
||||
postfix :
|
||||
'(' expression (',' expression)* ')'
|
||||
| '[' expression ']';
|
||||
|
||||
primary returns [SLExpressionNode result]:
|
||||
primary returns [LamaExpressionNode result]:
|
||||
DECIMAL_LITERAL
|
||||
| STRING_LITERAL
|
||||
| CHAR_LITERAL
|
||||
|
|
|
|||
|
|
@ -5,9 +5,12 @@ package org.programsnail.truffle_lama.parser;
|
|||
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"})
|
||||
public class LamaLexer extends Lexer {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package org.programsnail.truffle_lama.parser;
|
||||
|
||||
import com.oracle.truffle.api.source.Source;
|
||||
import org.programsnail.truffle_lama.LamaLanguage;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
|
||||
public class LamaNodeFactory {
|
||||
public LamaNodeFactory(LamaLanguage language, Source source) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public LamaExpressionNode getRootExpr() {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// TODO: build expr tree from parsed tokens
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package org.programsnail.truffle_lama.parser;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.exception.AbstractTruffleException;
|
||||
import com.oracle.truffle.api.interop.ExceptionType;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.library.ExportLibrary;
|
||||
import com.oracle.truffle.api.library.ExportMessage;
|
||||
import com.oracle.truffle.api.source.Source;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
public class LamaParseError extends AbstractTruffleException {
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
private final Source source;
|
||||
private final int line;
|
||||
private final int column;
|
||||
private final int length;
|
||||
|
||||
public LamaParseError(Source source, int line, int column, int length, String message) {
|
||||
super(message);
|
||||
this.source = source;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that any subclass of {@link AbstractTruffleException} must always return
|
||||
* <code>true</code> for {@link InteropLibrary#isException(Object)}. That is why it is correct
|
||||
* to export {@link #getExceptionType()} without implementing
|
||||
* {@link InteropLibrary#isException(Object)}.
|
||||
*/
|
||||
@ExportMessage
|
||||
ExceptionType getExceptionType() {
|
||||
return ExceptionType.PARSE_ERROR;
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
boolean hasSourceLocation() {
|
||||
return source != null;
|
||||
}
|
||||
|
||||
@ExportMessage(name = "getSourceLocation")
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
SourceSection getSourceSection() throws UnsupportedMessageException {
|
||||
if (source == null) {
|
||||
throw UnsupportedMessageException.create();
|
||||
}
|
||||
return source.createSection(line, column, length);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package org.programsnail.truffle_lama.parser;
|
|||
|
||||
// DO NOT MODIFY - generated from Lama.g4
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -11,12 +12,15 @@ import com.oracle.truffle.api.source.Source;
|
|||
import com.oracle.truffle.api.strings.TruffleString;
|
||||
import org.programsnail.truffle_lama.LamaLanguage;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.nodes.LamaStatementNode;
|
||||
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
import org.antlr.v4.runtime.tree.*;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"})
|
||||
public class LamaParser extends Parser {
|
||||
|
|
@ -153,11 +157,11 @@ public class LamaParser extends Parser {
|
|||
int col = charPositionInLine + 1;
|
||||
String location = "-- line " + line + " col " + col + ": ";
|
||||
int length = token == null ? 1 : Math.max(token.getStopIndex() - token.getStartIndex(), 0);
|
||||
throw new SLParseError(source, line, col, length, String.format("Error(s) parsing script:%n" + location + message));
|
||||
throw new LamaParseError(source, line, col, length, String.format("Error(s) parsing script:%n" + location + message));
|
||||
}
|
||||
|
||||
public static Map<TruffleString, RootCallTarget> parseLama(LamaLanguage language, Source source) {
|
||||
LamaLexer lexer = new LamamLexer(CharStreams.fromString(source.getCharacters().toString()));
|
||||
public static LamaExpressionNode parseLama(LamaLanguage language, Source source) {
|
||||
LamaLexer lexer = new LamaLexer(CharStreams.fromString(source.getCharacters().toString()));
|
||||
LamaParser parser = new LamaParser(new CommonTokenStream(lexer));
|
||||
lexer.removeErrorListeners();
|
||||
parser.removeErrorListeners();
|
||||
|
|
@ -167,7 +171,7 @@ public class LamaParser extends Parser {
|
|||
parser.factory = new LamaNodeFactory(language, source);
|
||||
parser.source = source;
|
||||
parser.lama();
|
||||
return parser.factory.getAllFunctions();
|
||||
return parser.factory.getRootExpr();
|
||||
}
|
||||
|
||||
public LamaParser(TokenStream input) {
|
||||
|
|
@ -351,7 +355,7 @@ public class LamaParser extends Parser {
|
|||
setState(92);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,1,_ctx);
|
||||
} while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER );
|
||||
} while ( _alt!=2 && _alt!= ATN.INVALID_ALT_NUMBER );
|
||||
setState(95);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) {
|
||||
|
|
@ -1057,7 +1061,7 @@ public class LamaParser extends Parser {
|
|||
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public static class ExpressionContext extends ParserRuleContext {
|
||||
public SLExpressionNode result;
|
||||
public LamaExpressionNode result;
|
||||
public Basic_expressionContext basic_expression() {
|
||||
return getRuleContext(Basic_expressionContext.class,0);
|
||||
}
|
||||
|
|
@ -1119,7 +1123,7 @@ public class LamaParser extends Parser {
|
|||
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public static class Basic_expressionContext extends ParserRuleContext {
|
||||
public SLExpressionNode result;
|
||||
public LamaExpressionNode result;
|
||||
public Binary_expressionContext binary_expression() {
|
||||
return getRuleContext(Binary_expressionContext.class,0);
|
||||
}
|
||||
|
|
@ -1165,7 +1169,7 @@ public class LamaParser extends Parser {
|
|||
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public static class Binary_expressionContext extends ParserRuleContext {
|
||||
public SLExpressionNode result;
|
||||
public LamaExpressionNode result;
|
||||
public List<Postfix_expressionContext> postfix_expression() {
|
||||
return getRuleContexts(Postfix_expressionContext.class);
|
||||
}
|
||||
|
|
@ -1235,7 +1239,7 @@ public class LamaParser extends Parser {
|
|||
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public static class Postfix_expressionContext extends ParserRuleContext {
|
||||
public SLExpressionNode result;
|
||||
public LamaExpressionNode result;
|
||||
public PrimaryContext primary() {
|
||||
return getRuleContext(PrimaryContext.class,0);
|
||||
}
|
||||
|
|
@ -1400,7 +1404,7 @@ public class LamaParser extends Parser {
|
|||
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public static class PrimaryContext extends ParserRuleContext {
|
||||
public SLExpressionNode result;
|
||||
public LamaExpressionNode result;
|
||||
public TerminalNode DECIMAL_LITERAL() { return getToken(LamaParser.DECIMAL_LITERAL, 0); }
|
||||
public TerminalNode STRING_LITERAL() { return getToken(LamaParser.STRING_LITERAL, 0); }
|
||||
public TerminalNode CHAR_LITERAL() { return getToken(LamaParser.CHAR_LITERAL, 0); }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package org.programsnail.truffle_lama.runtime;
|
||||
|
||||
import com.oracle.truffle.api.exception.AbstractTruffleException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
|
||||
public class LamaException extends AbstractTruffleException {
|
||||
public LamaException(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
public LamaException(String message, Node location) {
|
||||
super(message, location);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package org.programsnail.truffle_lama.runtime;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class LamaSExp {
|
||||
public String name;
|
||||
public List<Object> elements;
|
||||
|
||||
LamaSExp(String name, List<Object> elements) {
|
||||
this.name = name;
|
||||
this.elements = elements;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package org.programsnail.truffle_lama.runtime;
|
||||
|
||||
// TODO: truffle object
|
||||
public final class LamaUnit {
|
||||
public static final LamaUnit INSTANCE = new LamaUnit();
|
||||
|
||||
private LamaUnit() { }
|
||||
}
|
||||
17
src/test/java/BasicNodesTest.java
Normal file
17
src/test/java/BasicNodesTest.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import com.oracle.truffle.api.CallTarget;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.programsnail.truffle_lama.nodes.LamaExpressionNode;
|
||||
import org.programsnail.truffle_lama.nodes.LamaRootNode;
|
||||
|
||||
public class BasicNodesTest {
|
||||
@Test
|
||||
public void basic_test() {
|
||||
LamaExpressionNode exprNode = null; // TODO
|
||||
var rootNode = new LamaRootNode(exprNode);
|
||||
CallTarget callTarget = rootNode.getCallTarget();
|
||||
var result = callTarget.call();
|
||||
|
||||
// TODO: check
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue