private static Scope CopyScope(Scope scope) { var r = new Scope(); foreach (var v in scope.variables) r.variables.Add(v.Key, new ScriptList(v.Value[v.Value.Count - 1])); return r; }
public void SerializeEnvironment(System.IO.TextWriter to, Scope scope) { var globalFunctions = new List<ScriptObject>(); var objects = new List<ObjectRecord>(); var lambdas = new List<ObjectRecord>(); //Build list of global non-system functions foreach (var func in functions) { if (Function.IsSystemFunction(func.Value)) continue; globalFunctions.Add(func.Value); } //Filter objects into objects and lambda list foreach (var func in globalFunctions) EnumerateObject(func["@declaration-scope"] as ScriptObject, globalFunctions, objects, lambdas); EnumerateObject(scope, globalFunctions, objects, lambdas); //Filter out objects with just a single reference objects = new List<ObjectRecord>(objects.Where((o) => { return o.referenceCount > 1; })); AddRef(scope, objects); to.WriteLine("(lastarg"); //Emit global functions foreach (var func in globalFunctions) EmitFunction(func, "defun", to, false, 0); //Create and emit lambda functions. to.WriteLine("(let ^(\n ^(\"lambdas\" ^("); foreach (var func in lambdas) { to.Write(" "); EmitFunction(func.obj, "lambda", to, false, 0); } to.WriteLine(")\n )\n ^(\"objects\" (array " + objects.Count + " (record)))\n)\n(lastarg\n"); //Set function declaration scopes. foreach (var func in globalFunctions) { to.WriteLine("(set " + func.gsp("@name") + " \"@declaration-scope\" "); EmitObjectProperty(to, func["@declaration-scope"], globalFunctions, objects, lambdas, 1); to.WriteLine(")\n"); } for (int i = 0; i < lambdas.Count; ++i) { var func = lambdas[i]; to.WriteLine("(set (index lambdas " + i + ") \"@declaration-scope\" "); EmitObjectProperty(to, func.obj["@declaration-scope"], globalFunctions, objects, lambdas, 1); to.WriteLine(")\n"); } //Emit remaining objects foreach (var obj in objects) EmitObjectRoot(to, obj.obj, globalFunctions, objects, lambdas); //Emit footer var thisIndex = IndexIn(scope, objects); to.Write("(index objects " + thisIndex + "))))"); }
public void PushScope(Scope scope) { scope.parentScope = Scope; scopeStack.Add(scope); }
public void ReplaceScope(Scope scope) { scopeStack.Clear(); PushScope(scope); }
private void SetupEnvironmentFunctions(Engine mispEngine) { mispEngine.AddFunction("save-environment", "", (context, arguments) => { Engine.ReportSerializationError = (str) => Write(str + "\n"); var file = new System.IO.StreamWriter(arguments[0].ToString()); mispEngine.SerializeEnvironment(file, context.Scope); file.Close(); return true; }, Arguments.Arg("file")); mispEngine.AddFunction("load-environment", "", (context, arguments) => { var newContext = new Context(); var newEngine = new Engine(); PrepareEnvironment(newEngine); if (arguments[2] != null) { newEngine.Evaluate(newContext, arguments[2], true, true); if (newContext.evaluationState == EvaluationState.UnwindingError) { Write("Prime error:\n"); Write(MISP.Console.PrettyPrint2(newContext.errorObject, 0)); return false; } } var result = newEngine.EvaluateString(newContext, System.IO.File.ReadAllText(arguments[0].ToString()), arguments[0].ToString()) as ScriptObject; if (newContext.evaluationState != EvaluationState.UnwindingError) { var environment = AddEnvironment(arguments[1].ToString(), newEngine, newContext); if (environment.name == this.environment.name) this.environment = environment; SetupEnvironmentFunctions(newEngine); var scope = new Scope(); foreach (var prop in result.ListProperties()) scope.PushVariable(prop as String, result.GetLocalProperty(prop as String)); newContext.ReplaceScope(scope); Write("Loaded.\n"); return true; } else { Write("Error:\n"); Write(MISP.Console.PrettyPrint2(newContext.errorObject, 0)); return false; } }, Arguments.Arg("file"), Arguments.Arg("name"), Arguments.Optional(Arguments.Lazy("prime"))); }
public static Object Invoke(ScriptObject func, Engine engine, Context context, ScriptList arguments) { var name = func.gsp("@name"); var argumentInfo = func["@arguments"] as ScriptList; if (context.trace != null) { context.trace(new String('.', context.traceDepth) + "Entering " + name +"\n"); context.traceDepth += 1; } var newArguments = new ScriptList(); //Check argument types if (argumentInfo.Count == 0 && arguments.Count != 0) { context.RaiseNewError("Function expects no arguments.", context.currentNode); return null; } int argumentIndex = 0; for (int i = 0; i < argumentInfo.Count; ++i) { var info = argumentInfo[i] as ScriptObject; if (info == null) throw new ScriptError("Invalid argument descriptor on function object", context.currentNode); if (info["@repeat"] != null) { var list = new ScriptList(); while (argumentIndex < arguments.Count) //Handy side effect: If no argument is passed for an optional repeat { //argument, it will get an empty list. list.Add(MutateArgument(arguments[argumentIndex], info, engine, context)); //list.Add((info["@type"] as Type).ProcessArgument(context, arguments[argumentIndex])); if (context.evaluationState != EvaluationState.Normal) return null; ++argumentIndex; } newArguments.Add(list); } else { if (argumentIndex < arguments.Count) { newArguments.Add(MutateArgument(arguments[argumentIndex], info, engine, context)); //newArguments.Add((info["@type"] as Type).ProcessArgument(context, arguments[argumentIndex])); if (context.evaluationState == EvaluationState.UnwindingError) return null; } else if (info["@optional"] != null) newArguments.Add(MutateArgument(null, info, engine, context)); else { context.RaiseNewError("Not enough arguments to " + name, context.currentNode); return null; } ++argumentIndex; } } if (argumentIndex < arguments.Count) { context.RaiseNewError("Too many arguments to " + name, context.currentNode); return null; } Object r = null; if (func["@function-body"] is ScriptObject) { var declarationScope = func["@declaration-scope"]; if (declarationScope is GenericScriptObject) { var newScope = new Scope(); foreach (var valueName in (declarationScope as GenericScriptObject).properties) newScope.PushVariable(valueName.Key, valueName.Value); func["@declaration-scope"] = newScope; } context.PushScope(func["@declaration-scope"] as Scope); for (int i = 0; i < argumentInfo.Count; ++i) context.Scope.PushVariable((argumentInfo[i] as ScriptObject).gsp("@name"), newArguments[i]); r = engine.Evaluate(context, func["@function-body"], true); for (int i = 0; i < argumentInfo.Count; ++i) context.Scope.PopVariable((argumentInfo[i] as ScriptObject).gsp("@name")); context.PopScope(); } else { try { r = (func["@function-body"] as Func<Context, ScriptList, Object>)(context, newArguments); } catch (Exception e) { context.RaiseNewError("System Exception: " + e.Message, context.currentNode); return null; } } if (context.trace != null) { context.traceDepth -= 1; context.trace(new String('.', context.traceDepth) + "Leaving " + name + (context.evaluationState == EvaluationState.UnwindingError ? (" -Error: " + context.errorObject.GetLocalProperty("message").ToString()) : "") + (context.evaluationState == EvaluationState.UnwindingBreak ? " -Breaking" : "") + "\n"); } return r; }
public static ScriptObject MakeFunction( String name, ScriptList arguments, String help, ScriptObject body, ScriptObject declarationScope, bool copyScope = false) { if (copyScope) { var newScope = new Scope(); foreach (var prop in declarationScope.ListProperties()) newScope.PushVariable(prop as String, declarationScope.GetLocalProperty(prop as String)); declarationScope = newScope; } return new GenericScriptObject( "@name", name, "@arguments", arguments, "@help", help, "@function-body", body, "@declaration-scope", declarationScope); }