mirror of
https://github.com/enso-org/enso.git
synced 2024-12-28 11:25:30 +03:00
Builtin methods can support array-like arguments (#7235)
This PR modifies the builtin method processor such that it forbids arrays of non-primitive and non-guest objects in builtin methods. And provides a proper implementation for the builtin methods in `EnsoFile`. - Remove last `to_array` calls from `File.enso`
This commit is contained in:
parent
3d2c0c0154
commit
7264d81f2a
@ -959,6 +959,15 @@ lazy val `interpreter-dsl-test` =
|
|||||||
"-Dgraalvm.locatorDisabled=true",
|
"-Dgraalvm.locatorDisabled=true",
|
||||||
s"--upgrade-module-path=${file("engine/runtime/build-cache/truffle-api.jar").absolutePath}"
|
s"--upgrade-module-path=${file("engine/runtime/build-cache/truffle-api.jar").absolutePath}"
|
||||||
),
|
),
|
||||||
|
Test / javacOptions ++= Seq(
|
||||||
|
"-s",
|
||||||
|
(Test / sourceManaged).value.getAbsolutePath
|
||||||
|
),
|
||||||
|
Compile / logManager :=
|
||||||
|
sbt.internal.util.CustomLogManager.excludeMsg(
|
||||||
|
"Could not determine source for class ",
|
||||||
|
Level.Warn
|
||||||
|
),
|
||||||
commands += WithDebugCommand.withDebug,
|
commands += WithDebugCommand.withDebug,
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
||||||
|
@ -36,6 +36,7 @@ polyglot java import java.io.OutputStream as Java_Output_Stream
|
|||||||
polyglot java import java.nio.file.FileSystems
|
polyglot java import java.nio.file.FileSystems
|
||||||
polyglot java import java.nio.file.Path
|
polyglot java import java.nio.file.Path
|
||||||
polyglot java import java.nio.file.StandardCopyOption
|
polyglot java import java.nio.file.StandardCopyOption
|
||||||
|
polyglot java import java.nio.file.StandardOpenOption
|
||||||
polyglot java import java.time.ZonedDateTime
|
polyglot java import java.time.ZonedDateTime
|
||||||
polyglot java import org.enso.base.DryRunFileManager
|
polyglot java import org.enso.base.DryRunFileManager
|
||||||
polyglot java import org.enso.base.encoding.ReportingStreamDecoder
|
polyglot java import org.enso.base.encoding.ReportingStreamDecoder
|
||||||
@ -145,9 +146,9 @@ type File
|
|||||||
with_output_stream self open_options action =
|
with_output_stream self open_options action =
|
||||||
new_output_stream : File -> Vector File_Access -> Output_Stream ! File_Error
|
new_output_stream : File -> Vector File_Access -> Output_Stream ! File_Error
|
||||||
new_output_stream file open_options =
|
new_output_stream file open_options =
|
||||||
opts = open_options . map (_.to_java) . to_array
|
opts = open_options . map (_.to_java)
|
||||||
stream = File_Error.handle_java_exceptions file <|
|
stream = File_Error.handle_java_exceptions file <|
|
||||||
file.output_stream_builtin opts.to_array
|
file.output_stream_builtin opts
|
||||||
## We re-wrap the File Not Found error to return the parent directory
|
## We re-wrap the File Not Found error to return the parent directory
|
||||||
instead of the file itself - because the file that is being written
|
instead of the file itself - because the file that is being written
|
||||||
may not exist and it will not be an error, it is the parent directory
|
may not exist and it will not be an error, it is the parent directory
|
||||||
@ -180,9 +181,10 @@ type File
|
|||||||
`File.with_input_stream` instead, which does resource management.
|
`File.with_input_stream` instead, which does resource management.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
- open_options: A vector of `File_Access` objects determining how to open
|
- open_options: A vector of `StandardOpenOption` polyglot objects
|
||||||
the stream. These options set the access properties of the stream.
|
determining how to open the stream. These options set the access
|
||||||
input_stream : Vector File_Access -> Input_Stream
|
properties of the stream.
|
||||||
|
input_stream : Vector StandardOpenOption -> Input_Stream
|
||||||
input_stream self options = @Builtin_Method "File.input_stream"
|
input_stream self options = @Builtin_Method "File.input_stream"
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
@ -564,8 +566,8 @@ type File
|
|||||||
File_Error.handle_java_exceptions self <| case replace_existing of
|
File_Error.handle_java_exceptions self <| case replace_existing of
|
||||||
True ->
|
True ->
|
||||||
copy_options = [StandardCopyOption.REPLACE_EXISTING]
|
copy_options = [StandardCopyOption.REPLACE_EXISTING]
|
||||||
self.copy_builtin destination copy_options.to_array
|
self.copy_builtin destination copy_options
|
||||||
False -> self.copy_builtin destination [].to_array
|
False -> self.copy_builtin destination []
|
||||||
|
|
||||||
## Moves the file to the specified destination.
|
## Moves the file to the specified destination.
|
||||||
|
|
||||||
@ -579,8 +581,8 @@ type File
|
|||||||
File_Error.handle_java_exceptions self <| case replace_existing of
|
File_Error.handle_java_exceptions self <| case replace_existing of
|
||||||
True ->
|
True ->
|
||||||
copy_options = [StandardCopyOption.REPLACE_EXISTING]
|
copy_options = [StandardCopyOption.REPLACE_EXISTING]
|
||||||
self.move_builtin destination copy_options.to_array
|
self.move_builtin destination copy_options
|
||||||
False -> self.move_builtin destination [].to_array
|
False -> self.move_builtin destination []
|
||||||
|
|
||||||
## Deletes the file if it exists on disk.
|
## Deletes the file if it exists on disk.
|
||||||
|
|
||||||
@ -609,8 +611,8 @@ type File
|
|||||||
new_input_stream : Vector File_Access -> Input_Stream ! File_Error
|
new_input_stream : Vector File_Access -> Input_Stream ! File_Error
|
||||||
new_input_stream self open_options =
|
new_input_stream self open_options =
|
||||||
if self.is_directory then Error.throw (File_Error.IO_Error self "File '"+self.path+"' is a directory") else
|
if self.is_directory then Error.throw (File_Error.IO_Error self "File '"+self.path+"' is a directory") else
|
||||||
opts = open_options . map (_.to_java) . to_array
|
opts = open_options . map (_.to_java)
|
||||||
stream = File_Error.handle_java_exceptions self (self.input_stream opts.to_array)
|
stream = File_Error.handle_java_exceptions self (self.input_stream opts)
|
||||||
resource = Managed_Resource.register stream close_stream
|
resource = Managed_Resource.register stream close_stream
|
||||||
Input_Stream.Value self resource
|
Input_Stream.Value self resource
|
||||||
|
|
||||||
|
@ -4,12 +4,16 @@ import com.oracle.truffle.api.CompilerDirectives;
|
|||||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||||
import com.oracle.truffle.api.TruffleFile;
|
import com.oracle.truffle.api.TruffleFile;
|
||||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
|
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
|
||||||
import com.oracle.truffle.api.interop.TruffleObject;
|
import com.oracle.truffle.api.interop.TruffleObject;
|
||||||
|
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||||
import com.oracle.truffle.api.library.CachedLibrary;
|
import com.oracle.truffle.api.library.CachedLibrary;
|
||||||
import com.oracle.truffle.api.library.ExportLibrary;
|
import com.oracle.truffle.api.library.ExportLibrary;
|
||||||
import com.oracle.truffle.api.library.ExportMessage;
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
import org.enso.interpreter.dsl.Builtin;
|
import org.enso.interpreter.dsl.Builtin;
|
||||||
import org.enso.interpreter.runtime.EnsoContext;
|
import org.enso.interpreter.runtime.EnsoContext;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -45,17 +49,58 @@ public final class EnsoFile implements TruffleObject {
|
|||||||
@Builtin.Method(name = "output_stream_builtin")
|
@Builtin.Method(name = "output_stream_builtin")
|
||||||
@Builtin.WrapException(from = IOException.class)
|
@Builtin.WrapException(from = IOException.class)
|
||||||
@Builtin.ReturningGuestObject
|
@Builtin.ReturningGuestObject
|
||||||
|
@Builtin.Specialize
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
public OutputStream outputStream(OpenOption[] opts) throws IOException {
|
public OutputStream outputStream(Object opts,
|
||||||
return this.truffleFile.newOutputStream(opts);
|
EnsoContext ctx,
|
||||||
|
@CachedLibrary(limit = "5") InteropLibrary interop) throws IOException {
|
||||||
|
OpenOption[] openOptions = convertInteropArray(opts, interop, ctx, OpenOption[]::new);
|
||||||
|
return this.truffleFile.newOutputStream(openOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Builtin.Method
|
@Builtin.Method
|
||||||
@Builtin.WrapException(from = IOException.class)
|
@Builtin.WrapException(from = IOException.class)
|
||||||
|
@Builtin.Specialize
|
||||||
@Builtin.ReturningGuestObject
|
@Builtin.ReturningGuestObject
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
public InputStream inputStream(OpenOption[] opts) throws IOException {
|
public InputStream inputStream(Object opts,
|
||||||
return this.truffleFile.newInputStream(opts);
|
EnsoContext ctx,
|
||||||
|
@CachedLibrary(limit = "5") InteropLibrary interop) throws IOException {
|
||||||
|
OpenOption[] openOptions = convertInteropArray(opts, interop, ctx, OpenOption[]::new);
|
||||||
|
return this.truffleFile.newInputStream(openOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T> T[] convertInteropArray(Object arr,
|
||||||
|
InteropLibrary interop,
|
||||||
|
EnsoContext ctx,
|
||||||
|
IntFunction<T[]> hostArrayCtor) {
|
||||||
|
if (!interop.hasArrayElements(arr)) {
|
||||||
|
var vecType = ctx.getBuiltins().vector().getType();
|
||||||
|
var typeError = ctx.getBuiltins().error().makeTypeError(vecType, arr, "opts");
|
||||||
|
throw new PanicException(typeError, interop);
|
||||||
|
}
|
||||||
|
T[] hostArr;
|
||||||
|
try {
|
||||||
|
int size = Math.toIntExact(interop.getArraySize(arr));
|
||||||
|
hostArr = hostArrayCtor.apply(size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
Object elem = interop.readArrayElement(arr, i);
|
||||||
|
if (!ctx.getEnvironment().isHostObject(elem)) {
|
||||||
|
var err = ctx.getBuiltins().error().makeUnsupportedArgumentsError(
|
||||||
|
new Object[]{arr},
|
||||||
|
"Arguments to opts should be host objects from java.io package"
|
||||||
|
);
|
||||||
|
throw new PanicException(err, interop);
|
||||||
|
}
|
||||||
|
hostArr[i] = (T) ctx.getEnvironment().asHostObject(elem);
|
||||||
|
}
|
||||||
|
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
|
||||||
|
throw new IllegalStateException("Unreachable", e);
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new PanicException(e, interop);
|
||||||
|
}
|
||||||
|
return hostArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Builtin.Method(name = "read_last_bytes_builtin")
|
@Builtin.Method(name = "read_last_bytes_builtin")
|
||||||
@ -221,16 +266,24 @@ public final class EnsoFile implements TruffleObject {
|
|||||||
|
|
||||||
@Builtin.Method(name = "copy_builtin", description = "Copy this file to a target destination")
|
@Builtin.Method(name = "copy_builtin", description = "Copy this file to a target destination")
|
||||||
@Builtin.WrapException(from = IOException.class)
|
@Builtin.WrapException(from = IOException.class)
|
||||||
|
@Builtin.Specialize
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
public void copy(EnsoFile target, CopyOption[] options) throws IOException {
|
public void copy(EnsoFile target, Object options,
|
||||||
truffleFile.copy(target.truffleFile, options);
|
@CachedLibrary(limit = "5") InteropLibrary interop,
|
||||||
|
EnsoContext ctx) throws IOException {
|
||||||
|
CopyOption[] copyOptions = convertInteropArray(options, interop, ctx, CopyOption[]::new);
|
||||||
|
truffleFile.copy(target.truffleFile, copyOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Builtin.Method(name = "move_builtin", description = "Move this file to a target destination")
|
@Builtin.Method(name = "move_builtin", description = "Move this file to a target destination")
|
||||||
@Builtin.WrapException(from = IOException.class)
|
@Builtin.WrapException(from = IOException.class)
|
||||||
|
@Builtin.Specialize
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
public void move(EnsoFile target, CopyOption[] options) throws IOException {
|
public void move(EnsoFile target, Object options,
|
||||||
truffleFile.move(target.truffleFile, options);
|
@CachedLibrary(limit = "5") InteropLibrary interop,
|
||||||
|
EnsoContext ctx) throws IOException {
|
||||||
|
CopyOption[] copyOptions = convertInteropArray(options, interop, ctx, CopyOption[]::new);
|
||||||
|
truffleFile.move(target.truffleFile, copyOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Builtin.Method
|
@Builtin.Method
|
||||||
|
@ -178,7 +178,7 @@ public class BuiltinsProcessor extends AbstractProcessor {
|
|||||||
try {
|
try {
|
||||||
MethodNodeClassGenerator classGenerator =
|
MethodNodeClassGenerator classGenerator =
|
||||||
new NoSpecializationClassGenerator(
|
new NoSpecializationClassGenerator(
|
||||||
method, builtinMethodNode, ownerClass, stdLibOwnerClass, i);
|
processingEnv, method, builtinMethodNode, ownerClass, stdLibOwnerClass, i);
|
||||||
classGenerator.generate(
|
classGenerator.generate(
|
||||||
processingEnv,
|
processingEnv,
|
||||||
methodName,
|
methodName,
|
||||||
@ -232,7 +232,7 @@ public class BuiltinsProcessor extends AbstractProcessor {
|
|||||||
if (encountered.size() == expected) {
|
if (encountered.size() == expected) {
|
||||||
MethodNodeClassGenerator classGenerator =
|
MethodNodeClassGenerator classGenerator =
|
||||||
new SpecializationClassGenerator(
|
new SpecializationClassGenerator(
|
||||||
encountered, builtinMethodNode, ownerClass, stdLibOwnerClass);
|
processingEnv, encountered, builtinMethodNode, ownerClass, stdLibOwnerClass);
|
||||||
classGenerator.generate(
|
classGenerator.generate(
|
||||||
processingEnv,
|
processingEnv,
|
||||||
builtinMethodName,
|
builtinMethodName,
|
||||||
@ -243,7 +243,7 @@ public class BuiltinsProcessor extends AbstractProcessor {
|
|||||||
} else {
|
} else {
|
||||||
MethodNodeClassGenerator classGenerator =
|
MethodNodeClassGenerator classGenerator =
|
||||||
new NoSpecializationClassGenerator(
|
new NoSpecializationClassGenerator(
|
||||||
method, builtinMethodNode, ownerClass, stdLibOwnerClass);
|
processingEnv, method, builtinMethodNode, ownerClass, stdLibOwnerClass);
|
||||||
classGenerator.generate(
|
classGenerator.generate(
|
||||||
processingEnv,
|
processingEnv,
|
||||||
builtinMethodName,
|
builtinMethodName,
|
||||||
|
@ -144,7 +144,6 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
|
|||||||
private void generateCode(MethodDefinition methodDefinition) throws IOException {
|
private void generateCode(MethodDefinition methodDefinition) throws IOException {
|
||||||
JavaFileObject gen =
|
JavaFileObject gen =
|
||||||
processingEnv.getFiler().createSourceFile(methodDefinition.getQualifiedName());
|
processingEnv.getFiler().createSourceFile(methodDefinition.getQualifiedName());
|
||||||
|
|
||||||
Set<String> allImports = new HashSet<>(necessaryImports);
|
Set<String> allImports = new HashSet<>(necessaryImports);
|
||||||
allImports.addAll(methodDefinition.getImports());
|
allImports.addAll(methodDefinition.getImports());
|
||||||
|
|
||||||
@ -156,6 +155,10 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
|
|||||||
|
|
||||||
out.println();
|
out.println();
|
||||||
|
|
||||||
|
out.println("/**");
|
||||||
|
out.println(" * Generated by {@link " + getClass().getName() + "}.");
|
||||||
|
out.println(" * From {@link " + methodDefinition.getOriginalClassName() + "}.");
|
||||||
|
out.println(" */");
|
||||||
out.println("@NodeInfo(");
|
out.println("@NodeInfo(");
|
||||||
out.println(" shortName = \"" + methodDefinition.getDeclaredName() + "\",");
|
out.println(" shortName = \"" + methodDefinition.getDeclaredName() + "\",");
|
||||||
out.println(" description = \"\"\"\n" + methodDefinition.getDescription() + "\"\"\")");
|
out.println(" description = \"\"\"\n" + methodDefinition.getDescription() + "\"\"\")");
|
||||||
@ -165,13 +168,13 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
|
|||||||
out.println("public class " + methodDefinition.getClassName() + " extends BuiltinRootNode implements InlineableNode.Root {");
|
out.println("public class " + methodDefinition.getClassName() + " extends BuiltinRootNode implements InlineableNode.Root {");
|
||||||
}
|
}
|
||||||
out.println(" private @Child " + methodDefinition.getOriginalClassName() + " bodyNode;");
|
out.println(" private @Child " + methodDefinition.getOriginalClassName() + " bodyNode;");
|
||||||
|
out.println();
|
||||||
out.println(" private static final class Internals {");
|
out.println(" private static final class Internals {");
|
||||||
out.println(" Internals(boolean s) {");
|
out.println(" Internals(boolean s) {");
|
||||||
out.println(" this.staticOfInstanceMethod = s;");
|
out.println(" this.staticOfInstanceMethod = s;");
|
||||||
out.println(" }");
|
out.println(" }");
|
||||||
out.println(" private final boolean staticOfInstanceMethod;");
|
|
||||||
|
|
||||||
out.println();
|
out.println();
|
||||||
|
out.println(" private final boolean staticOfInstanceMethod;");
|
||||||
|
|
||||||
for (MethodDefinition.ArgumentDefinition arg : methodDefinition.getArguments()) {
|
for (MethodDefinition.ArgumentDefinition arg : methodDefinition.getArguments()) {
|
||||||
if (arg.shouldCheckErrors()) {
|
if (arg.shouldCheckErrors()) {
|
||||||
@ -278,6 +281,7 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
|
|||||||
generateWarningsCheck(out, methodDefinition.getArguments(), "arguments");
|
generateWarningsCheck(out, methodDefinition.getArguments(), "arguments");
|
||||||
for (MethodDefinition.ArgumentDefinition argumentDefinition :
|
for (MethodDefinition.ArgumentDefinition argumentDefinition :
|
||||||
methodDefinition.getArguments()) {
|
methodDefinition.getArguments()) {
|
||||||
|
out.println(" /*** Start of processing argument " + argumentDefinition.getPosition() + " ***/");
|
||||||
if (argumentDefinition.isImplicit()) {
|
if (argumentDefinition.isImplicit()) {
|
||||||
} else if (argumentDefinition.isState()) {
|
} else if (argumentDefinition.isState()) {
|
||||||
callArgNames.add("state");
|
callArgNames.add("state");
|
||||||
@ -289,6 +293,7 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
|
|||||||
callArgNames.add(mkArgumentInternalVarName(argumentDefinition));
|
callArgNames.add(mkArgumentInternalVarName(argumentDefinition));
|
||||||
generateArgumentRead(out, argumentDefinition, "arguments");
|
generateArgumentRead(out, argumentDefinition, "arguments");
|
||||||
}
|
}
|
||||||
|
out.println(" /*** End of processing argument " + argumentDefinition.getPosition() + " ***/");
|
||||||
}
|
}
|
||||||
String executeCall = "bodyNode.execute(" + String.join(", ", callArgNames) + ")";
|
String executeCall = "bodyNode.execute(" + String.join(", ", callArgNames) + ")";
|
||||||
if (warningsPossible) {
|
if (warningsPossible) {
|
||||||
|
@ -19,8 +19,12 @@ public final class ExecuteMethodImplGenerator extends MethodGenerator {
|
|||||||
private final boolean needsVarargExpansion;
|
private final boolean needsVarargExpansion;
|
||||||
|
|
||||||
public ExecuteMethodImplGenerator(
|
public ExecuteMethodImplGenerator(
|
||||||
ExecutableElement method, boolean convertToGuestValue, int expandedVarargs) {
|
ProcessingEnvironment processingEnvironment,
|
||||||
|
ExecutableElement method,
|
||||||
|
boolean convertToGuestValue,
|
||||||
|
int expandedVarargs) {
|
||||||
this(
|
this(
|
||||||
|
processingEnvironment,
|
||||||
method,
|
method,
|
||||||
method.getReturnType().toString(),
|
method.getReturnType().toString(),
|
||||||
method.getModifiers().contains(Modifier.STATIC),
|
method.getModifiers().contains(Modifier.STATIC),
|
||||||
@ -31,6 +35,7 @@ public final class ExecuteMethodImplGenerator extends MethodGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ExecuteMethodImplGenerator(
|
private ExecuteMethodImplGenerator(
|
||||||
|
ProcessingEnvironment processingEnvironment,
|
||||||
ExecutableElement method,
|
ExecutableElement method,
|
||||||
String returnTpe,
|
String returnTpe,
|
||||||
boolean isStatic,
|
boolean isStatic,
|
||||||
@ -38,7 +43,12 @@ public final class ExecuteMethodImplGenerator extends MethodGenerator {
|
|||||||
boolean convertToGuestValue,
|
boolean convertToGuestValue,
|
||||||
int expandedVarargs,
|
int expandedVarargs,
|
||||||
boolean isVarargs) {
|
boolean isVarargs) {
|
||||||
super(isStatic, isConstructor, convertToGuestValue, TypeWithKind.createFromTpe(returnTpe));
|
super(
|
||||||
|
processingEnvironment,
|
||||||
|
isStatic,
|
||||||
|
isConstructor,
|
||||||
|
convertToGuestValue,
|
||||||
|
TypeWithKind.createFromTpe(returnTpe));
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.varargExpansion = expandedVarargs;
|
this.varargExpansion = expandedVarargs;
|
||||||
this.needsVarargExpansion = isVarargs && (varargExpansion > 0);
|
this.needsVarargExpansion = isVarargs && (varargExpansion > 0);
|
||||||
@ -112,6 +122,15 @@ public final class ExecuteMethodImplGenerator extends MethodGenerator {
|
|||||||
if (returnTpe.isValidGuestType()) {
|
if (returnTpe.isValidGuestType()) {
|
||||||
return new String[] {" return " + qual + "." + name + "(" + paramsApplied + ");"};
|
return new String[] {" return " + qual + "." + name + "(" + paramsApplied + ");"};
|
||||||
} else {
|
} else {
|
||||||
|
if (!convertToGuestValue) {
|
||||||
|
processingEnvironment
|
||||||
|
.getMessager()
|
||||||
|
.printMessage(
|
||||||
|
javax.tools.Diagnostic.Kind.ERROR,
|
||||||
|
"Cannot generate method body for "
|
||||||
|
+ method
|
||||||
|
+ " because it returns a host object and convertToGuestValue is false");
|
||||||
|
}
|
||||||
return new String[] {
|
return new String[] {
|
||||||
" return context",
|
" return context",
|
||||||
" .getEnvironment()",
|
" .getEnvironment()",
|
||||||
@ -134,14 +153,16 @@ public final class ExecuteMethodImplGenerator extends MethodGenerator {
|
|||||||
return result || params.stream().anyMatch(p -> p.needsToHostTranslation());
|
return result || params.stream().anyMatch(p -> p.needsToHostTranslation());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> generate(ProcessingEnvironment processingEnv, String name, String owner) {
|
public List<String> generate(String name, String owner) {
|
||||||
|
SafeWrapException[] exceptionWrappers = wrapExceptions(processingEnvironment, method);
|
||||||
SafeWrapException[] exceptionWrappers = wrapExceptions(processingEnv, method);
|
|
||||||
boolean wrapsExceptions = exceptionWrappers.length != 0;
|
boolean wrapsExceptions = exceptionWrappers.length != 0;
|
||||||
List<? extends VariableElement> rawParams = method.getParameters();
|
List<? extends VariableElement> rawParams = method.getParameters();
|
||||||
List<MethodParameter> params =
|
List<MethodParameter> params =
|
||||||
IntStream.range(0, method.getParameters().size())
|
IntStream.range(0, method.getParameters().size())
|
||||||
.mapToObj(i -> fromVariableElementToMethodParameter(i, rawParams.get(i)))
|
.mapToObj(
|
||||||
|
i ->
|
||||||
|
fromVariableElementToMethodParameter(
|
||||||
|
processingEnvironment, i, rawParams.get(i)))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
String[] body = bodyBase(name, owner, params);
|
String[] body = bodyBase(name, owner, params);
|
||||||
|
@ -14,14 +14,16 @@ import javax.annotation.processing.ProcessingEnvironment;
|
|||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
import javax.tools.Diagnostic.Kind;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.enso.interpreter.dsl.Builtin;
|
import org.enso.interpreter.dsl.Builtin;
|
||||||
|
|
||||||
public abstract class MethodGenerator {
|
public abstract class MethodGenerator {
|
||||||
protected final boolean isStatic;
|
protected final boolean isStatic;
|
||||||
protected final boolean isConstructor;
|
protected final boolean isConstructor;
|
||||||
private final boolean convertToGuestValue;
|
protected final boolean convertToGuestValue;
|
||||||
protected final TypeWithKind returnTpe;
|
protected final TypeWithKind returnTpe;
|
||||||
|
protected final ProcessingEnvironment processingEnvironment;
|
||||||
|
|
||||||
private static final WrapExceptionExtractor wrapExceptionsExtractor =
|
private static final WrapExceptionExtractor wrapExceptionsExtractor =
|
||||||
new WrapExceptionExtractor(Builtin.WrapException.class, Builtin.WrapExceptions.class);
|
new WrapExceptionExtractor(Builtin.WrapException.class, Builtin.WrapExceptions.class);
|
||||||
@ -32,18 +34,19 @@ public abstract class MethodGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MethodGenerator(
|
public MethodGenerator(
|
||||||
|
ProcessingEnvironment processingEnvironment,
|
||||||
boolean isStatic,
|
boolean isStatic,
|
||||||
boolean isConstructor,
|
boolean isConstructor,
|
||||||
boolean convertToGuestValue,
|
boolean convertToGuestValue,
|
||||||
TypeWithKind returnTpe) {
|
TypeWithKind returnTpe) {
|
||||||
|
this.processingEnvironment = processingEnvironment;
|
||||||
this.isStatic = isStatic;
|
this.isStatic = isStatic;
|
||||||
this.isConstructor = isConstructor;
|
this.isConstructor = isConstructor;
|
||||||
this.convertToGuestValue = convertToGuestValue;
|
this.convertToGuestValue = convertToGuestValue;
|
||||||
this.returnTpe = returnTpe;
|
this.returnTpe = returnTpe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract List<String> generate(
|
public abstract List<String> generate(String name, String owner);
|
||||||
ProcessingEnvironment processingEnv, String name, String owner);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate node's `execute` method definition (return type and necessary parameters). '
|
* Generate node's `execute` method definition (return type and necessary parameters). '
|
||||||
@ -91,10 +94,13 @@ public abstract class MethodGenerator {
|
|||||||
return tpe.baseType();
|
return tpe.baseType();
|
||||||
} else {
|
} else {
|
||||||
if (!convertToGuestValue) {
|
if (!convertToGuestValue) {
|
||||||
throw new RuntimeException(
|
processingEnvironment
|
||||||
"If intended, automatic conversion of value of type "
|
.getMessager()
|
||||||
+ tpe.baseType()
|
.printMessage(
|
||||||
+ " to guest value requires explicit '@Builtin.ReturningGuestObject' annotation");
|
Kind.ERROR,
|
||||||
|
"Automatic conversion of value of type "
|
||||||
|
+ tpe.baseType()
|
||||||
|
+ " to guest value requires explicit '@Builtin.ReturningGuestObject' annotation");
|
||||||
}
|
}
|
||||||
return "Object";
|
return "Object";
|
||||||
}
|
}
|
||||||
@ -111,14 +117,28 @@ public abstract class MethodGenerator {
|
|||||||
* @param v variable element representing the parameter
|
* @param v variable element representing the parameter
|
||||||
* @return MethodParameter encapsulating the method's parameter info
|
* @return MethodParameter encapsulating the method's parameter info
|
||||||
*/
|
*/
|
||||||
protected MethodParameter fromVariableElementToMethodParameter(int i, VariableElement v) {
|
protected MethodParameter fromVariableElementToMethodParameter(
|
||||||
|
ProcessingEnvironment processingEnv, int i, VariableElement v) {
|
||||||
String ensoName =
|
String ensoName =
|
||||||
CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, v.getSimpleName().toString());
|
CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, v.getSimpleName().toString());
|
||||||
|
TypeWithKind tpe = TypeWithKind.createFromTpe(v.asType().toString());
|
||||||
|
if (tpe.kind() == TypeKind.ARRAY && !tpe.isValidGuestType()) {
|
||||||
|
processingEnv
|
||||||
|
.getMessager()
|
||||||
|
.printMessage(
|
||||||
|
Kind.ERROR,
|
||||||
|
"Parameter "
|
||||||
|
+ v
|
||||||
|
+ " is an array of host objects, which "
|
||||||
|
+ "is not supported by the MethodGenerator. Either use array of primitive, or valid guest objects, "
|
||||||
|
+ "or accept the array as Object and transform it in the method body.",
|
||||||
|
v);
|
||||||
|
}
|
||||||
return new MethodParameter(
|
return new MethodParameter(
|
||||||
i,
|
i,
|
||||||
ensoName,
|
ensoName,
|
||||||
v.asType().toString(),
|
v.asType().toString(),
|
||||||
v.getAnnotationMirrors().stream().map(am -> am.toString()).collect(Collectors.toList()));
|
v.getAnnotationMirrors().stream().map(Object::toString).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Optional<Integer> expandVararg(int paramsLen, int paramIndex);
|
protected abstract Optional<Integer> expandVararg(int paramsLen, int paramIndex);
|
||||||
|
@ -42,7 +42,6 @@ public abstract class MethodNodeClassGenerator {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
JavaFileObject gen =
|
JavaFileObject gen =
|
||||||
processingEnv.getFiler().createSourceFile(builtinNode.jvmFriendlyFullyQualifiedName());
|
processingEnv.getFiler().createSourceFile(builtinNode.jvmFriendlyFullyQualifiedName());
|
||||||
;
|
|
||||||
try (PrintWriter out = new PrintWriter(gen.openWriter())) {
|
try (PrintWriter out = new PrintWriter(gen.openWriter())) {
|
||||||
String ensoMethodName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, methodName);
|
String ensoMethodName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, methodName);
|
||||||
String ensoTypeName = stdlibOwner.name().replaceAll("([a-z])([A-Z])", "$1_$2");
|
String ensoTypeName = stdlibOwner.name().replaceAll("([a-z])([A-Z])", "$1_$2");
|
||||||
@ -60,6 +59,12 @@ public abstract class MethodNodeClassGenerator {
|
|||||||
if (needsFrame != null) {
|
if (needsFrame != null) {
|
||||||
moduleOwnerInfo = moduleOwnerInfo + ", needsFrame = " + needsFrame;
|
moduleOwnerInfo = moduleOwnerInfo + ", needsFrame = " + needsFrame;
|
||||||
}
|
}
|
||||||
|
out.println("/**");
|
||||||
|
out.println(
|
||||||
|
" * Generated by {@link org.enso.interpreter.dsl.builtins.MethodNodeClassGenerator}.");
|
||||||
|
out.println(
|
||||||
|
" * From {@link " + ownerClazz.fullyQualifiedName() + "#" + ownerMethodName + "}.");
|
||||||
|
out.println(" */");
|
||||||
out.println(
|
out.println(
|
||||||
"@BuiltinMethod(type = \""
|
"@BuiltinMethod(type = \""
|
||||||
+ ensoTypeName
|
+ ensoTypeName
|
||||||
@ -83,7 +88,7 @@ public abstract class MethodNodeClassGenerator {
|
|||||||
out.println("public class " + builtinNode.jvmFriendlyName() + " extends Node {");
|
out.println("public class " + builtinNode.jvmFriendlyName() + " extends Node {");
|
||||||
out.println();
|
out.println();
|
||||||
}
|
}
|
||||||
for (String line : methodsGen().generate(processingEnv, ownerMethodName, ownerClazz.name())) {
|
for (String line : methodsGen().generate(ownerMethodName, ownerClazz.name())) {
|
||||||
out.println(" " + line);
|
out.println(" " + line);
|
||||||
}
|
}
|
||||||
out.println();
|
out.println();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.interpreter.dsl.builtins;
|
package org.enso.interpreter.dsl.builtins;
|
||||||
|
|
||||||
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
|
||||||
/** Generator for builtin method class with no specialization. */
|
/** Generator for builtin method class with no specialization. */
|
||||||
@ -7,8 +8,10 @@ public final class NoSpecializationClassGenerator extends MethodNodeClassGenerat
|
|||||||
|
|
||||||
ExecutableElement origin;
|
ExecutableElement origin;
|
||||||
int varArgExpansion;
|
int varArgExpansion;
|
||||||
|
private final ProcessingEnvironment processingEnvironment;
|
||||||
|
|
||||||
public NoSpecializationClassGenerator(
|
public NoSpecializationClassGenerator(
|
||||||
|
ProcessingEnvironment processingEnvironment,
|
||||||
ExecutableElement origin,
|
ExecutableElement origin,
|
||||||
ClassName builtinNode,
|
ClassName builtinNode,
|
||||||
ClassName ownerClazz,
|
ClassName ownerClazz,
|
||||||
@ -17,20 +20,22 @@ public final class NoSpecializationClassGenerator extends MethodNodeClassGenerat
|
|||||||
super(builtinNode, ownerClazz, stdlibOwner);
|
super(builtinNode, ownerClazz, stdlibOwner);
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
this.varArgExpansion = varArgExpansion;
|
this.varArgExpansion = varArgExpansion;
|
||||||
|
this.processingEnvironment = processingEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NoSpecializationClassGenerator(
|
public NoSpecializationClassGenerator(
|
||||||
|
ProcessingEnvironment processingEnvironment,
|
||||||
ExecutableElement origin,
|
ExecutableElement origin,
|
||||||
ClassName builtinNode,
|
ClassName builtinNode,
|
||||||
ClassName ownerClazz,
|
ClassName ownerClazz,
|
||||||
ClassName stdlibOwner) {
|
ClassName stdlibOwner) {
|
||||||
this(origin, builtinNode, ownerClazz, stdlibOwner, 0);
|
this(processingEnvironment, origin, builtinNode, ownerClazz, stdlibOwner, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MethodGenerator methodsGen() {
|
protected MethodGenerator methodsGen() {
|
||||||
return new ExecuteMethodImplGenerator(
|
return new ExecuteMethodImplGenerator(
|
||||||
origin, needsGuestValueConversion(origin), varArgExpansion);
|
processingEnvironment, origin, needsGuestValueConversion(origin), varArgExpansion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.enso.interpreter.dsl.builtins;
|
package org.enso.interpreter.dsl.builtins;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,19 +11,22 @@ import javax.lang.model.element.ExecutableElement;
|
|||||||
*/
|
*/
|
||||||
public class SpecializationClassGenerator extends MethodNodeClassGenerator {
|
public class SpecializationClassGenerator extends MethodNodeClassGenerator {
|
||||||
List<ExecutableElement> elements;
|
List<ExecutableElement> elements;
|
||||||
|
private final ProcessingEnvironment processingEnvironment;
|
||||||
|
|
||||||
public SpecializationClassGenerator(
|
public SpecializationClassGenerator(
|
||||||
|
ProcessingEnvironment processingEnvironment,
|
||||||
List<ExecutableElement> methodElements,
|
List<ExecutableElement> methodElements,
|
||||||
ClassName builtinNode,
|
ClassName builtinNode,
|
||||||
ClassName ownerClazz,
|
ClassName ownerClazz,
|
||||||
ClassName stdlibOwner) {
|
ClassName stdlibOwner) {
|
||||||
super(builtinNode, ownerClazz, stdlibOwner);
|
super(builtinNode, ownerClazz, stdlibOwner);
|
||||||
this.elements = methodElements;
|
this.elements = methodElements;
|
||||||
|
this.processingEnvironment = processingEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MethodGenerator methodsGen() {
|
protected MethodGenerator methodsGen() {
|
||||||
return new SpecializedMethodsGenerator(elements);
|
return new SpecializedMethodsGenerator(processingEnvironment, elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -13,6 +13,7 @@ import javax.lang.model.element.ElementKind;
|
|||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.VariableElement;
|
import javax.lang.model.element.VariableElement;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.enso.interpreter.dsl.AcceptsWarning;
|
import org.enso.interpreter.dsl.AcceptsWarning;
|
||||||
import org.enso.interpreter.dsl.Builtin;
|
import org.enso.interpreter.dsl.Builtin;
|
||||||
@ -23,12 +24,17 @@ public final class SpecializedMethodsGenerator extends MethodGenerator {
|
|||||||
private static final String WithWarningsClassName =
|
private static final String WithWarningsClassName =
|
||||||
"org.enso.interpreter.runtime.error.WithWarnings";
|
"org.enso.interpreter.runtime.error.WithWarnings";
|
||||||
|
|
||||||
public SpecializedMethodsGenerator(List<ExecutableElement> elements) {
|
public SpecializedMethodsGenerator(
|
||||||
this(elements, elements.get(0));
|
ProcessingEnvironment processingEnvironment, List<ExecutableElement> elements) {
|
||||||
|
this(processingEnvironment, elements, elements.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpecializedMethodsGenerator(List<ExecutableElement> elements, ExecutableElement first) {
|
private SpecializedMethodsGenerator(
|
||||||
|
ProcessingEnvironment processingEnvironment,
|
||||||
|
List<ExecutableElement> elements,
|
||||||
|
ExecutableElement first) {
|
||||||
this(
|
this(
|
||||||
|
processingEnvironment,
|
||||||
elements,
|
elements,
|
||||||
first.getModifiers().contains(Modifier.STATIC),
|
first.getModifiers().contains(Modifier.STATIC),
|
||||||
first.getKind() == ElementKind.CONSTRUCTOR,
|
first.getKind() == ElementKind.CONSTRUCTOR,
|
||||||
@ -45,12 +51,13 @@ public final class SpecializedMethodsGenerator extends MethodGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SpecializedMethodsGenerator(
|
public SpecializedMethodsGenerator(
|
||||||
|
ProcessingEnvironment processingEnvironment,
|
||||||
List<ExecutableElement> elements,
|
List<ExecutableElement> elements,
|
||||||
boolean isStatic,
|
boolean isStatic,
|
||||||
boolean isConstructor,
|
boolean isConstructor,
|
||||||
boolean convertToGuestValue,
|
boolean convertToGuestValue,
|
||||||
TypeWithKind returnTpe) {
|
TypeWithKind returnTpe) {
|
||||||
super(isStatic, isConstructor, convertToGuestValue, returnTpe);
|
super(processingEnvironment, isStatic, isConstructor, convertToGuestValue, returnTpe);
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,14 +66,14 @@ public final class SpecializedMethodsGenerator extends MethodGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> generate(ProcessingEnvironment processingEnv, String name, String owner) {
|
public List<String> generate(String name, String owner) {
|
||||||
SpecializationMeta meta = inferExecuteParameters();
|
SpecializationMeta meta = inferExecuteParameters(processingEnvironment);
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
|
|
||||||
result.add(methodSigDef(owner, meta.execParams(), true));
|
result.add(methodSigDef(owner, meta.execParams(), true));
|
||||||
result.add("");
|
result.add("");
|
||||||
result.addAll(
|
result.addAll(
|
||||||
paramsOfSpecializedMethods(processingEnv, meta.diffParam)
|
paramsOfSpecializedMethods(processingEnvironment, meta.diffParam)
|
||||||
.flatMap(
|
.flatMap(
|
||||||
specializeMethod ->
|
specializeMethod ->
|
||||||
specialize(owner, name, specializeMethod, meta.diffParam).stream())
|
specialize(owner, name, specializeMethod, meta.diffParam).stream())
|
||||||
@ -98,7 +105,10 @@ public final class SpecializedMethodsGenerator extends MethodGenerator {
|
|||||||
return new SpecializeMethodInfo(
|
return new SpecializeMethodInfo(
|
||||||
method,
|
method,
|
||||||
IntStream.range(0, params.size())
|
IntStream.range(0, params.size())
|
||||||
.mapToObj(i -> fromVariableElementToMethodParameter(i, params.get(i)))
|
.mapToObj(
|
||||||
|
i ->
|
||||||
|
fromVariableElementToMethodParameter(
|
||||||
|
processingEnv, i, params.get(i)))
|
||||||
.collect(Collectors.toList()),
|
.collect(Collectors.toList()),
|
||||||
wrapExceptions(processingEnv, method));
|
wrapExceptions(processingEnv, method));
|
||||||
});
|
});
|
||||||
@ -132,14 +142,17 @@ public final class SpecializedMethodsGenerator extends MethodGenerator {
|
|||||||
return p.tpe().equals("java.lang.Object") || p.tpe().equals("java.lang.String");
|
return p.tpe().equals("java.lang.Object") || p.tpe().equals("java.lang.String");
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpecializationMeta inferExecuteParameters() {
|
private SpecializationMeta inferExecuteParameters(ProcessingEnvironment processingEnv) {
|
||||||
Map<Integer, List<MethodParameter>> paramss =
|
Map<Integer, List<MethodParameter>> paramss =
|
||||||
elements.stream()
|
elements.stream()
|
||||||
.flatMap(
|
.flatMap(
|
||||||
method -> {
|
method -> {
|
||||||
List<? extends VariableElement> params = method.getParameters();
|
List<? extends VariableElement> params = method.getParameters();
|
||||||
return IntStream.range(0, params.size())
|
return IntStream.range(0, params.size())
|
||||||
.mapToObj(i -> fromVariableElementToMethodParameter(i, params.get(i)));
|
.mapToObj(
|
||||||
|
i ->
|
||||||
|
fromVariableElementToMethodParameter(
|
||||||
|
processingEnv, i, params.get(i)));
|
||||||
})
|
})
|
||||||
.collect(Collectors.groupingBy(p -> p.index()));
|
.collect(Collectors.groupingBy(p -> p.index()));
|
||||||
|
|
||||||
@ -268,7 +281,24 @@ public final class SpecializedMethodsGenerator extends MethodGenerator {
|
|||||||
" return new Array((Object[]) " + qual + "." + name + "(" + paramsApplied + "));");
|
" return new Array((Object[]) " + qual + "." + name + "(" + paramsApplied + "));");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
methodBody.add(" return " + qual + "." + name + "(" + paramsApplied + ");");
|
if (returnTpe.isValidGuestType()) {
|
||||||
|
methodBody.add(" return " + qual + "." + name + "(" + paramsApplied + ");");
|
||||||
|
} else if (convertToGuestValue) {
|
||||||
|
methodBody.add(" var result = " + qual + "." + name + "(" + paramsApplied + ");");
|
||||||
|
methodBody.add(" return EnsoContext.get(this).getEnvironment().asGuestValue(result);");
|
||||||
|
} else {
|
||||||
|
processingEnvironment
|
||||||
|
.getMessager()
|
||||||
|
.printMessage(
|
||||||
|
Diagnostic.Kind.ERROR,
|
||||||
|
"Cannot convert return type of "
|
||||||
|
+ owner
|
||||||
|
+ "."
|
||||||
|
+ name
|
||||||
|
+ " to guest value."
|
||||||
|
+ " Specify @ReturningGuestValue annotation",
|
||||||
|
methodInfo.origin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user