public object Cons(object pObject) { var deepCopy = new SharpList(); deepCopy.Add (pObject); foreach (var item in this) { deepCopy.Add (item); } return deepCopy; }
public object Rest() { if (this.Count == 0) { return null; } else { if (Count <= 1) { return null; } var deepCopy = new SharpList (); for(int i = 1; i < Count; i++) { deepCopy.Add (this[i]); } return deepCopy; } }
private object Set(SharpList pList, Scope pCurrentScope) { string symbolName = (pList [1] as SymbolToken).value; Scope s = pCurrentScope.TryResolveScope (symbolName); s.SetVar (symbolName, Eval(pList [2], pCurrentScope)); return s.vars[symbolName]; }
SharpList ReadList() { var list = new SharpList (); _indent++; while (CurrentToken().type != TokenType.RIGHT_PAREN) { object child = Read (); list.Add (child); //Console.WriteLine (GetIndentSpaces() + "Added " + child.ToString() + " to list"); } Step (); // skip the right parenthesis _indent--; return list; }
private object Let(SharpList pList, Scope pCurrentScope) { SharpVector bindingsVector = pList [1] as SharpVector; if(bindingsVector == null) { Error ("The first argument to let is not a bindings vector", pList); } Scope letScope = new Scope ("Let" + _letScopeCounter++, pCurrentScope); #if LOG_SCOPES Console.WriteLine ("Created new let scope: " + letScope.name); #endif for (int i = 0; i < bindingsVector.Count; i += 2) { SymbolToken symbolToken = bindingsVector [i] as SymbolToken; if(symbolToken == null) { Error("Argument " + (i).ToString() + " in let binding is not a symbol", pList); } letScope.SetVar (symbolToken.value, Eval (bindingsVector[i + 1], pCurrentScope)); } SharpList copy = new SharpList (); for (int i = 2; i < pList.Count; i++) { copy.Add(pList[i]); } object lastResult = null; foreach(var item in copy) { //Console.WriteLine("Time to eval " + item); lastResult = Eval (item, letScope); } return lastResult; }
private object Quote(SharpList pList, Scope pCurrentScope) { return pList [1]; }
object GetEvaled(SharpList pList, int pPosition, Scope pCurrentScope) { return Eval(pList [pPosition], pCurrentScope); }
private object If(SharpList pList, Scope pCurrentScope) { object condition = GetEvaled (pList, 1, pCurrentScope); bool isTrue = (condition != null); if (condition is bool) { isTrue = (bool)condition; } object result = null; if (isTrue) { result = GetEvaled (pList, 2, pCurrentScope); } else if(pList.Count > 3) { result = GetEvaled (pList, 3, pCurrentScope); } return result; }
private object Fn(SharpList pList, Scope pCurrentScope) { SharpVector argBindings = pList [1] as SharpVector; if(argBindings == null) { Error ("The first argument to fn is not a vector of args", pList); } SharpVector argBindingsDeepCopy = new SharpVector (); foreach(var argBinding in argBindings) { argBindingsDeepCopy.Add (argBinding); } SharpList body = new SharpList (); for (int i = 2; i < pList.Count; i++) { body.Add(pList[i]); } Scope closure = new Scope ("Closure" + _closureCounter++, pCurrentScope); #if LOG_SCOPES Console.WriteLine ("Created new closure: " + closure.name); #endif string functionName = "Fn" + _functionCounter++; return new SharpFunction(args => { Scope functionCallScope = new Scope ("FunctionCallScope" + _functionCallScopeCounter++, closure); #if LOG_SCOPES Console.WriteLine ("Created new function call scope: " + functionCallScope.name); #endif int argPos = 0; for(int argBindingPos = 0; argBindingPos < argBindingsDeepCopy.Count; argBindingPos++) { var argBinding = argBindingsDeepCopy[argBindingPos]; if(argBinding is ReservedToken && (argBinding as ReservedToken).type == TokenType.AMPERSAND) { argBindingPos++; SymbolToken finalSymbol = argBindingsDeepCopy[argBindingPos] as SymbolToken; if(finalSymbol == null) { Error ("Final arg binding after ampersand is not a symbol: " + argBindingsDeepCopy[argBindingPos], pList); } var restOfArgs = new SharpList (); while (argPos < args.Length) { restOfArgs.Add(args[argPos++]); } functionCallScope.SetVar(finalSymbol.value, restOfArgs); break; } SymbolToken symbol = argBinding as SymbolToken; if(symbol == null) { Error("Arg binding is not a symbol: " + symbol, pList); } functionCallScope.SetVar(symbol.value, args[argPos++]); } // Console.WriteLine(functionName + " was called with " + args.Length + " arguments:"); // foreach(var arg in args) { // if(arg == null) { // Console.WriteLine("null"); // } else { // Console.WriteLine(arg.ToString()); // } // } object lastResult = null; foreach(var item in body) { //Console.WriteLine("Time to eval " + item); lastResult = Eval (item, functionCallScope); } return lastResult; }, functionName); }
private object FunctionCall(SharpList pList, Scope pCurrentScope) { List<object> evaledArgs = new List<object> (); for (int i = 1; i < pList.Count; i++) { if(pList[i] != null) { evaledArgs.Add(GetEvaled (pList, i, pCurrentScope)); } else { evaledArgs.Add (null); } } SharpFunction f = GetEvaled(pList, 0, pCurrentScope) as SharpFunction; object result = f.function (evaledArgs.ToArray()); //Console.WriteLine ("(" + f + (evaledArgs.Count > 0 ? " " : "") + string.Join(" ", evaledArgs) + ") -> " + result); return result; }
private object EvalList(SharpList pList, Scope pCurrentScope) { if (pList.Count == 0) { return pList; } if (pList[0] is SymbolToken) { //Console.WriteLine ("Found symbol token " + pList[0]); if (_macroDefinitions.ContainsKey (((SymbolToken)pList[0]).value)) { SymbolToken macroName = pList [0] as SymbolToken; object result = CallMacro (_macroDefinitions[macroName.value], pList, pCurrentScope); return result; } } object firstItem = GetEvaled (pList, 0, pCurrentScope); if (firstItem is ReservedToken) { ReservedToken token = firstItem as ReservedToken; if (token.type == TokenType.DEF) { return Def (pList, pCurrentScope); } if (token.type == TokenType.FN) { return Fn (pList, pCurrentScope); } if (token.type == TokenType.LET) { return Let (pList, pCurrentScope); } if (token.type == TokenType.IF) { return If (pList, pCurrentScope); } if (token.type == TokenType.DEFMACRO) { return DefMacro (pList, pCurrentScope); } if (token.type == TokenType.QUOTE) { return Quote (pList, pCurrentScope); } if (token.type == TokenType.SET) { return Set (pList, pCurrentScope); } throw new Exception("Can't understand ReservedToken: " + token); } if (firstItem is SharpFunction) { return FunctionCall (pList, pCurrentScope); } Error ("Can't eval function with first item '" + firstItem, pList); return null; }
private void Error(string pDescription, SharpList pList) { throw new Exception (pDescription + " (line " + pList.line + " and position " + pList.position + ")"); }
private object DefMacro(SharpList pList, Scope pCurrentScope) { SymbolToken macroNameSymbol = pList [1] as SymbolToken; if (macroNameSymbol == null) { Error("The first argument to defmacro is not a string", pList); } _macroDefinitions[macroNameSymbol.value] = pList; return pList; }
private object Def(SharpList pList, Scope pCurrentScope) { SymbolToken symbolToken = pList [1] as SymbolToken; if(symbolToken == null) { Error ("The first argument to def is not a symbol", pList); } globalScope.SetVar(symbolToken.value, GetEvaled(pList, 2, pCurrentScope)); return symbolToken; }
private object CallMacro(SharpList pMacroForm, SharpList pInvokingList, Scope pCurrentScope) { SymbolToken macroNameSymbol = pMacroForm [1] as SymbolToken; if (macroNameSymbol == null) { Error("The first argument to macro is not a string", pInvokingList); } //Console.WriteLine ("Calling macro " + macroNameSymbol.value); var argBindings = pMacroForm [2] as SharpVector; if (argBindings == null) { Error("The second argument to macro is not a vector of args", pInvokingList); } List<object> args = new List<object> (); for (int i = 1; i < pInvokingList.Count; i++) { args.Add (pInvokingList[i]); } int argPos = 0; Scope macroScope = new Scope ("Macro scope " + _macroScopeCounter++, pCurrentScope); for(int argBindingPos = 0; argBindingPos < argBindings.Count; argBindingPos++) { var argBinding = argBindings [argBindingPos]; if(argBinding is ReservedToken && (argBinding as ReservedToken).type == TokenType.AMPERSAND) { argBindingPos++; SymbolToken finalSymbol = argBindings[argBindingPos] as SymbolToken; if(finalSymbol == null) { Error("Final arg binding after ampersand is not a symbol: " + argBindings[argBindingPos], pInvokingList); } var restOfArgs = new SharpList (); while (argPos < args.Count) { restOfArgs.Add(args[argPos++]); } macroScope.SetVar(finalSymbol.value, restOfArgs); break; } SymbolToken symbol = argBinding as SymbolToken; if (symbol == null) { Error ("One of the bindings to the macro is not a symbol", pInvokingList); } macroScope.SetVar(symbol.value, args[argPos]); #if MACRODEBUG Console.WriteLine ("Setting " + symbol.value + " to " + args[argPos] + " at arg pos " + argPos); #endif argPos++; } List<object> compiledForms = new List<object> (); for(int i = 3; i < pMacroForm.Count; i++) { object compiledBody = CompileMacro(pMacroForm [i], macroScope); compiledForms.Add (compiledBody); } #if MACRODEBUG Console.WriteLine("Compiled macro " + macroNameSymbol.value + " to the following forms: "); foreach(var form in compiledForms) { if(form != null) { Console.WriteLine(form.ToString ()); } else { Console.WriteLine("null"); } } #endif object lastResult = null; foreach(var form in compiledForms) { //Console.WriteLine ("Eval form " + form.ToString()); lastResult = Eval (form, pCurrentScope); } return lastResult; }