Providing access to bodyNode in the builtin methods

This commit is contained in:
Jaroslav Tulach 2024-11-20 17:45:38 +01:00
parent 0e42e9dd34
commit 0b4e1f84c7
3 changed files with 52 additions and 24 deletions

View File

@ -34,9 +34,10 @@ public final class Ref extends EnsoObject {
* @param referenceType type of reference to use
*/
@Builtin.Method(description = "Creates a new Ref", autoRegister = false)
public Ref(Object value, long referenceType) {
public Ref(Node node, Object value, long referenceType) {
var ctx = EnsoContext.get(node);
this.type = (byte) (referenceType & 0x03);
this.value = wrapValue(value);
this.value = wrapValue(ctx, value);
}
/**
@ -44,8 +45,9 @@ public final class Ref extends EnsoObject {
*/
@Builtin.Method(name = "get", description = "Gets the value stored in the reference")
@SuppressWarnings("generic-enso-builtin-type")
public Object getValue() {
return unwrapValue(value);
public Object getValue(Node node) {
var ctx = EnsoContext.get(node);
return unwrapValue(ctx, value);
}
/**
@ -56,10 +58,11 @@ public final class Ref extends EnsoObject {
*/
@Builtin.Method(name = "put", description = "Stores a new value in the reference")
@SuppressWarnings("generic-enso-builtin-type")
public Object setValue(Object value) {
public Object setValue(Node node, Object value) {
var ctx = EnsoContext.get(node);
Object old = this.value;
this.value = wrapValue(value);
return unwrapValue(old);
this.value = wrapValue(ctx, value);
return unwrapValue(ctx, old);
}
@ExportMessage
@ -82,19 +85,18 @@ public final class Ref extends EnsoObject {
return EnsoContext.get(node).getBuiltins().ref();
}
private final Object wrapValue(Object v) {
private final Object wrapValue(EnsoContext ctx, Object v) {
if (type == 0) {
return v;
}
assert !(v instanceof Reference<?>) : "Ref[" + type + ", " + v + "]";
var ctx = EnsoContext.get(null);
return ctx.getReferencesManager().create(v, type);
}
private final Object unwrapValue(Object v) {
private final Object unwrapValue(EnsoContext ctx, Object v) {
if (v instanceof Reference<?> ref) {
var ret = ref.get();
return ret == null ? EnsoContext.get(null).getNothing() : ret;
return ret == null ? ctx.getNothing() : ret;
} else {
return v;
}

View File

@ -206,10 +206,10 @@ public class MethodProcessor
out.println();
out.println(" private static final class Internals {");
out.println(" Internals(boolean s) {");
out.println(" this.staticOfInstanceMethod = s;");
out.println(" this.staticOrInstanceMethod = s;");
out.println(" }");
out.println();
out.println(" private final boolean staticOfInstanceMethod;");
out.println(" private final boolean staticOrInstanceMethod;");
for (MethodDefinition.ArgumentDefinition arg : methodDefinition.getArguments()) {
if (arg.shouldCheckErrors()) {
@ -239,10 +239,10 @@ public class MethodProcessor
out.println(
" private "
+ methodDefinition.getClassName()
+ "(EnsoLanguage language, boolean staticOfInstanceMethod) {");
+ "(EnsoLanguage language, boolean staticOrInstanceMethod) {");
out.println(" super(language);");
out.println(" this.bodyNode = " + methodDefinition.getConstructorExpression() + ";");
out.println(" this.internals = new Internals(staticOfInstanceMethod);");
out.println(" this.internals = new Internals(staticOrInstanceMethod);");
out.println(" }");
out.println();
@ -258,11 +258,11 @@ public class MethodProcessor
out.println();
out.println(
" public static Function makeFunction(EnsoLanguage language, boolean"
+ " staticOfInstanceMethod) {");
out.println(" if (staticOfInstanceMethod) {");
+ " staticOrInstanceMethod) {");
out.println(" if (staticOrInstanceMethod) {");
out.println(" return Function." + functionBuilderMethod + "(");
out.print(
" new " + methodDefinition.getClassName() + "(language, staticOfInstanceMethod)");
" new " + methodDefinition.getClassName() + "(language, staticOrInstanceMethod)");
List<String> argsStaticInstace =
generateMakeFunctionArgs(true, methodDefinition.getArguments());
if (!argsStaticInstace.isEmpty()) {
@ -272,7 +272,7 @@ public class MethodProcessor
out.println(" } else {");
out.println(" return Function." + functionBuilderMethod + "(");
out.print(
" new " + methodDefinition.getClassName() + "(language, staticOfInstanceMethod)");
" new " + methodDefinition.getClassName() + "(language, staticOrInstanceMethod)");
List<String> argsInstance = generateMakeFunctionArgs(false, methodDefinition.getArguments());
if (!argsInstance.isEmpty()) {
out.println(",");
@ -288,7 +288,7 @@ public class MethodProcessor
out.println(" class Inlineable extends InlineableNode {");
out.println(
" private final Internals extra = new"
+ " Internals(internals.staticOfInstanceMethod);");
+ " Internals(internals.staticOrInstanceMethod);");
out.println(
" private @Child "
+ methodDefinition.getOriginalClassName()
@ -334,7 +334,7 @@ public class MethodProcessor
+ " bodyNode, AppendWarningNode appendWarningNode, WarningsLibrary warnLib,"
+ " HashMapInsertAllNode mapInsertAllNode, Object[] args) {");
}
out.println(" var prefix = internals.staticOfInstanceMethod ? 1 : 0;");
out.println(" var prefix = internals.staticOrInstanceMethod ? 1 : 0;");
out.println(" State state = Function.ArgumentsHelper.getState(args);");
if (methodDefinition.needsCallerInfo()) {
out.println(" CallerInfo callerInfo = Function.ArgumentsHelper.getCallerInfo(args);");
@ -343,7 +343,11 @@ public class MethodProcessor
" Object[] arguments = Function.ArgumentsHelper.getPositionalArguments(args);");
List<String> callArgNames = new ArrayList<>();
for (MethodDefinition.ArgumentDefinition arg : methodDefinition.getArguments()) {
if (!(arg.isImplicit() || arg.isFrame() || arg.isState() || arg.isCallerInfo())) {
if (!(arg.isImplicit()
|| arg.isFrame()
|| arg.isState()
|| arg.isCallerInfo()
|| arg.isNode())) {
out.println(
" int arg" + arg.getPosition() + "Idx = " + arg.getPosition() + " + prefix;");
}
@ -361,6 +365,8 @@ public class MethodProcessor
callArgNames.add("state");
} else if (argumentDefinition.isFrame()) {
callArgNames.add("frame");
} else if (argumentDefinition.isNode()) {
callArgNames.add("bodyNode");
} else if (argumentDefinition.isCallerInfo()) {
callArgNames.add("callerInfo");
} else {
@ -414,7 +420,7 @@ public class MethodProcessor
out.println(
" return new "
+ methodDefinition.getClassName()
+ "(EnsoLanguage.get(this), internals.staticOfInstanceMethod);");
+ "(EnsoLanguage.get(this), internals.staticOrInstanceMethod);");
out.println(" }");
out.println();

View File

@ -288,6 +288,11 @@ public class MethodDefinition {
*/
boolean isFrame();
/**
* @return whether this argument should be passed the node implementing the method.
*/
boolean isNode();
/**
* @return whether this argument should be passed the caller info.
*/
@ -371,6 +376,11 @@ public class MethodDefinition {
return false;
}
@Override
public boolean isNode() {
return false;
}
@Override
public boolean isCallerInfo() {
return false;
@ -460,6 +470,7 @@ public class MethodDefinition {
/** A domain specific representation of a method argument. */
public static class ArgumentDefinitionFromParameter implements ArgumentDefinition {
private static final String VIRTUAL_FRAME = "com.oracle.truffle.api.frame.VirtualFrame";
private static final String NODE = "com.oracle.truffle.api.nodes.Node";
private static final String OBJECT = "java.lang.Object";
private static final String THUNK = "org.enso.interpreter.runtime.callable.argument.Thunk";
private static final String CALLER_INFO = "org.enso.interpreter.runtime.callable.CallerInfo";
@ -471,6 +482,7 @@ public class MethodDefinition {
private final TypeMirror type;
private final String name;
private final boolean isState;
private final boolean isNode;
private final boolean isFrame;
private final boolean isCallerInfo;
private final boolean isSuspended;
@ -498,6 +510,7 @@ public class MethodDefinition {
|| type.toString().equals(DATAFLOW_ERROR);
acceptsWarning = element.getAnnotation(AcceptsWarning.class) != null;
isFrame = type.toString().equals(VIRTUAL_FRAME);
isNode = type.toString().equals(NODE);
isCallerInfo = type.toString().equals(CALLER_INFO);
this.position = position;
}
@ -560,6 +573,13 @@ public class MethodDefinition {
return isFrame;
}
/**
* @return whether this argument should be passed the node.
*/
public boolean isNode() {
return isNode;
}
/**
* @return whether this argument should be passed the caller info.
*/
@ -571,7 +591,7 @@ public class MethodDefinition {
* @return whether this argument should be passed the next positional function argument.
*/
public boolean isPositional() {
return !isFrame() && !isState() && !isCallerInfo();
return !isFrame() && !isState() && !isCallerInfo() && !isNode();
}
/**