Progress on class def node analyzer

master
Apoorva Ranade 4 years ago
parent 79be979e13
commit 84b1c679b9

@ -12,9 +12,9 @@ import java.util.Objects;
public class ClassVType extends ValueType { public class ClassVType extends ValueType {
/** The name of the class. */ /** The name of the class. */
private final String className; public final String className;
public SymbolTable<Type> scope; public SymbolTable<Type> scope;
public Identifier super_class; public ClassVType super_class;
/** A class type for the class named CLASSNAME. */ /** A class type for the class named CLASSNAME. */
@JsonCreator @JsonCreator
public ClassVType(@JsonProperty String className) { public ClassVType(@JsonProperty String className) {

@ -4,7 +4,7 @@ import chocopy.common.analysis.AbstractNodeAnalyzer;
import chocopy.common.analysis.SymbolTable; import chocopy.common.analysis.SymbolTable;
import chocopy.common.analysis.types.*; import chocopy.common.analysis.types.*;
import chocopy.common.astnodes.*; import chocopy.common.astnodes.*;
import java.util.*;
/** Analyzes declarations to create a top-level symbol table. */ /** Analyzes declarations to create a top-level symbol table. */
public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type> public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
{ {
@ -15,7 +15,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
private final SymbolTable<Type> globals = sym; private final SymbolTable<Type> globals = sym;
/** Receiver for semantic error messages. */ /** Receiver for semantic error messages. */
private final Errors errors; private final Errors errors;
private ClassVType current_class=null;
/** A new declaration analyzer sending errors to ERRORS0. */ /** A new declaration analyzer sending errors to ERRORS0. */
public DeclarationAnalyzer(Errors errors0) public DeclarationAnalyzer(Errors errors0)
{ {
@ -23,18 +23,30 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
ClassVType cvt = new ClassVType("object"); ClassVType cvt = new ClassVType("object");
FuncValueType init = new FuncValueType(Type.OBJECT_TYPE); FuncValueType init = new FuncValueType(Type.OBJECT_TYPE);
init.parameters.add(Type.OBJECT_TYPE); init.parameters.add(Type.OBJECT_TYPE);
SymbolTable<Type> cvt_scope=new SymbolTable<>(sym);
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("object", cvt); sym.put("object", cvt);
cvt = new ClassVType("int"); cvt = new ClassVType("int");
init = new FuncValueType(Type.INT_TYPE); init = new FuncValueType(Type.INT_TYPE);
init.parameters.add(Type.INT_TYPE); init.parameters.add(Type.INT_TYPE);
cvt_scope=new SymbolTable<>(sym);
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("int", cvt); sym.put("int", cvt);
cvt = new ClassVType("str"); cvt = new ClassVType("str");
init = new FuncValueType(Type.STR_TYPE); init = new FuncValueType(Type.STR_TYPE);
init.parameters.add(Type.STR_TYPE); init.parameters.add(Type.STR_TYPE);
cvt_scope=new SymbolTable<>(sym);
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("str", cvt); sym.put("str", cvt);
cvt = new ClassVType("bool"); cvt = new ClassVType("bool");
init = new FuncValueType(Type.BOOL_TYPE); init = new FuncValueType(Type.BOOL_TYPE);
init.parameters.add(Type.BOOL_TYPE); init.parameters.add(Type.BOOL_TYPE);
cvt_scope=new SymbolTable<>(sym);
cvt_scope.put("init",init);
cvt.scope=cvt_scope;
sym.put("bool", cvt); sym.put("bool", cvt);
} }
@ -62,6 +74,12 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
errors.semError( errors.semError(
id, "Duplicate declaration of identifier in same " + "scope: %s", name); id, "Duplicate declaration of identifier in same " + "scope: %s", name);
} }
else if (sym.get(name)!= null && sym.get(name) instanceof ClassVType)
{
errors.semError(
id, "Cannot shadow class name: %s", name);
continue;
}
else else
{ {
sym.put(name, type); sym.put(name, type);
@ -76,11 +94,6 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
} }
return null; return null;
} }
@Override
public Type analyze(VarDef varDef) {
return ValueType.annotationToValueType(varDef.var.type);
}
@Override @Override
public Type analyze(FuncDef node) { public Type analyze(FuncDef node) {
FuncValueType current_func=new FuncValueType((ValueType) node.returnType.dispatch(this)); FuncValueType current_func=new FuncValueType((ValueType) node.returnType.dispatch(this));
@ -97,9 +110,8 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
} }
else if (sym.get(param.identifier.name)!= null && sym.get(param.identifier.name) instanceof ClassVType) else if (sym.get(param.identifier.name)!= null && sym.get(param.identifier.name) instanceof ClassVType)
{ {
System.out.println("Error:"+sym.get(param.identifier.name));
errors.semError( errors.semError(
node.name, "Parameter shadows class name: %s", param.identifier.name); param.identifier, "Cannot shadow class name: %s", param.identifier.name);
continue; continue;
} }
@ -114,18 +126,29 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
String name = id.name; String name = id.name;
Type type = decl.dispatch(this); Type type = decl.dispatch(this);
if (type == null)
if (type == null) { {
continue; continue;
} }
if (sym.declares(name)) { if (sym.declares(name))
{
errors.semError( errors.semError(
id, "Duplicate declaration of identifier in same " + "scope: %s", name); id, "Duplicate declaration of identifier in same " + "scope: %s", name);
} else { continue;
}
else if (sym.get(name)!= null && sym.get(name) instanceof ClassVType)
{
errors.semError(id, "Cannot shadow class name: %s", name);
continue;
}
else
{
sym.put(name, type); sym.put(name, type);
} }
} }
/*for(String s:sym.getDeclaredSymbols())
System.out.println(" "+s);*/
sym = sym.getParent(); sym = sym.getParent();
return current_func; return current_func;
} }
@ -140,14 +163,27 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
} }
return globals.get(node.variable.name); return globals.get(node.variable.name);
} }
public boolean compare_functions(FuncValueType fun1, FuncValueType fun2) {
if (fun1.returnType.equals(fun2.returnType)==false)
return false;
if (fun1.parameters.size() != fun2.parameters.size())
return false;
for (int i=1; i<fun1.parameters.size(); i++)
if (fun1.parameters.get(i).equals(fun2.parameters.get(i))==false)
return false;
return true;
}
@Override @Override
public Type analyze(ClassDef node) public Type analyze(ClassDef node)
{ {
ClassVType cvt=new ClassVType(node.name.name); ClassVType cvt=new ClassVType(node.name.name);
SymbolTable current_scope=new SymbolTable<>(sym); SymbolTable<Type> current_scope=new SymbolTable<>(sym);
sym=current_scope; sym=current_scope;
current_class=cvt;
Type super_class = sym.get(node.superClass.name); Type super_class = sym.get(node.superClass.name);
cvt.super_class = node.superClass; cvt.super_class = (ClassVType)super_class;
SymbolTable<Type> super_scope=null;
Set<String> super_syms=null;
if (super_class == null) if (super_class == null)
{ {
errors.semError( errors.semError(
@ -165,22 +201,79 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<Type>
} }
else else
{ {
super_scope = cvt.super_class.scope;
super_syms = super_scope.getDeclaredSymbols();
for (Declaration decl : node.declarations) for (Declaration decl : node.declarations)
{ {
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);
if (sym.declares(name)) {
if (type == null)
continue;
if (sym.declares(name))
{
errors.semError( errors.semError(
id, "Duplicate declaration of identifier in same " + "scope: %s", name); id, "Duplicate declaration of identifier in same " + "scope: %s", name);
} }
if (type instanceof ClassVType || type instanceof ListValueType)
{//Check for attribute type
if (super_syms.contains(name))
{//Check for redefined superclass attribute
errors.semError(
id, "Cannot re-define attribute: %s", name);
}
else
sym.put(name, type);
}
else if(type instanceof FuncValueType)
{//For function declarations
List<ValueType> params = ((FuncValueType)type).parameters;
if(params.size() < 1 || (params.get(0) instanceof ClassVType==false) || ((ClassVType)params.get(0)).className.equals(current_class.className)==false)
errors.semError(
id, "First parameter of method must be of same class: %s", name);
if (super_syms.contains(name))
{
if ((super_scope.get(id.name) instanceof FuncValueType)==false)
errors.semError(id, "Cannot re-define attribute: %s" + name);
else else
{ {
FuncValueType super_func = (FuncValueType) super_scope.get(id.name);
FuncValueType current_func = (FuncValueType) type;
if (compare_functions(super_func, current_func))
sym.put(name, type);
else
errors.semError(
id, "Method overridden with different type signature: %s" + name);
}
}
else
sym.put(name, type); sym.put(name, type);
} }
} }
} }
for (String super_sym : super_syms)
{
if (sym.getDeclaredSymbols().contains(super_sym)==false)
sym.put(super_sym, super_scope.get(super_sym));
}
sym = sym.getParent(); sym = sym.getParent();
current_class=null;
return cvt; return cvt;
} }
@Override
public Type analyze(VarDef node)
{
Type var_type = sym.get(node.var.identifier.name);
if (node.var.identifier.name!=current_class.className && var_type==null)
errors.semError(
node, "Cannot re-define attribute: %s", node.var.identifier.name);
return ValueType.annotationToValueType(node.var.type);
}
@Override
public Type analyze(ListType node)
{
return ValueType.annotationToValueType(node);
}
} }

Loading…
Cancel
Save