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)); } } }
public void ProperListToString() { ILispValue properList = Lisp.List(Lisp.Symbol("test"), Lisp.Constant(1), Lisp.Constant("foo"), Lisp.List(Lisp.Constant(1), Lisp.Constant(2), Lisp.Constant(3)), Lisp.Constant(true)); Assert.IsInstanceOfType(properList, typeof(ConsBox)); Assert.AreEqual("(test 1 \"foo\" (1 2 3) #t)", properList.ToString()); }
bool IEquatable <ILispValue> .Equals(ILispValue other) { if (other == null) { return(false); } if (!(other is List)) { return(false); } List otherList = (List)other; if (this.IsEmpty != otherList.IsEmpty) { return(false); } else if (this.IsEmpty && otherList.IsEmpty) { return(true); } else { return(((ConsBox)this).Equals((ConsBox)other)); } }
private static ILispValue EvaluateProgn(IList <ILispValue> args, ILispEnvironment environment) { ILispValue result = Nil.Instance; foreach (ILispValue arg in args) { result = Evaluate(arg, environment); } return(result); }
bool IEquatable <ILispValue> .Equals(ILispValue other) { if (other is Symbol) { return(Equals((Symbol)other)); } else { return(false); } }
bool IEquatable <ILispValue> .Equals(ILispValue other) { if (other == null) { return(false); } if (!(other is SimpleValue <T>)) { return(false); } return(this.Value.Equals(((SimpleValue <T>)other).Value)); }
public ILispValue execute(LispArray array) { if (array.getSize() == 2) { value = array [1]; return(value); } else { return(value); } }
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))); }
public static void AreEqual(ILispValue expected, ILispValue actual) { Assert.IsNotNull(expected); Assert.IsNotNull(actual); if (!EqualityComparer <ILispValue> .Default.Equals(expected, actual)) { throw new AssertFailedException(string.Format( "Values are different.{0}Expected: {1}, Actual: {2}", System.Environment.NewLine, expected, actual)); } }
bool IEquatable <ILispValue> .Equals(ILispValue other) { if (other == null) { return(false); } else if (other is String) { return(string.Equals(this.Value, ((String)other).Value)); } else { return(false); } }
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)); } }
public void ProperListConstruction() { ILispValue helperConstructedList = Lisp.List( Lisp.Symbol("test"), Lisp.Constant(1), Lisp.Constant("foo"), Lisp.List(Lisp.Constant(1), Lisp.Constant(2), Lisp.Constant(3)), Lisp.Constant(true)); ILispValue manuallyConstructedList = new ConsBox { Head = Lisp.Symbol("test"), Tail = new ConsBox { Head = Lisp.Constant(1), Tail = new ConsBox { Head = Lisp.Constant("foo"), Tail = new ConsBox { Head = new ConsBox { Head = Lisp.Constant(1), Tail = new ConsBox { Head = Lisp.Constant(2), Tail = new ConsBox { Head = Lisp.Constant(3), Tail = Nil.Instance } } }, Tail = new ConsBox { Head = Lisp.Constant(true), Tail = Nil.Instance } } } } }; // Do not use Assert.AreEqual here since it doesn't use IEquatable. LispAssert.AreEqual(manuallyConstructedList, helperConstructedList); }
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)); } }
public static void ThrowsWhenEvaluated(ILispValue expression, ILispEnvironment environment = null) { ThrowsWhenEvaluated <LispException>(expression, environment); }
public void Set(Symbol name, ILispValue value) { _Variables[name] = value; }
private static Dictionary <string, ILispValue> BindParameters(ILispLambda lambda, IList <ILispValue> parameters) { Dictionary <string, ILispValue> bindings = new Dictionary <string, ILispValue>(); Queue <ILispValue> actualParameters = new Queue <ILispValue>(parameters); foreach (LambdaParameter definedParameter in lambda.Parameters) { switch (definedParameter.ParameterType) { case LambdaParameterType.Normal: { if (actualParameters.Count == 0) { throw new SignatureMismatchException("missing required argument: " + definedParameter.Name); } ILispValue value = actualParameters.Dequeue(); if (definedParameter.ValueType != LispValueType.Unknown && definedParameter.ValueType != value.Type) { throw new TypeMismatchException(definedParameter.Name, definedParameter.ValueType, value.Type); } bindings[definedParameter.Name.Name] = value; } break; case LambdaParameterType.Optional: { if (actualParameters.Count > 0) { goto case LambdaParameterType.Normal; } switch (definedParameter.ValueType) { case LispValueType.Unknown: case LispValueType.List: bindings[definedParameter.Name.Name] = Nil.Instance; break; case LispValueType.Boolean: bindings[definedParameter.Name.Name] = new TiaLisp.Values.Boolean(false); break; case LispValueType.String: bindings[definedParameter.Name.Name] = new TiaLisp.Values.String(string.Empty); break; case LispValueType.Number: bindings[definedParameter.Name.Name] = new Number(0); break; case LispValueType.Char: bindings[definedParameter.Name.Name] = new Character(default(char)); break; default: throw new LispException("do not know how to construct a default value for type " + definedParameter.ValueType); } } break; case LambdaParameterType.Rest: { foreach (ILispValue actualParameter in actualParameters) { if (definedParameter.ValueType != LispValueType.Unknown && definedParameter.ValueType != actualParameter.Type) { throw new TypeMismatchException(definedParameter.Name, definedParameter.ValueType, actualParameter.Type); } } bindings[definedParameter.Name.Name] = Lisp.List(actualParameters.ToArray()); actualParameters.Clear(); } break; } } if (actualParameters.Count > 0) { throw new SignatureMismatchException("too many arguments supplied"); } return(bindings); }
ILispValue execute(ILispValue a) { throw new NotImplementedException(); }
public static List Quote(ILispValue value) { return(Lisp.List(Lisp.Symbol("quote"), value)); }
public static ConsBox Cons(ILispValue head, ILispValue tail) { return(new ConsBox { Head = head, Tail = tail }); }
bool IEquatable <ILispValue> .Equals(ILispValue other) { return(false); }
bool IEquatable <ILispValue> .Equals(ILispValue other) { return(object.ReferenceEquals(this, other)); }
bool IEquatable <ILispValue> .Equals(ILispValue other) { // TODO: implement return(object.ReferenceEquals(this, other)); }
public LispBoundValue(ILispValue val) { value = val; }
/// <summary> /// Parse the specified code using a specified registry and bank. /// </summary> /// <param name="data">The code to parse</param> /// <param name="registry">Registry of the context</param> /// <param name="bank">Bank of the context</param> public ILispValue parse(string data, Dictionary <string, ILispNative> registry, Dictionary <string, ILispValue> bank) { ParserState state = new ParserState(); state.position = 0; state.data = data + " "; state.root = new List <ILispValue>(); for (; state.position < state.data.Length; state.position++) { int sign = 1; bool no_eval; switch (state.data [state.position]) { case '\'': case '(': if (state.data [state.position] == '\'') { no_eval = true; state.position++; } else { no_eval = false; } var n = resolve_parenthesis(ref state); string child = state.data.Substring(n.beg + 1, n.end - n.beg - 1); LispArray tmp_insertee = (LispArray)parse(child, registry, bank); tmp_insertee.force_eval = !no_eval; state.root.Add(tmp_insertee); state.position--; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case '-': if ( Char.IsDigit(state.data [state.position]) || state.data [state.position] == '.' || ( Char.IsDigit(state.data [state.position + 1]) && state.data [state.position] == '-' )) { if (state.data [state.position] == '-') { sign = -1; state.position++; } ILispValue symn = resolve_numeric(ref state, sign); state.root.Add(symn); state.position--; } else { goto default; } break; case '"': ILispValue symst = new LispString(resolve_string(ref state)); state.root.Add(symst); break; case ' ': case '\t': case '\n': break; default: string syms = resolve_symbol(ref state); if (syms != "") { state.root.Add(registry [syms]); state.position--; } break; } } return(new LispArray(state.root)); }