diff --git a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java index a7f4e39..1c995b9 100644 --- a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java +++ b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java @@ -28,6 +28,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer firstPass = true; errors = errors0; globals = sym; + // Symbol table entry for object class ClassVType cvt = new ClassVType("object"), obj = cvt; FuncType init = new FuncType(Type.OBJECT_TYPE); init.parameters.add(Type.OBJECT_TYPE); @@ -35,6 +36,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer cvt_scope.put("init",init); cvt.scope=cvt_scope; sym.put("object", cvt); + //Symbol table entry for int class cvt = new ClassVType("int"); cvt.super_class = obj; init = new FuncType(Type.INT_TYPE); @@ -43,6 +45,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer cvt_scope.put("init",init); cvt.scope=cvt_scope; sym.put("int", cvt); + //Symbol table entry for str class cvt = new ClassVType("str"); cvt.super_class = obj; init = new FuncType(Type.STR_TYPE); @@ -51,6 +54,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer cvt_scope.put("init",init); cvt.scope=cvt_scope; sym.put("str", cvt); + //Symbol table entry for bool class cvt = new ClassVType("bool"); cvt.super_class = obj; init = new FuncType(Type.BOOL_TYPE); @@ -59,24 +63,25 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer cvt_scope.put("init",init); cvt.scope=cvt_scope; sym.put("bool", cvt); - + //Symbol table entry for None return type cvt = new ClassVType(""); cvt.super_class = obj; sym.put("", cvt); - + //Symbol table entry for inbuilt print function ArrayList param = new ArrayList(); param.add(Type.OBJECT_TYPE); sym.put("print", new FuncType(param, Type.NONE_TYPE)); - + //Symbol table entry for inbuilt len function param = new ArrayList(); param.add(Type.OBJECT_TYPE); sym.put("len", new FuncType(param, Type.INT_TYPE)); - + //Symbol table entry for inbuilt input function sym.put("input", new FuncType(new ArrayList<>(), Type.STR_TYPE)); typeChecker = new TypeChecker(globals, errors); } - public DeclarationAnalyzer(Errors errors0, TypeChecker typeChecker, SymbolTable globals){ + public DeclarationAnalyzer(Errors errors0, TypeChecker typeChecker, SymbolTable globals) + { firstPass = false; this.typeChecker = typeChecker; errors = errors0; @@ -86,27 +91,18 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer { return globals; } - private void putSymChecked(Node node, String name, Type ty){ - if (ty == null) - { - return; - } - - if (globals.get(name)!= null && !(ty instanceof ClassVType) && globals.get(name) instanceof ClassVType) //class names are only in global scope - { - errors.semError(node, "Cannot shadow class name: %s", name); - } - else if (sym.declares(name)) - { - errors.semError( + private void putSymChecked(Node node, String name, Type ty) + { + if (ty == null) + return; + + if (globals.get(name)!= null && !(ty instanceof ClassVType) && globals.get(name) instanceof ClassVType) //class names are only in global scope + errors.semError(node, "Cannot shadow class name: %s", name); + else if (sym.declares(name)) + errors.semError( node, "Duplicate declaration of identifier in same scope: %s", name); - - } - - else - { - sym.put(name, ty); - } + else + sym.put(name, ty); } @Override public Type analyze(Program program) @@ -116,8 +112,6 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer Identifier id = decl.getIdentifier(); String name = id.name; Type type = decl.dispatch(this); - - } // Check for return statements at top for (Stmt stmt : program.statements) @@ -130,11 +124,13 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer } @Override - public Type analyze(FuncDef node) { + public Type analyze(FuncDef node) + { Type fTy = globals.get(node.name.name); FuncType current_func=null; - if(!(fTy instanceof FuncType)){ + if(!(fTy instanceof FuncType)) + { if(fTy == null) { current_func = new FuncType(new ArrayList(), @@ -187,7 +183,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer else otherDefs.add(decl); for (Declaration decl : varDefs) - if(decl instanceof VarDef) + if(decl instanceof VarDef||decl instanceof NonLocalDecl) decl.dispatch(this); else decl.dispatch(typeChecker); @@ -200,7 +196,8 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer return current_func; } - public boolean compare_functions(FuncType fun1, FuncType fun2) { + public boolean compare_functions(FuncType fun1, FuncType fun2) + { if (fun1.returnType.equals(fun2.returnType)==false) return false; if (fun1.parameters.size() != fun2.parameters.size()) @@ -305,7 +302,27 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer putSymChecked(node.name, node.name.name, cvt); return cvt; } - + boolean isVariableType(Type ty) + { + return ty.isSpecialType() || ty.equals(Type.OBJECT_TYPE); + } + @Override + public Type analyze(NonLocalDecl node) + { + SymbolTable curr_sym=sym; + while(curr_sym.getParent()!=null) + { + if (curr_sym.declares(node.variable.name) && isVariableType(sym.get(node.variable.name))) + { + sym.put(node.variable.name, sym.get(node.variable.name)); + return sym.get(node.variable.name); + } + curr_sym=curr_sym.getParent(); + } + errors.semError( + node.variable, "Not a nonlocal variable: %s", node.variable.name); + return null; + } @Override public Type analyze(VarDef node) { @@ -332,10 +349,12 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer return var_type; } - public void setScope(SymbolTable currentScope) { + public void setScope(SymbolTable currentScope) + { sym = currentScope; } - public void setCurrClass(ClassVType current_class){ + public void setCurrClass(ClassVType current_class) + { this.current_class = current_class; } } diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java index 7b4fe2e..c131a60 100644 --- a/src/main/java/chocopy/pa2/TypeChecker.java +++ b/src/main/java/chocopy/pa2/TypeChecker.java @@ -16,6 +16,8 @@ import static chocopy.common.analysis.types.Type.OBJECT_TYPE; import java.util.ArrayList; +import javax.swing.text.StyledEditorKit.BoldAction; + import com.fasterxml.jackson.annotation.JacksonInject.Value; /** @@ -31,7 +33,7 @@ public class TypeChecker extends AbstractNodeAnalyzer { private boolean returned = false, member = false; /** Collector for errors. */ private final Errors errors; - + private Boolean assign = false; /** * Creates a type checker using GLOBALSYMBOLS for the initial global symbol table and ERRORS0 to * receive semantic errors. @@ -87,6 +89,7 @@ public class TypeChecker extends AbstractNodeAnalyzer { Type tr = node.value.dispatch(this); Type tl; boolean error = false; + assign=true; for (Expr ex : node.targets) { tl = ex.dispatch(this); @@ -114,6 +117,7 @@ public class TypeChecker extends AbstractNodeAnalyzer { error = true; } } + assign=false; return null; } @@ -317,7 +321,7 @@ public class TypeChecker extends AbstractNodeAnalyzer { public Type analyze(NoneLiteral node) { return node.setInferredType(Type.NONE_TYPE); } - + /* @Override public Type analyze(NonLocalDecl node) { SymbolTable parent = currentScope.getParent(); @@ -337,7 +341,7 @@ public class TypeChecker extends AbstractNodeAnalyzer { } return null; } - + */ @Override public Type analyze(ReturnStmt node) { if(node.value != null) @@ -472,10 +476,13 @@ public class TypeChecker extends AbstractNodeAnalyzer { public Type analyze(Identifier id) { String varName = id.name; Type varType = currentScope.get(varName); - if(varType!=null && !currentScope.getDeclaredSymbols().contains(varName)){ - err(id, "Cannot assign to variable that is not explicitly declared in this scope: %s", varName); + if(varType!=null) + { + if(assign==true && !currentScope.getDeclaredSymbols().contains(varName)) + err(id, "Cannot assign to variable that is not explicitly declared in this scope: %s", varName); + else if(assign==false && currentScope.get(varName)==null) + err(id, "Variable not declared in scope: %s", varName); } - if (varType != null && varType.isValueType()) { return id.setInferredType(varType); } @@ -488,16 +495,14 @@ public class TypeChecker extends AbstractNodeAnalyzer { public Type analyze(GlobalDecl node) { Type ty = sym.get(node.variable.name); - if (sym.declares(node.variable.name)==false || - !isVariableType(ty) - ) + if (sym.declares(node.variable.name)==false || !isVariableType(ty)) { - errors.semError( + err( node.variable, "Not a global variable: %s", node.variable.name); return null; } else if(currentScope.getDeclaredSymbols().contains(node.variable.name)){ - errors.semError( + err( node.variable, "Duplicate declaration of identifier in same scope: %s", node.variable.name); } else