public override void TypeCheck(MiniPL.Runnable context) { // if initial value specified check it agaist the type if (initialValue != null) { initialValue.TypeCheck(context); switch (type) { case ValueType.Boolean: if (initialValue.Type(context) == ValueType.String) { context.errors.Add(new SemanticError(Token, "cannot assign string value to boolean " + identifier)); } break; case ValueType.Integer: if (initialValue.Type(context) != ValueType.Integer) { context.errors.Add(new SemanticError(Token, "expected integer type value for " + identifier)); } break; case ValueType.String: if (initialValue.Type(context) != ValueType.String) { context.errors.Add(new SemanticError(Token, "expected string type value for " + identifier)); } break; } } }
public override void TypeCheck(MiniPL.Runnable context) { // typecheck value expr.TypeCheck(context); // check that value type matches variable switch (context.declarations[identifier].Type) { case ValueType.Boolean: if (expr.Type(context) == ValueType.String) { context.errors.Add(new SemanticError(Token, "cannot assign string value to boolean " + identifier)); } break; case ValueType.Integer: if (expr.Type(context) != ValueType.Integer) { context.errors.Add(new SemanticError(Token, "expected integer type value for " + identifier)); } break; case ValueType.String: if (expr.Type(context) != ValueType.String) { context.errors.Add(new SemanticError(Token, "expected string type value for " + identifier)); } break; } }
public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout) { if (expr.Type(context) == ValueType.String) { throw new Exception("TYPE CHECKING FAILED"); } // if expression evaluates to false, stop execution with a runtime error if (expr.Evaluate(context).BooleanValue() == false) { return(new RuntimeError(Token, "assertion failed")); } return(null); }
override public Value Evaluate(MiniPL.Runnable context) { if (op == '!') { if (expr.Type(context) == ValueType.Boolean) { return(new Value(!expr.Evaluate(context).BooleanValue())); } if (expr.Type(context) == ValueType.Integer) { return(new Value(expr.Evaluate(context).IntValue() == 0)); } throw new Exception("TYPE CHECKING FAILED"); } throw new Exception("UNEXPECTED OPERATION " + op); }
public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout) { // print value of parameter to output stream switch (expr.Type(context)) { case ValueType.Integer: stdout.Write(expr.Evaluate(context).IntValue()); break; case ValueType.String: stdout.Write(expr.Evaluate(context).StringValue()); break; default: throw new Exception("TYPE CHECK FAILED"); } return(null); }
public override void TypeCheck(MiniPL.Runnable context) { // typecheck parameters, control variable, and every statement in loop startVal.TypeCheck(context); endVal.TypeCheck(context); if (context.declarations[identifier].Type != ValueType.Integer) { context.errors.Add(new SemanticError(Token, "bad for-loop control type")); } if (startVal.Type(context) != ValueType.Integer) { context.errors.Add(new SemanticError(startVal.Token, "bad for-loop start value type")); } if (endVal.Type(context) != ValueType.Integer) { context.errors.Add(new SemanticError(startVal.Token, "bad for-loop end value type")); } foreach (Statement stmt in block) { stmt.TypeCheck(context); } }
// apply the appropriate operation on operands override public Value Evaluate(MiniPL.Runnable context) { switch (op) { case '+': if (rhs.Type(context) == ValueType.Integer && lhs.Type(context) == ValueType.Integer) { return(new Value(lhs.Evaluate(context).IntValue() + rhs.Evaluate(context).IntValue())); } if (rhs.Type(context) == ValueType.String && lhs.Type(context) == ValueType.String) { return(new Value(lhs.Evaluate(context).StringValue() + rhs.Evaluate(context).StringValue())); } throw new Exception("TYPECHECKING FAILED"); case '-': if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer) { throw new Exception("TYPECHECKING FAILED"); } return(new Value(lhs.Evaluate(context).IntValue() - rhs.Evaluate(context).IntValue())); case '*': if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer) { throw new Exception("TYPECHECKING FAILED"); } return(new Value(lhs.Evaluate(context).IntValue() * rhs.Evaluate(context).IntValue())); case '/': if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer) { throw new Exception("TYPECHECKING FAILED"); } int denominator = rhs.Evaluate(context).IntValue(); if (denominator == 0) { throw new MiniPL_DivideByZeroException(new RuntimeError(Token, "divide by zero")); } return(new Value(lhs.Evaluate(context).IntValue() / denominator)); case '<': if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer) { throw new Exception("TYPECHECKING FAILED"); } return(new Value(lhs.Evaluate(context).IntValue() < rhs.Evaluate(context).IntValue())); case '=': if (rhs.Type(context) != lhs.Type(context)) { throw new Exception("TYPECHECKING FAILED"); } switch (rhs.Type(context)) { case ValueType.Boolean: return(new Value(rhs.Evaluate(context).BooleanValue() == lhs.Evaluate(context).BooleanValue())); case ValueType.Integer: return(new Value(rhs.Evaluate(context).IntValue() == lhs.Evaluate(context).IntValue())); case ValueType.String: return(new Value(rhs.Evaluate(context).StringValue() == lhs.Evaluate(context).StringValue())); } break; case '&': if (rhs.Type(context) == ValueType.String || lhs.Type(context) == ValueType.String) { throw new Exception("TYPECHECKING FAILED"); } return(new Value(rhs.Evaluate(context).BooleanValue() && lhs.Evaluate(context).BooleanValue())); } throw new Exception("UNEXPECTED OPERATOR " + op); }