package typelang;
import java.util.ArrayList;
import java.util.List;
import typelang.AST.*;
import typelang.Env.ExtendEnv;
import typelang.Env.GlobalEnv;
import typelang.Type.*;
public class Checker implements Visitor
Printer.Formatter ts = new Printer.Formatter();
Env
private Env
GlobalEnv
/* Type for procedure: (read
List
formalTypes.add(new Type.StringT());
initEnv.extend(“read”, new Type.FuncT(formalTypes, new Type.StringT()));
/* Type for procedure: (require
formalTypes = new ArrayList
formalTypes.add(new Type.StringT());
initEnv.extend(“eval”, new Type.FuncT(formalTypes, new Type.UnitT()));
/* Add type for new built-in procedures here */
return initEnv;
}
Type check(Program p) {
return (Type) p.accept(this, null);
}
public Type visit(Program p, Env
Env
for (DefineDecl d: p.decls()) {
Type type = (Type)d.accept(this, new_env);
if (type instanceof ErrorT) { return type; }
Type dType = d.type();
if (!type.typeEqual(dType)) {
return new ErrorT(“Expected ” + dType + ” found ” + type + ” in ” + ts.visit(d, null));
}
new_env = new ExtendEnv
}
return (Type) p.e().accept(this, new_env);
}
public Type visit(VarExp e, Env
try {
return env.get(e.name());
} catch(Exception ex) {
return new ErrorT(“Variable ” + e.name() +
” has not been declared in ” + ts.visit(e, null));
}
}
public Type visit(LetExp e, Env
List
List
List
List
int i = 0;
for (Exp exp : value_exps) {
Type type = (Type)exp.accept(this, env);
if (type instanceof ErrorT) { return type; }
Type argType = types.get(i);
if (!type.typeEqual(argType)) {
return new ErrorT(“The declared type of the ” + i +
” let variable and the actual type mismatch, expect ” +
argType.tostring() + ” found ” + type.tostring() +
” in ” + ts.visit(e, null));
}
values.add(type);
i++;
}
Env
for (int index = 0; index < names.size(); index++)
new_env = new ExtendEnv
values.get(index));
return (Type) e.body().accept(this, new_env);
}
public Type visit(DefineDecl d, Env
String name = d.name();
Type t =(Type) d._value_exp.accept(this, env);
((GlobalEnv
return t;
}
public Type visit(LambdaExp e, Env
List
List
String message = “The number of formal parameters and the number of ”
+ “arguments in the function type do not match in “;
if (types.size() == names.size()) {
Env
int index = 0;
for (Type argType : types) {
new_env = new ExtendEnv
argType);
index++;
}
Type bodyType = (Type) e.body().accept(this, new_env);
return new FuncT(types,bodyType);
}
return new ErrorT(message + ts.visit(e, null));
}
public Type visit(CallExp e, Env
// answer question 6
}
public Type visit(LetrecExp e, Env
List
List
List
// collect the environment
Env
for (int index = 0; index < names.size(); index++) {
new_env = new ExtendEnv
types.get(index));
}
// verify the types of the variables
for (int index = 0; index < names.size(); index++) {
Type type = (Type)fun_exps.get(index).accept(this, new_env);
if (type instanceof ErrorT) { return type; }
if (!assignable(types.get(index), type)) {
return new ErrorT("The expected type of the " + index +
" variable is " + types.get(index).tostring() +
" found " + type.tostring() + " in " +
ts.visit(e, null));
}
}
return (Type) e.body().accept(this, new_env);
}
public Type visit(IfExp e, Env
// answer question 5
}
public Type visit(CarExp e, Env
// answer question 2(a)
}
public Type visit(CdrExp e, Env
Exp exp = e.arg();
Type type = (Type)exp.accept(this, env);
if (type instanceof ErrorT) { return type; }
if (type instanceof PairT) {
PairT pt = (PairT)type;
return pt.snd();
}
return new ErrorT(“The cdr expect an expression of type Pair, found ”
+ type.tostring() + ” in ” + ts.visit(e, null));
}
public Type visit(ConsExp e, Env
Exp fst = e.fst();
Exp snd = e.snd();
Type t1 = (Type)fst.accept(this, env);
if (t1 instanceof ErrorT) { return t1; }
Type t2 = (Type)snd.accept(this, env);
if (t2 instanceof ErrorT) { return t2; }
return new PairT(t1, t2);
}
public Type visit(ListExp e, Env
// answer question 2(b)
}
public Type visit(NullExp e, Env
Exp arg = e.arg();
Type type = (Type)arg.accept(this, env);
if (type instanceof ErrorT) { return type; }
if (type instanceof ListT) { return BoolT.getInstance(); }
return new ErrorT(“The null? expect an expression of type List, found ”
+ type.tostring() + ” in ” + ts.visit(e, null));
}
public Type visit(RefExp e, Env
Exp value = e.value_exp();
Type type = e.type();
Type expType = (Type)value.accept(this, env);
if (type instanceof ErrorT) { return type; }
if (expType.typeEqual(type)) {
return new RefT(type);
}
return new ErrorT(“The Ref expression expect type ” + type.tostring() +
” found ” + expType.tostring() + ” in ” + ts.visit(e, null));
}
public Type visit(DerefExp e, Env
// answer question 1(a)
}
public Type visit(AssignExp e, Env
// answer question 1(b)
}
public Type visit(FreeExp e, Env
Exp exp = e.value_exp();
Type type = (Type)exp.accept(this, env);
if (type instanceof ErrorT) { return type; }
if (type instanceof RefT) { return UnitT.getInstance(); }
return new ErrorT(“The free expression expect a reference type ” +
“found ” + type.tostring() + ” in ” + ts.visit(e, null));
}
public Type visit(UnitExp e, Env
return Type.UnitT.getInstance();
}
public Type visit(NumExp e, Env
return NumT.getInstance();
}
public Type visit(StrExp e, Env
return Type.StringT.getInstance();
}
public Type visit(BoolExp e, Env
return Type.BoolT.getInstance();
}
public Type visit(LessExp e, Env
return visitBinaryComparator(e, env, ts.visit(e, null));
}
public Type visit(EqualExp e, Env
return visitBinaryComparator(e, env, ts.visit(e, null));
}
public Type visit(GreaterExp e, Env
return visitBinaryComparator(e, env, ts.visit(e, null));
}
private Type visitBinaryComparator(BinaryComparator e, Env
String printNode) {
// answer question 4
}
public Type visit(AddExp e, Env
return visitCompoundArithExp(e, env, ts.visit(e, null));
}
public Type visit(DivExp e, Env
return visitCompoundArithExp(e, env, ts.visit(e, null));
}
public Type visit(MultExp e, Env
return visitCompoundArithExp(e, env, ts.visit(e, null));
}
public Type visit(SubExp e, Env
return visitCompoundArithExp(e, env, ts.visit(e, null));
}
private Type visitCompoundArithExp(CompoundArithExp e, Env
// answer question 3
}
private static boolean assignable(Type t1, Type t2) {
if (t2 instanceof UnitT) { return true; }
return t1.typeEqual(t2);
}
public Type visit(ReadExp e, Env
return UnitT.getInstance();
}
public Type visit(EvalExp e, Env
return UnitT.getInstance();
}
}