# HG changeset patch # User Christos Kotselidis # Date 1377864479 -7200 # Node ID 1cd98fee213964d1586994da2b46195699fc087a # Parent c121402a62d8419fbc4be600d349e65597733101# Parent 1ccb36a32f87ef45e37032e858a93eae364d5cd5 Merge diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java Fri Aug 30 14:07:59 2013 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; + +public class CompilerErrorTest { + + abstract static class Visiblity01 extends ValueNode { + + @Specialization + @SuppressWarnings("static-method") + @ExpectError("Method annotated with @Specialization must not be private.") + private Object s() { + return null; + } + + } + + @ExpectError("Classes containing a @Specialization annotation must not be private.") + private abstract static class Visiblity02 extends ValueNode { + + @Specialization + public Object s() { + return null; + } + + } + + // assert no error + @ExpectError({}) + private abstract static class Visiblity03 extends ValueNode { + + } + +} diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java Fri Aug 30 14:07:59 2013 +0200 @@ -26,10 +26,12 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug1Factory; import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestGroupingFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.SimpleTypes; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; +import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; /** @@ -154,6 +156,50 @@ } + @Test + public void testElseConnectionBug1() { + CallTarget target = TestHelper.createCallTarget(TestElseConnectionBug1Factory.create(new GenericInt())); + Assert.assertEquals(42, target.call()); + } + + @SuppressWarnings("unused") + @NodeChild(value = "genericChild", type = GenericInt.class) + public abstract static class TestElseConnectionBug1 extends ValueNode { + + @Specialization(order = 1, rewriteOn = {SlowPathException.class}, guards = "isInitialized") + public int doInteger(int value) throws SlowPathException { + throw new SlowPathException(); + } + + @Specialization(order = 3, guards = "isInitialized") + public int doObject(int value) { + return value == 42 ? value : 0; + } + + @Specialization(order = 4, guards = "!isInitialized") + public Object doUninitialized(int value) { + throw new AssertionError(); + } + + boolean isInitialized(int value) { + return true; + } + } + + public static final class GenericInt extends ValueNode { + + @Override + public Object execute(VirtualFrame frame) { + return executeInt(frame); + } + + @Override + public int executeInt(VirtualFrame frame) { + return 42; + } + + } + private static class MockAssumption implements Assumption { int checked; diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java Fri Aug 30 14:07:59 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.api.dsl.test; +import static org.junit.Assert.*; + import java.util.*; import com.oracle.truffle.api.*; @@ -75,4 +77,69 @@ return createCallTarget(node).call(new TestArguments(values)); } + static Object array(Object... val) { + return val; + } + + static List> permutations(List list) { + return permutations(new ArrayList(), list, new ArrayList>()); + } + + static Object[][] permutations(Object... list) { + List> permutations = permutations(Arrays.asList(list)); + + Object[][] a = new Object[permutations.size()][]; + int index = 0; + for (List p : permutations) { + a[index] = p.toArray(new Object[p.size()]); + index++; + } + + return a; + } + + static List> permutations(List prefix, List suffix, List> output) { + if (suffix.size() == 1) { + ArrayList newElement = new ArrayList<>(prefix); + newElement.addAll(suffix); + output.add(newElement); + return output; + } + + for (int i = 0; i < suffix.size(); i++) { + List newPrefix = new ArrayList<>(prefix); + newPrefix.add(suffix.get(i)); + List newSuffix = new ArrayList<>(suffix); + newSuffix.remove(i); + permutations(newPrefix, newSuffix, output); + } + + return output; + } + + /* Methods tests all test values in combinational order. */ + static void assertRuns(NodeFactory factory, Object result, Object... testValues) { + // test each run by its own. + for (int i = 0; i < testValues.length; i++) { + assertValue(createRoot(factory), result, testValues); + } + + // test all combinations of the test values + List> permuts = permutations(Arrays.asList(testValues)); + for (List list : permuts) { + TestRootNode root = createRoot(factory); + for (Object object : list) { + assertValue(root, result, object); + } + } + } + + static void assertValue(TestRootNode root, Object result, Object testValues) { + if (testValues instanceof Object[]) { + assertEquals(result, executeWith(root, (Object[]) testValues)); + } else { + assertEquals(result, executeWith(root, testValues)); + } + } + } diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java Fri Aug 30 14:07:59 2013 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl.test; + +import com.oracle.truffle.api.dsl.*; + +public class TypeSystemErrorsTest { + + @TypeSystem({int.class, boolean.class}) + public static class Types0 { + + } + + @ExpectError("Invalid type order. The type(s) [java.lang.String] are inherited from a earlier defined type java.lang.CharSequence.") + @TypeSystem({CharSequence.class, String.class}) + public static class Types1 { + + } + + @TypeSystem({int.class, boolean.class}) + public static class Types2 { + + @TypeCast + @ExpectError("The provided return type \"String\" does not match expected return type \"int\".%") + String asInteger(Object value) { + return (String) value; + } + + } + + @TypeSystem({int.class, boolean.class}) + public static class Types3 { + + @TypeCast + @ExpectError("The provided return type \"boolean\" does not match expected return type \"int\".%") + boolean asInteger(Object value) { + return (boolean) value; + } + + } + +} diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ExpectError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ExpectError.java Fri Aug 30 14:07:59 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +/** + * This annotation is internally known by the dsl processor and used to expect errors for testing + * purposes. This is not part of public API. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ExpectError { + + String[] value(); + +} diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImplicitCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImplicitCast.java Fri Aug 30 14:07:59 2013 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.dsl; + +import java.lang.annotation.*; + +/** + * EXPERIMENTAL Filter feature. May change or disappear without notice. This feature is not + * functional yet. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface ImplicitCast { + +} diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AbstractParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -65,7 +65,7 @@ return null; } - model.emitMessages((TypeElement) element, log); + model.emitMessages(context, (TypeElement) element, log); return filterErrorElements(model); } catch (CompileErrorException e) { log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage()); diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Fri Aug 30 14:07:59 2013 +0200 @@ -30,6 +30,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; @@ -56,6 +57,7 @@ private final TypeMirror compilerAsserts; private final DeclaredType slowPath; private final DeclaredType truffleOptions; + private final TypeElement expectError; private final List errors = new ArrayList<>(); @@ -74,6 +76,11 @@ nodeInfoKind = getRequired(context, NodeInfo.Kind.class); slowPath = getRequired(context, SlowPath.class); truffleOptions = getRequired(context, TruffleOptions.class); + expectError = (TypeElement) getRequired(context, ExpectError.class).asElement(); + } + + public TypeElement getExpectError() { + return expectError; } public DeclaredType getNodeInfoAnnotation() { diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Utils.java Fri Aug 30 14:07:59 2013 +0200 @@ -423,6 +423,8 @@ return getSimpleName(mirror); case ERROR: throw new CompileErrorException("Type error " + mirror); + case EXECUTABLE: + return ((ExecutableType) mirror).toString(); case NONE: return "$none"; default: @@ -755,6 +757,10 @@ public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List mirrors, Class annotationClass) { TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); + return findAnnotationMirror(mirrors, expectedAnnotationType); + } + + public static AnnotationMirror findAnnotationMirror(List mirrors, TypeElement expectedAnnotationType) { for (AnnotationMirror mirror : mirrors) { DeclaredType annotationType = mirror.getAnnotationType(); TypeElement actualAnnotationType = (TypeElement) annotationType.asElement(); diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -61,7 +61,7 @@ } @Override - public CreateCastData create(TemplateMethod method) { + public CreateCastData create(TemplateMethod method, boolean invalid) { AnnotationMirror mirror = method.getMarkerAnnotation(); List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); CreateCastData cast = new CreateCastData(method, childNames); diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -83,7 +83,7 @@ } @Override - public ExecutableTypeData create(TemplateMethod method) { + public ExecutableTypeData create(TemplateMethod method, boolean invalid) { TypeData resolvedType = method.getReturnType().getTypeSystemType(); return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType); } diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -61,7 +61,7 @@ } @Override - public SpecializationData create(TemplateMethod method) { + public SpecializationData create(TemplateMethod method, boolean invalid) { SpecializationData data = new SpecializationData(method, true, false, false); return data; } diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -85,10 +85,14 @@ return methodSpec; } - private void addDefaultChildren(boolean shortCircuitsEnabled, String shortCircuitName, MethodSpec methodSpec) { + public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec methodSpec) { // children are null when parsing executable types if (getNode().getChildren() != null) { for (NodeChildData child : getNode().getChildren()) { + String valueName = child.getName(); + if (breakName != null && valueName.equals(breakName)) { + break; + } if (child.getExecutionKind() == ExecutionKind.DEFAULT) { ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size()); if (child.getCardinality().isMany()) { @@ -97,10 +101,6 @@ } methodSpec.addRequired(spec); } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { - String valueName = child.getName(); - if (shortCircuitName != null && valueName.equals(shortCircuitName)) { - break; - } if (shortCircuitsEnabled) { methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class))); diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -199,6 +199,10 @@ } for (NodeData splittedNode : nodes) { + if (templateType.getModifiers().contains(Modifier.PRIVATE) && splittedNode.getSpecializations().size() > 0) { + splittedNode.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName()); + } + finalizeSpecializations(elements, splittedNode); verifyNode(splittedNode, elements); createPolymorphicSpecializations(splittedNode); diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -58,7 +58,7 @@ } @Override - public ShortCircuitData create(TemplateMethod method) { + public ShortCircuitData create(TemplateMethod method, boolean invalid) { String shortCircuitValue = Utils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value"); if (!shortCircuitValues.contains(shortCircuitValue)) { diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java Fri Aug 30 14:07:59 2013 +0200 @@ -41,12 +41,14 @@ private final List typeGuards; private final List guards; + private final NodeData node; private final SpecializationData specialization; private final List children = new ArrayList<>(); private SpecializationGroup parent; private SpecializationGroup(SpecializationData data) { + this.node = data.getNode(); this.assumptions = new ArrayList<>(); this.typeGuards = new ArrayList<>(); this.guards = new ArrayList<>(); @@ -61,9 +63,11 @@ } public SpecializationGroup(List children, List assumptionMatches, List typeGuardsMatches, List guardMatches) { + assert !children.isEmpty() : "children must not be empty"; this.assumptions = assumptionMatches; this.typeGuards = typeGuardsMatches; this.guards = guardMatches; + this.node = children.get(0).node; this.specialization = null; updateChildren(children); } @@ -114,8 +118,7 @@ return null; } GuardData previousGuard = previous.getGuards().get(elseConnectedGuards.size()); - if (guard.getMethod().equals(previousGuard.getMethod())) { - assert guard.isNegated() != previousGuard.isNegated(); + if (guard.getMethod().equals(previousGuard.getMethod()) && guard.isNegated() != previousGuard.isNegated()) { return guard; } } @@ -205,16 +208,29 @@ for (Iterator iterator = guardMatches.iterator(); iterator.hasNext();) { GuardData guardMatch = iterator.next(); - List guardTypes = TemplateMethod.getSignatureTypes(guardMatch.getParameters()); - for (int i = 0; i < guardTypes.size(); i++) { - TypeMirror guardType = guardTypes.get(i); - int signatureIndex = i + 1; + int signatureIndex = 0; + for (ActualParameter parameter : guardMatch.getParameters()) { + signatureIndex++; + if (parameter.getSpecification().isSignature()) { + continue; + } + + TypeMirror guardType = parameter.getType(); // object guards can be safely moved up if (Utils.isObject(guardType)) { continue; } + // generic guards can be safely moved up + SpecializationData generic = first.node.getGenericSpecialization(); + if (generic != null) { + ActualParameter genericParameter = generic.findParameter(parameter.getLocalName()); + if (genericParameter != null && Utils.typeEquals(genericParameter.getType(), guardType)) { + continue; + } + } + // signature index required for moving up guards if (containsIndex(typeGuardsMatches, signatureIndex) || (first.getParent() != null && first.getParent().containsTypeGuardIndex(signatureIndex))) { continue; diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationListenerParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -47,7 +47,7 @@ } @Override - public SpecializationListenerData create(TemplateMethod method) { + public SpecializationListenerData create(TemplateMethod method, boolean invalid) { return new SpecializationListenerData(method); } diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationMethodParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -44,7 +44,7 @@ } @Override - public SpecializationData create(TemplateMethod method) { + public SpecializationData create(TemplateMethod method, boolean invalid) { return parseSpecialization(method); } @@ -57,7 +57,6 @@ int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order"); if (order < 0 && order != Specialization.DEFAULT_ORDER) { method.addError("Invalid order attribute %d. The value must be >= 0 or the default value."); - return null; } AnnotationValue rewriteValue = Utils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn"); diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java Fri Aug 30 14:07:59 2013 +0200 @@ -51,13 +51,21 @@ public abstract Element getMessageElement(); - public final void emitMessages(TypeElement baseElement, Log log) { - emitMessagesImpl(baseElement, log, new HashSet()); + public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) { + emitMessagesImpl(context, baseElement, log, new HashSet(), null); } - private void emitMessagesImpl(TypeElement baseElement, Log log, Set visitedSinks) { + private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set visitedSinks, List verifiedMessages) { + List childMessages; + if (verifiedMessages == null) { + childMessages = collectMessagesWithElementChildren(new HashSet(), getMessageElement()); + } else { + childMessages = verifiedMessages; + } + verifyExpectedMessages(context, log, childMessages); + for (Message message : getMessages()) { - emitDefault(baseElement, log, message); + emitDefault(context, baseElement, log, message); } for (MessageContainer sink : findChildContainers()) { @@ -66,18 +74,95 @@ } visitedSinks.add(sink); - sink.emitMessagesImpl(baseElement, log, visitedSinks); + if (sink.getMessageElement() == this.getMessageElement()) { + sink.emitMessagesImpl(context, baseElement, log, visitedSinks, childMessages); + } else { + sink.emitMessagesImpl(context, baseElement, log, visitedSinks, null); + } + } + } + + private List collectMessagesWithElementChildren(Set visitedSinks, Element e) { + if (visitedSinks.contains(this)) { + return Collections.emptyList(); + } + visitedSinks.add(this); + + List foundMessages = new ArrayList<>(); + if (Utils.typeEquals(getMessageElement().asType(), e.asType())) { + foundMessages.addAll(getMessages()); + } + for (MessageContainer sink : findChildContainers()) { + foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e)); + } + return foundMessages; + } + + private void verifyExpectedMessages(ProcessorContext context, Log log, List msgs) { + TypeElement expectError = context.getTruffleTypes().getExpectError(); + if (expectError != null) { + Element element = getMessageElement(); + AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError); + if (mirror != null) { + List values = Utils.getAnnotationValueList(String.class, mirror, "value"); + if (values == null) { + values = Collections.emptyList(); + } + if (values.size() != msgs.size()) { + log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size())); + } + } } } - private void emitDefault(TypeElement baseType, Log log, Message message) { + private void emitDefault(ProcessorContext context, TypeElement baseType, Log log, Message message) { + Kind kind = message.getKind(); + + Element messageElement = getMessageElement(); + AnnotationMirror messageAnnotation = getMessageAnnotation(); + AnnotationValue messageValue = getMessageAnnotationValue(); + if (message.getAnnotationValue() != null) { + messageValue = message.getAnnotationValue(); + } + + String text = message.getText(); + TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement()); - if (rootEnclosing != null && Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) && this == message.getOriginalContainer()) { - log.message(message.getKind(), getMessageElement(), getMessageAnnotation(), getMessageAnnotationValue(), message.getText()); - } else { + TypeElement baseEnclosing = Utils.findRootEnclosingType(baseType); + if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType()) || this != message.getOriginalContainer()) { + // redirect message MessageContainer original = message.getOriginalContainer(); - log.message(message.getKind(), baseType, null, null, wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText())); + messageElement = baseType; + messageAnnotation = null; + messageValue = null; + text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText()); } + + TypeElement expectError = context.getTruffleTypes().getExpectError(); + if (expectError != null) { + AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError); + if (mirror != null) { + List expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value"); + boolean found = false; + for (String expectedText : expectedTexts) { + if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) { + found = true; + break; + } else if (text.equals(expectedText)) { + found = true; + break; + } + } + if (!found) { + log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text); + } else { + return; + } + + } + } + + log.message(kind, messageElement, messageAnnotation, messageValue, text); } private static String wrapText(Element element, AnnotationMirror mirror, String text) { diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -43,7 +43,7 @@ protected final T template; private boolean emitErrors = true; - private boolean parseNullOnError = true; + private boolean parseNullOnError = false; public TemplateMethodParser(ProcessorContext context, T template) { this.template = template; @@ -76,7 +76,7 @@ public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror); - public abstract E create(TemplateMethod method); + public abstract E create(TemplateMethod method, boolean invalid); public abstract boolean isParsable(ExecutableElement method); @@ -104,7 +104,8 @@ E parsedMethod = parse(method, mirror); if (method.getModifiers().contains(Modifier.PRIVATE) && emitErrors) { - parsedMethod.addError("Method must not be private."); + parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName()); + parsedMethods.add(parsedMethod); valid = false; continue; } @@ -142,7 +143,7 @@ ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false); if (returnTypeMirror == null) { if (emitErrors) { - E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); String expectedReturnType = returnTypeSpec.toSignatureString(true); String actualReturnType = Utils.getSimpleName(method.getReturnType()); @@ -163,7 +164,7 @@ List parameters = parseParameters(methodSpecification, parameterTypes); if (parameters == null) { if (isEmitErrors()) { - E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList())); + E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections. emptyList()), true); String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method), methodSpecification.toSignatureString(method.getSimpleName().toString())); invalidMethod.addError(message); @@ -173,7 +174,7 @@ } } - return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters)); + return create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false); } private static String createActualSignature(MethodSpec spec, ExecutableElement method) { diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -79,7 +79,7 @@ } @Override - public GuardData create(TemplateMethod method) { + public GuardData create(TemplateMethod method, boolean invalid) { GuardData guard = new GuardData(method, specialization, negated); /* * Update parameters in way that parameter specifications match again the node field names diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastData.java Fri Aug 30 14:07:59 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.typesystem; + +import com.oracle.truffle.dsl.processor.template.*; + +public class ImplicitCastData extends TemplateMethod { + + public ImplicitCastData(TemplateMethod method) { + super(method); + } + +} diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.typesystem; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.template.*; + +public class ImplicitCastParser extends TypeSystemMethodParser { + + public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) { + super(context, typeSystem); + } + + @Override + public Class getAnnotationType() { + return ImplicitCast.class; + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + List types = new ArrayList<>(); + for (TypeData typeData : getTypeSystem().getTypes()) { + types.add(typeData.getPrimitiveType()); + } + MethodSpec spec = new MethodSpec(new ParameterSpec("target", types)); + spec.addRequired(new ParameterSpec("source", types)).setSignature(true); + return spec; + } + + @Override + public ImplicitCastData create(TemplateMethod method, boolean invalid) { + return new ImplicitCastData(method); + } + +} diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCastParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -48,10 +48,25 @@ } @Override - public TypeCastData create(TemplateMethod method) { + public TypeCastData create(TemplateMethod method, boolean invalid) { + if (invalid) { + return new TypeCastData(method, null, null); + } + TypeData targetType = findTypeByMethodName(method, "as"); ActualParameter parameter = method.findParameter("valueValue"); - return new TypeCastData(method, parameter.getTypeSystemType(), targetType); + + TypeData sourceType = null; + if (parameter != null) { + sourceType = getTypeSystem().findTypeData(parameter.getType()); + } + TypeCastData cast = new TypeCastData(method, sourceType, targetType); + + if (targetType != method.getReturnType().getTypeSystemType()) { + cast.addError("Cast type %s does not match to the returned type %s.", Utils.getSimpleName(targetType.getPrimitiveType()), + method.getReturnType() != null ? Utils.getSimpleName(method.getReturnType().getTypeSystemType().getPrimitiveType()) : null); + } + return cast; } @Override diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeCheckParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -48,7 +48,7 @@ } @Override - public TypeCheckData create(TemplateMethod method) { + public TypeCheckData create(TemplateMethod method, boolean invalid) { TypeData checkedType = findTypeByMethodName(method, "is"); assert checkedType != null; ActualParameter parameter = method.findParameter("valueValue"); diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemData.java Fri Aug 30 14:07:59 2013 +0200 @@ -36,6 +36,9 @@ private List primitiveTypeMirrors = new ArrayList<>(); private List boxedTypeMirrors = new ArrayList<>(); + private List casts; + private List checks; + private TypeMirror genericType; private TypeData voidType; @@ -58,6 +61,14 @@ } } + public void setCasts(List casts) { + this.casts = casts; + } + + public void setChecks(List checks) { + this.checks = checks; + } + void setGenericType(TypeMirror genericType) { this.genericType = genericType; } @@ -72,6 +83,12 @@ if (types != null) { sinks.addAll(types); } + if (checks != null) { + sinks.addAll(checks); + } + if (casts != null) { + sinks.addAll(casts); + } return sinks; } diff -r c121402a62d8 -r 1cd98fee2139 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Fri Aug 30 13:56:58 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Fri Aug 30 14:07:59 2013 +0200 @@ -37,7 +37,7 @@ public class TypeSystemParser extends TemplateParser { - public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class); + public static final List> ANNOTATIONS = Arrays.asList(TypeSystem.class, ExpectError.class); public TypeSystemParser(ProcessorContext c) { super(c); @@ -84,11 +84,17 @@ verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class); List elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType)); - + List implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements); List casts = new TypeCastParser(context, typeSystem).parse(elements); List checks = new TypeCheckParser(context, typeSystem).parse(elements); - if (casts == null || checks == null) { + if (casts == null || checks == null || implicitCasts == null) { + return typeSystem; + } + typeSystem.setCasts(casts); + typeSystem.setChecks(checks); + + if (typeSystem.hasErrors()) { return typeSystem; }