Commits

Tim Vernum committed e391fb5

Lookup lambda method name/arguments

  • Participants
  • Parent commits 0ba1b2a

Comments (0)

Files changed (10)

convert/source/java/main/org/adjective/syntactic/convert/j7to8/ClassFinder.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  ------------------------------------------------------------------------
+ */
+package org.adjective.syntactic.convert.j7to8;
+
+public class ClassFinder
+{
+    public boolean hasClass(final String qualifiedName)
+    {
+        return getClass(qualifiedName) != null;
+    }
+
+    public TypeInfo getClass(final String qualifiedName)
+    {
+        try
+        {
+            final Class<?> cls = Class.forName(qualifiedName);
+            return new ClassInfo(cls);
+        }
+        catch (ClassNotFoundException e)
+        {
+            return null;
+        }
+    }
+}

convert/source/java/main/org/adjective/syntactic/convert/j7to8/ClassInfo.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  ------------------------------------------------------------------------
+ */
+package org.adjective.syntactic.convert.j7to8;
+
+import org.adjective.syntactic.parser.util.BaseType;
+import org.adjective.syntactic.parser.util.JavaType;
+import org.adjective.syntactic.parser.util.ParameterizedName;
+import org.adjective.syntactic.parser.util.UnparameterizedName;
+
+public class ClassInfo implements TypeInfo, JavaType
+{
+    private final Class<?> _cls;
+
+    public ClassInfo(final Class<?> cls)
+    {
+        _cls = cls;
+    }
+
+    @Override
+    public MethodInfo[] getMethods()
+    {
+        return ClassMethodInfo.array(_cls.getMethods());
+    }
+
+    @Override
+    public String getName()
+    {
+        return _cls.getName();
+    }
+
+    @Override
+    public BaseType getBaseType()
+    {
+        if (_cls.isPrimitive())
+        {
+            if (_cls == Void.TYPE)
+            {
+                return BaseType.VOID;
+            }
+            if (_cls == Boolean.TYPE)
+            {
+                return BaseType.BOOLEAN;
+            }
+            if (_cls == Byte.TYPE)
+            {
+                return BaseType.BYTE;
+            }
+            if (_cls == Short.TYPE)
+            {
+                return BaseType.SHORT;
+            }
+            if (_cls == Integer.TYPE)
+            {
+                return BaseType.INT;
+            }
+            if (_cls == Long.TYPE)
+            {
+                return BaseType.LONG;
+            }
+            if (_cls == Float.TYPE)
+            {
+                return BaseType.FLOAT;
+            }
+            if (_cls == Double.TYPE)
+            {
+                return BaseType.DOUBLE;
+            }
+            if (_cls == Character.TYPE)
+            {
+                return BaseType.CHAR;
+            }
+        }
+        return BaseType.OBJECT;
+    }
+
+    @Override
+    public String getTypeName()
+    {
+        return _cls.getName();
+    }
+
+    @Override
+    public ParameterizedName[] getParameterizedTypeName()
+    {
+        final String[] parts = getTypeName().split("\\.");
+        final ParameterizedName[] names = new ParameterizedName[parts.length];
+        for (int i = 0; i < names.length; i++)
+        {
+            names[i] = new UnparameterizedName(parts[i]);
+        }
+        return names;
+    }
+
+    @Override
+    public int getArrayDepth()
+    {
+        int depth = 0;
+        for (Class cls = _cls; cls.isArray(); cls = cls.getComponentType())
+        {
+            depth++;
+        }
+        return depth;
+    }
+
+    public static ClassInfo[] array(final Class<?>[] classes)
+    {
+        final ClassInfo[] info = new ClassInfo[classes.length];
+        for (int i = 0; i < info.length; i++)
+        {
+            info[i] = new ClassInfo(classes[i]);
+        }
+        return info;
+    }
+}

