diff graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java @ 8251:cb70ed101b5f

Added automatic generation of generic specialization which throws unsupported operation if reached.
author Christian Humer <christian.humer@gmail.com>
date Wed, 13 Mar 2013 11:32:43 +0100
parents c4c3f50fa9c2
children 0905d796944a
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Tue Mar 12 11:38:52 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Wed Mar 13 11:32:43 2013 +0100
@@ -120,6 +120,10 @@
             return null; // not a node
         }
 
+        if (type.getModifiers().contains(Modifier.PRIVATE)) {
+            return null; // not visible
+        }
+
         TypeElement nodeType;
         boolean needsSplit;
         if (methodNodes != null) {
@@ -130,10 +134,6 @@
             nodeType = type;
         }
 
-        if (type.getModifiers().contains(Modifier.PRIVATE)) {
-            return null; // not visible
-        }
-
         NodeData nodeData = parseNodeData(type, nodeType);
         if (nodeData == null) {
             return null;
@@ -271,28 +271,63 @@
             }
         }
 
+        if (generics.size() == 1 && specializations.size() == 1) {
+            for (SpecializationData generic : generics) {
+                log.error(generic.getMethod(), "@%s defined but no @%s.", Generic.class.getSimpleName(), Specialization.class.getSimpleName());
+            }
+        }
+
         SpecializationData genericSpecialization = null;
         if (generics.size() > 1) {
             for (SpecializationData generic : generics) {
-                log.error(generic.getMethod(), "Only one method with @%s is allowed per operation.", Generic.class.getSimpleName());
+                log.error(generic.getMethod(), "Only @%s is allowed per operation.", Generic.class.getSimpleName());
             }
             return false;
         } else if (generics.size() == 1) {
             genericSpecialization = generics.get(0);
-        } else {
-            // TODO support generation of generic if not ambiguous.
-        }
+            if (!node.needsRewrites(context)) {
+                log.error(genericSpecialization.getMethod(), "Generic specialization is not reachable.", Generic.class.getSimpleName());
+                return false;
+            }
+        } else if (node.needsRewrites(context)) {
+            SpecializationData specialization = specializations.get(0);
+            GenericParser parser = new GenericParser(context, node);
+            MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, null);
+
+            ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context);
+            if (anyGenericReturnType == null) {
+                // TODO fail invalid executable type. should be validated by field. (assertion
+// failure!?)
+            }
 
-        if (specializations.size() > 1 && genericSpecialization == null) {
-            log.error(node.getTemplateType(), "Need a @%s method.", Generic.class.getSimpleName());
-            return false;
+            ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType().getPrimitiveType(), 0, false);
+            List<ActualParameter> parameters = new ArrayList<>();
+            for (ActualParameter specializationParameter : specialization.getParameters()) {
+                ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName());
+                NodeFieldData field = node.findField(parameterSpec.getName());
+                TypeMirror actualType;
+                if (field == null) {
+                    actualType = specializationParameter.getActualType();
+                } else {
+                    ExecutableTypeData paramType = field.getNodeData().findAnyGenericExecutableType(context);
+                    if (paramType == null) {
+                        // TODO fail
+                    }
+                    actualType = paramType.getType().getPrimitiveType();
+                }
+                parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isHidden()));
+            }
+            TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters);
+            genericSpecialization = new SpecializationData(genericMethod, true, false, true);
+
+            specializations.add(genericSpecialization);
         }
 
         if (genericSpecialization != null) {
             CodeExecutableElement uninitializedMethod = new CodeExecutableElement(Utils.modifiers(Modifier.PUBLIC), context.getType(void.class), "doUninitialized");
-            TemplateMethod uninializedMethod = new TemplateMethod(genericSpecialization.getId(), node, genericSpecialization.getSpecification(), uninitializedMethod,
-                            genericSpecialization.getMarkerAnnotation(), genericSpecialization.getReturnType(), genericSpecialization.getParameters());
-            specializations.add(new SpecializationData(uninializedMethod, false, true));
+            TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", node, genericSpecialization.getSpecification(), uninitializedMethod, genericSpecialization.getMarkerAnnotation(),
+                            genericSpecialization.getReturnType(), genericSpecialization.getParameters());
+            specializations.add(new SpecializationData(uninializedMethod, false, true, true));
         }
 
         Collections.sort(specializations, new Comparator<SpecializationData>() {