private MObject EvalProgram(Program program, Environment env) { MObject rs = null; foreach (var statement in program.Statements) { rs = Eval(statement, env); if (rs == null) { return(rs); } var t = rs.GetType(); if (t == typeof(ReturnValue)) { return(((ReturnValue)rs).value); } else if (t == typeof(Error)) { return(rs); } } return(rs); }
private bool IsError(MObject obj) { if (obj == null) { return(false); } return(obj.MType() == ObjectType.ERROR_OBJ); }
private MObject UnwrapReturnValue(MObject obj) { if (obj.GetType() == typeof(ReturnValue)) { return(((ReturnValue)obj).value); } return(obj); }
private MObject ApplyFunction(MObject fn, MObject[] args) { var function = (Function)fn; var extendedEnv = ExtendFunctionEnv(function, args); var evaluated = Eval(function.body, extendedEnv); return(UnwrapReturnValue(evaluated)); }
public MObject Set(string name, MObject obj) { if (store.ContainsKey(name)) { store[name] = obj; } else { store.Add(name, obj); } return(obj); }
private MObject EvalMinusPrefixOperatorExpression(MObject right) { if (right.MType() != ObjectType.INTEGER_OBJ) { return(NewError(string.Format("unknown operator: -%s", right.MType()))); } var val = ((MInt)right).value; return(new MInt() { value = -val }); }
private MObject EvalPrefixExpression(string op, MObject right, Environment env) { switch (op) { case "!": return(EvalBangOperatorExpression(right)); case "-": return(EvalMinusPrefixOperatorExpression(right)); default: return(NewError(string.Format("unknown operator: %s%s", op, right.MType()))); } }
private MObject EvalIntegerInfixExpression(string op, MObject left, MObject right) { var lv = ((MInt)left).value; var rv = ((MInt)right).value; switch (op) { case "+": return(new MInt() { value = lv + rv }); case "-": return(new MInt() { value = lv - rv }); case "*": return(new MInt() { value = lv * rv }); case "/": return(new MInt() { value = lv / rv }); case ">": return(NativeBoolToMBool(lv > rv)); case "<": return(NativeBoolToMBool(lv < rv)); case "==": return(NativeBoolToMBool(lv == rv)); case "!=": return(NativeBoolToMBool(lv != rv)); default: return(NewError(string.Format("unknown operator: %s %s %s", left.MType(), op, right.MType()))); } }
private MObject EvalBlockStatement(BlockStatement block, Environment env) { MObject rs = null; foreach (var statement in block.Statements) { rs = Eval(statement, env); if (rs != null) { var t = rs.MType(); if (t == ObjectType.RETURN_VALUE_OBJ || t == ObjectType.ERROR_OBJ) { return(rs); } } } return(rs); }
private MObject EvalBangOperatorExpression(MObject right) { if (right == TRUE) { return(FALSE); } else if (right == FALSE) { return(TRUE); } else if (right == NIL) { return(TRUE); } else { return(FALSE); } }
private bool IsTruthy(MObject obj) { if (obj == TRUE) { return(true); } else if (obj == FALSE) { return(false); } else if (obj == NIL) { return(false); } else { return(true); } }
private MObject EvalInfixExpression(string op, MObject left, MObject right, Environment env) { if (left.MType() == ObjectType.INTEGER_OBJ && right.MType() == ObjectType.INTEGER_OBJ) { return(EvalIntegerInfixExpression(op, left, right)); } else if (op == "==") { return(NativeBoolToMBool(left == right)); } else if (op == "!=") { return(NativeBoolToMBool(left != right)); } else if (left.MType() != right.MType()) { return(NewError(string.Format("type mismatch: %s %s %s", left.MType(), op, right.MType()))); } else { return(NewError(string.Format("unknown operator: %s %s %s", left.MType(), op, right.MType()))); } }