# HG changeset patch
# User Christian Humer
# Date 1372414791 -7200
# Node ID 3cc5fb59916ebaaa592ebb84dba1b9611c83eaaa
# Parent 6eb8d63cea347fac2fa18a5df26897c741dbc654
Truffle-DSL: Renamed @NodeClass to @NodeContainer. splitByMethodName is not an option anymore and is always enabled if a @NodeContainer is used.
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java Wed Jun 26 17:21:59 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * 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.codegen.test;
-
-import static com.oracle.truffle.api.codegen.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrAccessContextFactory;
-import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrConcatFactory;
-import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrLengthFactory;
-import com.oracle.truffle.api.codegen.test.BuiltinTestFactory.StrFactory.StrSubstrFactory;
-import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode;
-
-public class BuiltinTest {
-
- @Test
- public void testConcat() {
- TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context());
- Str str1 = new Str("42");
- Str str2 = new Str(" is the number.");
- assertEquals(str1.concat(str2), executeWith(node, str1, str2));
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testConcatUnsupported() {
- TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context());
- executeWith(node, 42, new Str(" is the number."));
- }
-
- @Test
- public void testSubstrSpecialized() {
- TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context());
- Str str = new Str("test 42");
-
- assertEquals(str.substr(5, 7), executeWith(node, str, 5, 7));
- }
-
- @Test
- public void testSubstrGeneric() {
- TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context());
- Str str = new Str("test 42");
-
- assertEquals(Str.substr(str, "5", "7"), executeWith(node, str, "5", "7"));
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testSubstrUnsupported() {
- TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context());
- executeWith(node, new Object(), "5", "7");
- }
-
- @Test
- public void testLength() {
- TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context());
- Str testStr = new Str("test 42");
- assertEquals(testStr.length(), executeWith(node, testStr));
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testLengthUnsupported() {
- TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context());
- executeWith(node, new Object());
- }
-
- @Test
- public void testAccessContext() {
- Context context = new Context();
- TestRootNode node = createRoot(StrAccessContextFactory.getInstance(), context);
- // accessible by node
- assertSame(context, node.getNode().getContext());
- // accessible by execution
- assertSame(context, executeWith(node));
- }
-
- @NodeClass(value = BuiltinNode.class, splitByMethodName = true)
- static class Str {
-
- private final String internal;
-
- public Str(String internal) {
- this.internal = internal;
- }
-
- @Specialization
- Str concat(Str s1) {
- return new Str(internal + s1.internal);
- }
-
- @Specialization
- Str substr(int beginIndex, int endIndex) {
- return new Str(internal.substring(beginIndex, endIndex));
- }
-
- @Generic
- static Str substr(Object thisValue, Object beginIndex, Object endIndex) {
- if (!(thisValue instanceof Str)) {
- throw new UnsupportedOperationException();
- }
- return ((Str) thisValue).substr(convertInt(beginIndex), convertInt(endIndex));
- }
-
- @Specialization
- int length() {
- return internal.length();
- }
-
- @Specialization
- static Object accessContext(Context context) {
- return context;
- }
-
- static int convertInt(Object value) {
- if (value instanceof Number) {
- return ((Number) value).intValue();
- } else if (value instanceof String) {
- return Integer.parseInt((String) value);
- }
- throw new RuntimeException("Invalid datatype");
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof Str) {
- return internal.equals(((Str) obj).internal);
- }
- return super.equals(obj);
- }
-
- @Override
- public String toString() {
- return internal;
- }
-
- @Override
- public int hashCode() {
- return internal.hashCode();
- }
- }
-
- @NodeChild(value = "children", type = ValueNode[].class)
- abstract static class BuiltinNode extends ValueNode {
-
- protected final Context context;
-
- public BuiltinNode(BuiltinNode node) {
- this(node.context);
- }
-
- public BuiltinNode(Context context) {
- this.context = context;
- }
-
- public Context getContext() {
- return context;
- }
- }
-
- static class Context {
-
- }
-
-}
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/NodeContainerTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/NodeContainerTest.java Fri Jun 28 12:19:51 2013 +0200
@@ -0,0 +1,186 @@
+/*
+ * 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.codegen.test;
+
+import static com.oracle.truffle.api.codegen.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrAccessContextFactory;
+import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrConcatFactory;
+import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrLengthFactory;
+import com.oracle.truffle.api.codegen.test.NodeContainerTestFactory.StrFactory.StrSubstrFactory;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode;
+
+public class NodeContainerTest {
+
+ @Test
+ public void testConcat() {
+ TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context());
+ Str str1 = new Str("42");
+ Str str2 = new Str(" is the number.");
+ assertEquals(str1.concat(str2), executeWith(node, str1, str2));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testConcatUnsupported() {
+ TestRootNode node = createRoot(StrConcatFactory.getInstance(), new Context());
+ executeWith(node, 42, new Str(" is the number."));
+ }
+
+ @Test
+ public void testSubstrSpecialized() {
+ TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context());
+ Str str = new Str("test 42");
+
+ assertEquals(str.substr(5, 7), executeWith(node, str, 5, 7));
+ }
+
+ @Test
+ public void testSubstrGeneric() {
+ TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context());
+ Str str = new Str("test 42");
+
+ assertEquals(Str.substr(str, "5", "7"), executeWith(node, str, "5", "7"));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testSubstrUnsupported() {
+ TestRootNode node = createRoot(StrSubstrFactory.getInstance(), new Context());
+ executeWith(node, new Object(), "5", "7");
+ }
+
+ @Test
+ public void testLength() {
+ TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context());
+ Str testStr = new Str("test 42");
+ assertEquals(testStr.length(), executeWith(node, testStr));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testLengthUnsupported() {
+ TestRootNode node = createRoot(StrLengthFactory.getInstance(), new Context());
+ executeWith(node, new Object());
+ }
+
+ @Test
+ public void testAccessContext() {
+ Context context = new Context();
+ TestRootNode node = createRoot(StrAccessContextFactory.getInstance(), context);
+ // accessible by node
+ assertSame(context, node.getNode().getContext());
+ // accessible by execution
+ assertSame(context, executeWith(node));
+ }
+
+ @NodeContainer(BuiltinNode.class)
+ static class Str {
+
+ private final String internal;
+
+ public Str(String internal) {
+ this.internal = internal;
+ }
+
+ @Specialization
+ Str concat(Str s1) {
+ return new Str(internal + s1.internal);
+ }
+
+ @Specialization
+ Str substr(int beginIndex, int endIndex) {
+ return new Str(internal.substring(beginIndex, endIndex));
+ }
+
+ @Generic
+ static Str substr(Object thisValue, Object beginIndex, Object endIndex) {
+ if (!(thisValue instanceof Str)) {
+ throw new UnsupportedOperationException();
+ }
+ return ((Str) thisValue).substr(convertInt(beginIndex), convertInt(endIndex));
+ }
+
+ @Specialization
+ int length() {
+ return internal.length();
+ }
+
+ @Specialization
+ static Object accessContext(Context context) {
+ return context;
+ }
+
+ static int convertInt(Object value) {
+ if (value instanceof Number) {
+ return ((Number) value).intValue();
+ } else if (value instanceof String) {
+ return Integer.parseInt((String) value);
+ }
+ throw new RuntimeException("Invalid datatype");
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Str) {
+ return internal.equals(((Str) obj).internal);
+ }
+ return super.equals(obj);
+ }
+
+ @Override
+ public String toString() {
+ return internal;
+ }
+
+ @Override
+ public int hashCode() {
+ return internal.hashCode();
+ }
+ }
+
+ @NodeChild(value = "children", type = ValueNode[].class)
+ abstract static class BuiltinNode extends ValueNode {
+
+ protected final Context context;
+
+ public BuiltinNode(BuiltinNode node) {
+ this(node.context);
+ }
+
+ public BuiltinNode(Context context) {
+ this.context = context;
+ }
+
+ public Context getContext() {
+ return context;
+ }
+ }
+
+ static class Context {
+
+ }
+
+}
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Wed Jun 26 17:21:59 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java Fri Jun 28 12:19:51 2013 +0200
@@ -26,7 +26,7 @@
import com.oracle.truffle.api.*;
import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.api.codegen.test.BuiltinTest.*;
+import com.oracle.truffle.api.codegen.test.NodeContainerTest.*;
import com.oracle.truffle.api.codegen.test.TypeSystemTest.*;
/**
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java Wed Jun 26 17:21:59 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/package-info.java Fri Jun 28 12:19:51 2013 +0200
@@ -41,7 +41,7 @@
*
*
* - What do I need to get started? {@link com.oracle.truffle.api.codegen.test.TypeSystemTest}
- * - How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.codegen.test.BuiltinTest}
+ * - How would you generate function nodes for runtime objects? {@link com.oracle.truffle.api.codegen.test.NodeContainerTest}
*
*
*
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java Wed Jun 26 17:21:59 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java Fri Jun 28 12:19:51 2013 +0200
@@ -36,7 +36,7 @@
String value() default "";
- Class> type() default NodeClass.InheritNode.class;
+ Class> type() default Node.class;
/**
* The {@link #executeWith()} property allows a node to pass the result of one child's
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeClass.java Wed Jun 26 17:21:59 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * 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.codegen;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface NodeClass {
-
- public static final class InheritNode extends Node {
- }
-
- Class extends Node> value() default InheritNode.class;
-
- boolean splitByMethodName() default false;
-
-}
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeContainer.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeContainer.java Fri Jun 28 12:19:51 2013 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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.codegen;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A node container can be used to enable Truffle-DSL in classes which do not extend {@link Node}.
+ * Compared to normal {@link Node} implementation the nodes are not identified by a class but by
+ * their method name. There are cases were method signatures are matching exactly but should be in
+ * the same {@link Node}. In this case use {@link NodeId} to disambiguate such cases.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface NodeContainer {
+
+ /** The node class to use as base class for {@link Node} definitions grouped by method names. */
+ Class extends Node> value();
+
+}
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Wed Jun 26 17:21:59 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Fri Jun 28 12:19:51 2013 +0200
@@ -37,7 +37,7 @@
private final String nodeId;
private NodeData declaringNode;
private List declaredNodes = new ArrayList<>();
- private boolean splitByMethodName;
+ private boolean nodeContainer;
private TypeSystemData typeSystem;
private List children;
@@ -91,8 +91,8 @@
return shortName;
}
- public boolean isSplitByMethodName() {
- return splitByMethodName;
+ public boolean isNodeContainer() {
+ return nodeContainer;
}
void setTypeSystem(TypeSystemData typeSystem) {
@@ -107,8 +107,8 @@
return fields;
}
- void setSplitByMethodName(boolean splitByMethodName) {
- this.splitByMethodName = splitByMethodName;
+ void setNodeContainer(boolean splitByMethodName) {
+ this.nodeContainer = splitByMethodName;
}
@Override
diff -r 6eb8d63cea34 -r 3cc5fb59916e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Wed Jun 26 17:21:59 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Fri Jun 28 12:19:51 2013 +0200
@@ -31,7 +31,6 @@
import javax.tools.Diagnostic.Kind;
import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.api.codegen.NodeClass.InheritNode;
import com.oracle.truffle.api.nodes.*;
import com.oracle.truffle.codegen.processor.*;
import com.oracle.truffle.codegen.processor.node.NodeChildData.Cardinality;
@@ -42,7 +41,7 @@
public class NodeParser extends TemplateParser {
public static final List> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
- NodeClass.class, NodeChild.class, NodeChildren.class, NodeId.class);
+ NodeContainer.class, NodeChild.class, NodeChildren.class, NodeId.class);
private Map parsedNodes;
@@ -90,6 +89,16 @@
return true;
}
+ @Override
+ public Class extends Annotation> getAnnotationType() {
+ return null;
+ }
+
+ @Override
+ public List> getTypeDelegatedAnnotationTypes() {
+ return ANNOTATIONS;
+ }
+
private NodeData resolveNode(TypeElement rootType) {
String typeName = Utils.getQualifiedName(rootType);
if (parsedNodes.containsKey(typeName)) {
@@ -133,7 +142,7 @@
List lookupTypes = findSuperClasses(new ArrayList(), templateType);
Collections.reverse(lookupTypes);
- AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class);
+ AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeContainer.class);
TypeMirror nodeType = null;
if (Utils.isAssignable(context, templateType.asType(), context.getTruffleTypes().getNode())) {
nodeType = templateType.asType();
@@ -152,9 +161,10 @@
}
}
- Set elementSet = new HashSet<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
+ Elements elementUtil = context.getEnvironment().getElementUtils();
+ Set elementSet = new HashSet<>(elementUtil.getAllMembers(templateType));
if (!Utils.typeEquals(templateType.asType(), nodeType)) {
- elementSet.addAll(context.getEnvironment().getElementUtils().getAllMembers(Utils.fromTypeMirror(nodeType)));
+ elementSet.addAll(elementUtil.getAllMembers(Utils.fromTypeMirror(nodeType)));
List nodeLookupTypes = findSuperClasses(new ArrayList(), Utils.fromTypeMirror(nodeType));
Collections.reverse(nodeLookupTypes);
@@ -186,7 +196,7 @@
List nodes;
- if (node.isSplitByMethodName()) {
+ if (node.isNodeContainer()) {
nodes = splitNodeData(node);
} else {
nodes = new ArrayList<>();
@@ -198,7 +208,7 @@
verifyNode(splittedNode, elements);
}
- if (node.isSplitByMethodName()) {
+ if (node.isNodeContainer()) {
node.setDeclaredNodes(nodes);
node.setSpecializationListeners(new ArrayList());
node.setSpecializations(new ArrayList());
@@ -208,6 +218,226 @@
}
}
+ private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List extends Element> elements, List lookupTypes) {
+ NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString());
+
+ AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class);
+ if (typeSystemMirror == null) {
+ nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType));
+ return nodeData;
+ }
+
+ TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
+ final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
+ if (typeSystem == null) {
+ nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType));
+ return nodeData;
+ }
+
+ List assumptionsList = new ArrayList<>();
+
+ for (int i = lookupTypes.size() - 1; i >= 0; i--) {
+ TypeElement type = lookupTypes.get(i);
+ AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
+ if (assumptions != null) {
+ List assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
+ for (String string : assumptionStrings) {
+ if (assumptionsList.contains(string)) {
+ assumptionsList.remove(string);
+ }
+ assumptionsList.add(string);
+ }
+ }
+ }
+ AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class);
+ if (nodeInfoMirror != null) {
+ nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
+ }
+
+ nodeData.setAssumptions(new ArrayList<>(assumptionsList));
+ nodeData.setNodeType(nodeType);
+ AnnotationMirror nodeContainer = findFirstAnnotation(lookupTypes, NodeContainer.class);
+ nodeData.setNodeContainer(nodeContainer != null);
+ nodeData.setTypeSystem(typeSystem);
+ nodeData.setFields(parseFields(elements));
+ parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
+ // parseChildren invokes cyclic parsing.
+ nodeData.setChildren(parseChildren(elements, lookupTypes));
+ nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
+
+ return nodeData;
+ }
+
+ private static List parseFields(List extends Element> elements) {
+ List fields = new ArrayList<>();
+ for (VariableElement field : ElementFilter.fieldsIn(elements)) {
+ if (field.getModifiers().contains(Modifier.STATIC)) {
+ continue;
+ }
+ if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
+ fields.add(new NodeFieldData(field));
+ }
+ }
+ return fields;
+ }
+
+ private List parseChildren(List extends Element> elements, final List typeHierarchy) {
+ Set shortCircuits = new HashSet<>();
+ for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+ AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+ if (mirror != null) {
+ shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
+ }
+ }
+ Map castNodeTypes = new HashMap<>();
+ for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+ AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
+ if (mirror != null) {
+ List children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
+ if (children != null) {
+ for (String child : children) {
+ castNodeTypes.put(child, method.getReturnType());
+ }
+ }
+ }
+ }
+
+ List parsedChildren = new ArrayList<>();
+ List typeHierarchyReversed = new ArrayList<>(typeHierarchy);
+ Collections.reverse(typeHierarchyReversed);
+ for (TypeElement type : typeHierarchyReversed) {
+ AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeContainer.class);
+ AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
+
+ TypeMirror nodeClassType = type.getSuperclass();
+ if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) {
+ nodeClassType = null;
+ }
+
+ if (nodeClassMirror != null) {
+ nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType);
+ }
+
+ List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
+ int index = 0;
+ for (AnnotationMirror childMirror : children) {
+ String name = Utils.getAnnotationValue(String.class, childMirror, "value");
+ if (name.equals("")) {
+ name = "child" + index;
+ }
+
+ Cardinality cardinality = Cardinality.ONE;
+
+ TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
+ if (childType.getKind() == TypeKind.ARRAY) {
+ cardinality = Cardinality.MANY;
+ }
+
+ TypeMirror originalChildType = childType;
+ TypeMirror castNodeType = castNodeTypes.get(name);
+ if (castNodeType != null) {
+ childType = castNodeType;
+ }
+
+ Element getter = findGetter(elements, name, childType);
+
+ ExecutionKind kind = ExecutionKind.DEFAULT;
+ if (shortCircuits.contains(name)) {
+ kind = ExecutionKind.SHORT_CIRCUIT;
+ }
+
+ NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
+
+ parsedChildren.add(nodeChild);
+
+ verifyNodeChild(nodeChild);
+ if (nodeChild.hasErrors()) {
+ continue;
+ }
+
+ NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType));
+ nodeChild.setNode(fieldNodeData);
+ if (fieldNodeData == null) {
+ nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
+ }
+
+ }
+ index++;
+ }
+
+ List filteredChildren = new ArrayList<>();
+ Set encounteredNames = new HashSet<>();
+ for (int i = parsedChildren.size() - 1; i >= 0; i--) {
+ NodeChildData child = parsedChildren.get(i);
+ if (!encounteredNames.contains(child.getName())) {
+ filteredChildren.add(0, child);
+ encounteredNames.add(child.getName());
+ }
+ }
+
+ for (NodeChildData child : filteredChildren) {
+ List executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
+ AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
+ List executeWith = new ArrayList<>();
+ for (String executeWithString : executeWithStrings) {
+
+ if (child.getName().equals(executeWithString)) {
+ child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
+ continue;
+ }
+
+ NodeChildData found = null;
+ boolean before = true;
+ for (NodeChildData resolveChild : filteredChildren) {
+ if (resolveChild == child) {
+ before = false;
+ continue;
+ }
+ if (resolveChild.getName().equals(executeWithString)) {
+ found = resolveChild;
+ break;
+ }
+ }
+
+ if (found == null) {
+ child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
+ continue;
+ } else if (!before) {
+ child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
+ executeWithString);
+ continue;
+ }
+ executeWith.add(found);
+ }
+ child.setExecuteWith(executeWith);
+ if (child.getNodeData() == null) {
+ continue;
+ }
+
+ List types = child.findGenericExecutableTypes(context);
+ if (types.isEmpty()) {
+ child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType()));
+ continue;
+ }
+ }
+
+ return filteredChildren;
+ }
+
+ private void parseMethods(final NodeData node, List elements) {
+ node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements));
+ node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
+ List generics = new GenericParser(context, node).parse(elements);
+ List specializations = new SpecializationMethodParser(context, node).parse(elements);
+ node.setCasts(new CreateCastParser(context, node).parse(elements));
+
+ List allSpecializations = new ArrayList<>();
+ allSpecializations.addAll(generics);
+ allSpecializations.addAll(specializations);
+
+ node.setSpecializations(allSpecializations);
+ }
+
private static List splitNodeData(NodeData node) {
SortedMap> groupedSpecializations = groupByNodeId(node.getSpecializations());
SortedMap> groupedListeners = groupByNodeId(node.getSpecializationListeners());
@@ -252,33 +482,6 @@
return splitted;
}
- private static SortedMap> groupByNodeId(List methods) {
- SortedMap> grouped = new TreeMap<>();
- for (M m : methods) {
- List list = grouped.get(m.getId());
- if (list == null) {
- list = new ArrayList<>();
- grouped.put(m.getId(), list);
- }
- list.add(m);
- }
- return grouped;
- }
-
- private void parseMethods(final NodeData node, List elements) {
- node.setShortCircuits(new ShortCircuitParser(context, node).parse(elements));
- node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements));
- List generics = new GenericParser(context, node).parse(elements);
- List specializations = new SpecializationMethodParser(context, node).parse(elements);
- node.setCasts(new CreateCastParser(context, node).parse(elements));
-
- List allSpecializations = new ArrayList<>();
- allSpecializations.addAll(generics);
- allSpecializations.addAll(specializations);
-
- node.setSpecializations(allSpecializations);
- }
-
private void finalizeSpecializations(List elements, final NodeData node) {
List specializations = new ArrayList<>(node.getSpecializations());
@@ -394,6 +597,87 @@
}
}
+ private void assignShortCircuitsToSpecializations(NodeData node) {
+ Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
+
+ boolean valid = true;
+ for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) {
+ String valueName = field.getName();
+ List availableCircuits = groupedShortCircuits.get(valueName);
+
+ if (availableCircuits == null || availableCircuits.isEmpty()) {
+ node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
+ valid = false;
+ continue;
+ }
+
+ boolean sameMethodName = true;
+ String methodName = availableCircuits.get(0).getMethodName();
+ for (ShortCircuitData circuit : availableCircuits) {
+ if (!circuit.getMethodName().equals(methodName)) {
+ sameMethodName = false;
+ }
+ }
+
+ if (!sameMethodName) {
+ for (ShortCircuitData circuit : availableCircuits) {
+ circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
+ }
+ valid = false;
+ continue;
+ }
+
+ ShortCircuitData genericCircuit = null;
+ for (ShortCircuitData circuit : availableCircuits) {
+ if (isGenericShortCutMethod(node, circuit)) {
+ genericCircuit = circuit;
+ break;
+ }
+ }
+
+ if (genericCircuit == null) {
+ node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+ valid = false;
+ continue;
+ }
+
+ for (ShortCircuitData circuit : availableCircuits) {
+ if (circuit != genericCircuit) {
+ circuit.setGenericShortCircuitMethod(genericCircuit);
+ }
+ }
+ }
+
+ if (!valid) {
+ return;
+ }
+
+ NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
+ for (SpecializationData specialization : node.getSpecializations()) {
+ List assignedShortCuts = new ArrayList<>(fields.length);
+
+ for (int i = 0; i < fields.length; i++) {
+ List availableShortCuts = groupedShortCircuits.get(fields[i].getName());
+
+ ShortCircuitData genericShortCircuit = null;
+ ShortCircuitData compatibleShortCircuit = null;
+ for (ShortCircuitData circuit : availableShortCuts) {
+ if (circuit.isGeneric()) {
+ genericShortCircuit = circuit;
+ } else if (circuit.isCompatibleTo(specialization)) {
+ compatibleShortCircuit = circuit;
+ }
+ }
+
+ if (compatibleShortCircuit == null) {
+ compatibleShortCircuit = genericShortCircuit;
+ }
+ assignedShortCuts.add(compatibleShortCircuit);
+ }
+ specialization.setShortCircuits(assignedShortCuts);
+ }
+ }
+
private void matchGuards(List elements, SpecializationData specialization) {
if (specialization.getGuardDefinitions().isEmpty()) {
specialization.setGuards(Collections. emptyList());
@@ -546,83 +830,12 @@
verifySpecializationThrows(nodeData);
}
- private NodeData parseNodeData(TypeElement templateType, TypeMirror nodeType, List extends Element> elements, List lookupTypes) {
- NodeData nodeData = new NodeData(templateType, templateType.getSimpleName().toString());
-
- AnnotationMirror typeSystemMirror = findFirstAnnotation(lookupTypes, TypeSystemReference.class);
- if (typeSystemMirror == null) {
- nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), Utils.getQualifiedName(nodeType));
- return nodeData;
- }
-
- TypeMirror typeSytemType = Utils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
- final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true);
- if (typeSystem == null) {
- nodeData.addError("The used type system '%s' is invalid or not a Node.", Utils.getQualifiedName(typeSytemType));
- return nodeData;
- }
-
- boolean splitByMethodName = false;
- AnnotationMirror nodeClass = findFirstAnnotation(lookupTypes, NodeClass.class);
- if (nodeClass != null) {
- splitByMethodName = Utils.getAnnotationValue(Boolean.class, nodeClass, "splitByMethodName");
- }
-
- List assumptionsList = new ArrayList<>();
-
- for (int i = lookupTypes.size() - 1; i >= 0; i--) {
- TypeElement type = lookupTypes.get(i);
- AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
- if (assumptions != null) {
- List assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
- for (String string : assumptionStrings) {
- if (assumptionsList.contains(string)) {
- assumptionsList.remove(string);
- }
- assumptionsList.add(string);
- }
- }
+ private static void verifyNodeChild(NodeChildData nodeChild) {
+ if (nodeChild.getNodeType() == null) {
+ nodeChild.addError("No valid node type could be resoleved.");
}
- AnnotationMirror nodeInfoMirror = findFirstAnnotation(lookupTypes, NodeInfo.class);
- if (nodeInfoMirror != null) {
- nodeData.setShortName(Utils.getAnnotationValue(String.class, nodeInfoMirror, "shortName"));
- }
-
- nodeData.setAssumptions(new ArrayList<>(assumptionsList));
- nodeData.setNodeType(nodeType);
- nodeData.setSplitByMethodName(splitByMethodName);
- nodeData.setTypeSystem(typeSystem);
- nodeData.setFields(parseFields(elements));
- parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
- // parseChildren invokes cyclic parsing.
- nodeData.setChildren(parseChildren(elements, lookupTypes));
- nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
-
- return nodeData;
- }
-
- private static boolean verifySpecializationParameters(NodeData nodeData) {
- boolean valid = true;
- int args = -1;
- for (SpecializationData specializationData : nodeData.getSpecializations()) {
- int signatureArgs = 0;
- for (ActualParameter param : specializationData.getParameters()) {
- if (param.getSpecification().isSignature()) {
- signatureArgs++;
- }
- }
- if (args != -1 && args != signatureArgs) {
- valid = false;
- break;
- }
- args = signatureArgs;
- }
- if (!valid) {
- for (SpecializationData specialization : nodeData.getSpecializations()) {
- specialization.addError("All specializations must have the same number of arguments.");
- }
- }
- return valid;
+ // FIXME verify node child
+ // FIXME verify node type set
}
private static void verifyMissingAbstractMethods(NodeData nodeData, List extends Element> originalElements) {
@@ -691,361 +904,28 @@
nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type));
}
- private static Map> groupExecutableTypes(List executableTypes) {
- Map> groupedTypes = new HashMap<>();
- for (ExecutableTypeData type : executableTypes) {
- int evaluatedCount = type.getEvaluatedCount();
-
- List types = groupedTypes.get(evaluatedCount);
- if (types == null) {
- types = new ArrayList<>();
- groupedTypes.put(evaluatedCount, types);
- }
- types.add(type);
- }
-
- for (List types : groupedTypes.values()) {
- Collections.sort(types);
- }
- return groupedTypes;
- }
-
- private AnnotationMirror findFirstAnnotation(List extends Element> elements, Class extends Annotation> annotation) {
- for (Element element : elements) {
- AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation);
- if (mirror != null) {
- return mirror;
- }
- }
- return null;
- }
-
- private static List parseFields(List extends Element> elements) {
- List fields = new ArrayList<>();
- for (VariableElement field : ElementFilter.fieldsIn(elements)) {
- if (field.getModifiers().contains(Modifier.STATIC)) {
- continue;
- }
- if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
- fields.add(new NodeFieldData(field));
- }
- }
- return fields;
- }
-
- private List parseChildren(List extends Element> elements, final List typeHierarchy) {
- Set shortCircuits = new HashSet<>();
- for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
- AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
- if (mirror != null) {
- shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
- }
- }
- Map castNodeTypes = new HashMap<>();
- for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
- AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class);
- if (mirror != null) {
- List children = (Utils.getAnnotationValueList(String.class, mirror, "value"));
- if (children != null) {
- for (String child : children) {
- castNodeTypes.put(child, method.getReturnType());
- }
+ private static boolean verifySpecializationParameters(NodeData nodeData) {
+ boolean valid = true;
+ int args = -1;
+ for (SpecializationData specializationData : nodeData.getSpecializations()) {
+ int signatureArgs = 0;
+ for (ActualParameter param : specializationData.getParameters()) {
+ if (param.getSpecification().isSignature()) {
+ signatureArgs++;
}
}
- }
-
- List parsedChildren = new ArrayList<>();
- List typeHierarchyReversed = new ArrayList<>(typeHierarchy);
- Collections.reverse(typeHierarchyReversed);
- for (TypeElement type : typeHierarchyReversed) {
- AnnotationMirror nodeClassMirror = Utils.findAnnotationMirror(processingEnv, type, NodeClass.class);
- AnnotationMirror nodeChildrenMirror = Utils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
-
- TypeMirror nodeClassType = type.getSuperclass();
- if (!Utils.isAssignable(context, nodeClassType, context.getTruffleTypes().getNode())) {
- nodeClassType = null;
- }
-
- if (nodeClassMirror != null) {
- nodeClassType = inheritType(nodeClassMirror, "value", nodeClassType);
+ if (args != -1 && args != signatureArgs) {
+ valid = false;
+ break;
}
-
- List children = Utils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
- int index = 0;
- for (AnnotationMirror childMirror : children) {
- String name = Utils.getAnnotationValue(String.class, childMirror, "value");
- if (name.equals("")) {
- name = "child" + index;
- }
-
- Cardinality cardinality = Cardinality.ONE;
-
- TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
- if (childType.getKind() == TypeKind.ARRAY) {
- cardinality = Cardinality.MANY;
- }
-
- TypeMirror originalChildType = childType;
- TypeMirror castNodeType = castNodeTypes.get(name);
- if (castNodeType != null) {
- childType = castNodeType;
- }
-
- Element getter = findGetter(elements, name, childType);
-
- ExecutionKind kind = ExecutionKind.DEFAULT;
- if (shortCircuits.contains(name)) {
- kind = ExecutionKind.SHORT_CIRCUIT;
- }
-
- NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
-
- parsedChildren.add(nodeChild);
-
- verifyNodeChild(nodeChild);
- if (nodeChild.hasErrors()) {
- continue;
- }
-
- NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(childType));
- nodeChild.setNode(fieldNodeData);
- if (fieldNodeData == null) {
- nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
- }
-
- }
- index++;
+ args = signatureArgs;
}
-
- List filteredChildren = new ArrayList<>();
- Set encounteredNames = new HashSet<>();
- for (int i = parsedChildren.size() - 1; i >= 0; i--) {
- NodeChildData child = parsedChildren.get(i);
- if (!encounteredNames.contains(child.getName())) {
- filteredChildren.add(0, child);
- encounteredNames.add(child.getName());
+ if (!valid) {
+ for (SpecializationData specialization : nodeData.getSpecializations()) {
+ specialization.addError("All specializations must have the same number of arguments.");
}
}
-
- for (NodeChildData child : filteredChildren) {
- List executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
- AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
- List executeWith = new ArrayList<>();
- for (String executeWithString : executeWithStrings) {
-
- if (child.getName().equals(executeWithString)) {
- child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
- continue;
- }
-
- NodeChildData found = null;
- boolean before = true;
- for (NodeChildData resolveChild : filteredChildren) {
- if (resolveChild == child) {
- before = false;
- continue;
- }
- if (resolveChild.getName().equals(executeWithString)) {
- found = resolveChild;
- break;
- }
- }
-
- if (found == null) {
- child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
- continue;
- } else if (!before) {
- child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
- executeWithString);
- continue;
- }
- executeWith.add(found);
- }
- child.setExecuteWith(executeWith);
- if (child.getNodeData() == null) {
- continue;
- }
-
- List types = child.findGenericExecutableTypes(context);
- if (types.isEmpty()) {
- child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType()));
- continue;
- }
- }
-
- return filteredChildren;
- }
-
- private static void verifyNodeChild(NodeChildData nodeChild) {
- if (nodeChild.getNodeType() == null) {
- nodeChild.addError("No valid node type could be resoleved.");
- }
- // FIXME verify node child
- // FIXME verify node type set
- }
-
- private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
- TypeMirror inhertNodeType = context.getType(InheritNode.class);
- TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName);
- if (Utils.typeEquals(inhertNodeType, value)) {
- return parentType;
- } else {
- return value;
- }
- }
-
- private Element findGetter(List extends Element> elements, String variableName, TypeMirror type) {
- if (type == null) {
- return null;
- }
- String methodName;
- if (Utils.typeEquals(type, context.getType(boolean.class))) {
- methodName = "is" + Utils.firstLetterUpperCase(variableName);
- } else {
- methodName = "get" + Utils.firstLetterUpperCase(variableName);
- }
-
- for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
- if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) {
- return method;
- }
- }
- return null;
- }
-
- private void assignShortCircuitsToSpecializations(NodeData node) {
- Map> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
-
- boolean valid = true;
- for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) {
- String valueName = field.getName();
- List availableCircuits = groupedShortCircuits.get(valueName);
-
- if (availableCircuits == null || availableCircuits.isEmpty()) {
- node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
- valid = false;
- continue;
- }
-
- boolean sameMethodName = true;
- String methodName = availableCircuits.get(0).getMethodName();
- for (ShortCircuitData circuit : availableCircuits) {
- if (!circuit.getMethodName().equals(methodName)) {
- sameMethodName = false;
- }
- }
-
- if (!sameMethodName) {
- for (ShortCircuitData circuit : availableCircuits) {
- circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
- }
- valid = false;
- continue;
- }
-
- ShortCircuitData genericCircuit = null;
- for (ShortCircuitData circuit : availableCircuits) {
- if (isGenericShortCutMethod(node, circuit)) {
- genericCircuit = circuit;
- break;
- }
- }
-
- if (genericCircuit == null) {
- node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
- valid = false;
- continue;
- }
-
- for (ShortCircuitData circuit : availableCircuits) {
- if (circuit != genericCircuit) {
- circuit.setGenericShortCircuitMethod(genericCircuit);
- }
- }
- }
-
- if (!valid) {
- return;
- }
-
- NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
- for (SpecializationData specialization : node.getSpecializations()) {
- List assignedShortCuts = new ArrayList<>(fields.length);
-
- for (int i = 0; i < fields.length; i++) {
- List availableShortCuts = groupedShortCircuits.get(fields[i].getName());
-
- ShortCircuitData genericShortCircuit = null;
- ShortCircuitData compatibleShortCircuit = null;
- for (ShortCircuitData circuit : availableShortCuts) {
- if (circuit.isGeneric()) {
- genericShortCircuit = circuit;
- } else if (circuit.isCompatibleTo(specialization)) {
- compatibleShortCircuit = circuit;
- }
- }
-
- if (compatibleShortCircuit == null) {
- compatibleShortCircuit = genericShortCircuit;
- }
- assignedShortCuts.add(compatibleShortCircuit);
- }
- specialization.setShortCircuits(assignedShortCuts);
- }
- }
-
- private static void verifyNamingConvention(List extends TemplateMethod> methods, String prefix) {
- for (int i = 0; i < methods.size(); i++) {
- TemplateMethod m1 = methods.get(i);
- if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
- m1.addError("Naming convention: method name must start with '%s'.", prefix);
- }
- }
- }
-
- private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
- for (ActualParameter parameter : method.getParameters()) {
- NodeChildData field = node.findChild(parameter.getSpecification().getName());
- if (field == null) {
- continue;
- }
- ExecutableTypeData found = null;
- List executableElements = field.findGenericExecutableTypes(context);
- for (ExecutableTypeData executable : executableElements) {
- if (executable.getType().equalsType(parameter.getTypeSystemType())) {
- found = executable;
- break;
- }
- }
- if (found == null) {
- return false;
- }
- }
- return true;
- }
-
- private static Map> groupShortCircuits(List shortCircuits) {
- Map> group = new HashMap<>();
- for (ShortCircuitData shortCircuit : shortCircuits) {
- List circuits = group.get(shortCircuit.getValueName());
- if (circuits == null) {
- circuits = new ArrayList<>();
- group.put(shortCircuit.getValueName(), circuits);
- }
- circuits.add(shortCircuit);
- }
- return group;
- }
-
- private static List findSuperClasses(List collection, TypeElement element) {
- if (element.getSuperclass() != null) {
- TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass());
- if (superElement != null) {
- findSuperClasses(collection, superElement);
- }
- }
- collection.add(element);
- return collection;
+ return valid;
}
private static void verifySpecializationOrder(NodeData node) {
@@ -1094,14 +974,129 @@
}
}
- @Override
- public Class extends Annotation> getAnnotationType() {
+ private static void verifyNamingConvention(List extends TemplateMethod> methods, String prefix) {
+ for (int i = 0; i < methods.size(); i++) {
+ TemplateMethod m1 = methods.get(i);
+ if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
+ m1.addError("Naming convention: method name must start with '%s'.", prefix);
+ }
+ }
+ }
+
+ private static Map> groupExecutableTypes(List executableTypes) {
+ Map> groupedTypes = new HashMap<>();
+ for (ExecutableTypeData type : executableTypes) {
+ int evaluatedCount = type.getEvaluatedCount();
+
+ List types = groupedTypes.get(evaluatedCount);
+ if (types == null) {
+ types = new ArrayList<>();
+ groupedTypes.put(evaluatedCount, types);
+ }
+ types.add(type);
+ }
+
+ for (List types : groupedTypes.values()) {
+ Collections.sort(types);
+ }
+ return groupedTypes;
+ }
+
+ private AnnotationMirror findFirstAnnotation(List extends Element> elements, Class extends Annotation> annotation) {
+ for (Element element : elements) {
+ AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, element, annotation);
+ if (mirror != null) {
+ return mirror;
+ }
+ }
return null;
}
- @Override
- public List> getTypeDelegatedAnnotationTypes() {
- return ANNOTATIONS;
+ private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
+ TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
+ TypeMirror value = Utils.getAnnotationValue(TypeMirror.class, annotation, valueName);
+ if (Utils.typeEquals(inhertNodeType, value)) {
+ return parentType;
+ } else {
+ return value;
+ }
+ }
+
+ private Element findGetter(List extends Element> elements, String variableName, TypeMirror type) {
+ if (type == null) {
+ return null;
+ }
+ String methodName;
+ if (Utils.typeEquals(type, context.getType(boolean.class))) {
+ methodName = "is" + Utils.firstLetterUpperCase(variableName);
+ } else {
+ methodName = "get" + Utils.firstLetterUpperCase(variableName);
+ }
+
+ for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+ if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
+ for (ActualParameter parameter : method.getParameters()) {
+ NodeChildData field = node.findChild(parameter.getSpecification().getName());
+ if (field == null) {
+ continue;
+ }
+ ExecutableTypeData found = null;
+ List executableElements = field.findGenericExecutableTypes(context);
+ for (ExecutableTypeData executable : executableElements) {
+ if (executable.getType().equalsType(parameter.getTypeSystemType())) {
+ found = executable;
+ break;
+ }
+ }
+ if (found == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static Map> groupShortCircuits(List shortCircuits) {
+ Map> group = new HashMap<>();
+ for (ShortCircuitData shortCircuit : shortCircuits) {
+ List circuits = group.get(shortCircuit.getValueName());
+ if (circuits == null) {
+ circuits = new ArrayList<>();
+ group.put(shortCircuit.getValueName(), circuits);
+ }
+ circuits.add(shortCircuit);
+ }
+ return group;
+ }
+
+ private static SortedMap> groupByNodeId(List methods) {
+ SortedMap> grouped = new TreeMap<>();
+ for (M m : methods) {
+ List list = grouped.get(m.getId());
+ if (list == null) {
+ list = new ArrayList<>();
+ grouped.put(m.getId(), list);
+ }
+ list.add(m);
+ }
+ return grouped;
+ }
+
+ private static List findSuperClasses(List collection, TypeElement element) {
+ if (element.getSuperclass() != null) {
+ TypeElement superElement = Utils.fromTypeMirror(element.getSuperclass());
+ if (superElement != null) {
+ findSuperClasses(collection, superElement);
+ }
+ }
+ collection.add(element);
+ return collection;
}
}