You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
3.3 KiB
97 lines
3.3 KiB
package chocopy.pa2;
|
|
|
|
import chocopy.common.analysis.SymbolTable;
|
|
import chocopy.common.analysis.types.ClassVType;
|
|
import chocopy.common.analysis.types.ClassValueType;
|
|
import chocopy.common.analysis.types.Type;
|
|
import chocopy.common.analysis.types.ValueType;
|
|
import chocopy.common.astnodes.ClassType;
|
|
import chocopy.common.astnodes.Program;
|
|
import java.util.ArrayList;
|
|
/** Top-level class for performing semantic analysis. */
|
|
public class StudentAnalysis {
|
|
|
|
/**
|
|
* Perform semantic analysis on PROGRAM, adding error messages and type annotations. Provide
|
|
* debugging output iff DEBUG. Returns modified tree.
|
|
*/
|
|
|
|
public static
|
|
boolean subClassOf(Type p, Type c, SymbolTable<Type> sym){
|
|
String pName = p.className();
|
|
if(pName!=null && pName.equals("object"))
|
|
return true;
|
|
if(c instanceof ClassValueType)
|
|
c = sym.get(c.className());
|
|
if(c instanceof ClassVType){
|
|
ClassVType child = (ClassVType) c;
|
|
|
|
String typename = child.className;
|
|
while(typename!=null){
|
|
if(typename.equals(pName))
|
|
return true;
|
|
child = child.super_class;
|
|
if(child!=null)
|
|
typename = child.className;
|
|
else
|
|
return false;
|
|
}
|
|
return false;
|
|
} else return p.equals(c);
|
|
}
|
|
private static void extractInhPath(Type ty, ArrayList<Type> res){
|
|
if(ty == null)
|
|
{
|
|
res.add(Type.OBJECT_TYPE);
|
|
return;
|
|
}
|
|
if(ty instanceof ClassVType){
|
|
ClassVType t1 = (ClassVType) ty;
|
|
String typename = t1.className;
|
|
while(typename!=null){
|
|
res.add(new ClassValueType(typename));
|
|
t1 = t1.super_class;
|
|
if(t1 != null)
|
|
typename = t1.className();
|
|
else break;
|
|
}
|
|
} else res.add(ty);
|
|
if(!res.get(res.size() - 1).equals(Type.OBJECT_TYPE))
|
|
res.add(Type.OBJECT_TYPE);
|
|
}
|
|
public static Type lowestCommonType(Type p, Type c, SymbolTable<Type> sym){
|
|
if(p instanceof ClassValueType)
|
|
p = sym.get(p.className());
|
|
if(c instanceof ClassValueType)
|
|
c = sym.get(c.className());
|
|
ArrayList<Type> inhPath1 = new ArrayList<Type>(),
|
|
inhPath2 = new ArrayList<Type>();
|
|
extractInhPath(p, inhPath1);
|
|
extractInhPath(c, inhPath2);
|
|
int l1 = inhPath1.size(), l2 = inhPath2.size(),
|
|
len = l1 < l2 ? l1 : l2;
|
|
int i = 1;
|
|
for(; i <= len; ++ i){
|
|
if(!inhPath1.get(l1 - i).equals(inhPath2.get(l2 - i)))
|
|
break;
|
|
}
|
|
return inhPath1.get(l1 - i + 1);
|
|
}
|
|
public static Program process(Program program, boolean debug) {
|
|
if (program.hasErrors()) {
|
|
return program;
|
|
}
|
|
|
|
DeclarationAnalyzer declarationAnalyzer = new DeclarationAnalyzer(program.errors);
|
|
program.dispatch(declarationAnalyzer);
|
|
SymbolTable<Type> globalSym = declarationAnalyzer.getGlobals();
|
|
|
|
if (!program.hasErrors()) {
|
|
TypeChecker typeChecker = new TypeChecker(globalSym, program.errors);
|
|
program.dispatch(typeChecker);
|
|
}
|
|
//System.out.println(program);
|
|
return program;
|
|
}
|
|
}
|