org.eclipse.imp.asl.compiler.ASLCompiler.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.imp.asl.compiler.ASLCompiler.java

Source

/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation
    
*******************************************************************************/

package org.eclipse.imp.asl.compiler;

import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.imp.asl.ASLPlugin;
import org.eclipse.imp.asl.parser.ASLParseController;
import org.eclipse.imp.asl.parser.ast.ASTNode;
import org.eclipse.imp.asl.parser.ast.AbstractVisitor;
import org.eclipse.imp.asl.parser.ast.ItypeName;
import org.eclipse.imp.asl.parser.ast.algebraicTypeDeclaration;
import org.eclipse.imp.asl.parser.ast.ctorDeclaration;
import org.eclipse.imp.asl.parser.ast.formalArg;
import org.eclipse.imp.asl.parser.ast.formalArgList;
import org.eclipse.imp.asl.parser.ast.identifier;
import org.eclipse.imp.asl.parser.ast.optFormalArgList;
import org.eclipse.imp.asl.parser.ast.typeName0;
import org.eclipse.imp.asl.parser.ast.typeName1;
import org.eclipse.imp.asl.parser.ast.typeName2;
import org.eclipse.imp.asl.parser.ast.typeName3;
import org.eclipse.imp.builder.BuilderUtils;
import org.eclipse.imp.builder.MarkerCreator;
import org.eclipse.imp.model.ISourceProject;
import org.eclipse.imp.model.ModelFactory;
import org.eclipse.imp.model.ModelFactory.ModelException;
import org.eclipse.imp.parser.IParseController;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

public class ASLCompiler {
    public static class Pair<T1, T2> {
        public final T1 fFirst;
        public final T2 fSecond;

        public Pair(T1 v1, T2 v2) {
            fFirst = v1;
            fSecond = v2;
        }
    }

    public class Constructor {
        private final Type fOwningType;
        private List<Pair<String, String>> fArguments = new ArrayList<Pair<String, String>>();

        public Constructor(Type newType) {
            fOwningType = newType;
            fOwningType.addConstructor(this);
        }

        public void addArgument(String type, String name) {
            fArguments.add(new Pair<String, String>(type, name));
        }

        public List<Pair<String, String>> getArguments() {
            return fArguments;
        }

        public void generate(PrintWriter pw) {
            pw.print("    public " + fOwningType.fName + "(");
            int idx = 0;
            for (Pair<String, String> arg : fArguments) {
                if (idx > 0) {
                    pw.print(", ");
                }
                pw.print(arg.fFirst);
                pw.print(' ');
                pw.print(arg.fSecond);
            }
            pw.println(") {");
            for (Pair<String, String> arg : fArguments) {
                pw.println("        this." + arg.fSecond + " = " + arg.fSecond + ";");
            }
            pw.println("    }");
        }

        public Set<String> getReferencedTypes() {
            Set<String> result = new HashSet<String>();
            for (Pair<String, String> arg : fArguments) {
                result.add(arg.fFirst);
            }
            return result;
        }
    }

    public class Type {
        private final String fPackage;
        private final String fName;
        private final List<Constructor> fConstructors = new ArrayList<Constructor>();
        private final List<String> fImports = new ArrayList<String>();
        private final List<Pair<String, String>> fFields = new ArrayList<Pair<String, String>>();

        public Type(String typeName, String pkg) {
            fName = typeName;
            fPackage = pkg;
        }

        public void addConstructor(Constructor ctor) {
            fConstructors.add(ctor);
        }

        private void collectFields() {
            for (Constructor ctor : fConstructors) {
                fFields.addAll(ctor.getArguments());
            }
            Collections.sort(fImports);
        }

        private void collectTypes() {
            for (Constructor ctor : fConstructors) {
                fImports.addAll(ctor.getReferencedTypes());
            }
            Collections.sort(fImports);
        }

        public void generate(IProgressMonitor mon) {
            final String fileName = fName + ".java";
            IFile newFile = fFile.getProject()
                    .getFile(fFile.getProjectRelativePath().removeLastSegments(1).append(fileName));
            StringWriter sw = new StringWriter(256);

            collectTypes();
            collectFields();
            generate(new PrintWriter(sw));

            String typeSource = sw.toString();
            ByteArrayInputStream bais = new ByteArrayInputStream(typeSource.getBytes());

            try {
                if (!newFile.exists()) {
                    newFile.create(bais, true, mon);
                } else {
                    newFile.setContents(bais, true, false, mon);
                }
            } catch (CoreException ce) {
                System.err.println(ce.getMessage());
            }
        }

        public void generate(PrintWriter pw) {
            if (fPackage != null && fPackage.length() > 0) {
                pw.println("package " + fPackage + ";");
            }
            pw.println();
            if (!fImports.isEmpty()) {
                for (String imp : fImports) {
                    pw.println("import " + imp + ";");
                }
                pw.println();
            }
            pw.println("public class " + fName + " {");
            for (Pair<String, String> field : fFields) {
                pw.println("    " + field.fFirst + " " + field.fSecond + ";");
            }
            for (Constructor ctor : fConstructors) {
                ctor.generate(pw);
            }
            pw.println("}");
        }
    }

    public String PROBLEM_MARKER_ID;

    private IFile fFile;

    private String fPackage;

    public ASLCompiler(String problem_marker_id) {
        PROBLEM_MARKER_ID = problem_marker_id;
    }

    private final class TranslatorVisitor extends AbstractVisitor {
        private String fParentType;
        private final IProgressMonitor fMonitor;

        public TranslatorVisitor(IFile file, IProgressMonitor mon) {
            fFile = file;
            fMonitor = mon;
        }

        public void unimplementedVisitor(String s) {
            // System.err.println("Don't know how to translate node type '" + s + "'.");
        }

        @Override
        public boolean visit(algebraicTypeDeclaration n) {
            fParentType = n.getidentifier().getIDENTIFIER().toString();
            return true;
        }

        @Override
        public boolean visit(ctorDeclaration n) {
            String typeName = n.getidentifier().getIDENTIFIER().toString();
            Type newType = new Type(typeName, fPackage);
            Constructor ctor = new Constructor(newType);
            final optFormalArgList formalArgList = n.getoptFormalArgList();
            if (formalArgList != null) {
                formalArgList argList = formalArgList.getformalArgList();
                for (int i = 0; i < argList.size(); i++) {
                    formalArg arg = argList.getformalArgAt(i);
                    final String argType = getNameForType(arg.gettype());
                    String name = arg.getname().getIDENTIFIER().toString();
                    ctor.addArgument(argType, name);
                }
            }
            newType.generate(fMonitor);
            return true;
        }

        private String getNameForType(ItypeName type) {
            if (type instanceof typeName0) {
                return "int";
            } else if (type instanceof typeName1) {
                return "double";
            } else if (type instanceof typeName2) {
                return "boolean";
            } else if (type instanceof typeName3) {
                return "String";
            }
            return ((identifier) type).toString();
        }
    }

    public ASLCompiler() {
        super();
    }

    public String getFileContents(IFile file) {
        try {
            return BuilderUtils.getFileContents(file);
        } catch (Exception e) {
            System.err.println("ASLCompiler.getFileContents(..):  " + e.getMessage());
        }
        return "";
    }

    private String getPackageFor(IFile file) throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(file.getProject());
        IPath srcFolderRelPath = findSrcFolderRelativePath(file, javaProject);
        return srcFolderRelPath.toPortableString().replace('/', '.');
    }

    private IPath findSrcFolderRelativePath(IFile file, IJavaProject javaProject) throws JavaModelException {
        final IPath folderPath = file.getFullPath().removeLastSegments(1);
        IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);

        for (IClasspathEntry entry : entries) {
            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                final IPath entryPath = entry.getPath();
                if (entryPath.isPrefixOf(folderPath)) {
                    int segCount = entryPath.matchingFirstSegments(folderPath);
                    return folderPath.removeFirstSegments(segCount);
                }
            }
        }
        return null;
    }

    public void compile(IFile file, IProgressMonitor mon) {
        if (file == null) {
            System.err.println("ASLCompiler.compile(..):  File is null; returning without parsing");
            return;
        }
        IProject project = file.getProject();
        if (project == null) {
            System.err.println("ASLCompiler.compile(..):  Project is null; returning without parsing");
            return;
        }
        ISourceProject sourceProject = null;
        try {
            sourceProject = ModelFactory.open(project);
        } catch (ModelException me) {
            System.err.println("ASLCompiler.compile(..):  Model exception:\n" + me.getMessage()
                    + "\nReturning without parsing");
            return;
        }
        try {
            fPackage = getPackageFor(file);
        } catch (JavaModelException e) {
            ASLPlugin.getInstance()
                    .logException("Exception encountered determining package containing ASL source file.", e);
            return;
        }
        IParseController parseController = new ASLParseController();
        // Marker creator handles error messages from the parse controller
        MarkerCreator markerCreator = new MarkerCreator(file, PROBLEM_MARKER_ID);
        // If we have a kind of parser that might be receptive, tell it
        // what types of problem marker the builder will create
        parseController.getAnnotationTypeInfo().addProblemMarkerType(PROBLEM_MARKER_ID);
        parseController.initialize(file.getProjectRelativePath(), sourceProject, markerCreator);
        parseController.parse(getFileContents(file), mon);
        ASTNode currentAst = (ASTNode) parseController.getCurrentAst();
        if (currentAst == null) {
            System.err.println("ASLCompiler.compile(..):  current AST is null (parse errors?); unable to compile.");
            return;
        }
        currentAst.accept(new TranslatorVisitor(file, mon));
    }
}