convert/source/java/main/org/adjective/syntactic/convert/j7to8/ClassMethodInfo.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  ------------------------------------------------------------------------
+ */
+package org.adjective.syntactic.convert.j7to8;
+
+import org.adjective.syntactic.parser.util.JavaType;
+
+import java.lang.reflect.Method;
+
+public class ClassMethodInfo implements MethodInfo
+{
+    private final Method _method;
+
+    public ClassMethodInfo(final Method method)
+    {
+
+        _method = method;
+    }
+
+    public static ClassMethodInfo[] array(final Method[] methods)
+    {
+        final ClassMethodInfo[] info = new ClassMethodInfo[methods.length];
+        for (int i = 0; i < methods.length; i++)
+        {
+            info[i] = new ClassMethodInfo(methods[i]);
+        }
+        return info;
+    }
+
+    @Override
+    public JavaType getReturnType()
+    {
+        return new ClassInfo(_method.getReturnType());
+    }
+
+    @Override
+    public String getName()
+    {
+        return _method.getName();
+    }
+
+    @Override
+    public JavaType[] getParameterTypes()
+    {
+        final Class<?>[] parameters = _method.getParameterTypes();
+        return ClassInfo.array(parameters);
+    }
+
+    @Override
+    public String[] getParameterNames()
+    {
+        final String[] names = new String[_method.getParameterTypes().length];
+        for (int i = 0; i < names.length; i++)
+        {
+            names[i] = "p" + (i + 1);
+        }
+        return names;
+    }
+
+    @Override
+    public boolean isVarArgs()
+    {
+        return _method.isVarArgs();
+    }
+
+    @Override
+    public JavaType[] getExceptionTypes()
+    {
+        return ClassInfo.array(_method.getExceptionTypes());
+    }
+}

convert/source/java/main/org/adjective/syntactic/convert/j7to8/ConversionException.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  ------------------------------------------------------------------------
+ */
+package org.adjective.syntactic.convert.j7to8;
+
+public class ConversionException extends RuntimeException
+{
+    public ConversionException(final String message)
+    {
+        super(message);
+    }
+
+    public ConversionException(final String message, final Throwable cause)
+    {
+        super(message, cause);
+    }
+}

convert/source/java/main/org/adjective/syntactic/convert/j7to8/Convert7To8Visitor.java

 
 public class Convert7To8Visitor extends DefaultVisitor<Object, Object>
 {
-    private final Stack<String> className;
-    private final VariableStack vars;
-    private final List<Pair<VariableDeclarationNode, String>> toMarkFinal;
+    private final Stack<String> _className;
+    private final VariableStack _vars;
+    private final ClassFinder _classFinder;
+    private final Importer _importer;
+    private final List<Pair<VariableDeclarationNode, String>> _toMarkFinal;
 
     public Convert7To8Visitor()
     {
-        className = new Stack<String>();
-        vars = new VariableStack();
-        toMarkFinal = new ArrayList<Pair<VariableDeclarationNode, String>>();
+        _className = new Stack<String>();
+        _vars = new VariableStack();
+        _classFinder = new ClassFinder();
+        _importer = new Importer(_classFinder);
+        _toMarkFinal = new ArrayList<Pair<VariableDeclarationNode, String>>();
     }
 
     @Override
     public Object visit(final ASTCompilationUnit node, final Object data)
     {
         final Object val = super.visit(node, data);
-        for (Pair<VariableDeclarationNode, String> pair : toMarkFinal)
+        for (Pair<VariableDeclarationNode, String> pair : _toMarkFinal)
         {
             markFinal(pair.tail, pair.head);
         }
         return val;
     }
 
+    @Override
+    public Object visit(final ASTImportDeclaration node, final Object data)
+    {
+        _importer.add(node);
+        return super.visit(node, data);
+    }
+
     private void markFinal(final String name, final VariableDeclarationNode node)
     {
         if (node.isMultiVariable())
     @Override
     public Object visit(final ASTClassOrInterfaceDeclaration node, final Object data)
     {
-        className.push(node.getName().getIdentifier());
+        _className.push(node.getName().getIdentifier());
         try
         {
             return super.visit(node, data);
         }
         finally
         {
-            className.pop();
+            _className.pop();
         }
     }
 
     @Override
     public Object visit(final ASTMethodDeclaration node, final Object data)
     {
-        vars.pushScope();
+        _vars.pushScope();
         try
         {
             return super.visit(node, data);
         }
         finally
         {
-            vars.popScope();
+            _vars.popScope();
         }
     }
 
     @Override
     public Object visit(final ASTBlock node, final Object data)
     {
-        vars.pushScope();
+        _vars.pushScope();
         try
         {
             return super.visit(node, data);
         }
         finally
         {
-            vars.popScope();
+            _vars.popScope();
         }
     }
 
     @Override
     public Object visit(final ASTFormalParameter node, final Object data)
     {
-        vars.store(node.getName().getIdentifier(), node);
+        _vars.store(node.getName().getIdentifier(), node);
         return super.visit(node, data);
     }
 
     {
         for (ASTVariableDeclarator var : node.getVariables())
         {
-            // TODO - Split declaration if one var needs to be final
-            vars.store(var.getIdentifier().getIdentifier(), node);
+            _vars.store(var.getIdentifier().getIdentifier(), node);
 
             if (!var.hasInitializer())
             {
                 }
                 if (prefix.is(ASTThis.class))
                 {
-                    final ASTQualifiedIdentifier newPrefix = new ASTQualifiedIdentifier(className.peek());
+                    final ASTQualifiedIdentifier newPrefix = new ASTQualifiedIdentifier(_className.peek());
                     final ASTMemberSuffix newSuffix = new ASTMemberSuffix(prefix.as(ASTThis.class));
                     node.setTo(newPrefix, merge(newSuffix, node.getSuffixes()));
                 }
 
     private void markFinal(final String var)
     {
-        final VariableDeclarationNode node = vars.get(var);
+        final VariableDeclarationNode node = _vars.get(var);
         if (node == null)
         {
             return;
         }
-        toMarkFinal.add(new Pair<VariableDeclarationNode, String>(node, var));
+        _toMarkFinal.add(new Pair<VariableDeclarationNode, String>(node, var));
     }
 
     private <T> Iterable<T> merge(final T first, final Iterable<T> rest)
     private ASTMethodDeclaration makeMethodDeclaration(final JavaType forType, final ASTLambdaParameters parameters,
                                                        final ASTLambdaBody lambdaBody)
     {
-        assert forType.getTypeName().equals("Runnable"); // TODO lookup class
+        String name = forType.getTypeName();
+        if (forType.getParameterizedTypeName().length == 1)
+        {
+            String qN = _importer.getQualifiedName(name);
+            if (qN != null)
+            {
+                name = qN;
+            }
+        }
+
+        final TypeInfo typeInfo = _classFinder.getClass(name);
+        if (typeInfo == null)
+        {
+            throw new ConversionException("Cannot find '" + name + "'");
+        }
+        final MethodInfo[] methods = typeInfo.getMethods();
+        if (methods.length != 1)
+        {
+            throw new ConversionException("Class '" + typeInfo.getName() + "' should have exactly 1 method but has " + methods.length);
+        }
+
+        MethodInfo method = methods[0];
+
         final ASTMethodBody body = new ASTMethodBody(lambdaBody.getBlock());
-        return new ASTMethodDeclaration(new ASTVoidType(),
-                                        new ASTIdentifier("run"),
-                                        new ASTFormalParameters(),
+        return makeMethodDeclaration(method, body);
+    }
+
+    private ASTMethodDeclaration makeMethodDeclaration(final MethodInfo method, final ASTMethodBody body)
+    {
+        final ASTNameList exceptions = method.getExceptionTypes().length == 0 ? null : new ASTNameList(method.getExceptionTypes());
+        return new ASTMethodDeclaration(method.getReturnType(),
+                                        new ASTIdentifier(method.getName()),
+                                        makeFormalParameters(method),
                                         new ASTArraySuffixList(),
-                                        null,
+                                        exceptions,
                                         body);
     }
+
+    private ASTFormalParameters makeFormalParameters(final MethodInfo method)
+    {
+        final JavaType[] parameterTypes = method.getParameterTypes();
+        final String[] parameterNames = method.getParameterNames();
+        ASTFormalParameter[] formalParameters = new ASTFormalParameter[parameterTypes.length];
+        for (int i = 0; i < formalParameters.length; i++)
+        {
+            formalParameters[i] = new ASTFormalParameter(parameterTypes[i],
+                                                         i == formalParameters.length - 1 && method.isVarArgs(),
+                                                         parameterNames[i]);
+        }
+        return new ASTFormalParameters(formalParameters);
+    }
 }

convert/source/java/main/org/adjective/syntactic/convert/j7to8/Importer.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  ------------------------------------------------------------------------
+ */
+package org.adjective.syntactic.convert.j7to8;
+
+import org.adjective.syntactic.parser.ast.ASTImportDeclaration;
+import org.adjective.syntactic.parser.ast.ASTQualifiedIdentifier;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Importer
+{
+    private final ClassFinder _classFinder;
+    private final Map<String, String> typeImports;
+    private final List<String> typeOnDemandImports;
+
+    public Importer(final ClassFinder classFinder)
+    {
+        _classFinder = classFinder;
+        this.typeImports = new LinkedHashMap<String, String>();
+        this.typeOnDemandImports = new ArrayList<String>();
+    }
+
+    public void add(final ASTImportDeclaration node)
+    {
+        if (node.isStatic())
+        {
+            return;
+        }
+        final ASTQualifiedIdentifier identifier = node.getIdentifier();
+        if (node.isOnDemand())
+        {
+            typeOnDemandImports.add(identifier.getName());
+        }
+        else
+        {
+            typeImports.put(identifier.getLastIdentifier().getIdentifier(), identifier.getName());
+        }
+    }
+
+    public String getQualifiedName(String simpleName)
+    {
+        final String importedName = typeImports.get(simpleName);
+        if (importedName != null)
+        {
+            return importedName;
+        }
+        for (String pkg : typeOnDemandImports)
+        {
+            final String qualifiedName = lookupClass(pkg, simpleName);
+            if (qualifiedName != null)
+            {
+                return qualifiedName;
+            }
+        }
+        return lookupClass("java.lang", simpleName);
+    }
+
+    private String lookupClass(final String pkg, final String simpleName)
+    {
+        final String qualifiedName = pkg + "." + simpleName;
+        if (classExists(qualifiedName))
+        {
+            return qualifiedName;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    private boolean classExists(final String qualifiedName)
+    {
+        return _classFinder.hasClass(qualifiedName);
+    }
+}

convert/source/java/main/org/adjective/syntactic/convert/j7to8/MethodInfo.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  ------------------------------------------------------------------------
+ */
+package org.adjective.syntactic.convert.j7to8;
+
+import org.adjective.syntactic.parser.util.JavaType;
+
+public interface MethodInfo {
+
+    public JavaType getReturnType();
+    public String getName();
+    public JavaType[] getParameterTypes();
+    public String[] getParameterNames();
+    public boolean isVarArgs();
+    public JavaType[] getExceptionTypes();
+}

convert/source/java/main/org/adjective/syntactic/convert/j7to8/TypeInfo.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  ------------------------------------------------------------------------
+ */
+package org.adjective.syntactic.convert.j7to8;
+
+public interface TypeInfo
+{
+    public MethodInfo[] getMethods();
+    public String getName();
+}

convert/source/java/main/org/adjective/syntactic/convert/j7to8/VariableStack.java

 
     public void store(String name, VariableDeclarationNode var)
     {
-        System.err.println("Store: " + name + " [ " + var + "]");
         final Map<String, VariableDeclarationNode> map = _stack.peek();
         if (map.containsKey(name))
         {

convert/source/java/samples/sample/LambdaEffectiveFinal.java

  */
 package sample;
 
+import java.util.concurrent.Callable;
+
 public class LambdaEffectiveFinal
 {
-    public Runnable getRunnable(int i)
+    public Callable<Integer> getCallable(int i)
     {
-        int j = -i, k=9;
-        Runnable r = () -> {
-            System.out.println(i + " : " + j);
-        };
+        int j = -i, k=j;
+        Callable<Integer> c = () -> { return i*j; };
         k++;
-        return r;
+        return c;
     }
 }