Fixed nonlocal declaration errors
This commit is contained in:
@@ -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,28 +91,19 @@ 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);
|
errors.semError(node, "Cannot shadow class name: %s", name);
|
||||||
}
|
|
||||||
else if (sym.declares(name))
|
else if (sym.declares(name))
|
||||||
{
|
|
||||||
errors.semError(
|
errors.semError(
|
||||||
node, "Duplicate declaration of identifier in same scope: %s", name);
|
node, "Duplicate declaration of identifier in same scope: %s", name);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
sym.put(name, ty);
|
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)
|
||||||
|
{
|
||||||
|
if(assign==true && !currentScope.getDeclaredSymbols().contains(varName))
|
||||||
err(id, "Cannot assign to variable that is not explicitly declared in this scope: %s", 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
|
||||||
|
|||||||
Reference in New Issue
Block a user