public static void ThrowsWhenEvaluated <TException>(ILispValue expression, ILispEnvironment environment = null) where TException : LispException { Assert.IsNotNull(expression); try { ILispValue actual = Evaluator.Evaluate(expression, environment ?? new GlobalEnvironment()); throw new AssertFailedException(string.Format( "Expression returned value instead of throwing: {1}{0}Expected: {2}, Actual: {3}", System.Environment.NewLine, expression, typeof(TException).FullName, actual)); } catch (LispException ex) { if (!(ex is TException)) { throw new AssertFailedException(string.Format( "Expression threw incorrect exception type: {1}{0}Expected: {2}{0}Actual: {3}", System.Environment.NewLine, expression, typeof(TException).FullName, ex)); } } }
private static ILispValue EvaluateProgn(IList <ILispValue> args, ILispEnvironment environment) { ILispValue result = Nil.Instance; foreach (ILispValue arg in args) { result = Evaluate(arg, environment); } return(result); }
private static ILispValue EvaluateQuote(IList <ILispValue> args, ILispEnvironment environment) { if (args.Count == 0) { throw new SignatureMismatchException("missing argument to 'quote'"); } if (args.Count > 1) { throw new SignatureMismatchException("too many arguments supplied"); } return(args[0]); }
public static void EvaluatesTo(ILispValue expected, ILispValue expression, ILispEnvironment environment = null) { Assert.IsNotNull(expected); Assert.IsNotNull(expression); ILispValue actual = Evaluator.Evaluate(expression, environment ?? new GlobalEnvironment()); if (!EqualityComparer <ILispValue> .Default.Equals(expected, actual)) { throw new AssertFailedException(string.Format( "Computed incorrect value while evaluating {1}.{0}Expected: {2}, Actual: {3}", System.Environment.NewLine, expression, expected, actual)); } }
private static ILispValue EvaluateList(List list, ILispEnvironment environment) { if (list.IsEmpty) { return(list); } ILispValue head = list.GetHead(); IList <ILispValue> parameters = list.CollectProperList().Skip(1).ToList(); if (head.Type == LispValueType.Symbol) { // Look for special forms and process them, um..., specially. switch (((Symbol)head).Name) { case "quote": return(EvaluateQuote(parameters, environment)); case "if": return(EvaluateIf(parameters, environment)); case "progn": return(EvaluateProgn(parameters, environment)); case "set!": return(EvaluateSet(parameters, environment)); case "lambda": return(EvaluateLambdaDefinition(parameters, environment)); default: return(EvaluateInvocation((Symbol)head, parameters, environment)); } } else { head = Evaluate(head, environment); if (head.Type != LispValueType.Symbol) { throw new TypeMismatchException(new Symbol("function"), LispValueType.Symbol, head.Type); } return(EvaluateInvocation((Symbol)head, parameters, environment)); } }
public static ILispValue Evaluate(ILispValue value, ILispEnvironment environment) { switch (value.Type) { case LispValueType.Boolean: case LispValueType.Char: case LispValueType.Lambda: case LispValueType.Number: case LispValueType.String: default: return(value); case LispValueType.Symbol: return(environment.Lookup((Symbol)value)); case LispValueType.List: return(EvaluateList((List)value, environment)); } }
private static ILispValue EvaluateSet(IList <ILispValue> args, ILispEnvironment environment) { if (args.Count < 2) { throw new SignatureMismatchException("too few arguments supplied"); } if (args.Count > 2) { throw new SignatureMismatchException("too many arguments supplied"); } // this is a special form since we do not evaluate the first argument, which must be a symbol if (args[0].Type != LispValueType.Symbol) { throw new TypeMismatchException(new Symbol("variable"), LispValueType.Symbol, args[0].Type); } ILispValue value = Evaluate(args[1], environment); environment.Set((Symbol)args[0], value); return(value); }
private static ILispValue EvaluateIf(IList <ILispValue> args, ILispEnvironment environment) { if (args.Count < 3) { throw new SignatureMismatchException("too few arguments supplied"); } if (args.Count > 3) { throw new SignatureMismatchException("too many arguments supplied"); } ILispValue test = Evaluate(args[0], environment); switch (test.Type) { case LispValueType.Boolean: if (!((TiaLisp.Values.Boolean)test).Value) { return(Evaluate(args[2], environment)); } else { return(Evaluate(args[1], environment)); } case LispValueType.List: if (((List)test).IsEmpty) { return(Evaluate(args[2], environment)); } else { return(Evaluate(args[1], environment)); } default: // Any other value than #f or () is considered true: return(Evaluate(args[1], environment)); } }
internal LocalEnvironment(ILispEnvironment parentEnvironment) { this._ParentEnvironment = parentEnvironment; }
public static void ThrowsWhenEvaluated(ILispValue expression, ILispEnvironment environment = null) { ThrowsWhenEvaluated <LispException>(expression, environment); }
private static ILispValue EvaluateInvocation(Symbol funcName, IList <ILispValue> args, ILispEnvironment environment) { ILispValue func = environment.Lookup(funcName); if (func.Type != LispValueType.Lambda) { throw new TypeMismatchException(new Symbol("function"), LispValueType.Lambda, func.Type); } ILispLambda lambda = (ILispLambda)func; IList <ILispValue> parameterValues = args.Select(arg => Evaluate(arg, environment)).ToList(); return(lambda.Execute(BindParameters(lambda, parameterValues))); }
private static ILispValue EvaluateLambdaDefinition(IList <ILispValue> args, ILispEnvironment environment) { throw new NotImplementedException(); }