diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Typecheck.java | 69 | ||||
-rw-r--r-- | manifest.scm | 5 | ||||
-rw-r--r-- | minijava/PPrinter.java | 5 | ||||
-rw-r--r-- | minijava/SymTableVis.java | 43 | ||||
-rw-r--r-- | minijava/TypeCheckSimp.java | 683 | ||||
-rw-r--r-- | minijava/TypeEnum.java | 5 | ||||
-rw-r--r-- | minijava/TypeInstance.java | 29 | ||||
-rwxr-xr-x | run_tests.sh | 2 | ||||
-rw-r--r-- | tests/Empty.java | 5 | ||||
-rw-r--r-- | tests/SimpleArithmetic.java | 6 |
11 files changed, 813 insertions, 40 deletions
@@ -1,4 +1,3 @@ -/manifest.scm *.class /javacc-6.0/ /syntaxtree/ diff --git a/Typecheck.java b/Typecheck.java index 039e94d..be979f5 100644 --- a/Typecheck.java +++ b/Typecheck.java @@ -8,43 +8,44 @@ import minijava.*; public class Typecheck { public static void main(String[] args) { - Node root = null; - try { - root = new MiniJavaParser(System.in).Goal(); + Node root = null; + try { + root = new MiniJavaParser(System.in).Goal(); - // Pretty-print the tree. PPrinter inherits from - // GJDepthFirst<R,A>. R=Void, A=String. - // PPrinter<Void,String> pp = new PPrinter<Void,String>(); - // root.accept(pp, ""); + // Pretty-print the tree. PPrinter inherits from + // GJDepthFirst<R,A>. R=Void, A=String. + PPrinter<Void,String> pp = new PPrinter<Void,String>(); + root.accept(pp, ""); - // // Build the symbol table. Top-down visitor, inherits from - // // GJDepthFirst<R,A>. R=Void, A=Integer. - // SymTableVis<Void, Integer> pv = - // new SymTableVis<Void,Integer>(); - // root.accept(pv, 0); - // HashMap<String, String> symt = pv.symt; + // // Build the symbol table. Top-down visitor, inherits from + // // GJDepthFirst<R,A>. R=Void, A=Integer. + // SymTableVis<Void, Integer> pv = + // new SymTableVis<Void,Integer>(); + // root.accept(pv, 0); + // HashMap<String, String> symt = pv.symt; - // // Do type checking. Bottom-up visitor, also inherits from - // // GJDepthFirst. Visit functions return MyTpe (=R), and - // // take a symbol table (HashMap<String,String>) as - // // argument (=A). You may implement things differently of - // // course! - // TypeCheckSimp ts = new TypeCheckSimp(); - // MyType res = root.accept(ts, symt); + // Do type checking. Bottom-up visitor, also inherits from + // GJDepthFirst. Visit functions return MyTpe (=R), and + // take a symbol table (HashMap<String,String>) as + // argument (=A). You may implement things differently of + // course! + TypeCheckSimp ts = new TypeCheckSimp(); + TypeInstance res = root.accept(ts, null); + + // Ugly code not to be inspired from: "my" way of storing + // type info / typecheck property: if some of my internal + // structure is empty, then things don't typecheck for + // me. This is specific to my own implementation. + // if (res != null && res.type_array.size() > 0) + if (res.get_type() != TypeEnum.ERROR) + System.out.println("Program type checked successfully"); + else + System.out.println("Type error"); + } + catch (ParseException e) { + System.out.println(e.toString()); + System.exit(1); + } - // // Ugly code not to be inspired from: "my" way of storing - // // type info / typecheck property: if some of my internal - // // structure is empty, then things don't typecheck for - // // me. This is specific to my own implementation. - // if (res != null && res.type_array.size() > 0) - // System.out.println("Program type checked successfully"); - // else - // System.out.println("Type error"); - System.out.println("Type error"); - } - catch (ParseException e) { - System.out.println(e.toString()); - System.exit(1); - } } } diff --git a/manifest.scm b/manifest.scm new file mode 100644 index 0000000..62e4d88 --- /dev/null +++ b/manifest.scm @@ -0,0 +1,5 @@ +(specifications->manifest + '( + "icedtea:jdk" ; provides JDK 8 + "make" + )) diff --git a/minijava/PPrinter.java b/minijava/PPrinter.java index 7dd484b..aed7ec4 100644 --- a/minijava/PPrinter.java +++ b/minijava/PPrinter.java @@ -1,8 +1,5 @@ -// -// Generated by JTB 1.3.2 -// - package minijava; + import syntaxtree.*; import visitor.*; import java.util.*; diff --git a/minijava/SymTableVis.java b/minijava/SymTableVis.java new file mode 100644 index 0000000..3d8003b --- /dev/null +++ b/minijava/SymTableVis.java @@ -0,0 +1,43 @@ +package minijava; + +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> implements GJVisitor<R,A> { + + public HashMap<String,String> symt = new HashMap<>(); + + private void print_filter(String message) { + boolean debug = true; + if (debug) + System.out.println(message); + } + + public R visit(VarDeclaraction n, A argu) { + R _ret=null; + + this.print_filter("Processing declaration"); + + String type = ""; + switch (n.f0.f0.which) { + case 2: + type = "Int"; break; + default: + this.print_filter("Unsupported case"); + } + + String id = n.f1.f0.tokenImage; + + this.printfilter("Inserting " + id + " => " + type); + // Safe? + symt.put(id, type); + + return _ret; + } + +} diff --git a/minijava/TypeCheckSimp.java b/minijava/TypeCheckSimp.java new file mode 100644 index 0000000..01f8b27 --- /dev/null +++ b/minijava/TypeCheckSimp.java @@ -0,0 +1,683 @@ +package minijava; + +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,String>> { + + private void print_filter(String message) { + boolean debug = true; + if (debug) + System.out.println(message); + } + // + // Auto class visitors--probably don't need to be overridden. + // + public TypeInstance visit(NodeList n, HashMap<String,String> argu) { + TypeInstance _ret=null; + int _count=0; + for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { + e.nextElement().accept(this,argu); + _count++; + } + return _ret; + } + + public TypeInstance visit(NodeListOptional n, HashMap<String,String> argu) { + if ( n.present() ) { + TypeInstance _ret=null; + int _count=0; + for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { + e.nextElement().accept(this,argu); + _count++; + } + return _ret; + } + else + return null; + } + + public TypeInstance visit(NodeOptional n, HashMap<String,String> argu) { + if ( n.present() ) + return n.node.accept(this,argu); + else + return null; + } + + public TypeInstance visit(NodeSequence n, HashMap<String,String> argu) { + TypeInstance _ret=null; + int _count=0; + for ( Enumeration<Node> e = n.elements(); e.hasMoreElements(); ) { + e.nextElement().accept(this,argu); + _count++; + } + return _ret; + } + + public TypeInstance visit(NodeToken n, HashMap<String,String> argu) { return null; } + + // + // User-generated visitor methods below + // + + /** + * f0 -> MainClass() + * f1 -> ( TypeDeclaration() )* + * f2 -> <EOF> + */ + public TypeInstance visit(Goal n, HashMap<String,String> argu) { + TypeInstance ret = n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + 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,String> argu) { + 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); + 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); + return stmt; + } + + /** + * f0 -> ClassDeclaration() + * | ClassExtendsDeclaration() + */ + public TypeInstance visit(TypeDeclaration n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "class" + * f1 -> Identifier() + * f2 -> "{" + * f3 -> ( VarDeclaration() )* + * f4 -> ( MethodDeclaration() )* + * f5 -> "}" + */ + public TypeInstance visit(ClassDeclaration n, HashMap<String,String> argu) { + TypeInstance _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); + return _ret; + } + + /** + * f0 -> "class" + * f1 -> Identifier() + * f2 -> "extends" + * f3 -> Identifier() + * f4 -> "{" + * f5 -> ( VarDeclaration() )* + * f6 -> ( MethodDeclaration() )* + * f7 -> "}" + */ + public TypeInstance visit(ClassExtendsDeclaration n, HashMap<String,String> argu) { + TypeInstance _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); + return _ret; + } + + // FIXME + /** + * f0 -> Type() + * f1 -> Identifier() + * f2 -> ";" + */ + public TypeInstance visit(VarDeclaration n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + return new TypeInstance(TypeEnum.CHECK); + } + + /** + * 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,String> argu) { + TypeInstance _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); + return _ret; + } + + /** + * f0 -> FormalParameter() + * f1 -> ( FormalParameterRest() )* + */ + public TypeInstance visit(FormalParameterList n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> Type() + * f1 -> Identifier() + */ + public TypeInstance visit(FormalParameter n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> "," + * f1 -> FormalParameter() + */ + public TypeInstance visit(FormalParameterRest n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> ArrayType() + * | BooleanType() + * | IntegerType() + * | Identifier() + */ + public TypeInstance visit(Type n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "int" + * f1 -> "[" + * f2 -> "]" + */ + public TypeInstance visit(ArrayType n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + return new TypeInstance(TypeEnum.int_array); + } + + /** + * f0 -> "boolean" + */ + public TypeInstance visit(BooleanType n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "int" + */ + public TypeInstance visit(IntegerType n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> Block() + * | AssignmentStatement() + * | ArrayAssignmentStatement() + * | IfStatement() + * | WhileStatement() + * | PrintStatement() + */ + public TypeInstance visit(Statement n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> "{" + * f1 -> ( Statement() )* + * f2 -> "}" + */ + public TypeInstance visit(Block n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + return ret; + } + + /** + * f0 -> Identifier() + * f1 -> "=" + * f2 -> Expression() + * f3 -> ";" + */ + public TypeInstance visit(AssignmentStatement n, HashMap<String,String> argu) { + TypeInstance lhs = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance rhs = n.f2.accept(this, argu); + n.f3.accept(this, argu); + return (lhs.equal_type(rhs)) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> Identifier() + * f1 -> "[" + * f2 -> Expression() //int + * f3 -> "]" + * f4 -> "=" + * f5 -> Expression() //int + * f6 -> ";" + */ + public TypeInstance visit(ArrayAssignmentStatement n, HashMap<String,String> argu) { + 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); + return (index.get_type() == TypeEnum.integer && + value.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "if" + * f1 -> "(" + * f2 -> Expression() + * f3 -> ")" + * f4 -> Statement() + * f5 -> "else" + * f6 -> Statement() + */ + public TypeInstance visit(IfStatement n, HashMap<String,String> argu) { + 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); + return (expr.get_type() == TypeEnum.bool && + stmt1.get_type() == stmt2.get_type() == TypeEnum.CHECK) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "while" + * f1 -> "(" + * f2 -> Expression() + * f3 -> ")" + * f4 -> Statement() + */ + public TypeInstance visit(WhileStatement n, HashMap<String,String> argu) { + 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); + return (expr.get_type() == TypeEnum.bool && + stmt.get_type() == TypeEnum.CHECK) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "System.out.println" + * f1 -> "(" + * f2 -> Expression() + * f3 -> ")" + * f4 -> ";" + */ + public TypeInstance visit(PrintStatement n, HashMap<String,String> argu) { + 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); + return (ret.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.CHECK) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> AndExpression() + * | CompareExpression() + * | PlusExpression() + * | MinusExpression() + * | TimesExpression() + * | ArrayLookup() + * | ArrayLength() + * | MessageSend() + * | PrimaryExpression() + */ + public TypeInstance visit(Expression n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> PrimaryExpressionppp() + * f1 -> "&&" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(AndExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.bool && + oper2.get_type() == TypeEnum.bool) ? + new TypeInstance(TypeEnum.bool) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "<" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(CompareExpression n, HashMap<String,String> argu) { + TypeInstance _ret=null; + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.bool) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "+" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(PlusExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "-" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(MinusExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "*" + * f2 -> PrimaryExpression() + */ + public TypeInstance visit(TimesExpression n, HashMap<String,String> argu) { + TypeInstance oper1 = n.f0.accept(this, argu); + n.f1.accept(this, argu); + TypeInstance oper2 = n.f2.accept(this, argu); + return (oper1.get_type() == TypeEnum.integer && + oper2.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "[" + * f2 -> PrimaryExpression() + * f3 -> "]" + */ + public TypeInstance visit(ArrayLookup n, HashMap<String,String> argu) { + TypeInstance _ret=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); + return (array.get_type() == TypeEnum.int_array && + index.get_type() == TypeEnum.integer) ? + new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "." + * f2 -> "length" + */ + public TypeInstance visit(ArrayLength n, HashMap<String,String> argu) { + // can only act on an array + TypeInstance _ret=null; + TypeInstance ret = n.f0.accept(this, argu); + n.f1.accept(this, argu); + n.f2.accept(this, argu); + return (ret.get_type() == TypeEnum.int_array) ? new TypeInstance(TypeEnum.integer) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> PrimaryExpression() + * f1 -> "." + * f2 -> Identifier() + * f3 -> "(" + * f4 -> ( ExpressionList() )? + * f5 -> ")" + */ + public TypeInstance visit(MessageSend n, HashMap<String,String> argu) { + TypeInstance _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); + return _ret; + } + + // FIXME + /** + * f0 -> Expression() + * f1 -> ( ExpressionRest() )* + */ + public TypeInstance visit(ExpressionList n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + n.f1.accept(this, argu); + return _ret; + } + + /** + * f0 -> "," + * f1 -> Expression() + */ + public TypeInstance visit(ExpressionRest n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + return ret; + } + + /** + * f0 -> IntegerLiteral() + * | TrueLiteral() + * | FalseLiteral() + * | Identifier() + * | ThisExpression() + * | ArrayAllocationExpression() + * | AllocationExpression() + * | NotExpression() + * | BracketExpression() + */ + public TypeInstance visit(PrimaryExpression n, HashMap<String,String> argu) { + return n.f0.accept(this, argu); + } + + /** + * f0 -> <INTEGER_LITERAL> + */ + public TypeInstance visit(IntegerLiteral n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.integer); + } + + /** + * f0 -> "true" + */ + public TypeInstance visit(TrueLiteral n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.bool); + } + + /** + * f0 -> "false" + */ + public TypeInstance visit(FalseLiteral n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.bool); + } + + /** + * f0 -> <IDENTIFIER> + */ + public TypeInstance visit(Identifier n, HashMap<String,String> argu) { + return new TypeInstance(TypeEnum.CHECK); + } + + //FIXME + /** + * f0 -> "this" + */ + public TypeInstance visit(ThisExpression n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + return _ret; + } + + /** + * f0 -> "new" + * f1 -> "int" + * f2 -> "[" + * f3 -> Expression() + * f4 -> "]" + */ + public TypeInstance visit(ArrayAllocationExpression n, HashMap<String,String> argu) { + TypeInstance _ret=null; + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + n.f4.accept(this, argu); + return (ret.get_type() == TypeEnum.integer) ? new TypeInstance(TypeEnum.int_array) : + new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "new" + * f1 -> Identifier() + * f2 -> "(" + * f3 -> ")" + */ + public TypeInstance visit(AllocationExpression n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + n.f3.accept(this, argu); + return ret; + } + + /** + * f0 -> "!" + * f1 -> Expression() + */ + public TypeInstance visit(NotExpression n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + return (ret.get_type() == TypeEnum.bool) ? ret : new TypeInstance(TypeEnum.ERROR); + } + + /** + * f0 -> "(" + * f1 -> Expression() + * f2 -> ")" + */ + public TypeInstance visit(BracketExpression n, HashMap<String,String> argu) { + n.f0.accept(this, argu); + TypeInstance ret = n.f1.accept(this, argu); + n.f2.accept(this, argu); + return ret; + } + +} diff --git a/minijava/TypeEnum.java b/minijava/TypeEnum.java new file mode 100644 index 0000000..4003eba --- /dev/null +++ b/minijava/TypeEnum.java @@ -0,0 +1,5 @@ +package minijava; + +public enum TypeEnum { + int_array, bool, integer, CHECK, ERROR +} diff --git a/minijava/TypeInstance.java b/minijava/TypeInstance.java new file mode 100644 index 0000000..13920e4 --- /dev/null +++ b/minijava/TypeInstance.java @@ -0,0 +1,29 @@ +package minijava; + +public class TypeInstance { + TypeEnum type; + + public TypeInstance(TypeEnum type) { + this.type = type; + } + + 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 TypeEnum get_type() { + return this.type; + } + +} diff --git a/run_tests.sh b/run_tests.sh index 6c63a22..bbecc70 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -7,5 +7,5 @@ for i in ./tests/*.java; do actual=$(java Typecheck < $i) echo -n "$(basename ${i}): " - [[ $expected != $actual ]] && echo -e "FAILED---Expected: $expected" || echo 'PASSED' + [[ $expected == $actual ]] && echo 'PASSED' || echo -e "FAILED---Expected: $expected" done diff --git a/tests/Empty.java b/tests/Empty.java new file mode 100644 index 0000000..dc665df --- /dev/null +++ b/tests/Empty.java @@ -0,0 +1,5 @@ +class Empty { + public static void main(String[] a) { + System.out.println(1); + } +} diff --git a/tests/SimpleArithmetic.java b/tests/SimpleArithmetic.java new file mode 100644 index 0000000..94c780e --- /dev/null +++ b/tests/SimpleArithmetic.java @@ -0,0 +1,6 @@ +class SimpleArithmetic{ + public static void main(String[] a){ + int x; + x = 1 + 2; + } +} |