public GenericScriptObject(params Object[] args) { if (args.Length % 2 != 0) { throw new InvalidProgramException("Generic Script Object must be initialized with pairs"); } for (int i = 0; i < args.Length; i += 2) { SetProperty(ScriptObject.AsString(args[i]), args[i + 1]); } }
public String AsString(int depth) { if (depth < 0) { return("L" + Count); } return("L" + Count + "{" + String.Join(", ", this.Select((o) => { return ScriptObject.AsString(o, depth - 1); })) + " }"); }
public String AsString(int depth) { if (depth < 0) { return(this.GetType().Name); } else { return("SO{" + String.Join(", ", (this as ScriptObject).ListProperties().Select((o) => { return o.ToString() + ": " + ScriptObject.AsString(this.GetProperty(o.ToString()), depth - 1); })) + " }"); } }
public void PrepareEnvironment(Engine engine) { SetupStandardConsoleFunctions(engine); if (SetupHost != null) { SetupHost(engine); } engine.AddFunction("run-file", "Load and run a file.", (_context, arguments) => { var text = System.IO.File.ReadAllText(ScriptObject.AsString(arguments[0])); return(engine.EvaluateString(_context, text, ScriptObject.AsString(arguments[0]), false)); }, Arguments.Arg("name")); }
private ScriptObject defunImple(Context context, ScriptList arguments, bool addToScope) { var functionName = ArgumentType <String>(arguments[0]); ScriptList argumentInfo = null; try { argumentInfo = ArgumentType <ScriptList>(arguments[1]); } catch (ScriptError e) { context.RaiseNewError(e.Message, context.currentNode); return(null); } var functionBody = ArgumentType <ScriptObject>(arguments[2]); var newFunction = Function.MakeFunction( functionName, argumentInfo, "Script-defined function", functionBody, CopyScope(context.Scope)); if (arguments[3] != null) { newFunction["@help"] = ScriptObject.AsString(arguments[3]); } if (addToScope) { (newFunction["declaration-scope"] as Scope).PushVariable(functionName, newFunction); } return(newFunction); }
private static object SetObjectProperty(Context context, Object obj, String name, Object value) { if (obj is ScriptObject) { try { (obj as ScriptObject)[name] = value; } catch (Exception e) { context.RaiseNewError("System Exception: " + e.Message, context.currentNode); } } else { var field = obj.GetType().GetField(ScriptObject.AsString(name)); if (field != null) { field.SetValue(obj, value); } else { var prop = obj.GetType().GetProperty(ScriptObject.AsString(name)); if (prop != null) { prop.SetValue(obj, value, null); } else { context.RaiseNewError("Could not find member with name '" + ScriptObject.AsString(name) + "' on object" + " of type '" + obj.GetType().ToString() + "'", context.currentNode); } } } return(value); }
private void SetupVariableFunctions() { AddFunction("var", "name value : Assign value to a variable named [name].", (context, arguments) => { if (specialVariables.ContainsKey(ScriptObject.AsString(arguments[0]))) { context.RaiseNewError("Can't assign to protected variable name.", context.currentNode); } else { try { context.Scope.ChangeVariable(ScriptObject.AsString(arguments[0]), arguments[1]); } catch (Exception e) { context.RaiseNewError(e.Message, context.currentNode); } } return(arguments[1]); }, Arguments.Mutator(Arguments.Lazy("name"), "(@identifier value)"), Arguments.Arg("value")); AddFunction("let", "^( ^(\"name\" value ?cleanup-code) ^(...) ) code : Create temporary variables, run code. Optional clean-up code for each variable.", (context, arguments) => { var variables = ArgumentType <ScriptObject>(arguments[0]); if (!String.IsNullOrEmpty(variables.gsp("@prefix"))) /* Raise warning */ } { var code = ArgumentType <ScriptObject>(arguments[1]); var cleanUp = new List <LetVariable>(); Object result = null; foreach (var item in variables._children) { var sitem = item as ScriptObject; if (sitem._children.Count <= 1 || sitem._children.Count > 3) { context.RaiseNewError("Bad variable definition in let", context.currentNode); goto RUN_CLEANUP; } var nameObject = sitem._child(0) as ScriptObject; var varName = ""; if (nameObject.gsp("@type") == "token") { varName = nameObject.gsp("@token"); } else { varName = AutoBind.StringArgument(Evaluate(context, nameObject, true)); } if (context.evaluationState != EvaluationState.Normal) { goto RUN_CLEANUP; } var varValue = Evaluate(context, sitem._child(1), false); if (context.evaluationState != EvaluationState.Normal) { goto RUN_CLEANUP; } context.Scope.PushVariable(varName, varValue); cleanUp.Add(new LetVariable { name = varName, cleanupCode = sitem._children.Count == 3 ? sitem._child(2) : null }); } result = Evaluate(context, code, true); RUN_CLEANUP: var pre_state = context.evaluationState; foreach (var item in cleanUp) { if (item.cleanupCode != null) { context.evaluationState = EvaluationState.Normal; Evaluate(context, item.cleanupCode, true, true); } context.Scope.PopVariable(item.name); } context.evaluationState = pre_state; return(result); },
private void SetupFileFunctions() { var file_functions = new GenericScriptObject(); file_functions.SetProperty("open", Function.MakeSystemFunction("open", Arguments.Args("file-name", "mode"), "Opens a file", (context, arguments) => { var mode = AutoBind.StringArgument(arguments[1]).ToUpperInvariant(); if (mode == "READ") { return(System.IO.File.OpenText(AutoBind.StringArgument(arguments[0]))); } else if (mode == "WRITE") { return(System.IO.File.CreateText(AutoBind.StringArgument(arguments[0]))); } else if (mode == "APPEND") { return(System.IO.File.AppendText(AutoBind.StringArgument(arguments[0]))); } else { context.RaiseNewError("Invalid mode specifier", context.currentNode); } return(null); })); file_functions.SetProperty("close", Function.MakeSystemFunction("close", Arguments.Args("file"), "Close a file.", (context, arguments) => { if (arguments[0] is System.IO.StreamReader) { (arguments[0] as System.IO.StreamReader).Close(); } else if (arguments[0] is System.IO.StreamWriter) { (arguments[0] as System.IO.StreamWriter).Close(); } else { context.RaiseNewError("Argument is not a file.", context.currentNode); } return(null); })); file_functions.SetProperty("read-line", Function.MakeSystemFunction("read-line", Arguments.Args("file"), "Read a line from a file.", (context, arguments) => { var file = arguments[0] as System.IO.StreamReader; if (file == null) { context.RaiseNewError("Argument is not a read file.", context.currentNode); return(null); } return(file.ReadLine()); })); file_functions.SetProperty("read-all", Function.MakeSystemFunction("read-all", Arguments.Args("file"), "Read all of a file.", (context, arguments) => { var file = arguments[0] as System.IO.StreamReader; if (file == null) { context.RaiseNewError("Argument is not a read file.", context.currentNode); return(null); } return(file.ReadToEnd()); })); file_functions.SetProperty("write", Function.MakeSystemFunction("write", Arguments.Args("file", "text"), "Write to a file.", (context, arguments) => { var file = arguments[0] as System.IO.StreamWriter; if (file == null) { context.RaiseNewError("Argument is not a write file.", context.currentNode); return(null); } file.Write(ScriptObject.AsString(arguments[1])); return(null); })); file_functions.SetProperty("more", Function.MakeSystemFunction("more", Arguments.Args("file"), "Is there more to read in this file?", (context, arguments) => { var file = arguments[0] as System.IO.StreamReader; if (file == null) { context.RaiseNewError("Argument is not a read file.", context.currentNode); return(null); } if (file.EndOfStream) { return(null); } return(true); })); AddGlobalVariable("file", c => file_functions); }
private void SetupStandardLibrary() { //types.Add("STRING", new TypeString()); //types.Add("INTEGER", new TypePrimitive(typeof(int), true)); //types.Add("LIST", new TypeList()); //types.Add("OBJECT", new TypePrimitive(typeof(ScriptObject), false)); //types.Add("CODE", new TypePrimitive(typeof(ScriptObject), false)); //types.Add("IDENTIFIER", new TypeString()); //types.Add("FUNCTION", new TypePrimitive(typeof(ScriptObject), false)); //types.Add("ANYTHING", Type.Anything); //types.Add("FLOAT", new TypePrimitive(typeof(float), true)); //foreach (var type in types) // type.Value.Typename = type.Key; specialVariables.Add("null", (c) => { return(null); }); specialVariables.Add("functions", (c) => { return(new ScriptList(functions.Select((pair) => { return pair.Value; }))); }); specialVariables.Add("true", (c) => { return(true); }); specialVariables.Add("false", (c) => { return(null); }); specialVariables.Add("@scope", (c) => { return(c.Scope); }); //AddFunction("net-module", "Loads a module from a .net assembly", // (context, arguments) => // { // NetModule.LoadModule(context, this, ScriptObject.AsString(arguments[0]), ScriptObject.AsString(arguments[1])); // return null; // }, "string assembly", "string module"); AddFunction("@list", "If the argument is a list, great. If not, now it is.", (context, arguments) => { if (arguments[0] == null) { return(new ScriptList()); } if (arguments[0] is ScriptList) { return(arguments[0]); } return(new ScriptList(arguments[0])); }, Arguments.Arg("value")); AddFunction("@lazy-list", "Mutates a lazy argument into a list. Effectively makes the ^ optional.", (context, arguments) => { var node = arguments[0] as ScriptObject; if (node == null) { return(new ScriptList()); } var r = new ScriptList(); foreach (var child in node._children) { r.Add(Evaluate(context, child)); } return(r); }, Arguments.Arg("arg")); AddFunction("@identifier", "Mutates a lazy argument. If it's a token, return as a string. If not, evaluate and return as a string.", (context, arguments) => { var arg = arguments[0] as ScriptObject; if (arg != null && arg.gsp("@type") == "token") { return(arg.gsp("@token")); } return(ScriptObject.AsString(Evaluate(context, arg, true))); }, Arguments.Arg("arg")); AddFunction("@identifier-if-token", "Mutates a lazy argument. If it's a token, return as a string. If not, evaluate and return.", (context, arguments) => { var arg = arguments[0] as ScriptObject; if (arg != null && arg.gsp("@type") == "token") { return(arg.gsp("@token")); } return(Evaluate(context, arg, true)); }, Arguments.Arg("arg")); AddFunction("arg", "create an argument", (context, arguments) => { if (arguments[0] is ScriptObject) { return(arguments[0]); } else { return(Arguments.Arg(ScriptObject.AsString(arguments[0]))); } }, Arguments.Mutator(Arguments.Lazy("name"), "(@identifier value)")); AddFunction("arg-lazy", "create a lazy argument", (context, arguments) => { if (arguments[0] is ScriptObject) { (arguments[0] as ScriptObject)["@lazy"] = true; return(arguments[0]); } else { return(Arguments.Lazy(Arguments.Arg(ScriptObject.AsString(arguments[0])))); } }, Arguments.Mutator(Arguments.Lazy("name"), "(@identifier-if-token value)")); AddFunction("arg-optional", "create an optional argument", (context, arguments) => { if (arguments[0] is ScriptObject) { (arguments[0] as ScriptObject)["@optional"] = true; return(arguments[0]); } else { return(Arguments.Optional(Arguments.Arg(ScriptObject.AsString(arguments[0])))); } }, Arguments.Mutator(Arguments.Lazy("name"), "(@identifier-if-token value)")); AddFunction("arg-repeat", "create a repeat argument", (context, arguments) => { if (arguments[0] is ScriptObject) { (arguments[0] as ScriptObject)["@repeat"] = true; return(arguments[0]); } else { return(Arguments.Repeat(Arguments.Arg(ScriptObject.AsString(arguments[0])))); } }, Arguments.Mutator(Arguments.Lazy("name"), "(@identifier-if-token value)")); AddFunction("arg-mutator", "Add a mutator to an argument", (context, arguments) => { if (arguments[0] is ScriptObject) { (arguments[0] as ScriptObject)["@mutator"] = arguments[1]; return(arguments[0]); } else { var r = Arguments.Arg(ScriptObject.AsString(arguments[0])); r["@mutator"] = arguments[1]; return(r); } }, Arguments.Mutator(Arguments.Lazy("name"), "(@identifier-if-token value)"), Arguments.Lazy("mutator")); AddFunction("eval", "Evaluates it's argument.", (context, arguments) => { return(Evaluate(context, arguments[0], true)); }, Arguments.Arg("arg")); AddFunction("lastarg", "Returns last argument", (context, arguments) => { return((arguments[0] as ScriptList).LastOrDefault()); }, Arguments.Repeat("child")); AddFunction("nop", "Returns null.", (context, arguments) => { return(null); }, Arguments.Optional(Arguments.Repeat("value"))); AddFunction("coalesce", "B if A is null, A otherwise.", (context, arguments) => { if (arguments[0] == null) { return(Evaluate(context, arguments[1], true, false)); } else { return(arguments[0]); } }, Arguments.Arg("A"), Arguments.Lazy("B")); AddFunction("raise-error", "Raises a new error.", (context, arguments) => { context.RaiseNewError(MISP.ScriptObject.AsString(arguments[0]), context.currentNode); return(null); }, Arguments.Arg("message")); AddFunction("catch-error", "Evaluate and return A unless error generated; if error Evaluate and return B.", (context, arguments) => { var result = Evaluate(context, arguments[0], true, false); if (context.evaluationState == EvaluationState.UnwindingError) { context.evaluationState = EvaluationState.Normal; return(Evaluate(context, arguments[1], true, false)); } return(result); }, Arguments.Lazy("good"), Arguments.Lazy("bad")); AddFunction("break", "Aborts loops and supplies a return value.", (context, arguments) => { context.evaluationState = EvaluationState.UnwindingBreak; context.breakObject = arguments[0]; return(null); }, Arguments.Arg("value")); AddFunction("reflect", "Examine an object using .net reflection.", (context, arguments) => { var stream = new System.IO.StringWriter(); if (arguments[0] == null) { stream.Write("null\n"); } else { stream.Write(arguments[0].GetType().Name + "\n"); foreach (var field in arguments[0].GetType().GetFields()) { stream.Write("field: " + field.Name + " " + field.FieldType.Name + "\n"); } foreach (var method in arguments[0].GetType().GetMethods()) { stream.Write("method: " + method.Name + " " + method.ReturnType.Name + "\n"); } } return(stream.ToString()); }, Arguments.Arg("object")); AddFunction("lazy-overloads", "Examine all possible overloads of a lazy binding.", (context, arguments) => { var binding = arguments[0] as ScriptObject; var stream = new System.IO.StringWriter(); if (binding.GetProperty("@lazy-reflection") == null) { stream.Write("Not a lazy binding object."); } else { var sourceType = binding.GetProperty("@source-type") as System.Type; var methods = sourceType.GetMethods().Where((m) => m.Name == binding.gsp("@lazy-reflection")); stream.Write("Methods found:\n"); foreach (var method in methods) { stream.Write("args: "); stream.Write(String.Join(" ", method.GetParameters().Select((p) => p.ParameterType.Name))); stream.Write("\n"); } } return(stream.ToString()); }, Arguments.Arg("object")); AddFunction("emitt", "Emit in tight-formatting style.", (context, arguments) => { return(TightFormat(arguments[0])); }, Arguments.Arg("object", "Meant for use with objects generated via AutoBind.")); AddFunction("emitf", "Emit a function", (context, arguments) => { var stream = new System.IO.StringWriter(); var obj = arguments[0] as ScriptObject; stream.Write("Name: "); stream.Write(obj.gsp("@name") + "\nHelp: " + obj.gsp("@help") + "\nArguments: \n"); foreach (var arg_ in obj["@arguments"] as ScriptList) { stream.Write(" "); var arg = arg_ as ScriptObject; //stream.Write((arg["@type"] as Type).Typename + " "); if (arg["@optional"] != null) { stream.Write("?"); } if (arg["@repeat"] != null) { stream.Write("+"); } if (arg["@lazy"] != null) { stream.Write("*"); } stream.Write(arg["@name"] + " "); if (arg["@mutator"] != null) { Engine.SerializeCode(stream, arg["@mutator"] as ScriptObject); } if (arg["@help"] != null) { stream.Write(" - " + arg["@help"].ToString()); } stream.Write("\n"); } stream.Write("\nBody: "); if (obj["@function-body"] is ScriptObject) { Engine.SerializeCode(stream, obj["@function-body"] as ScriptObject); } else { stream.Write("System"); } stream.Write("\n"); return(stream.ToString()); }, Arguments.Arg("func", "Must be a function.")); AddFunction("serialize", "Serialize an object", (context, arguments) => { var stream = new System.IO.StringWriter(); SerializeObject(stream, arguments[0] as ScriptObject); return(stream.ToString()); }, Arguments.Arg("object")); SetupVariableFunctions(); SetupObjectFunctions(); SetupMathFunctions(); SetupFunctionFunctions(); SetupBranchingFunctions(); SetupLoopFunctions(); SetupListFunctions(); SetupStringFunctions(); SetupEncryptionFunctions(); SetupFileFunctions(); SetupRegexFunctions(); }
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 string StringArgument(Object obj) { return(ScriptObject.AsString(obj)); }
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 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")); }