diff truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java @ 22368:0d4b0e4263ee

Convert NodeClass and NodeFieldAccessor to interfaces
author Christian Wimmer <christian.wimmer@oracle.com>
date Fri, 13 Nov 2015 10:29:52 -0800
parents 4df3d8fd6cfd
children 6598b9b7aafd
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java	Fri Nov 13 16:25:04 2015 +0100
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java	Fri Nov 13 10:29:52 2015 -0800
@@ -24,9 +24,6 @@
  */
 package com.oracle.truffle.api.nodes;
 
-import com.oracle.truffle.api.nodes.Node.Child;
-import com.oracle.truffle.api.nodes.Node.Children;
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
@@ -35,170 +32,206 @@
 import java.util.Iterator;
 import java.util.List;
 
-/**
- * Information about a {@link Node} class. A single instance of this class is allocated for every
- * subclass of {@link Node} that is used.
- */
-public final class NodeClass {
-    private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
-        @SuppressWarnings("unchecked")
-        @Override
-        protected NodeClass computeValue(final Class<?> clazz) {
-            assert Node.class.isAssignableFrom(clazz);
-            return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() {
-                public NodeClass run() {
-                    return new NodeClass((Class<? extends Node>) clazz);
-                }
-            });
-        }
-    };
-
-    private static final NodeFieldAccessor[] EMPTY_NODE_FIELD_ARRAY = new NodeFieldAccessor[0];
-
-    // The comprehensive list of all fields.
-    private final NodeFieldAccessor[] fields;
-    // Separate arrays for the frequently accessed fields.
-    private final NodeFieldAccessor parentField;
-    private final NodeFieldAccessor nodeClassField;
-    private final NodeFieldAccessor[] childFields;
-    private final NodeFieldAccessor[] childrenFields;
-    private final NodeFieldAccessor[] cloneableFields;
-
-    private final Class<? extends Node> clazz;
-
-    public static NodeClass get(Class<? extends Node> clazz) {
-        return nodeClasses.get(clazz);
-    }
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldAccessorImpl;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 
-    public static NodeClass get(Node node) {
-        return node.getNodeClass();
-    }
-
-    NodeClass(Class<? extends Node> clazz) {
-        List<NodeFieldAccessor> fieldsList = new ArrayList<>();
-        NodeFieldAccessor parentFieldTmp = null;
-        NodeFieldAccessor nodeClassFieldTmp = null;
-        List<NodeFieldAccessor> childFieldList = new ArrayList<>();
-        List<NodeFieldAccessor> childrenFieldList = new ArrayList<>();
-        List<NodeFieldAccessor> cloneableFieldList = new ArrayList<>();
-
-        for (Field field : NodeUtil.getAllFields(clazz)) {
-            if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
-                continue;
-            }
+public interface NodeClass {
 
-            NodeFieldAccessor nodeField;
-            if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) {
-                assert Node.class.isAssignableFrom(field.getType());
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.PARENT, field);
-                parentFieldTmp = nodeField;
-            } else if (field.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) {
-                assert NodeClass.class.isAssignableFrom(field.getType());
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field);
-                nodeClassFieldTmp = nodeField;
-            } else if (field.getAnnotation(Child.class) != null) {
-                checkChildField(field);
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILD, field);
-                childFieldList.add(nodeField);
-            } else if (field.getAnnotation(Children.class) != null) {
-                checkChildrenField(field);
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILDREN, field);
-                childrenFieldList.add(nodeField);
-            } else {
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.DATA, field);
-                if (NodeCloneable.class.isAssignableFrom(field.getType())) {
-                    cloneableFieldList.add(nodeField);
-                }
-            }
-            fieldsList.add(nodeField);
+    public static class Lookup {
+        public static NodeClass get(Class<? extends Node> clazz) {
+            return NodeClassImpl.nodeClasses.get(clazz);
         }
 
-        if (parentFieldTmp == null) {
-            throw new AssertionError("parent field not found");
-        }
-
-        this.fields = fieldsList.toArray(EMPTY_NODE_FIELD_ARRAY);
-        this.nodeClassField = nodeClassFieldTmp;
-        this.parentField = parentFieldTmp;
-        this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
-        this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
-        this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
-        this.clazz = clazz;
-    }
-
-    public NodeFieldAccessor getNodeClassField() {
-        return nodeClassField;
-    }
-
-    public NodeFieldAccessor[] getCloneableFields() {
-        return cloneableFields;
-    }
-
-    private static boolean isNodeType(Class<?> clazz) {
-        return Node.class.isAssignableFrom(clazz) || (clazz.isInterface() && NodeInterface.class.isAssignableFrom(clazz));
-    }
-
-    private static void checkChildField(Field field) {
-        if (!isNodeType(field.getType())) {
-            throw new AssertionError("@Child field type must be a subclass of Node or an interface extending NodeInterface (" + field + ")");
-        }
-        if (Modifier.isFinal(field.getModifiers())) {
-            throw new AssertionError("@Child field must not be final (" + field + ")");
+        public static NodeClass get(Node node) {
+            return node.getNodeClass();
         }
     }
 
-    private static void checkChildrenField(Field field) {
-        if (!(field.getType().isArray() && isNodeType(field.getType().getComponentType()))) {
-            throw new AssertionError("@Children field type must be an array of a subclass of Node or an interface extending NodeInterface (" + field + ")");
+    NodeFieldAccessor getNodeClassField();
+
+    NodeFieldAccessor[] getCloneableFields();
+
+    NodeFieldAccessor[] getFields();
+
+    NodeFieldAccessor getParentField();
+
+    NodeFieldAccessor[] getChildFields();
+
+    NodeFieldAccessor[] getChildrenFields();
+
+    Iterator<Node> makeIterator(Node node);
+
+    /**
+     * Information about a {@link Node} class. A single instance of this class is allocated for
+     * every subclass of {@link Node} that is used.
+     */
+    public final class NodeClassImpl implements NodeClass {
+        static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
+            @SuppressWarnings("unchecked")
+            @Override
+            protected NodeClass computeValue(final Class<?> clazz) {
+                assert Node.class.isAssignableFrom(clazz);
+                return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() {
+                    public NodeClass run() {
+                        return new NodeClassImpl((Class<? extends Node>) clazz);
+                    }
+                });
+            }
+        };
+
+        private static final NodeFieldAccessor[] EMPTY_NODE_FIELD_ARRAY = new NodeFieldAccessor[0];
+
+        // The comprehensive list of all fields.
+        private final NodeFieldAccessor[] fields;
+        // Separate arrays for the frequently accessed fields.
+        private final NodeFieldAccessor parentField;
+        private final NodeFieldAccessor nodeClassField;
+        private final NodeFieldAccessor[] childFields;
+        private final NodeFieldAccessor[] childrenFields;
+        private final NodeFieldAccessor[] cloneableFields;
+
+        private final Class<? extends Node> clazz;
+
+        public static NodeClass get(Class<? extends Node> clazz) {
+            return nodeClasses.get(clazz);
+        }
+
+        public static NodeClass get(Node node) {
+            return node.getNodeClass();
         }
-        if (!Modifier.isFinal(field.getModifiers())) {
-            throw new AssertionError("@Children field must be final (" + field + ")");
+
+        NodeClassImpl(Class<? extends Node> clazz) {
+            List<NodeFieldAccessor> fieldsList = new ArrayList<>();
+            NodeFieldAccessor parentFieldTmp = null;
+            NodeFieldAccessor nodeClassFieldTmp = null;
+            List<NodeFieldAccessor> childFieldList = new ArrayList<>();
+            List<NodeFieldAccessor> childrenFieldList = new ArrayList<>();
+            List<NodeFieldAccessor> cloneableFieldList = new ArrayList<>();
+
+            for (Field field : NodeUtil.getAllFields(clazz)) {
+                if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
+                    continue;
+                }
+
+                NodeFieldAccessor nodeField;
+                if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) {
+                    assert Node.class.isAssignableFrom(field.getType());
+                    nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.PARENT, field);
+                    parentFieldTmp = nodeField;
+                } else if (field.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) {
+                    assert NodeClass.class.isAssignableFrom(field.getType());
+                    nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.NODE_CLASS, field);
+                    nodeClassFieldTmp = nodeField;
+                } else if (field.getAnnotation(Child.class) != null) {
+                    checkChildField(field);
+                    nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.CHILD, field);
+                    childFieldList.add(nodeField);
+                } else if (field.getAnnotation(Children.class) != null) {
+                    checkChildrenField(field);
+                    nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.CHILDREN, field);
+                    childrenFieldList.add(nodeField);
+                } else {
+                    nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.DATA, field);
+                    if (NodeCloneable.class.isAssignableFrom(field.getType())) {
+                        cloneableFieldList.add(nodeField);
+                    }
+                }
+                fieldsList.add(nodeField);
+            }
+
+            if (parentFieldTmp == null) {
+                throw new AssertionError("parent field not found");
+            }
+
+            this.fields = fieldsList.toArray(EMPTY_NODE_FIELD_ARRAY);
+            this.nodeClassField = nodeClassFieldTmp;
+            this.parentField = parentFieldTmp;
+            this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
+            this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
+            this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
+            this.clazz = clazz;
+        }
+
+        public Class<? extends Node> getNodeClass() {
+            return clazz;
+        }
+
+        public NodeFieldAccessor getNodeClassField() {
+            return nodeClassField;
+        }
+
+        public NodeFieldAccessor[] getCloneableFields() {
+            return cloneableFields;
+        }
+
+        private static boolean isNodeType(Class<?> clazz) {
+            return Node.class.isAssignableFrom(clazz) || (clazz.isInterface() && NodeInterface.class.isAssignableFrom(clazz));
+        }
+
+        private static void checkChildField(Field field) {
+            if (!isNodeType(field.getType())) {
+                throw new AssertionError("@Child field type must be a subclass of Node or an interface extending NodeInterface (" + field + ")");
+            }
+            if (Modifier.isFinal(field.getModifiers())) {
+                throw new AssertionError("@Child field must not be final (" + field + ")");
+            }
+        }
+
+        private static void checkChildrenField(Field field) {
+            if (!(field.getType().isArray() && isNodeType(field.getType().getComponentType()))) {
+                throw new AssertionError("@Children field type must be an array of a subclass of Node or an interface extending NodeInterface (" + field + ")");
+            }
+            if (!Modifier.isFinal(field.getModifiers())) {
+                throw new AssertionError("@Children field must be final (" + field + ")");
+            }
+        }
+
+        public NodeFieldAccessor[] getFields() {
+            return fields;
+        }
+
+        public NodeFieldAccessor getParentField() {
+            return parentField;
+        }
+
+        public NodeFieldAccessor[] getChildFields() {
+            return childFields;
+        }
+
+        public NodeFieldAccessor[] getChildrenFields() {
+            return childrenFields;
+        }
+
+        @Override
+        public int hashCode() {
+            return clazz.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof NodeClassImpl) {
+                NodeClassImpl other = (NodeClassImpl) obj;
+                return clazz.equals(other.clazz);
+            }
+            return false;
+        }
+
+        public Iterator<Node> makeIterator(Node node) {
+            assert clazz.isInstance(node);
+            return new NodeIterator(this, node);
         }
     }
 
