public static void Validate(IExpression e, Functions funcs, TypeMap tm) { if (e is Value) { return; } if (e is Call) { Validate((Call)e, funcs, tm); return; } if (e is Variable) { Variable v = (Variable)e; Check(tm.ContainsKey(v), "Caught undeclared variable in static type Check: " + v); return; } if (e is Binary) { Binary b = (Binary)e; Type type1 = TypeOf(b.Term1(), funcs, tm); Type type2 = TypeOf(b.Term2(), funcs, tm); Validate(b.Term1(), funcs, tm); Validate(b.Term2(), funcs, tm); if (b.Operator().IsArithmeticOp()) { Check((type1 == Type.INT && type2 == Type.INT) || (type1 == Type.FLOAT && type2 == Type.FLOAT) || (type1 == Type.INT && type2 == Type.FLOAT) || (type1 == Type.FLOAT && type2 == Type.INT), "Type error for arithmetic op " + b.Operator() + "; got types " + type1 + " and " + type2); } else if (b.Operator().IsRelationalOp()) { Check((type1 == Type.INT && type2 == Type.INT) || (type1 == Type.FLOAT && type2 == Type.FLOAT) || (type1 == Type.INT && type2 == Type.FLOAT) || (type1 == Type.FLOAT && type2 == Type.INT) || (type1 == Type.BOOL && type2 == Type.BOOL) || (type1 == Type.CHAR && type2 == Type.CHAR), "Type error for relational op " + b.Operator() + "; got types " + type1 + " and " + type2); } else if (b.Operator().IsBooleanOp()) { Check(type1 == Type.BOOL && type2 == Type.BOOL, "Caught non-bool operand for " + b.Operator() + " in static type Checker; got types " + type1 + " and " + type2); } else { throw new IException("Type Checking Error", "", "Semantic", 0, 0); } return; } else if (e is Unary) { Unary u = (Unary)e; Type t = TypeOf(u.term, funcs, tm); Validate(u.term, funcs, tm); if (u.Operator().IsNotOp()) { Check(t == Type.BOOL, "Attempted not operation on non-bool (attempted on " + t + ")"); } else if (u.Operator().IsNegateOp()) { Check(t == Type.FLOAT || t == Type.INT, "Attempted negate operation on something other than a float or int (attempted on " + t + ")"); } else if (u.Operator().IsIntOp()) { Check(t == Type.FLOAT || t == Type.CHAR, "Attempted int cast from something other than a float or a char (attempted on " + t + ")"); } else if (u.Operator().IsFloatOp()) { Check(t == Type.INT, "Attempted float cast from something other than an int (attempted on " + t + ")"); } else if (u.Operator().IsCharOp()) { Check(t == Type.INT, "Attempted char cast from something other than an int (attempted on " + t + ")"); } } else { throw new IException("Type Checking Error", "", "Semantic", 0, 0); } }
public static Type TypeOf(IExpression e, Functions funcs, TypeMap tm) { if (e is Value) { return(((Value)e).Type()); } else if (e is Call) { Call c = (Call)e; Function f = funcs[c.Identifier().ToString()]; return(f.type()); } else if (e is Variable) { Variable v = (Variable)e; Check(tm.ContainsKey(v), "Caught undefined variable in static type Checker: " + v); return((Type)tm[v]); } else if (e is Binary) { Binary b = (Binary)e; if (b.Operator().IsArithmeticOp()) { if (TypeOf(b.Term1(), funcs, tm) == Type.INT && TypeOf(b.Term1(), funcs, tm) == Type.INT) { return(Type.INT); } else { return(Type.FLOAT); } } else if (b.Operator().IsRelationalOp() || b.Operator().IsBooleanOp()) { return(Type.BOOL); } else { throw new IException("Unknown binary op in static type Checker, expression: " + e, "", "Semantic", 0, 0); } } else if (e is Unary) { Unary u = (Unary)e; if (u.Operator().IsNotOp()) { return(Type.BOOL); } else if (u.Operator().IsNegateOp()) { return(TypeOf(u.term, funcs, tm)); } else if (u.Operator().IsIntOp()) { return(Type.INT); } else if (u.Operator().IsFloatOp()) { return(Type.FLOAT); } else if (u.Operator().IsCharOp()) { return(Type.CHAR); } } throw new IException("Type Checking Error", "", "Semantic", 0, 0); }
public static Value Interpret(Unary u, Functions funcs, State state) { Operator op = u.Operator(); Value v = Interpret(u.term, funcs, state); StaticTypeCheck.Check(!v.Undefined(), "reference to undef value in unary op"); if (op.val.Equals(Operator.NOT)) { if (v.Type() != Type.BOOL) { throw new IException("Can only apply ! operator to bool (attempted on " + v + ")", "", "Semantic", 0, 0); } else { return(new BoolValue(!v.DBoolValue())); } } else if (op.val.Equals(Operator.NEG)) { if (v.Type() == Type.FLOAT) { return(new FloatValue(-v.DFloatValue())); } else if (v.Type() == Type.INT) { return(new IntValue(-v.DIntValue())); } else { throw new IException("Can only apply - operator to int or float (attempted on " + v + ")", "", "Semantic", 0, 0); } } else if (op.val.Equals(Operator.FLOAT)) { if (v.Type() != Type.INT) { throw new IException("Can only cast int to float (tried to cast " + v + ")", "", "Semantic", 0, 0); } else { return(new FloatValue((float)v.DIntValue())); } } else if (op.val.Equals(Operator.INT)) { if (v.Type() == Type.FLOAT) { return(new IntValue((int)v.DFloatValue())); } else if (v.Type() == Type.CHAR) { return(new IntValue((int)v.DCharValue())); } else { throw new IException("Can only cast float or char to int (tried to cast " + v + ")", "", "Semantic", 0, 0); } } else if (op.val.Equals(Operator.CHAR)) { if (v.Type() == Type.INT) { return(new CharValue((char)v.DIntValue())); } else { throw new IException("Can only cast int to char (tried to cast " + v + ")", "", "Semantic", 0, 0); } } throw new IException("Semantic Error", "", "Semantic", 0, 0); }