Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi value casts tests and robustness changes #11525

Draft
wants to merge 8 commits into
base: develop
Choose a base branch
from

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,27 @@
public final class ReadArgumentNode extends ExpressionNode {
private final int index;
@Child ExpressionNode defaultValue;
@Child ReadArgumentCheckNode checkType;
private final CountingConditionProfile defaultingProfile = CountingConditionProfile.create();

private ReadArgumentNode(int position, ExpressionNode defaultValue, ReadArgumentCheckNode check) {
private ReadArgumentNode(int position, ExpressionNode defaultValue) {
this.index = position;
this.defaultValue = defaultValue;
this.checkType = check;
}

/**
* Creates an instance of this node.
*
* @param position the argument's position at the definition site
* @param defaultValue the default value provided for that argument
* @param check {@code null} or node to check type of input
* @return a node representing the argument at position {@code idx}
*/
public static ReadArgumentNode build(
int position, ExpressionNode defaultValue, ReadArgumentCheckNode check) {
return new ReadArgumentNode(position, defaultValue, check);
public static ReadArgumentNode build(int position, ExpressionNode defaultValue) {
return new ReadArgumentNode(position, defaultValue);
}

ReadArgumentNode plainRead() {
/** Copies the read argument node. Removes all type checks associated with it. */
public final ReadArgumentNode copyWithoutCheck() {
var node = (ReadArgumentNode) this.copy();
node.checkType = null;
return node;
}

Expand Down Expand Up @@ -68,9 +64,6 @@ public Object executeGeneric(VirtualFrame frame) {
v = arguments[index];
}
}
if (checkType != null) {
v = checkType.handleCheckOrConversion(frame, v);
}
return v;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.enso.interpreter.node.typecheck;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import java.util.Arrays;
import java.util.stream.Collectors;
import org.enso.interpreter.node.ExpressionNode;
import org.enso.interpreter.runtime.data.EnsoMultiValue;
import org.enso.interpreter.runtime.data.Type;
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;

final class AllOfNode extends TypeCheckValueNode {

@Children private TypeCheckValueNode[] checks;
@Child private TypesLibrary types;

AllOfNode(String name, TypeCheckValueNode[] checks) {
super(name);
this.checks = checks;
this.types = TypesLibrary.getFactory().createDispatched(checks.length);
}

TypeCheckValueNode[] getChecks() {
return checks;
}

@Override
Object findDirectMatch(VirtualFrame frame, Object value) {
return null;
}

@Override
@ExplodeLoop
Object executeCheckOrConversion(VirtualFrame frame, Object value, ExpressionNode expr) {
var values = new Object[checks.length];
var valueTypes = new Type[checks.length];
var at = 0;
for (var n : checks) {
var result = n.executeCheckOrConversion(frame, value, expr);
if (result == null) {
return null;
}
values[at] = result;
valueTypes[at] = types.getType(result);
at++;
}
return EnsoMultiValue.create(valueTypes, values);
}

@Override
String expectedTypeMessage() {
var parts =
Arrays.stream(checks)
.map(TypeCheckValueNode::expectedTypeMessage)
.collect(Collectors.toList());
return joinTypeParts(parts, "&");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.enso.interpreter.node.typecheck;

import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
import org.enso.interpreter.node.BaseNode;
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.callable.function.FunctionSchema;

final class LazyCheckRootNode extends RootNode {

@Child private ThunkExecutorNode evalThunk;
@Child private TypeCheckValueNode check;
static final FunctionSchema SCHEMA =
FunctionSchema.newBuilder()
.argumentDefinitions(
new ArgumentDefinition(
0, "delegate", null, null, ArgumentDefinition.ExecutionMode.EXECUTE))
.hasPreapplied(true)
.build();

LazyCheckRootNode(TruffleLanguage<?> language, TypeCheckValueNode check) {
super(language);
this.check = check;
this.evalThunk = ThunkExecutorNode.build();
}

Function wrapThunk(Function thunk) {
return new Function(getCallTarget(), thunk.getScope(), SCHEMA, new Object[] {thunk}, null);
}

@Override
public Object execute(VirtualFrame frame) {
org.enso.interpreter.runtime.state.State state =
Function.ArgumentsHelper.getState(frame.getArguments());
java.lang.Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
assert args.length == 1;
assert args[0] instanceof Function fn && fn.isThunk();
java.lang.Object raw =
evalThunk.executeThunk(frame, args[0], state, BaseNode.TailStatus.NOT_TAIL);
java.lang.Object result = check.handleCheckOrConversion(frame, raw, null);
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.enso.interpreter.node.typecheck;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import org.enso.interpreter.node.expression.builtin.meta.IsValueOfTypeNode;
import org.enso.interpreter.runtime.util.CachingSupplier;

abstract class MetaCheckNode extends TypeCheckValueNode {

private final CachingSupplier<? extends Object> expectedSupplier;
@CompilerDirectives.CompilationFinal private String expectedTypeMessage;

MetaCheckNode(String name, CachingSupplier<? extends Object> expectedMetaSupplier) {
super(name);
this.expectedSupplier = expectedMetaSupplier;
}

abstract Object executeCheckOrConversion(VirtualFrame frame, Object value);

@Override
Object findDirectMatch(VirtualFrame frame, Object value) {
return executeCheckOrConversion(frame, value);
}

@Specialization
Object verifyMetaObject(VirtualFrame frame, Object v, @Cached IsValueOfTypeNode isA) {
if (isAllFitValue(v)) {
return v;
}
if (isA.execute(expectedSupplier.get(), v)) {
return v;
} else {
return null;
}
}

@Override
String expectedTypeMessage() {
if (expectedTypeMessage != null) {
return expectedTypeMessage;
}
CompilerDirectives.transferToInterpreterAndInvalidate();
com.oracle.truffle.api.interop.InteropLibrary iop = InteropLibrary.getUncached();
try {
expectedTypeMessage = iop.asString(iop.getMetaQualifiedName(expectedSupplier.get()));
} catch (UnsupportedMessageException ex) {
expectedTypeMessage = expectedSupplier.get().toString();
}
return expectedTypeMessage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.enso.interpreter.node.typecheck;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import java.util.Arrays;
import java.util.stream.Collectors;
import org.enso.interpreter.node.ExpressionNode;

final class OneOfNode extends TypeCheckValueNode {

@Children private TypeCheckValueNode[] checks;

OneOfNode(String name, TypeCheckValueNode[] checks) {
super(name);
this.checks = checks;
}

@Override
@ExplodeLoop
final Object findDirectMatch(VirtualFrame frame, Object value) {
for (org.enso.interpreter.node.typecheck.TypeCheckValueNode n : checks) {
java.lang.Object result = n.findDirectMatch(frame, value);
if (result != null) {
return result;
}
}
return null;
}

@Override
@ExplodeLoop
Object executeCheckOrConversion(VirtualFrame frame, Object value, ExpressionNode expr) {
java.lang.Object direct = findDirectMatch(frame, value);
if (direct != null) {
return direct;
}
for (org.enso.interpreter.node.typecheck.TypeCheckValueNode n : checks) {
java.lang.Object result = n.executeCheckOrConversion(frame, value, expr);
if (result != null) {
return result;
}
}
return null;
}

@Override
String expectedTypeMessage() {
java.util.List<java.lang.String> parts =
Arrays.stream(checks)
.map(TypeCheckValueNode::expectedTypeMessage)
.collect(Collectors.toList());
return joinTypeParts(parts, "|");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.enso.interpreter.node.typecheck;

import com.oracle.truffle.api.frame.VirtualFrame;
import org.enso.interpreter.node.ExpressionNode;

final class TypeCheckExpressionNode extends ExpressionNode {

@Child private ExpressionNode original;
@Child private TypeCheckValueNode check;

TypeCheckExpressionNode(ExpressionNode original, TypeCheckValueNode check) {
this.check = check;
this.original = original;
}

ExpressionNode getOriginal() {
return original;
}

@Override
public Object executeGeneric(VirtualFrame frame) {
java.lang.Object value = original.executeGeneric(frame);
java.lang.Object result = check.handleCheckOrConversion(frame, value, original);
return result;
}

@Override
public boolean isInstrumentable() {
return false;
}
}
Loading
Loading