-    public NodeFieldAccessor[] getFields() {
-        return fields;
-    }
-
-    public NodeFieldAccessor getParentField() {
-        return parentField;
-    }
-
-    public NodeFieldAccessor[] getChildFields() {
-        return childFields;
-    }
-
-    public NodeFieldAccessor[] getChildrenFields() {
-        return childrenFields;
-    }
-
-    @Override
-    public int hashCode() {
-        return clazz.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof NodeClass) {
-            NodeClass other = (NodeClass) obj;
-            return clazz.equals(other.clazz);
-        }
-        return false;
-    }
-
-    public Iterator<Node> makeIterator(Node node) {
-        assert clazz.isInstance(node);
-        return new NodeIterator(this, node);
-    }
-
-    private static final class NodeIterator implements Iterator<Node> {
+    public static final class NodeIterator implements Iterator<Node> {
         private final NodeFieldAccessor[] childFields;
         private final NodeFieldAccessor[] childrenFields;
         private final Node node;
         private final int childrenCount;
         private int index;
 
-        protected NodeIterator(NodeClass nodeClass, Node node) {
+        public NodeIterator(NodeClass nodeClass, Node node) {
             this.childFields = nodeClass.getChildFields();
             this.childrenFields = nodeClass.getChildrenFields();
             this.node = node;