Skip to content
Snippets Groups Projects
Verified Commit 2cf77637 authored by Recolic Keghart's avatar Recolic Keghart
Browse files

fix class inherit problems, fix type conversion, fix class member, fix some expr infer, etc

parent 0afe8c44
No related branches found
No related tags found
No related merge requests found
Pipeline #49 passed with warnings with stages
in 3 minutes and 30 seconds
...@@ -18,12 +18,20 @@ public class ClassValueType extends ValueType { ...@@ -18,12 +18,20 @@ public class ClassValueType extends ValueType {
@JsonIgnore @JsonIgnore
public Map<String, SymbolType> memberMap = null; public Map<String, SymbolType> memberMap = null;
@JsonIgnore
public ClassValueType parent = OBJECT_TYPE;
/** A class type for the class named CLASSNAME. */ /** A class type for the class named CLASSNAME. */
@JsonCreator @JsonCreator
public ClassValueType(@JsonProperty String className) { public ClassValueType(@JsonProperty String className) {
this.className = className; this.className = className;
} }
public ClassValueType(String className, ClassValueType parentType) {
this.className = className;
parent = parentType;
}
/** A class type for the class referenced by CLASSTYPEANNOTATION. */ /** A class type for the class referenced by CLASSTYPEANNOTATION. */
public ClassValueType(ClassType classTypeAnnotation) { public ClassValueType(ClassType classTypeAnnotation) {
this.className = classTypeAnnotation.className; this.className = classTypeAnnotation.className;
......
...@@ -102,6 +102,8 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -102,6 +102,8 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
// My-name already pushed to symbolMap // My-name already pushed to symbolMap
// TA doesn't like this: // classDef.name.dispatch(this); // TA doesn't like this: // classDef.name.dispatch(this);
// TA doesn't like this: // classDef.superClass.dispatch(this); // TA doesn't like this: // classDef.superClass.dispatch(this);
ClassValueType superType = (ClassValueType) classDef.superClass.dispatch(this);
classDef.superClass.setInferredType(null); // make TA happy
// Append parent to child if not exist. // Append parent to child if not exist.
if(!classDef.superClass.name.equals("object")) { if(!classDef.superClass.name.equals("object")) {
...@@ -115,7 +117,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -115,7 +117,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
} }
} }
ClassValueType result_type = new ClassValueType(classDef.name.name); ClassValueType result_type = new ClassValueType(classDef.name.name, superType);
result_type.memberMap = classDef.memberMap; result_type.memberMap = classDef.memberMap;
SymbolTable<SymbolType> symLayer = new SymbolTable<>(sym); SymbolTable<SymbolType> symLayer = new SymbolTable<>(sym);
// TODO: Maybe this is not necessary. I'm a cxx programmer. // TODO: Maybe this is not necessary. I'm a cxx programmer.
...@@ -245,6 +247,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -245,6 +247,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
Identifier id = (Identifier) target; Identifier id = (Identifier) target;
left_type = id.dispatch(this); left_type = id.dispatch(this);
} }
else if(target instanceof MemberExpr) {
MemberExpr memberExpr = (MemberExpr) target;
left_type = memberExpr.dispatch(this);
}
else { else {
err(node, "Not implemented assignStmt, target=" + target.getClass().getName()); err(node, "Not implemented assignStmt, target=" + target.getClass().getName());
} }
...@@ -512,7 +518,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -512,7 +518,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
err(node, "undefined identifier " + node.member.name + " as object member."); err(node, "undefined identifier " + node.member.name + " as object member.");
return NONE_TYPE; return NONE_TYPE;
} }
return resultType; return node.setInferredType(resultType);
} }
@Override @Override
...@@ -525,13 +531,31 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -525,13 +531,31 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
FuncType funcType = (FuncType) methodType; FuncType funcType = (FuncType) methodType;
List<SymbolType> args_type = new ArrayList<>(); List<SymbolType> args_type = new ArrayList<>();
if(node.method instanceof MemberExpr) {
args_type.add(((MemberExpr)node.method).object.getInferredType());
}
for(Expr expr : node.args) { for(Expr expr : node.args) {
args_type.add(expr.dispatch(this)); args_type.add(expr.dispatch(this));
} }
if(!args_type.equals(funcType.parameters)) {
err(node, "function/method parameter list mismatch"); if(!matchArgList(args_type, funcType.parameters)) {
err(node, "function/method parameter list mismatch. Got " + args_type.toString() + ",expecting " + funcType.parameters);
}
return node.setInferredType(funcType.returnType);
}
private boolean matchArgList(List<SymbolType> got, List<ValueType> expect) {
System.out.println("debug> match arg> " + got + " -> " + expect + ", size " + got.size() + expect.size());
if(got.size() != expect.size())
return false;
for(int cter = 0; cter < got.size(); ++cter) {
System.out.println("debug> match arg> " + got.get(cter).toString() + " -> " + expect.get(cter).toString());
if(typeConvertible(got.get(cter), expect.get(cter)))
continue; // ok
else
return false;
} }
return funcType.returnType; System.out.println("debug> SUCC match arg> " + got + " -> " + expect + ", size " + got.size() + expect.size());
return true;
} }
///////////////////////////// Others ////////////////////////////////////// ///////////////////////////// Others //////////////////////////////////////
...@@ -587,14 +611,44 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -587,14 +611,44 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
if(from.equals(EMPTY_TYPE)) from = new ListValueType(NONE_TYPE); if(from.equals(EMPTY_TYPE)) from = new ListValueType(NONE_TYPE);
if(to.equals(EMPTY_TYPE)) to = new ListValueType(NONE_TYPE); if(to.equals(EMPTY_TYPE)) to = new ListValueType(NONE_TYPE);
if(!from.isListType() || !to.isListType()) { if(!from.isListType() || !to.isListType()) {
// Cast class to parent
if(from instanceof ClassValueType && to instanceof ClassValueType) {
if(_typeConvertible_calcClassInheritChainCommonNode((ClassValueType) from, (ClassValueType) to).equals(to))
return true; // Can cast from->to
}
return from.equals(to); return from.equals(to);
} }
// Convert list to list:
ListValueType lsFrom = (ListValueType) from, lsTo = (ListValueType) to; ListValueType lsFrom = (ListValueType) from, lsTo = (ListValueType) to;
if(lsFrom.elementType == null || lsFrom.elementType.equals(NONE_TYPE)) if(lsFrom.elementType == null || lsFrom.elementType.equals(NONE_TYPE))
return true; return true;
return typeConvertible(lsFrom.elementType, lsTo.elementType); return typeConvertible(lsFrom.elementType, lsTo.elementType);
} }
private ClassValueType _typeConvertible_calcClassInheritChainCommonNode(ClassValueType l, ClassValueType r) {
int l_depth = 1, r_depth = 1;
ClassValueType l_curr = l, r_curr = r;
while(!l_curr.equals(OBJECT_TYPE)) {
++l_depth;
l_curr = l_curr.parent;
}
while(!r_curr.equals(OBJECT_TYPE)) {
++r_depth;
r_curr = r_curr.parent;
}
l_curr = l;
r_curr = r;
for(;l_depth > r_depth; --l_depth)
l_curr = l_curr.parent;
for(;r_depth > l_depth; --r_depth)
r_curr = r_curr.parent;
while(!l_curr.equals(r_curr)) { // NOTE: Use reference compare
l_curr = l_curr.parent;
r_curr = r_curr.parent;
}
if(l_curr == null) return OBJECT_TYPE;
else return l_curr;
}
private SymbolType calcCommonType(SymbolType another, SymbolType preferred) { private SymbolType calcCommonType(SymbolType another, SymbolType preferred) {
SymbolType l = another, r = preferred; SymbolType l = another, r = preferred;
if(l == null || r == null) if(l == null || r == null)
...@@ -607,6 +661,9 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -607,6 +661,9 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
return r; return r;
if(typeConvertible(r, l)) if(typeConvertible(r, l))
return l; return l;
if(another instanceof ClassValueType && preferred instanceof ClassValueType) {
return _typeConvertible_calcClassInheritChainCommonNode((ClassValueType) another, (ClassValueType) preferred);
}
return OBJECT_TYPE; return OBJECT_TYPE;
} }
private boolean typeIsUserDefinedClass(SymbolType type) { private boolean typeIsUserDefinedClass(SymbolType type) {
...@@ -622,13 +679,11 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { ...@@ -622,13 +679,11 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
} }
private ValueType fixClassTypeProblem(ValueType valType) { private ValueType fixClassTypeProblem(ValueType valType) {
if(typeIsUserDefinedClass(valType)) { if(typeIsUserDefinedClass(valType)) {
System.out.println("debug: annotation class name resolved." + valType.className());
ClassValueType realType = (ClassValueType)sym.get(valType.className()); ClassValueType realType = (ClassValueType)sym.get(valType.className());
if(realType == null) { if(realType == null) {
System.out.println("FIXME: annotation uses an unknown class type. Unable to assign member map."); System.out.println("FIXME: annotation uses an unknown class type. Unable to assign member map.");
return valType; return valType;
} }
System.out.println("debug: -m- " + realType.memberMap);
return realType; return realType;
} }
else else
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment