summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd-912 <bdunahu@colostate.edu>2024-03-16 22:06:32 -0600
committerbd-912 <bdunahu@colostate.edu>2024-03-16 22:06:32 -0600
commit6a24c69232901de51f50beab9c3d3b3760dee334 (patch)
tree70c71b9ec25d3f6085d71c83e2be3719fe638ae9
parent5b09fb3697f4b1cc1f2f3781f10e1334ada69c22 (diff)
(Nonfunctional) Implemented many type-checking rules
-rw-r--r--.gitignore1
-rw-r--r--Typecheck.java69
-rw-r--r--manifest.scm5
-rw-r--r--minijava/PPrinter.java5
-rw-r--r--minijava/SymTableVis.java43
-rw-r--r--minijava/TypeCheckSimp.java683
-rw-r--r--minijava/TypeEnum.java5
-rw-r--r--minijava/TypeInstance.java29
-rwxr-xr-xrun_tests.sh2
-rw-r--r--tests/Empty.java5
-rw-r--r--tests/SimpleArithmetic.java6
11 files changed, 813 insertions, 40 deletions
diff --git a/.gitignore b/.gitignore
index 22cdebe..79f66fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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;
+ }
+}