|
|
@ -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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|