static public dynamic vertexdata(LispList args, LispEnvironment env) { using (var stream = new MemoryStream()) { int elementCount = 0; foreach (LispElement arg in args) { dynamic vertices = arg.Eval(env); if (vertices is LispList) { foreach (var vertex in vertices) { writeVertexToStream(vertex, stream); elementCount++; } } else { writeVertexToStream(vertices, stream); elementCount++; } } var dataStream = new SlimDX.DataStream(stream.Length, false, true); stream.WriteTo(dataStream); dataStream.Position = 0; return(dataStream); } }
private static IEnumerable <object> ReplaceSymbolWithValueInExpression(LispVariant symbol, object symbolValue, IEnumerable <object> expression, bool macroArgsReplace, ref bool replacedAnything) { var ret = new List <object>(); foreach (var elem in expression) { // is the current element the symbol which should be replaced? --> Yes if (symbol.SymbolCompare(elem)) { IEnumerable <object> l = symbolValue as IEnumerable <object>; if (l != null && macroArgsReplace) { ret.AddRange(l); } else { ret.Add(symbolValue); } replacedAnything = true; } // is it an expression? --> recursive call else if (LispEnvironment.IsExpression(elem)) { IEnumerable <object> temp = ReplaceSymbolWithValueInExpression(symbol, symbolValue, LispEnvironment.GetExpression(elem) /*.ToArray()*/, macroArgsReplace, ref replacedAnything); ret.Add(temp); } // current element is not the symbol which should by replaced ! else { ret.Add(elem); } } return(ret); }
static public dynamic indexdata(LispList args, LispEnvironment env) { using (var stream = new MemoryStream()) { foreach (LispElement arg in args) { dynamic indexes = arg.Eval(env); if (indexes is LispList) { foreach (var curIndexes in indexes) { stream.Write(curIndexes, 0, curIndexes.Length); } } else { stream.Write(indexes, 0, indexes.Length); } } var dataStream = new SlimDX.DataStream(stream.Length, false, true); stream.WriteTo(dataStream); dataStream.Position = 0; return(dataStream); } }
/// <summary> /// Evals the specified lisp code. /// An exception may occure if the lisp code is invalid. /// </summary> /// <param name="lispCode">The lisp code.</param> /// <param name="scope">The scope.</param> /// <param name="moduleName">The module name and path.</param> /// <param name="tracing">if set to <c>true</c> [tracing].</param> /// <param name="onlyMacroExpand">if set to <c>true</c> [macro expanding].</param> /// <param name="nativeItems">The dictionary with native items.</param> /// <returns>The result of the script evaluation</returns> public static LispVariant Eval(string lispCode, LispScope scope = null, string moduleName = null, bool tracing = false, bool onlyMacroExpand = false, Dictionary <string, object> nativeItems = null) { // first create global scope, needed for macro expanding var currentScope = scope ?? LispEnvironment.CreateDefaultScope(); currentScope.ModuleName = moduleName; currentScope.Tracing = tracing; RegisterNativeObjects(nativeItems, currentScope); int offset; string code = LispUtils.DecorateWithBlock(lispCode, out offset); var ast = LispParser.Parse(code, offset, currentScope); #if ENABLE_COMPILE_TIME_MACROS var expandedAst = LispInterpreter.ExpandMacros(ast, currentScope); #else var expandedAst = ast; #endif LispVariant result = null; if (onlyMacroExpand) { result = new LispVariant(expandedAst); } else { result = LispInterpreter.EvalAst(expandedAst, currentScope); } return(result); }
static public dynamic material(LispList args, LispEnvironment env) { IEnumerator <dynamic> arg = args.GetEnumerator(); arg.MoveNext(); var technique = arg.Current.Eval(env); arg.MoveNext(); var effect = arg.Current.Eval(env); arg.MoveNext(); List <KeyValuePair <string, ResourceHandle> > textures = arg.Current.Eval(env); arg.MoveNext(); var constants = arg.Current.Eval(env); var mat = new MaterialResource(effect, technique); foreach (var texture in textures) { mat.AddTexture(texture.Key, texture.Value); } foreach (var constant in constants) { mat.AddConstant(constant.Key, constant.Value); } return(mat); //var material = new MaterialResource(); throw new NotImplementedException(); }
static public dynamic texture(LispList args, LispEnvironment env) { ResourceManager manager = ((LispObject)env.Lookup(new LispSymbol("manager"))).Value; return(new KeyValuePair <string, ResourceHandle>( args.Elems[0].Eval(env).Value, manager.GetResource(args.Elems[1].Eval(env).Value, "texture"))); }
static public dynamic element(LispList args, LispEnvironment env) { LispSymbol name = args[0].Eval(env); LispString format = args[1].Eval(env); env.Add(name, VertexFormats.getParserFor(format.Value)); return(new InputElement(name.Value, 0, VertexFormats.getDXFormatOf(format.Value), 0, 0)); }
static public dynamic seq(LispList args, LispEnvironment env) { dynamic result = null; foreach (dynamic arg in args) { result = arg.Eval(env); } return(result); }
static public dynamic div(LispList args, LispEnvironment env) { var accum = args.First.Eval(env); foreach (var elem in args.Elems.Skip(1)) { accum /= elem.Eval(env); } return(accum); }
static public dynamic vertex(LispList args, LispEnvironment env) { LinkedList <byte[]> bytes = new LinkedList <byte[]>(); foreach (LispElement arg in args) { bytes.AddLast(arg.Eval(env)); } return(bytes); }
public dynamic Eval(LispEnvironment env, dynamic e = null) { if (e == null) { return(this); } else { return(e.First); } }
static public dynamic mesh(LispList args, LispEnvironment env) { IEnumerator <dynamic> arg = args.GetEnumerator(); arg.MoveNext(); var topology = arg.Current.Eval(env); arg.MoveNext(); var layout = arg.Current.Eval(env); var resource = new MeshResource(); resource.elementSize = layout.elementSize; resource.inputLayout = layout.elements; resource.primitiveTopology = topology; env.Add(new LispSymbol("vertexSize"), new LispInteger(resource.elementSize)); arg.MoveNext(); resource.vertexstream = arg.Current.Eval(env); resource.elementCount = (int)resource.vertexstream.Length / resource.elementSize; if (arg.MoveNext()) { resource.indexed = true; if (resource.elementCount <= ushort.MaxValue) { env.Add(new LispSymbol("indexes"), VertexFormats.R16UIntIndexes); resource.indexFormat = SlimDX.DXGI.Format.R16_UInt; } else { env.Add(new LispSymbol("indexes"), VertexFormats.R32UIntIndexes); resource.indexFormat = SlimDX.DXGI.Format.R32_UInt; } resource.indexstream = arg.Current.Eval(env); if (resource.indexFormat == SlimDX.DXGI.Format.R16_UInt) { resource.indexCount = (int)resource.indexstream.Length / 2; } else { resource.indexCount = (int)resource.indexstream.Length / 4; } } else { resource.indexed = false; resource.indexFormat = SlimDX.DXGI.Format.Unknown; } return(resource); }
public static dynamic R16UIntIndexes(LispList args, LispEnvironment env) { using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { foreach (LispElement arg in args) { writer.Write((ushort)arg.Eval(env).Value); } return(stream.ToArray()); } }
static public dynamic scalar(LispList args, LispEnvironment env) { IEnumerator <dynamic> arg = args.GetEnumerator(); arg.MoveNext(); string name = arg.Current.Eval(env).Value; arg.MoveNext(); float x = arg.Current; return(new KeyValuePair <string, float>(name, x)); }
private static byte[] parse16UInt(LispList args, LispEnvironment env, int count) { byte[] result = new byte[count * sizeof(ushort)]; using (var stream = new MemoryStream(result)) using (var writer = new BinaryWriter(stream)) { foreach (LispElement arg in args) { writer.Write((ushort)arg.Eval(env).Value); } } return(result); }
/// <summary> /// See interface. /// </summary> public LispVariant DebuggerLoop(string script, string moduleName, bool tracing = false) { LispVariant result = null; var bRestart = true; while (bRestart) { // save the source code if the script is transfered via command line if (moduleName == LispUtils.CommandLineModule) { CommandLineScript = script; } var globalScope = LispEnvironment.CreateDefaultScope(); globalScope.Input = Input; globalScope.Output = Output; globalScope.Debugger = this; try { result = Lisp.Eval(script, globalScope, moduleName, tracing: tracing); Reset(); } catch (LispStopDebuggerException) { bRestart = false; } catch (Exception exception) { Output.WriteLine("\nException: {0}", exception); string stackInfo = exception.Data.Contains(LispUtils.StackInfo) ? (string)exception.Data[LispUtils.StackInfo] : string.Empty; Output.WriteLine("\nStack:\n{0}", stackInfo); bRestart = InteractiveLoop(this, globalScope, startedFromMain: true); } if (bRestart) { Output.WriteLine("restart program"); // process empty script --> just start interactive loop if (result == null) { bRestart = InteractiveLoop(this, globalScope, startedFromMain: true); } } globalScope.Debugger = null; } return(result); }
static void Main(string[] args) { var examplList = new[] { "(add 1 2)", "(add 1 (add 2 3))", "(define a 2) (add 2 a)", "(define a 2) (define b 3) (add a b)", "(define a 2) (define b 3) (define c (add 3 3)) (add c b)", @"(define inc (lambda (n) (add n 1))) (inc 1)", @"(if (> 1 2) (+ 4 5) (+ 10 8))", @"(quote some-test-string)", @"(quote (1 2 3 4 5 6))", "(define inc (lambda (n) (add n 1)))", "(lambda (n) (add n 1))" }; foreach (var e in examplList) { Console.WriteLine(" {0}", e); } Console.WriteLine(); Console.WriteLine(); //var lexer = new LispLexer(); var lexer = new LispLexerOld(); var parser = new LispParser(); var evaluator = new LispEvaluator(); var env = new LispEnvironment(); int i = 1; while (true) { Console.Write("{0}> ", i++); string input = string.Empty; var line = Console.ReadLine(); input += line + Environment.NewLine; var tokens = lexer.GetTokenList(input); var program = parser.Parse(tokens); foreach (var statment in program) { var res = evaluator.Eval(env, statment); Console.WriteLine("==> "+res); } Console.WriteLine(); } }
static public dynamic vector2(LispList args, LispEnvironment env) { IEnumerator <dynamic> arg = args.GetEnumerator(); arg.MoveNext(); string name = arg.Current.Eval(env).Value; arg.MoveNext(); float x = arg.Current.Value; arg.MoveNext(); float y = arg.Current.Value; return(new KeyValuePair <string, Vector2>(name, new Vector2(x, y))); }
/// <summary> /// Resolves the given element in this scope. /// </summary> /// <param name="elem">The element.</param> /// <param name="isFirst">Is the element the first one in the list.</param> /// <returns>Resolved value or null</returns> public object ResolveInScopes(object elem, bool isFirst) { object result; // try to access the cached function value (speed optimization) LispVariant elemAsVariant = elem as LispVariant; if (elemAsVariant != null && elemAsVariant.CachedFunction != null) { return(elemAsVariant.CachedFunction); } var name = elem.ToString(); LispScope foundClosureScope; // first try to resolve in this scope if (TryGetValue(name, out result)) { UpdateFunctionCache(elemAsVariant, result, isFirst); } // then try to resolve in global scope else if (GlobalScope != null && GlobalScope.TryGetValue(name, out result)) { UpdateFunctionCache(elemAsVariant, result, isFirst); } // then try to resolve in closure chain scope(s) else if (IsInClosureChain(name, out foundClosureScope, out result)) { UpdateFunctionCache(elemAsVariant, result, isFirst); } // then try to resolve in scope of loaded modules else if (LispEnvironment.IsInModules(name, GlobalScope)) { result = LispEnvironment.GetFunctionInModules(name, GlobalScope); } else { // activate this code if symbols must be resolved in parameter evaluation --> (println blub) //if (elemAsVariant != null && elemAsVariant.IsSymbol && name != "fuellib") //{ // throw new LispException($"Could not resolve symbol {name}"); //} result = elem; } return(result); }
/// <summary> /// Compiles the specified lisp code into C# code. /// </summary> /// <param name="code">The lisp code.</param> /// <returns>The C# code packed into a LispVariant</returns> public /*static*/ LispVariant CompileToCsCode(string code) { var globalScope = LispEnvironment.CreateDefaultScope(); int offset; code = LispUtils.DecorateWithBlock(code, out offset); var ast = LispParser.Parse(code, offset, globalScope); //var expandedAst = ExpandMacros(ast, globalScope); var compileResult = Compile(ast, globalScope, " ", "__return__", "scope"); var csCode = "namespace CsLisp\n{\nusing System;\nclass CompiledLisp\n{\n // functions:\n" + ShiftLines(compileResult.Item2, " ") + "\n public static LispVariant LispMain(string[] args)\n {\n var scope = new LispScope();\n LispVariant __return__;\n\n" + ShiftLines(compileResult.Item1, " ") + " return __return__;\n }\n\n public static void Main(string[] args)\n {\n var startTickCount = Environment.TickCount;\n LispMain(args);\n Console.WriteLine(string.Format(\"Execution time = {0} s\", (Environment.TickCount - startTickCount)*0.001));\n }\n}\n}"; return(new LispVariant(csCode)); }
static public dynamic constants(LispList args, LispEnvironment env) { var constList = new List <dynamic>(args.Elems.Length); foreach (LispElement arg in args) { var constants = arg.Eval(env); if (constants is LispList) { constList.AddRange(constants); } else { constList.Add(constants); } } return(constList); }
static public dynamic textures(LispList args, LispEnvironment env) { var texList = new List <KeyValuePair <string, ResourceHandle> >(args.Elems.Length); foreach (LispElement arg in args) { var textures = arg.Eval(env); if (textures is LispList) { texList.AddRange(textures); } else { texList.Add(textures); } } return(texList); }
static public dynamic vertexlayout(LispList args, LispEnvironment env) { int accum = 0; InputElement[] elements = new InputElement[args.Elems.Length]; int i = 0; foreach (LispElement arg in args) { InputElement current = arg.Eval(env); current.AlignedByteOffset = accum; accum += VertexFormats.getByteCountOf(current.Format); elements[i] = current; i++; } return(new { elements, elementSize = accum }); }
public abstract LispObject Apply(Cons arguments, LispEnvironment env);
/// <summary> /// Evaluates the given ast. /// </summary> /// <param name="ast">The ast.</param> /// <param name="scope">The scope.</param> /// <returns>The result of ast evaluation.</returns> /// <exception cref="System.Exception">Unexpected macro modus!</exception> public static LispVariant EvalAst(object ast, LispScope scope) { if (ast == null) { return(null); } IList <object> astAsList; if (ast is LispVariant) { var item = (LispVariant)ast; // evaluate the value for the symbol if (item.IsSymbol) { item = new LispVariant(scope.ResolveInScopes(item, false)); return(item); } else if (item.IsList && !item.IsNil) { astAsList = item.ListValue.ToList(); } else { return(item); } } else { astAsList = ((IEnumerable <object>)ast).ToList(); } if (astAsList.Count == 0) { return(new LispVariant(LispType.Nil)); } // is this function a macro ==> process the macro and return if (LispEnvironment.IsMacro(astAsList.First(), scope.GlobalScope)) { // check the macro modus: evaluate or expand or lambda var macro = LispEnvironment.GetMacro(astAsList.First(), scope.GlobalScope); // evaluate macro at run time: if (macro is LispMacroRuntimeEvaluate) { // Example for macro at runtime handling: // // macro definition: // (define-macro-eval my-setf (x value) (setf x value)) // // call (ast): // (my-setf a (+ \"blub\" \"xyz\")) // | | // v v // x value // // Result: // (setf a (+ \"blub\" \"xyz\")) <-- replace formal arguments (as symbol) bool anyMacroReplaced = false; var runtimeMacro = (LispMacroRuntimeEvaluate)macro; var expression = ReplaceFormalArgumentsInExpression(runtimeMacro.FormalArguments, astAsList, runtimeMacro.Expression, scope, ref anyMacroReplaced); return(EvalAst(expression, scope)); } // expand macro at compile time: --> nothing to do at run time ! // code not needed, because code for compile time macros will be removed in ExpandMacro phase //if (macro is LispMacroCompileTimeExpand) //{ // return new LispVariant(); //} throw new Exception("Unexpected macro modus!"); } // for debugging: update the current line number at the current scope var currentToken = ((LispVariant)(astAsList.First())).Token; scope.CurrentToken = currentToken != null ? currentToken : scope.CurrentToken; // resolve values via local and global scope var astWithResolvedValues = ResolveArgsInScopes(scope, astAsList, false); // get first element --> this is the function ! var function = astWithResolvedValues.First(); // normal evaluation... LispFunctionWrapper functionWrapper = ((LispVariant)function).FunctionValue; // trace current function (if tracing is enabled) if (scope.GlobalScope.Tracing) { scope.GlobalScope.Output.WriteLine("--> {0}", astAsList.First()); } // evaluate arguments, but allow recursive lists var arguments = new object[astWithResolvedValues.Count - 1]; for (var i = 1; i < arguments.Length + 1; i++) { //var asContainer = LispUtils.GetAsContainer(astWithResolvedValues[i]); //var needEvaluation = (asContainer != null) && !functionWrapper.IsSpecialForm; //arguments[i - 1] = needEvaluation ? EvalAst(asContainer, scope) : astWithResolvedValues[i]; var needEvaluation = (astWithResolvedValues[i] is IEnumerable <object>) && !functionWrapper.IsSpecialForm; var result = needEvaluation ? EvalAst(astWithResolvedValues[i], scope) : astWithResolvedValues[i]; // process statemens like this: `,@l with l = (1 2 3) LispVariant variant = result as LispVariant; if (variant != null) { if (variant.IsUnQuoted == LispUnQuoteModus.UnQuoteSplicing && variant.IsList) { var lst = variant.ListRef; var newArguments = new object[arguments.Length + lst.Count - 1]; arguments.CopyTo(newArguments, 0); foreach (var elem in lst) { newArguments[i - 1] = elem; i++; } arguments = newArguments; break; } } arguments[i - 1] = result; } // debugger processing var debugger = scope.GlobalScope.Debugger; if (debugger != null && debugger.NeedsBreak(scope, GetPosInfo(astAsList[0]))) { debugger.InteractiveLoop(scope, astAsList); } // call the function with the arguments return(functionWrapper.Function(arguments, scope)); }
private static object ExpandMacros(object ast, LispScope globalScope, ref bool anyMacroReplaced) { if (ast == null || ast is LispVariant) { return(ast); } var astAsList = ((IEnumerable <object>)ast).ToList(); if (astAsList.Count == 0) { return(ast); } // compile time macro: process define-macro statements ==> call special form, this will add macro to global scope as side effect var function = astAsList.First(); var functionName = function.ToString(); if (globalScope != null && globalScope.ContainsKey(functionName)) { var fcn = ((LispVariant)globalScope[functionName]).FunctionValue; if (fcn.IsEvalInExpand) { var args = new List <object>(astAsList); args.RemoveAt(0); // process compile time macro definition // --> side effect: add macro definition to internal macro scope fcn.Function(args.ToArray(), globalScope); // compile time macros definitions will be removed from code in expand macro phase // because only the side effect above is needed for further macro replacements return(null); } } // compile time macros: process macro expansion in an expression which calls a macro if (LispEnvironment.IsMacro(function, globalScope)) { var macro = LispEnvironment.GetMacro(function, globalScope); if (macro is LispMacroCompileTimeExpand) { anyMacroReplaced = true; var macroExpand = (LispMacroCompileTimeExpand)macro; var astWithReplacedArguments = ReplaceFormalArgumentsInExpression(macroExpand.FormalArguments, astAsList, macroExpand.Expression, globalScope, ref anyMacroReplaced).ToList(); // PATCH // process recursive macro expands (do not wrap list as LispVariant at this point) return(ConvertLispVariantListToListIfNeeded(EvalAst(astWithReplacedArguments, globalScope))); } } var expandedAst = new List <object>(); // Expand recursively and handle enumarations (make them flat !) foreach (var elem in astAsList) { var expandResult = ExpandMacros(elem, globalScope); // ignore code which is removed in macro expand phase if (expandResult != null) { // process recursive macro expands (do not wrap list as LispVariant at this point) expandedAst.Add(ConvertLispVariantListToListIfNeeded(expandResult)); } } return(expandedAst); }
public static dynamic R32G32Float(LispList args, LispEnvironment env) { return(parse32Float(args, env, 2)); }
static public dynamic effect(LispList args, LispEnvironment env) { ResourceManager manager = ((LispObject)env.Lookup(new LispSymbol("manager"))).Value; return(manager.GetResource(args.First.Eval(env).Value, "effect")); }
static public dynamic technique(LispList args, LispEnvironment env) { return(args.First.Eval(env).Value); }
static public dynamic framelayout(LispList args, LispEnvironment env) { return(null);//throw new NotImplementedException(); }
static public dynamic instancedata(LispList args, LispEnvironment env) { return(null);//throw new NotImplementedException(); }
static public dynamic shaderbinding(LispList args, LispEnvironment env) { return(null);//throw new NotImplementedException(); }