Fixed nonlocal declaration errors

master
Apoorva Ranade 3 years ago
parent e47bc2df75
commit 31201bcf33

@ -28,6 +28,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
firstPass = true; firstPass = true;
errors = errors0; errors = errors0;
globals = sym; globals = sym;
// Symbol table entry for object class
ClassVType cvt = new ClassVType("object"), obj = cvt; ClassVType cvt = new ClassVType("object"), obj = cvt;
FuncType init = new FuncType(Type.OBJECT_TYPE); FuncType init = new FuncType(Type.OBJECT_TYPE);
init.parameters.add(Type.OBJECT_TYPE); init.parameters.add(Type.OBJECT_TYPE);
@ -35,6 +36,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
cvt_scope.put("init",init); cvt_scope.put("init",init);
cvt.scope=cvt_scope; cvt.scope=cvt_scope;
sym.put("object", cvt); sym.put("object", cvt);
//Symbol table entry for int class
cvt = new ClassVType("int"); cvt = new ClassVType("int");
cvt.super_class = obj; cvt.super_class = obj;
init = new FuncType(Type.INT_TYPE); init = new FuncType(Type.INT_TYPE);
@ -43,6 +45,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
cvt_scope.put("init",init); cvt_scope.put("init",init);
cvt.scope=cvt_scope; cvt.scope=cvt_scope;
sym.put("int", cvt); sym.put("int", cvt);
//Symbol table entry for str class
cvt = new ClassVType("str"); cvt = new ClassVType("str");
cvt.super_class = obj; cvt.super_class = obj;
init = new FuncType(Type.STR_TYPE); init = new FuncType(Type.STR_TYPE);
@ -51,6 +54,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
cvt_scope.put("init",init); cvt_scope.put("init",init);
cvt.scope=cvt_scope; cvt.scope=cvt_scope;
sym.put("str", cvt); sym.put("str", cvt);
//Symbol table entry for bool class
cvt = new ClassVType("bool"); cvt = new ClassVType("bool");
cvt.super_class = obj; cvt.super_class = obj;
init = new FuncType(Type.BOOL_TYPE); init = new FuncType(Type.BOOL_TYPE);
@ -59,24 +63,25 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
cvt_scope.put("init",init); cvt_scope.put("init",init);
cvt.scope=cvt_scope; cvt.scope=cvt_scope;
sym.put("bool", cvt); sym.put("bool", cvt);
//Symbol table entry for None return type
cvt = new ClassVType("<None>"); cvt = new ClassVType("<None>");
cvt.super_class = obj; cvt.super_class = obj;
sym.put("<None>", cvt); sym.put("<None>", cvt);
//Symbol table entry for inbuilt print function
ArrayList<ValueType> param = new ArrayList<ValueType>(); ArrayList<ValueType> param = new ArrayList<ValueType>();
param.add(Type.OBJECT_TYPE); param.add(Type.OBJECT_TYPE);
sym.put("print", new FuncType(param, Type.NONE_TYPE)); sym.put("print", new FuncType(param, Type.NONE_TYPE));
//Symbol table entry for inbuilt len function
param = new ArrayList<ValueType>(); param = new ArrayList<ValueType>();
param.add(Type.OBJECT_TYPE); param.add(Type.OBJECT_TYPE);
sym.put("len", new FuncType(param, Type.INT_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)); sym.put("input", new FuncType(new ArrayList<>(), Type.STR_TYPE));
typeChecker = new TypeChecker(globals, errors); typeChecker = new TypeChecker(globals, errors);
} }
public DeclarationAnalyzer(Errors errors0, TypeChecker typeChecker, SymbolTable<Type> globals){ public DeclarationAnalyzer(Errors errors0, TypeChecker typeChecker, SymbolTable<Type> globals)
{
firstPass = false; firstPass = false;
this.typeChecker = typeChecker; this.typeChecker = typeChecker;
errors = errors0; errors = errors0;
@ -86,27 +91,18 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
{ {
return globals; return globals;
} }
private void putSymChecked(Node node, String name, Type ty){ private void putSymChecked(Node node, String name, Type ty)
if (ty == null) {
{ if (ty == null)
return; return;
}
if (globals.get(name)!= null && !(ty instanceof ClassVType) && globals.get(name) instanceof ClassVType) //class names are only in global scope
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, "Cannot shadow class name: %s", name); errors.semError(
}
else if (sym.declares(name))
{
errors.semError(
node, "Duplicate declaration of identifier in same scope: %s", name); node, "Duplicate declaration of identifier in same scope: %s", name);
else
} sym.put(name, ty);
else
{
sym.put(name, ty);
}
} }
@Override @Override
public Type analyze(Program program) public Type analyze(Program program)
@ -116,8 +112,6 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
Identifier id = decl.getIdentifier(); Identifier id = decl.getIdentifier();
String name = id.name; String name = id.name;
Type type = decl.dispatch(this); Type type = decl.dispatch(this);
} }
// Check for return statements at top // Check for return statements at top
for (Stmt stmt : program.statements) for (Stmt stmt : program.statements)
@ -130,11 +124,13 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
} }
@Override @Override
public Type analyze(FuncDef node) { public Type analyze(FuncDef node)
{
Type fTy = globals.get(node.name.name); Type fTy = globals.get(node.name.name);
FuncType current_func=null; FuncType current_func=null;
if(!(fTy instanceof FuncType)){ if(!(fTy instanceof FuncType))
{
if(fTy == null) if(fTy == null)
{ {
current_func = new FuncType(new ArrayList<ValueType>(), current_func = new FuncType(new ArrayList<ValueType>(),
@ -187,7 +183,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
else else
otherDefs.add(decl); otherDefs.add(decl);
for (Declaration decl : varDefs) for (Declaration decl : varDefs)
if(decl instanceof VarDef) if(decl instanceof VarDef||decl instanceof NonLocalDecl)
decl.dispatch(this); decl.dispatch(this);
else else
decl.dispatch(typeChecker); decl.dispatch(typeChecker);
@ -200,7 +196,8 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
return current_func; 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) if (fun1.returnType.equals(fun2.returnType)==false)
return false; return false;
if (fun1.parameters.size() != fun2.parameters.size()) if (fun1.parameters.size() != fun2.parameters.size())
@ -305,7 +302,27 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
putSymChecked(node.name, node.name.name, cvt); putSymChecked(node.name, node.name.name, cvt);
return cvt; return cvt;
} }
boolean isVariableType(Type ty)
{
return ty.isSpecialType() || ty.equals(Type.OBJECT_TYPE);
}
@Override
public Type analyze(NonLocalDecl node)
{
SymbolTable<Type> 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 @Override
public Type analyze(VarDef node) public Type analyze(VarDef node)
{ {
@ -332,10 +349,12 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
return var_type; return var_type;
} }
public void setScope(SymbolTable<Type> currentScope) { public void setScope(SymbolTable<Type> currentScope)
{
sym = currentScope; sym = currentScope;
} }
public void setCurrClass(ClassVType current_class){ public void setCurrClass(ClassVType current_class)
{
this.current_class = current_class; this.current_class = current_class;
} }
} }

@ -16,6 +16,8 @@ import static chocopy.common.analysis.types.Type.OBJECT_TYPE;
import java.util.ArrayList; import java.util.ArrayList;
import javax.swing.text.StyledEditorKit.BoldAction;
import com.fasterxml.jackson.annotation.JacksonInject.Value; import com.fasterxml.jackson.annotation.JacksonInject.Value;
/** /**
@ -31,7 +33,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<Type> {
private boolean returned = false, member = false; private boolean returned = false, member = false;
/** Collector for errors. */ /** Collector for errors. */
private final Errors errors; private final Errors errors;
private Boolean assign = false;
/** /**
* Creates a type checker using GLOBALSYMBOLS for the initial global symbol table and ERRORS0 to * Creates a type checker using GLOBALSYMBOLS for the initial global symbol table and ERRORS0 to
* receive semantic errors. * receive semantic errors.
@ -87,6 +89,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<Type> {
Type tr = node.value.dispatch(this); Type tr = node.value.dispatch(this);
Type tl; Type tl;
boolean error = false; boolean error = false;
assign=true;
for (Expr ex : node.targets) for (Expr ex : node.targets)
{ {
tl = ex.dispatch(this); tl = ex.dispatch(this);
@ -114,6 +117,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<Type> {
error = true; error = true;
} }
} }
assign=false;
return null; return null;
} }
@ -317,7 +321,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<Type> {
public Type analyze(NoneLiteral node) { public Type analyze(NoneLiteral node) {
return node.setInferredType(Type.NONE_TYPE); return node.setInferredType(Type.NONE_TYPE);
} }
/*
@Override @Override
public Type analyze(NonLocalDecl node) { public Type analyze(NonLocalDecl node) {
SymbolTable<Type> parent = currentScope.getParent(); SymbolTable<Type> parent = currentScope.getParent();
@ -337,7 +341,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<Type> {
} }
return null; return null;
} }
*/
@Override @Override
public Type analyze(ReturnStmt node) { public Type analyze(ReturnStmt node) {
if(node.value != null) if(node.value != null)
@ -472,10 +476,13 @@ public class TypeChecker extends AbstractNodeAnalyzer<Type> {
public Type analyze(Identifier id) { public Type analyze(Identifier id) {
String varName = id.name; String varName = id.name;
Type varType = currentScope.get(varName); Type varType = currentScope.get(varName);
if(varType!=null && !currentScope.getDeclaredSymbols().contains(varName)){ if(varType!=null)
err(id, "Cannot assign to variable that is not explicitly declared in this scope: %s", varName); {
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()) { if (varType != null && varType.isValueType()) {
return id.setInferredType(varType); return id.setInferredType(varType);
} }
@ -488,16 +495,14 @@ public class TypeChecker extends AbstractNodeAnalyzer<Type> {
public Type analyze(GlobalDecl node) public Type analyze(GlobalDecl node)
{ {
Type ty = sym.get(node.variable.name); Type ty = sym.get(node.variable.name);
if (sym.declares(node.variable.name)==false || if (sym.declares(node.variable.name)==false || !isVariableType(ty))
!isVariableType(ty)
)
{ {
errors.semError( err(
node.variable, "Not a global variable: %s", node.variable.name); node.variable, "Not a global variable: %s", node.variable.name);
return null; return null;
} }
else if(currentScope.getDeclaredSymbols().contains(node.variable.name)){ else if(currentScope.getDeclaredSymbols().contains(node.variable.name)){
errors.semError( err(
node.variable, "Duplicate declaration of identifier in same scope: %s", node.variable.name); node.variable, "Duplicate declaration of identifier in same scope: %s", node.variable.name);
} }
else else

Loading…
Cancel
Save