internal static bool CheckPrefix(ScriptObject node) { if (allowed == null) { var allTypes = new string[] { "node", "stringexpression", "memberaccess", "string", "number", "token" }; allowed = new Dictionary<string, List<string>>(); foreach (var type in allTypes) allowed.Add(type, new List<string>()); allowed["node"].Add("$"); allowed["node"].Add("^"); allowed["node"].Add("*"); allowed["node"].Add("#"); allowed["node"].Add(":"); allowed["token"].Add("$"); allowed["token"].Add("#"); allowed["token"].Add(":"); allowed["string"].Add("*"); allowed["string"].Add(":"); allowed["stringexpression"].Add("*"); allowed["stringexpression"].Add(":"); } if (String.IsNullOrEmpty(node.gsp("@prefix"))) return true; if (allowed.ContainsKey(node.gsp("@type"))) return allowed[node.gsp("@type")].Contains(node.gsp("@prefix")); return false; }
public static void SerializeCode(System.IO.TextWriter to, ScriptObject root, int indent = -1) { if (root.gsp("@type") == "string") to.Write(root.gsp("@prefix") + "\"" + root.gsp("@token") + "\""); else if (root.gsp("@type") == "stringexpression") { to.Write(root.gsp("@prefix")); to.Write("\""); foreach (var item in root._children) { if ((item as ScriptObject).gsp("@type") == "string") to.Write((item as ScriptObject).gsp("@token")); else SerializeCode(to, item as ScriptObject); } to.Write("\""); } else if (root.gsp("@type") == "node") { to.Write(root.gsp("@prefix") + "("); foreach (var item in root._children) { //if (indent >= 0) //{ // to.Write("\n" + new String(' ', indent * 3)); // SerializeCode(to, item as ScriptObject, indent + 1); //} //else SerializeCode(to, item as ScriptObject); to.Write(" "); } to.Write(")"); } else if (root.gsp("@type") == "memberaccess") { SerializeCode(to, root._child(0) as ScriptObject); to.Write(root.gsp("@token")); SerializeCode(to, root._child(1) as ScriptObject); } else if (root.gsp("@type") == "dictionaryentry") { to.Write(root.gsp("@prefix") + "["); foreach (var item in root._children) { SerializeCode(to, item as ScriptObject); to.Write(" "); } to.Write("]"); } else { to.Write(root.gsp("@token")); } }
public void EmitFunction(ScriptObject func, string type, System.IO.TextWriter to, bool recall = false, int indent = -1) { to.Write((recall ? "" : "(") + type + " " + func.gsp("@name") + " ^("); var arguments = func["@arguments"] as ScriptList; foreach (var arg in arguments) { if (indent >= 0) to.Write("\n "); emitArgumentSpec(arg as ScriptObject, to); } if (indent >= 0) to.Write("\n"); to.Write(") "); Engine.SerializeCode(to, func["@function-body"] as ScriptObject, indent); if (!recall) to.Write((indent >= 0 ? "\n" : "") + " \"" + func.gsp("@help") + "\")\n"); }
public static ScriptObject GetArgumentInfo(ScriptObject func, Context context, int index) { var arguments = func["@arguments"] as ScriptList; if (arguments == null) return null; if (index >= arguments.Count) { if (arguments.Count > 0 && (arguments[arguments.Count - 1] as ScriptObject)["@repeat"] != null) return arguments[arguments.Count - 1] as ScriptObject; else { context.RaiseNewError("Argument out of bounds", null); return null; } } else return arguments[index] as ScriptObject; }
public void RaiseNewError(String message, ScriptObject location) { errorObject = new GenericScriptObject("message", message, "location", location, "stack-trace", new ScriptList()); evaluationState = EvaluationState.UnwindingError; }
public GenericScriptObject(ScriptObject cloneFrom) { foreach (var str in cloneFrom.ListProperties()) SetProperty(str as String, cloneFrom.GetProperty(str as String)); }
private void EmitFunctionListItem(ScriptObject item) { Write(item.gsp("@name")); if (item.gsp("@name").Length < 16) Write(new String(' ', 16 - item.gsp("@name").Length)); Write(item.gsp("@help") + "\n"); }
public static ScriptObject Optional(ScriptObject arg) { arg["@optional"] = true; return arg; }
private static void EmitObject( System.IO.TextWriter to, ScriptObject obj, List<ScriptObject> globalFunctions, List<ObjectRecord> objects, List<ObjectRecord> lambdas, int depth, bool ignoreFunctions = false) { to.WriteLine("(record "); EmitObjectProperties(to, obj, globalFunctions, objects, lambdas, depth + 1, ignoreFunctions); to.Write(")"); }
private static bool AddRef(ScriptObject obj, List<ObjectRecord> list) { var spot = list.FirstOrDefault((o) => { return Object.ReferenceEquals(o.obj, obj); }); if (spot != null) { spot.referenceCount++; return false; } else { list.Add(new ObjectRecord { obj = obj, referenceCount = 1 }); return true; } }
public static bool IsFunction(ScriptObject obj) { if (obj == null) return false; return obj["@function-body"] != null; }
public Object Evaluate( Context context, Object what, bool ignoreStar = false, bool discardResults = false) { if (context.evaluationState != EvaluationState.Normal) { throw new ScriptError("Invalid Context", null); } if (context.callDepth >= context.maximumCallDepth) { context.RaiseNewError("Overflow.", null); return(null); } context.callDepth += 1; //All exit points must decrement depth. if (what is String) { var r = EvaluateString(context, what as String, "", discardResults); context.callDepth -= 1; return(r); } else if (!(what is ScriptObject)) { context.callDepth -= 1; return(what); } var node = what as ScriptObject; context.currentNode = node; if (context.limitExecutionTime && (DateTime.Now - context.executionStart > context.allowedExecutionTime)) { context.RaiseNewError("Timeout.", node); context.callDepth -= 1; return(null); } if (node.gsp("@prefix") == "*" && !ignoreStar) //Object is a quoted node { context.callDepth -= 1; return(node); } var type = node.gsp("@type"); if (String.IsNullOrEmpty(type)) { context.callDepth -= 1; return(node); } //Object is not evaluatable code. object result = null; if (type == "string") { result = node["@token"]; } else if (type == "stringexpression") { if (discardResults) //Don't bother assembling the string expression. { foreach (var piece in node._children) { if ((piece as ScriptObject).gsp("@type") == "string") { continue; } else { Evaluate(context, piece); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } } } result = null; } else { if (node._children.Count == 1) //If there's only a single item, the result is that item. { result = Evaluate(context, node._child(0)); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } } else { var resultString = String.Empty; foreach (var piece in node._children) { resultString += ScriptObject.AsString(Evaluate(context, piece)); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } } result = resultString; } } } else if (type == "token") { result = LookupToken(context, node.gsp("@token")); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } } else if (type == "memberaccess") { var lhs = Evaluate(context, node._child(0)); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } String rhs = ""; if ((node._child(1) as ScriptObject).gsp("@type") == "token") { rhs = (node._child(1) as ScriptObject).gsp("@token"); } else { rhs = ScriptObject.AsString(Evaluate(context, node._child(1), false)); } if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } if (lhs == null) { result = null; } else if (lhs is ScriptObject) { result = (lhs as ScriptObject).GetProperty(ScriptObject.AsString(rhs)); if (node.gsp("@token") == ":") { context.Scope.PushVariable("this", lhs); result = Evaluate(context, result, true, false); context.Scope.PopVariable("this"); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } } } else { var field = lhs.GetType().GetField(ScriptObject.AsString(rhs)); if (field != null) { result = field.GetValue(lhs); } else { var prop = lhs.GetType().GetProperty(ScriptObject.AsString(rhs)); if (prop != null) { result = prop.GetValue(lhs, null); } else { var members = lhs.GetType().FindMembers(System.Reflection.MemberTypes.Method, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, new System.Reflection.MemberFilter((minfo, obj) => { return(minfo.Name == obj.ToString()); }), ScriptObject.AsString(rhs)); if (members.Length != 0) { result = new GenericScriptObject( "@lazy-reflection", ScriptObject.AsString(rhs), "@source-object", lhs, "@source-type", lhs.GetType()); } else { result = null; } } } } } else if (type == "node") { if (!ignoreStar && node.gsp("@prefix") == "*") { result = node; } else { bool eval = node.gsp("@prefix") != "^"; var arguments = new ScriptList(); foreach (var child in node._children) { evaluateNodeChild(eval, child, arguments, context); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } } if (node.gsp("@prefix") == "^") { result = arguments; } else { if (arguments.Count > 0 && Function.IsFunction(arguments[0] as ScriptObject)) { result = Function.Invoke((arguments[0] as ScriptObject), this, context, new ScriptList(arguments.GetRange(1, arguments.Count - 1))); if (context.evaluationState != EvaluationState.Normal) { if (context.evaluationState == EvaluationState.UnwindingError) { context.PushStackTrace((arguments[0] as ScriptObject).gsp("@name")); } context.callDepth -= 1; return(null); } } else if (arguments.Count > 0 && arguments[0] is ScriptObject && (arguments[0] as ScriptObject).GetProperty("@lazy-reflection") != null) { var sObj = arguments[0] as ScriptObject; var argumentTypes = arguments.GetRange(1, arguments.Count - 1).Select( (obj) => obj.GetType()).ToArray(); var sourceObject = sObj.GetProperty("@source-object"); var method = (sObj.GetProperty("@source-type") as System.Type) .GetMethod(sObj.gsp("@lazy-reflection"), argumentTypes); if (method == null) { throw new ScriptError("Could not find overload for " + sObj.gsp("@lazy-reflection") + " that takes argument types " + String.Join(", ", argumentTypes.Select((t) => t.Name)) + " on type " + sObj.GetProperty("@source-type").ToString(), what as ScriptObject); } result = method.Invoke(sourceObject, arguments.GetRange(1, arguments.Count - 1).ToArray()); } else if (arguments.Count > 0) { result = arguments[0]; } else { result = null; } } } } else if (type == "root") { var results = new ScriptList(); foreach (var child in node._children) { results.Add(Evaluate(context, child, false, false)); if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } } return(results); } else if (type == "number") { try { if (node.gsp("@token").Contains('.')) { result = Convert.ToSingle(node.gsp("@token")); } else { var numberString = node.gsp("@token"); if (numberString.StartsWith("0x")) { result = Convert.ToInt32(numberString.Substring(2), 16); } else if (numberString.StartsWith("0b")) { var accumulator = 0; foreach (var c in numberString.Substring(2)) { accumulator <<= 1; if (c == '1') { accumulator += 1; } } result = accumulator; } else { result = Int32.Parse(numberString); } } } catch (Exception e) { context.RaiseNewError("Number format error.", node); { context.callDepth -= 1; return(null); } } } else if (type == "char") { context.callDepth -= 1; return(node.gsp("@token")[0]); } else { context.RaiseNewError("Internal evaluator error.", node); { context.callDepth -= 1; return(null); } } if (node.gsp("@prefix") == ":" && !ignoreStar) { result = Evaluate(context, result); } if (context.evaluationState != EvaluationState.Normal) { context.callDepth -= 1; return(null); } ; if (node.gsp("@prefix") == ".") { result = LookupToken(context, ScriptObject.AsString(result)); } context.callDepth -= 1; return(result); }
private void SetupStringFunctions() { AddFunction("split", "Split a string into pieces", (context, arguments) => { var pieces = AutoBind.StringArgument(arguments[0]).Split( new String[] { AutoBind.StringArgument(arguments[1]) }, Int32.MaxValue, StringSplitOptions.RemoveEmptyEntries); var r = new ScriptList(pieces); return(r); }, Arguments.Arg("string"), Arguments.Arg("split-chars")); AddFunction("strlen", "string : Returns length of string.", (context, arguments) => { return(ScriptObject.AsString(arguments[0]).Length); }, Arguments.Arg("string")); AddFunction("strind", "string n : Returns nth element in string.", (context, arguments) => { var index = arguments[1] as int?; if (index == null || !index.HasValue) { return(null); } if (index.Value < 0) { return(null); } var str = ScriptObject.AsString(arguments[0]); if (index.Value >= str.Length) { return(null); } return(str[index.Value]); }, Arguments.Arg("string"), Arguments.Arg("n")); AddFunction("substr", "Returns a portion of the input string.", (context, arguments) => { var str = ScriptObject.AsString(arguments[0]); var start = AutoBind.IntArgument(arguments[1]); if (arguments[2] == null) { return(str.Substring(start)); } else { return(str.Substring(start, AutoBind.IntArgument(arguments[2]))); } }, Arguments.Arg("string"), Arguments.Arg("start"), Arguments.Optional("length")); AddFunction("strcat", "Concatenate many strings into one.", (context, arguments) => { var r = new StringBuilder(); foreach (var obj in AutoBind.ListArgument(arguments[0])) { r.Append(ScriptObject.AsString(obj)); } return(r.ToString()); }, Arguments.Repeat("item")); AddFunction("itoa", "Change a number to the string representation.", (context, arguments) => { return(arguments[0].ToString()); }, Arguments.Arg("i")); AddFunction("atoi", "", (context, arguments) => { return(Convert.ToInt32(arguments[0])); }, Arguments.Arg("i")); AddFunction("unescape", "", (context, arguments) => { return(Console.UnescapeString(ScriptObject.AsString(arguments[0]))); }, Arguments.Arg("string")); AddFunction("format", "Format a string.", (context, arguments) => { return(String.Format(AutoBind.StringArgument(arguments[0]), AutoBind.ListArgument(arguments[1]).ToArray())); }, Arguments.Arg("format-string"), Arguments.Optional(Arguments.Repeat("value"))); }
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 string StringArgument(Object obj) { return(ScriptObject.AsString(obj)); }
public static ScriptObject Repeat(ScriptObject arg) { arg["@repeat"] = true; return arg; }
private static ScriptList children(ScriptObject obj) { var list = obj["@children"]; if (list == null) { list = new ScriptList(); obj["@children"] = list; } return list as ScriptList; }
private static void EmitObjectProperties( System.IO.TextWriter to, ScriptObject obj, List<ScriptObject> globalFunctions, List<ObjectRecord> objects, List<ObjectRecord> lambdas, int depth, bool ignoreFunctions = false) { foreach (var propertyName in obj.ListProperties()) { to.Write("\n" + new String(' ', depth * 3) + "(" + propertyName as String + " "); var value = obj.GetLocalProperty(propertyName as String); EmitObjectProperty(to, value, globalFunctions, objects, lambdas, depth, ignoreFunctions); to.Write(")"); } }
private static bool isType(ScriptObject obj, String type) { return obj.gsp("@type") == type; }
private static void EnumerateObject( ScriptObject obj, List<ScriptObject> globalFunctions, List<ObjectRecord> objects, List<ObjectRecord> lambdas, bool ignoreFunctions = false) { if (obj == null) return; if (Function.IsFunction(obj)) { if (ignoreFunctions) return; //System function? if (Function.IsSystemFunction(obj)) return; //Lambda function? if (globalFunctions.Contains(obj)) return; if (AddRef(obj, lambdas)) EnumerateObject(obj["declaration-scope"] as ScriptObject, globalFunctions, objects, lambdas, ignoreFunctions); } else { foreach (var prop in obj.ListProperties()) { var value = obj.GetLocalProperty(prop as String); if (value is ScriptObject) { if (AddRef(value as ScriptObject, objects)) EnumerateObject(value as ScriptObject, globalFunctions, objects, lambdas, ignoreFunctions); } else if (value is ScriptList) { foreach (var item in value as ScriptList) { if (item is ScriptObject) if (AddRef(item as ScriptObject, objects)) EnumerateObject(item as ScriptObject, globalFunctions, objects, lambdas, ignoreFunctions); } } } } }
private static void emitArgumentSpec(ScriptObject arg, System.IO.TextWriter to) { if (arg["@mutator"] == null && arg["@optional"] == null && arg["@repeat"] == null && arg["@lazy"] == null) { to.Write("(arg " + arg["@name"] + ")"); return; } if (arg["@mutator"] != null) to.Write("(arg-mutator "); if (arg["@optional"] != null) to.Write("(arg-optional "); if (arg["@repeat"] != null) to.Write("(arg-repeat "); if (arg["@lazy"] != null) to.Write("(arg-lazy "); to.Write(arg["@name"]); if (arg["@lazy"] != null) to.Write(")"); if (arg["@repeat"] != null) to.Write(")"); if (arg["@optional"] != null) to.Write(")"); if (arg["@mutator"] != null) { to.Write(" "); SerializeCode(to, arg["@mutator"] as ScriptObject); to.Write(")"); } }
public void SerializeObject(System.IO.TextWriter to, ScriptObject obj) { if (obj == null) { to.WriteLine("(null)"); return; } var objects = new List<ObjectRecord>(); EnumerateObject(obj, null, objects, null, true); //Filter out objects with just a single reference objects = new List<ObjectRecord>(objects.Where((o) => { return o.referenceCount > 1; })); AddRef(obj, objects); //Create and emit lambda functions. to.WriteLine("(let ((\"objects\" (array " + objects.Count + " (record))))"); to.WriteLine(" (lastarg\n"); //Emit remaining objects foreach (var _obj in objects) EmitObjectRoot(to, _obj.obj, null, objects, null, true); //Emit footer var thisIndex = IndexIn(obj, objects); to.WriteLine(" (index objects " + thisIndex + ")"); to.WriteLine(" )"); to.WriteLine(")"); }
public static bool IsSystemFunction(ScriptObject obj) { if (obj == null) return false; return obj["@function-body"] is Func<Context, ScriptList, Object>; }
public TimeoutError(ScriptObject generatedBy) : base("Execution timed out.", generatedBy) { }
private static void EmitObjectRoot( System.IO.TextWriter to, ScriptObject obj, List<ScriptObject> globalFunctions, List<ObjectRecord> objects, List<ObjectRecord> lambdas, bool ignoreFunctions = false) { var index = IndexIn(obj, objects); to.WriteLine("(multi-set (index objects " + index + ") "); EmitObjectProperties(to, obj, globalFunctions, objects, lambdas, 1, ignoreFunctions); to.Write(")\n"); }
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); }
private static int IndexIn(ScriptObject obj, List<ObjectRecord> list) { for (int i = 0; i < list.Count; ++i) if (list[i].obj == obj) return i; return -1; }
private static Object MutateArgument(Object argument, ScriptObject argumentDescripter, Engine engine, Context context) { var mutator = argumentDescripter["@mutator"]; if (mutator == null) return argument; context.Scope.PushVariable("value", argument); var result = engine.Evaluate(context, mutator, true); context.Scope.PopVariable("value"); return result; }
public void ExecuteCode(ScriptObject obj) { try { environment.context.ResetTimer(); environment.context.evaluationState = EvaluationState.Normal; var result = environment.engine.Evaluate(environment.context, obj, true, false); if (environment.context.evaluationState != EvaluationState.UnwindingError) { if (!noEcho) Write(MISP.Console.PrettyPrint2(result, 0) + "\n"); } else { Write("Error:\n"); Write(MISP.Console.PrettyPrint2(environment.context.errorObject, 0)); } if (!environment.context.CheckScope()) Write("Error: Scopes not properly cleaned.\n"); noEcho = false; } catch (Exception e) { Write(e.Message + "\n"); } }
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 ScriptError(String msg, ScriptObject generatedAt) : base(msg) { this.generatedAt = generatedAt; }
public static ScriptObject ReorderMemberAccessNode(ScriptObject node) { //Convert (A (B (C D))) to (((A B) C) D) //Create an (A B C D) list. var nodeList = new LinkedList<AccessChainNode>(); for (var n = node; n != null; n = (isType(n, "memberaccess") ? child(n,1) as ScriptObject : null)) { if (isType(n, "memberaccess")) nodeList.AddLast(new AccessChainNode { node = child(n,0), token = n["@token"] }); else nodeList.AddLast(new AccessChainNode { node = n, token = "" }); } //Each iteration, take the first two nodes and combine them into a new member access node. //(A B C D) becomes ((A B) C D), etc. while (nodeList.Count > 1) { var lhs = nodeList.First(); nodeList.RemoveFirst(); var rhs = nodeList.First(); nodeList.RemoveFirst(); var newNode = new GenericScriptObject("@type", "memberaccess", "@start", (lhs.node as ScriptObject)["@start"], "@source", (lhs.node as ScriptObject)["@source"]); newNode["@token"] = lhs.token; children(newNode).Add(lhs.node); children(newNode).Add(rhs.node); nodeList.AddFirst(new AccessChainNode { node = newNode, token = rhs.token }); } return nodeList.First().node as ScriptObject; }
private static Object child(ScriptObject obj, int index) { return (obj["@children"] as ScriptList)[index]; }
public Context(ScriptObject obj) { Reset(); foreach (var name in obj.ListProperties()) Scope.PushVariable(name as String, obj.GetLocalProperty(name as String)); }
private void SetupObjectFunctions() { AddFunction("members", "Lists all members of an object", (context, arguments) => { var obj = ArgumentType <ScriptObject>(arguments[0]); return(obj.ListProperties()); }, Arguments.Arg("object")); AddFunction("record", "Create a new record.", (context, arguments) => { var obj = new GenericScriptObject(); var vars = AutoBind.ListArgument(arguments[0]); foreach (var item in vars) { var l = ArgumentType <ScriptObject>(item); if (l == null || l._children.Count != 2) { throw new ScriptError("Record expects a list of pairs.", null); } var arg = l._child(0) as ScriptObject; string mname = ""; if (arg != null && arg.gsp("@type") == "token") { mname = arg.gsp("@token"); } else { mname = Evaluate(context, arg, true).ToString(); } obj.SetProperty(mname, Evaluate(context, l._child(1))); } return(obj); }, Arguments.Repeat(Arguments.Lazy("pairs"))); AddFunction("clone", "Clone a record.", (context, arguments) => { var r = new GenericScriptObject(arguments[0] as ScriptObject); foreach (var item in arguments[1] as ScriptList) { var list = item as ScriptList; if (list == null || list.Count != 2) { throw new ScriptError("Record expects only pairs as arguments.", context.currentNode); } r[ScriptObject.AsString(list[0])] = list[1]; } return(r); }, Arguments.Arg("object"), Arguments.Mutator(Arguments.Repeat(Arguments.Optional("pairs")), "(@list value)")); AddFunction("set", "Set a member on an object.", (context, arguments) => { if (arguments[0] == null) { return(arguments[2]); } return(SetObjectProperty(context, arguments[0], ScriptObject.AsString(arguments[1]), arguments[2])); }, Arguments.Arg("object"), Arguments.Mutator(Arguments.Lazy("name"), "(@identifier-if-token value)"), Arguments.Arg("value")); AddFunction("multi-set", "Set multiple members of an object.", (context, arguments) => { var obj = ArgumentType <ScriptObject>(arguments[0]); var vars = AutoBind.ListArgument(arguments[1]); foreach (var item in vars) { var l = ArgumentType <ScriptObject>(item); if (l == null || l._children.Count != 2) { throw new ScriptError("Multi-set expects a list of pairs.", null); } var arg = l._child(0) as ScriptObject; string mname = ""; if (arg != null && arg.gsp("@type") == "token") { mname = arg.gsp("@token"); } else { mname = Evaluate(context, arg, true).ToString(); } SetObjectProperty(context, obj, mname, Evaluate(context, l._child(1))); } return(obj); }, Arguments.Arg("object"), Arguments.Repeat(Arguments.Lazy("pairs"))); AddFunction("delete", "Deletes a property from an object.", (context, arguments) => { var value = (arguments[0] as ScriptObject)[ScriptObject.AsString(arguments[1])]; if (arguments[0] is Scope) { (arguments[0] as Scope).PopVariable(ScriptObject.AsString(arguments[1])); } else { (arguments[0] as ScriptObject).DeleteProperty(ScriptObject.AsString(arguments[1])); } return(value); }, Arguments.Arg("object"), Arguments.Arg("property-name")); }