Instructions
Spremenite svoj prevajalnik tako, da dopušča uporabo konstante 0 namesto konstante nil (0 ima torej dva pomena: kot celoštevilska konstanta in kot kazalčna konstanta).
Test
var x: int
var p: ^int
fun main(): int =
x = 0,
p = 0,
return 0
Out
Before
Error
After
No error
Code
/seman/TypeChecker.java
public class TypeChecker implements AST.FullVisitor<TYP.Type, TypeChecker.Info> {
// ... other code ...
// --- CHANGED: Add pointer coercion for integer zero ---
private boolean coercible(TYP.Type t1, AST.Expr e1, TYP.Type t2) {
if (t1 instanceof TYP.IntType && t2.actualType() instanceof TYP.PtrType &&
e1 instanceof AST.AtomExpr atomE1 && atomE1.type == AST.AtomExpr.Type.INT && atomE1.value.equals("0"))
return true;
// --- CHANGED: Added e1 to all coercible calls
if (t1 instanceof TYP.IntType)
return typeEqu(t2, TYP.IntType.type);
if (t1 instanceof TYP.CharType)
return typeEqu(t2, TYP.CharType.type);
if (t1 instanceof TYP.BoolType)
return typeEqu(t2, TYP.BoolType.type);
if (t1 instanceof TYP.VoidType)
return t2 instanceof TYP.VoidType;
if (t1 instanceof TYP.PtrType ptrType1 && t2 instanceof TYP.PtrType ptrType2) {
return coercible(ptrType1.baseType, e1, ptrType2.baseType);
}
if (t1 instanceof TYP.ArrType arrType1 && t2 instanceof TYP.ArrType arrType2) {
return (arrType1.numElems.equals(arrType2.numElems) &&
coercible(arrType1.elemType, e1, arrType2.elemType));
}
if (t1 instanceof TYP.StrType strType1 && t2 instanceof TYP.StrType strType2) {
return coercible(strType1.compTypes, strType2.compTypes);
}
if (t1 instanceof TYP.UniType uniType1 && t2 instanceof TYP.UniType uniType2) {
return coercible(uniType1.compTypes, uniType2.compTypes);
}
if (t1 instanceof TYP.FunType funType1 && t2 instanceof TYP.FunType funType2) {
return (coercible(funType1.resType, e1, funType2.resType) &&
coercible(funType1.parTypes, funType2.parTypes));
}
if (t1 instanceof TYP.NameType nameType1 && t2 instanceof TYP.NameType nameType2) {
return (nameType1.name.equals(nameType2.name) &&
typeEqu(nameType1.actualType(), nameType2.actualType()));
}
return false;
}
// --- CHANGED: Update all calls to coercible to pass the expression as well ---
@Override
public TYP.Type visit(AST.AssignStmt assignStmt, Info info) {
// ... other code ...
if (!coercible(srcExprType, assignStmt.srcExpr, dstExprType))
throw new Report.Error(assignStmt.srcExpr, "TypeChecker error: Cannot assign non-coercible types");
// ... other code ...
}
@Override
public TYP.Type visit(AST.ReturnStmt returnStmt, Info info) {
// ... other code ...
if (!coercible(retExprType, returnStmt.retExpr, parentFunType.resType))
throw new Report.Error(returnStmt,
"TypeChecker error: Returned expression type must be coercible to function result type");
// ... other code ...
}
@Override
public TYP.Type visit(AST.BinExpr binExpr, Info info) {
// ... other code ...
boolean sndIntoFstCoercible = coercible(sndExprType, binExpr.sndExpr, fstExprType);
boolean fstIntoSndCoercible = coercible(fstExprType, binExpr.fstExpr, sndExprType);
// ... other code ...
}
@Override
public TYP.Type visit(AST.CallExpr callExpr, Info info) {
// ... other code ...
for (int i = 0; i < funParTypes.size(); i++) {
TYP.Type callArgExprType = SemAn.ofType.get(callExpr.argExprs.get(i));
TYP.Type funParType = funParTypes.get(i);
if (!coercible(callArgExprType, callExpr.argExprs.get(i), funParType))
throw new Report.Error(callExpr.argExprs.get(i),
"TypeChecker error: Function parameter type and argument type do not match");
}
// ... other code ...
}
}