diff options
Diffstat (limited to 'typecheck/library')
| -rw-r--r-- | typecheck/library/PPrinter.java | 737 | ||||
| -rw-r--r-- | typecheck/library/SymTableVis.java | 101 | ||||
| -rw-r--r-- | typecheck/library/TypeCheckSimp.java | 1070 | ||||
| -rw-r--r-- | typecheck/library/TypeEnum.java | 5 | ||||
| -rw-r--r-- | typecheck/library/TypeInstance.java | 43 | ||||
| -rw-r--r-- | typecheck/library/Utilities.java | 14 | 
6 files changed, 1970 insertions, 0 deletions
| diff --git a/typecheck/library/PPrinter.java b/typecheck/library/PPrinter.java new file mode 100644 index 0000000..e8e1b15 --- /dev/null +++ b/typecheck/library/PPrinter.java @@ -0,0 +1,737 @@ +package typecheck.library; + +import syntaxtree.*; +import visitor.*; +import java.util.*; + +/** + * Provides default methods which visit each node in the tree in depth-first + * order.  Your visitors may extend this class. + */ +public class PPrinter<R,A> extends GJDepthFirst<R,A> { + +    private int offset; + +    private void printNode(Node n, A argu) { +        for (int i=0; i < this.offset; ++i) +            Utilities.print_filter(".", false); +        Utilities.print_filter(n.getClass().getSimpleName(), true); +        ++this.offset; +    } + +    // +    // User-generated visitor methods below +    // + +    /** +     * f0 -> MainClass() +     * f1 -> ( TypeDeclaration() )* +     * f2 -> <EOF> +     */ +    public R visit(Goal n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "class" +     * f1 -> Identifier() +     * f2 -> "{" +     * f3 -> "public" +     * f4 -> "static" +     * f5 -> "void" +     * f6 -> "main" +     * f7 -> "(" +     * f8 -> "String" +     * f9 -> "[" +     * f10 -> "]" +     * f11 -> Identifier() +     * f12 -> ")" +     * f13 -> "{" +     * f14 -> ( VarDeclaration() )* +     * f15 -> ( Statement() )* +     * f16 -> "}" +     * f17 -> "}" +     */ +    public R visit(MainClass n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        n.f7.accept(this, argu); +        n.f8.accept(this, argu); +        n.f9.accept(this, argu); +        n.f10.accept(this, argu); +        n.f11.accept(this, argu); +        n.f12.accept(this, argu); +        n.f13.accept(this, argu); +        n.f14.accept(this, argu); +        n.f15.accept(this, argu); +        n.f16.accept(this, argu); +        n.f17.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> ClassDeclaration() +     *       | ClassExtendsDeclaration() +     */ +    public R visit(TypeDeclaration n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "class" +     * f1 -> Identifier() +     * f2 -> "{" +     * f3 -> ( VarDeclaration() )* +     * f4 -> ( MethodDeclaration() )* +     * f5 -> "}" +     */ +    public R visit(ClassDeclaration n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "class" +     * f1 -> Identifier() +     * f2 -> "extends" +     * f3 -> Identifier() +     * f4 -> "{" +     * f5 -> ( VarDeclaration() )* +     * f6 -> ( MethodDeclaration() )* +     * f7 -> "}" +     */ +    public R visit(ClassExtendsDeclaration n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        n.f7.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> Type() +     * f1 -> Identifier() +     * f2 -> ";" +     */ +    public R visit(VarDeclaration n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "public" +     * f1 -> Type() +     * f2 -> Identifier() +     * f3 -> "(" +     * f4 -> ( FormalParameterList() )? +     * f5 -> ")" +     * f6 -> "{" +     * f7 -> ( VarDeclaration() )* +     * f8 -> ( Statement() )* +     * f9 -> "return" +     * f10 -> Expression() +     * f11 -> ";" +     * f12 -> "}" +     */ +    public R visit(MethodDeclaration n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        n.f7.accept(this, argu); +        n.f8.accept(this, argu); +        n.f9.accept(this, argu); +        n.f10.accept(this, argu); +        n.f11.accept(this, argu); +        n.f12.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> FormalParameter() +     * f1 -> ( FormalParameterRest() )* +     */ +    public R visit(FormalParameterList n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> Type() +     * f1 -> Identifier() +     */ +    public R visit(FormalParameter n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "," +     * f1 -> FormalParameter() +     */ +    public R visit(FormalParameterRest n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> ArrayType() +     *       | BooleanType() +     *       | IntegerType() +     *       | Identifier() +     */ +    public R visit(Type n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "int" +     * f1 -> "[" +     * f2 -> "]" +     */ +    public R visit(ArrayType n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "boolean" +     */ +    public R visit(BooleanType n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "int" +     */ +    public R visit(IntegerType n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> Block() +     *       | AssignmentStatement() +     *       | ArrayAssignmentStatement() +     *       | IfStatement() +     *       | WhileStatement() +     *       | PrintStatement() +     */ +    public R visit(Statement n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "{" +     * f1 -> ( Statement() )* +     * f2 -> "}" +     */ +    public R visit(Block n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> Identifier() +     * f1 -> "=" +     * f2 -> Expression() +     * f3 -> ";" +     */ +    public R visit(AssignmentStatement n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> Identifier() +     * f1 -> "[" +     * f2 -> Expression() +     * f3 -> "]" +     * f4 -> "=" +     * f5 -> Expression() +     * f6 -> ";" +     */ +    public R visit(ArrayAssignmentStatement n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "if" +     * f1 -> "(" +     * f2 -> Expression() +     * f3 -> ")" +     * f4 -> Statement() +     * f5 -> "else" +     * f6 -> Statement() +     */ +    public R visit(IfStatement n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "while" +     * f1 -> "(" +     * f2 -> Expression() +     * f3 -> ")" +     * f4 -> Statement() +     */ +    public R visit(WhileStatement n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "System.out.println" +     * f1 -> "(" +     * f2 -> Expression() +     * f3 -> ")" +     * f4 -> ";" +     */ +    public R visit(PrintStatement n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> AndExpression() +     *       | CompareExpression() +     *       | PlusExpression() +     *       | MinusExpression() +     *       | TimesExpression() +     *       | ArrayLookup() +     *       | ArrayLength() +     *       | MessageSend() +     *       | PrimaryExpression() +     */ +    public R visit(Expression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "&&" +     * f2 -> PrimaryExpression() +     */ +    public R visit(AndExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "<" +     * f2 -> PrimaryExpression() +     */ +    public R visit(CompareExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "+" +     * f2 -> PrimaryExpression() +     */ +    public R visit(PlusExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "-" +     * f2 -> PrimaryExpression() +     */ +    public R visit(MinusExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "*" +     * f2 -> PrimaryExpression() +     */ +    public R visit(TimesExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "[" +     * f2 -> PrimaryExpression() +     * f3 -> "]" +     */ +    public R visit(ArrayLookup n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "." +     * f2 -> "length" +     */ +    public R visit(ArrayLength n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> PrimaryExpression() +     * f1 -> "." +     * f2 -> Identifier() +     * f3 -> "(" +     * f4 -> ( ExpressionList() )? +     * f5 -> ")" +     */ +    public R visit(MessageSend n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> Expression() +     * f1 -> ( ExpressionRest() )* +     */ +    public R visit(ExpressionList n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "," +     * f1 -> Expression() +     */ +    public R visit(ExpressionRest n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> IntegerLiteral() +     *       | TrueLiteral() +     *       | FalseLiteral() +     *       | Identifier() +     *       | ThisExpression() +     *       | ArrayAllocationExpression() +     *       | AllocationExpression() +     *       | NotExpression() +     *       | BracketExpression() +     */ +    public R visit(PrimaryExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> <INTEGER_LITERAL> +     */ +    public R visit(IntegerLiteral n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "true" +     */ +    public R visit(TrueLiteral n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "false" +     */ +    public R visit(FalseLiteral n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> <IDENTIFIER> +     */ +    public R visit(Identifier n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "this" +     */ +    public R visit(ThisExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "new" +     * f1 -> "int" +     * f2 -> "[" +     * f3 -> Expression() +     * f4 -> "]" +     */ +    public R visit(ArrayAllocationExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "new" +     * f1 -> Identifier() +     * f2 -> "(" +     * f3 -> ")" +     */ +    public R visit(AllocationExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "!" +     * f1 -> Expression() +     */ +    public R visit(NotExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    /** +     * f0 -> "(" +     * f1 -> Expression() +     * f2 -> ")" +     */ +    public R visit(BracketExpression n, A argu) { +        this.printNode(n, argu); +        R _ret=null; +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        --this.offset; +        return _ret; +    } + +    public R visit(NodeToken n, A argu) { +        for (int i=0; i < this.offset; ++i) +            Utilities.print_filter(".", false); +        Utilities.print_filter(n.getClass().getSimpleName() + +                               " => " + +                               n.toString(), true); +        R _ret=null; +        return _ret; +    } + +} diff --git a/typecheck/library/SymTableVis.java b/typecheck/library/SymTableVis.java new file mode 100644 index 0000000..615b1c9 --- /dev/null +++ b/typecheck/library/SymTableVis.java @@ -0,0 +1,101 @@ +package typecheck.library; + +import syntaxtree.*; +import visitor.*; +import java.util.*; + +/** + * Provides default methods which visit each node in the tree in depth-first + * order.  Your visitors may extend this class. + */ +public class SymTableVis<R,A> extends GJDepthFirst<R,A> { + +    public HashMap<String,TypeInstance> symt = new HashMap<>(); + +    /** +     * f0 -> "class" +     * f1 -> Identifier() +     * f2 -> "{" +     * f3 -> "public" +     * f4 -> "static" +     * f5 -> "void" +     * f6 -> "main" +     * f7 -> "(" +     * f8 -> "String" +     * f9 -> "[" +     * f10 -> "]" +     * f11 -> Identifier() +     * f12 -> ")" +     * f13 -> "{" +     * f14 -> ( VarDeclaration() )* +     * f15 -> ( Statement() )* +     * f16 -> "}" +     * f17 -> "}" +     */ +    public R visit(MainClass n, A argu) { + +        n.f1.accept(this, argu); +        n.f11.accept(this, argu); +        n.f14.accept(this, argu); +        n.f15.accept(this, argu); + +        Utilities.print_filter("Processing main", true); + +        String id = n.f1.f0.tokenImage; + +        TypeInstance type = new TypeInstance(id, TypeEnum.classname); +        Utilities.print_filter("Inserting " + id + " => " + type, true); +        symt.put(id, type); + +        return null; + +    } + +    /** +     * f0 -> Type() +     * f1 -> Identifier() +     * f2 -> ";" +     */ +    public R visit(VarDeclaration n, A argu) { + +        Utilities.print_filter("Processing declaration", true); + +        String id = n.f1.f0.tokenImage; +        TypeInstance type = new TypeInstance("ERROR", TypeEnum.ERROR); +        switch (n.f0.f0.which) { +        case 0: +            type = new TypeInstance("int_array", TypeEnum.int_array); break; +        case 1: +            type = new TypeInstance("bool", TypeEnum.bool); break; +        case 2: +            type = new TypeInstance("int", TypeEnum.integer); break; +        case 3: +            type = new TypeInstance(id, TypeEnum.classname); break; +        default: +            Utilities.print_filter("Unsupported case", true); +        } + +        Utilities.print_filter("Inserting " + id + " => " + type, true); +        // Safe? +        symt.put(id, type); + +        return null; +    } + +    public R visit(ClassDeclaration n, A argu) { + +        Utilities.print_filter("Processing class", true); + +        String id = n.f1.f0.tokenImage; + +        TypeInstance type = new TypeInstance(id, TypeEnum.classname); +        Utilities.print_filter("Inserting " + id + " => " + type, true); +        // Safe? +        symt.put(id, type); + +        return null; + +    } + + +} diff --git a/typecheck/library/TypeCheckSimp.java b/typecheck/library/TypeCheckSimp.java new file mode 100644 index 0000000..b4844a1 --- /dev/null +++ b/typecheck/library/TypeCheckSimp.java @@ -0,0 +1,1070 @@ +package typecheck.library; + +import syntaxtree.*; +import visitor.*; +import java.util.*; + +/** + * Provides default methods which visit each node in the tree in depth-first + * order.  Your visitors may extend this class. + */ +public class TypeCheckSimp implements GJVisitor<TypeInstance,HashMap<String,TypeInstance>> { + +    private int offset; + +    private void printNode(Node n, HashMap<String,TypeInstance> argu, boolean enter, TypeEnum consensus) { +        for (int i=0; i < this.offset; ++i) +            Utilities.print_filter(".", false); +        if (enter) +            Utilities.print_filter("Visiting ", false); +        else +            Utilities.print_filter("Leaving ", false); +        Utilities.print_filter(n.getClass().getSimpleName(), false); +        if (!enter) { +            if (consensus == TypeEnum.ERROR) +                Utilities.print_filter(" did not type check.", false); +            else +                Utilities.print_filter(" found type " + consensus, false); +        } +        Utilities.print_filter("", true); +    } + +    public TypeInstance visit(NodeList n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = new TypeInstance(null, TypeEnum.CHECK); +        int _count=0; +        for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { +            TypeInstance node = e.nextElement().accept(this,argu); +            e.nextElement().accept(this,argu); +            if (node.get_type() == TypeEnum.ERROR) +                ret = node; +            _count++; +        } + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    public TypeInstance visit(NodeListOptional n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret; +        if ( n.present() ) { +            ret = new TypeInstance(null, TypeEnum.CHECK); +            int _count=0; +            for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { +                TypeInstance node = e.nextElement().accept(this,argu); +                if (node.get_type() == TypeEnum.ERROR) +                    ret = node; +                _count++; +            } +        } +        else +            ret = new TypeInstance(null, TypeEnum.CHECK); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME +    public TypeInstance visit(NodeOptional n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret; + +        if ( n.present() ) +            ret = n.node.accept(this,argu); +        else +            ret = new TypeInstance(null, TypeEnum.CHECK); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    public TypeInstance visit(NodeSequence n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = new TypeInstance(null, TypeEnum.CHECK); +        int _count=0; +        for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { +            TypeInstance node = e.nextElement().accept(this,argu); +            if (node.get_type() == TypeEnum.ERROR) +                ret = node; +            _count++; +        } + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    public TypeInstance visit(NodeToken n, HashMap<String,TypeInstance> argu) { +        // A fixed string token. '⌣' +        for (int i=0; i < this.offset; ++i) +            Utilities.print_filter(".", false); +        Utilities.print_filter("Leaving " + n.getClass().getSimpleName() + +                               " => " + +                               n.toString(), true); +        return null; +    } + +    // +    // User-generated visitor methods below +    // + +    /** +     * f0 -> MainClass() +     * f1 -> ( TypeDeclaration() )* +     * f2 -> <EOF> +     */ +    public TypeInstance visit(Goal n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "class" +     * f1 -> Identifier() +     * f2 -> "{" +     * f3 -> "public" +     * f4 -> "static" +     * f5 -> "void" +     * f6 -> "main" +     * f7 -> "(" +     * f8 -> "String" +     * f9 -> "[" +     * f10 -> "]" +     * f11 -> Identifier() +     * f12 -> ")" +     * f13 -> "{" +     * f14 -> ( VarDeclaration() )* +     * f15 -> ( Statement() )* +     * f16 -> "}" +     * f17 -> "}" +     */ +    public TypeInstance visit(MainClass n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance name = n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        n.f7.accept(this, argu); +        n.f8.accept(this, argu); +        n.f9.accept(this, argu); +        n.f10.accept(this, argu); +        // TypeInstance args = n.f11.accept(this, argu); // FIXME Type in the main class declaration uses an illegal minijava type? +        n.f12.accept(this, argu); +        n.f13.accept(this, argu); +        TypeInstance var_dec = n.f14.accept(this, argu); +        TypeInstance stmt = n.f15.accept(this, argu); +        n.f16.accept(this, argu); +        n.f17.accept(this, argu); + +        this.printNode(n, argu, false, stmt.get_type()); +        --this.offset; +        return stmt; +    } + +    /** +     * f0 -> ClassDeclaration() +     *                               | ClassExtendsDeclaration() +     */ +    public TypeInstance visit(TypeDeclaration n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = n.f0.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "class" +     * f1 -> Identifier() +     * f2 -> "{" +     * f3 -> ( VarDeclaration() )* +     * f4 -> ( MethodDeclaration() )* +     * f5 -> "}" +     */ +    public TypeInstance visit(ClassDeclaration n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance id = n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        TypeInstance vars = n.f3.accept(this, argu); +        TypeInstance mehs = n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        TypeInstance ret = (id.get_type() == TypeEnum.classname && +                            vars.has_checked() && +                            mehs.has_checked()) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "class" +     * f1 -> Identifier() +     * f2 -> "extends" +     * f3 -> Identifier() +     * f4 -> "{" +     * f5 -> ( VarDeclaration() )* +     * f6 -> ( MethodDeclaration() )* +     * f7 -> "}" +     */ +    public TypeInstance visit(ClassExtendsDeclaration n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance id = n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        TypeInstance ext = n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        TypeInstance vars = n.f5.accept(this, argu); +        TypeInstance mehs = n.f6.accept(this, argu); +        n.f7.accept(this, argu); +        TypeInstance ret = (id.get_type() == TypeEnum.classname && +                            vars.has_checked() && +                            mehs.has_checked()) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME (this may be ST-only) +    /** +     * f0 -> Type() +     * f1 -> Identifier() +     * f2 -> ";" +     */ +    public TypeInstance visit(VarDeclaration n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME +    /** +     * f0 -> "public" +     * f1 -> Type() +     * f2 -> Identifier() +     * f3 -> "(" +     * f4 -> ( FormalParameterList() )? +     * f5 -> ")" +     * f6 -> "{" +     * f7 -> ( VarDeclaration() )* +     * f8 -> ( Statement() )* +     * f9 -> "return" +     * f10 -> Expression() +     * f11 -> ";" +     * f12 -> "}" +     */ +    public TypeInstance visit(MethodDeclaration n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret_type = n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        n.f7.accept(this, argu); +        TypeInstance stmt = n.f8.accept(this, argu); +        n.f9.accept(this, argu); +        TypeInstance retur = n.f10.accept(this, argu); +        n.f11.accept(this, argu); +        n.f12.accept(this, argu); +        TypeInstance ret = (stmt.equal_type(ret_type) && +                            stmt.has_checked()) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> FormalParameter() +     * f1 -> ( FormalParameterRest() )* +     */ +    public TypeInstance visit(FormalParameterList n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance _ret=null; +        TypeInstance para1 = n.f0.accept(this, argu); +        TypeInstance parar = n.f1.accept(this, argu); +        TypeInstance ret = (para1.has_checked() && +                            parar.has_checked()) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> Type() +     * f1 -> Identifier() +     */ +    public TypeInstance visit(FormalParameter n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = n.f0.accept(this, argu); +        n.f1.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "," +     * f1 -> FormalParameter() +     */ +    public TypeInstance visit(FormalParameterRest n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret = n.f1.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> ArrayType() +     *                               | BooleanType() +     *                               | IntegerType() +     *                               | Identifier() +     */ +    public TypeInstance visit(Type n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret =      n.f0.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "int" +     * f1 -> "[" +     * f2 -> "]" +     */ +    public TypeInstance visit(ArrayType n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = new TypeInstance(null, TypeEnum.int_array); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "boolean" +     */ +    public TypeInstance visit(BooleanType n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret =      new TypeInstance(null, TypeEnum.bool); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "int" +     */ +    public TypeInstance visit(IntegerType n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret =      new TypeInstance(null, TypeEnum.integer); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> Block() +     *                               | AssignmentStatement() +     *                               | ArrayAssignmentStatement() +     *                               | IfStatement() +     *                               | WhileStatement() +     *                               | PrintStatement() +     */ +    public TypeInstance visit(Statement n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret =      n.f0.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "{" +     * f1 -> ( Statement() )* +     * f2 -> "}" +     */ +    public TypeInstance visit(Block n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret = n.f1.accept(this, argu); +        n.f2.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME FIXME FIXME +    // Given we only have a few types, what is a subtype of what? +    /** +     * [23]: Expression is a subtype of identifier, and e typechecks* +     * +     * f0 -> Identifier() +     * f1 -> "=" +     * f2 -> Expression() +     * f3 -> ";" +     */ +    public TypeInstance visit(AssignmentStatement n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance lhs = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance rhs = n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        TypeInstance ret = (lhs.equal_type(rhs)) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME (this may be done) +    /** +     * [24]: Identifier is an integer array, expressions are both integers +     * +     * f0 -> Identifier() +     * f1 -> "[" +     * f2 -> Expression() +     * f3 -> "]" +     * f4 -> "=" +     * f5 -> Expression() +     * f6 -> ";" +     */ +    public TypeInstance visit(ArrayAssignmentStatement n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance id = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance index = n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        TypeInstance value = n.f5.accept(this, argu); +        n.f6.accept(this, argu); +        TypeInstance ret =      (id.get_type() == TypeEnum.int_array && +                                 index.get_type() == TypeEnum.integer && +                                 value.get_type() == TypeEnum.integer) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [25]: Expression is a bool, both statements type-check +     * +     * f0 -> "if" +     * f1 -> "(" +     * f2 -> Expression() +     * f3 -> ")" +     * f4 -> Statement() +     * f5 -> "else" +     * f6 -> Statement() +     */ +    public TypeInstance visit(IfStatement n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance expr = n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        TypeInstance stmt1 = n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        TypeInstance stmt2 = n.f6.accept(this, argu); +        TypeInstance ret = (expr.get_type() == TypeEnum.bool && +                            stmt1.get_type() == stmt2.get_type() && +                            stmt1.has_checked()) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; + +    } + +    /** +     * DONE [26]: Expression is a bool, statement type-checks +     * +     * f0 -> "while" +     * f1 -> "(" +     * f2 -> Expression() +     * f3 -> ")" +     * f4 -> Statement() +     */ +    public TypeInstance visit(WhileStatement n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance expr = n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        TypeInstance stmt = n.f4.accept(this, argu); +        TypeInstance ret = (expr.get_type() == TypeEnum.bool && +                            stmt.has_checked()) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [27]: Expression is an integer +     * +     * f0 -> "System.out.println" +     * f1 -> "(" +     * f2 -> Expression() +     * f3 -> ")" +     * f4 -> ";" +     */ +    public TypeInstance visit(PrintStatement n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance ret = n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        ret = (ret.get_type() == TypeEnum.integer) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> AndExpression() +     *                               | CompareExpression() +     *                               | PlusExpression() +     *                               | MinusExpression() +     *                               | TimesExpression() +     *                               | ArrayLookup() +     *                               | ArrayLength() +     *                               | MessageSend() +     *                               | PrimaryExpression() +     */ +    public TypeInstance visit(Expression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = n.f0.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [28]: If expressions are both booleans, return is a boolean +     * +     * f0 -> PrimaryExpression() +     * f1 -> "&&" +     * f2 -> PrimaryExpression() +     */ +    public TypeInstance visit(AndExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance oper1 = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance oper2 = n.f2.accept(this, argu); +        TypeInstance ret = (oper1.get_type() == TypeEnum.bool && +                            oper2.get_type() == TypeEnum.bool) ? +            new TypeInstance(null, TypeEnum.bool) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [29]: If expressions are both integers, return is a boolean +     * +     * f0 -> PrimaryExpression() +     * f1 -> "<" +     * f2 -> PrimaryExpression() +     */ +    public TypeInstance visit(CompareExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance oper1 = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance oper2 = n.f2.accept(this, argu); +        TypeInstance ret = (oper1.get_type() == TypeEnum.integer && +                            oper2.get_type() == TypeEnum.integer) ? +            new TypeInstance(null, TypeEnum.bool) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [30]: If expressions are both integers, return is an integer +     * +     * f0 -> PrimaryExpression() +     * f1 -> "+" +     * f2 -> PrimaryExpression() +     */ +    public TypeInstance visit(PlusExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance oper1 = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance oper2 = n.f2.accept(this, argu); +        TypeInstance ret = (oper1.get_type() == TypeEnum.integer && +                            oper2.get_type() == TypeEnum.integer) ? +            new TypeInstance(null, TypeEnum.integer) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [31]: If expressions are both integers, return is an integer +     * +     * f0 -> PrimaryExpression() +     * f1 -> "-" +     * f2 -> PrimaryExpression() +     */ +    public TypeInstance visit(MinusExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance oper1 = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance oper2 = n.f2.accept(this, argu); +        TypeInstance ret = (oper1.get_type() == TypeEnum.integer && +                            oper2.get_type() == TypeEnum.integer) ? +            new TypeInstance(null, TypeEnum.integer) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [32]: If expressions are both integers, return is an integer +     * +     * f0 -> PrimaryExpression() +     * f1 -> "*" +     * f2 -> PrimaryExpression() +     */ +    public TypeInstance visit(TimesExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance oper1 = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance oper2 = n.f2.accept(this, argu); +        TypeInstance ret = (oper1.get_type() == TypeEnum.integer && +                            oper2.get_type() == TypeEnum.integer) ? +            new TypeInstance(null, TypeEnum.integer) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [33]: If expr1 is an integer array and expr2 is an int, +     * return is an int +     * +     * f0 -> PrimaryExpression() +     * f1 -> "[" +     * f2 -> PrimaryExpression() +     * f3 -> "]" +     */ +    public TypeInstance visit(ArrayLookup n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance array = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        TypeInstance index = n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        TypeInstance ret = (array.get_type() == TypeEnum.int_array && +                            index.get_type() == TypeEnum.integer) ? +            new TypeInstance(null, TypeEnum.integer) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [34]: If expr1 is an integer array, return is an int +     * +     * f0 -> PrimaryExpression() +     * f1 -> "." +     * f2 -> "length" +     */ +    public TypeInstance visit(ArrayLength n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        ret = (ret.get_type() == TypeEnum.int_array) ? new TypeInstance(null, TypeEnum.integer) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME FIXME FIXME +    /** +     * [35]: PrimaryExpr must be a classname, id must be a method name, expressionlist must be correct? +     * +     * f0 -> PrimaryExpression() +     * f1 -> "." +     * f2 -> Identifier() +     * f3 -> "(" +     * f4 -> ( ExpressionList() )? +     * f5 -> ")" +     */ +    public TypeInstance visit(MessageSend n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        n.f5.accept(this, argu); +        --this.offset; +        return new TypeInstance(null, TypeEnum.ERROR); +    } + +    // FIXME +    /** +     * f0 -> Expression() +     * f1 -> ( ExpressionRest() )* +     */ +    public TypeInstance visit(ExpressionList n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance expr1 = n.f0.accept(this, argu); +        TypeInstance exprr =  n.f1.accept(this, argu); +        TypeInstance ret = (expr1.has_checked() && +                            exprr.has_checked()) ? +            new TypeInstance(null, TypeEnum.CHECK) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> "," +     * f1 -> Expression() +     */ +    public TypeInstance visit(ExpressionRest n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret = n.f1.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * f0 -> IntegerLiteral() +     *                               | TrueLiteral() +     *                               | FalseLiteral() +     *                               | Identifier() +     *                               | ThisExpression() +     *                               | ArrayAllocationExpression() +     *                               | AllocationExpression() +     *                               | NotExpression() +     *                               | BracketExpression() +     */ +    public TypeInstance visit(PrimaryExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = n.f0.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [36]: return is an int +     * +     * +     * f0 -> <INTEGER_LITERAL> +     */ +    public TypeInstance visit(IntegerLiteral n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        this.printNode(n, argu, false, TypeEnum.integer); +        --this.offset; +        return new TypeInstance(null, TypeEnum.integer); +    } + +    /** +     * DONE [37]: return is a bool +     * +     * f0 -> "true" +     */ +    public TypeInstance visit(TrueLiteral n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        this.printNode(n, argu, false, TypeEnum.bool); +        --this.offset; +        return new TypeInstance(null, TypeEnum.bool); +    } + +    /** +     * DONE [38]: return is a bool +     * +     * f0 -> "false" +     */ +    public TypeInstance visit(FalseLiteral n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        this.printNode(n, argu, false, TypeEnum.bool); +        --this.offset; +        return new TypeInstance(null, TypeEnum.bool); +    } + +    // FIXME +    /** +     * [39]: id is a symbol in the current domain, return is id's type +     * +     * f0 -> <IDENTIFIER> +     */ +    public TypeInstance visit(Identifier n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        TypeInstance ret = (argu.get(n.f0.tokenImage) != null) ? +            argu.get(n.f0.tokenImage) : new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME FIXME FIXME +    /** +     * [40]: method exists? but where is the token? +     * +     * f0 -> "this" +     */ +    public TypeInstance visit(ThisExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret = new TypeInstance(null, TypeEnum.CHECK); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * DONE [41]: if expression is an integer, return is an int array +     * +     * f0 -> "new" +     * f1 -> "int" +     * f2 -> "[" +     * f3 -> Expression() +     * f4 -> "]" +     */ +    public TypeInstance visit(ArrayAllocationExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        TypeInstance ret = n.f3.accept(this, argu); +        n.f4.accept(this, argu); +        ret = (ret.get_type() == TypeEnum.integer) ? new TypeInstance(null, TypeEnum.int_array) : +            new TypeInstance(null, TypeEnum.ERROR); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    // FIXME +    /** +     * [42]: +     * +     * f0 -> "new" +     * f1 -> Identifier() +     * f2 -> "(" +     * f3 -> ")" +     */ +    public TypeInstance visit(AllocationExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret = n.f1.accept(this, argu); +        n.f2.accept(this, argu); +        n.f3.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +    /** +     * [43]: if expression is a boolean, return is a boolean +     * +     * f0 -> "!" +     * f1 -> Expression() +     */ +    public TypeInstance visit(NotExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret = n.f1.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return (ret.get_type() == TypeEnum.bool) ? ret : new TypeInstance(null, TypeEnum.ERROR); +    } + +    /** +     * [44]: if e is a type, return is that same type +     * +     * f0 -> "(" +     * f1 -> Expression() +     * f2 -> ")" +     */ +    public TypeInstance visit(BracketExpression n, HashMap<String,TypeInstance> argu) { +        ++this.offset; +        this.printNode(n, argu, true, null); + +        n.f0.accept(this, argu); +        TypeInstance ret = n.f1.accept(this, argu); +        n.f2.accept(this, argu); + +        this.printNode(n, argu, false, ret.get_type()); +        --this.offset; +        return ret; +    } + +} diff --git a/typecheck/library/TypeEnum.java b/typecheck/library/TypeEnum.java new file mode 100644 index 0000000..be6cab2 --- /dev/null +++ b/typecheck/library/TypeEnum.java @@ -0,0 +1,5 @@ +package typecheck.library; + +public enum TypeEnum { +    classname, int_array, bool, integer, CHECK, ERROR +} diff --git a/typecheck/library/TypeInstance.java b/typecheck/library/TypeInstance.java new file mode 100644 index 0000000..756d39b --- /dev/null +++ b/typecheck/library/TypeInstance.java @@ -0,0 +1,43 @@ +package typecheck.library; + +public class TypeInstance { +    TypeEnum type; +    String type_name; + +    public String toString() { +        return "name:" + type_name + "|type:" + type; +    } + +    public TypeInstance(String type_name, TypeEnum type) { +        this.type = type; +        this.type_name = type_name; +    } + +    public boolean equal_type(TypeInstance other) { +        /** +         * Given a TypeInstance object other, +         * returns true if other object +         * is the same type as this one. +         * +         * We can say two types are equal, as +         * long as they are not equal on a +         * type error! +         */ + +        return this.type != TypeEnum.ERROR && +            this.type == other.type; +    } + +    public boolean has_checked() { +        return type != TypeEnum.ERROR; +    } + +    public TypeEnum get_type() { +        return this.type; +    } + +    public String get_type_name() { +        return this.type_name; +    } + +} diff --git a/typecheck/library/Utilities.java b/typecheck/library/Utilities.java new file mode 100644 index 0000000..fad1e7e --- /dev/null +++ b/typecheck/library/Utilities.java @@ -0,0 +1,14 @@ +package typecheck.library; + +public class Utilities { + +    public static void print_filter(String message, boolean newline) { +        boolean debug = false; +        if (debug) { +            System.out.print(message); +            if (newline) +                System.out.println(); +        } +    } + +} | 
