Пример #1
0
        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));
        }
Пример #2
0
        public static ScriptObject GenerateMethodBinding(System.Reflection.MethodInfo method)
        {
            ScriptList boundArguments = new ScriptList();

            if (!method.IsStatic)
            {
                boundArguments.Add(Arguments.Arg("object"));
            }
            foreach (var parameter in method.GetParameters())
            {
                if (parameter.IsOptional)
                {
                    boundArguments.Add(Arguments.Optional(parameter.Name, parameter.ParameterType.Name));
                }
                else
                {
                    boundArguments.Add(Arguments.Arg(parameter.Name, parameter.ParameterType.Name));
                }
            }
            return(Function.MakeSystemFunction(method.Name,
                                               boundArguments,
                                               "Auto bound function",
                                               (context, arguments) =>
            {
                var parameters = method.GetParameters();
                int start = method.IsStatic ? 0 : 1;
                var args = new object[arguments.Count - start];
                for (int i = 0; i < arguments.Count - start; ++i)
                {
                    args[i] = Convert.ChangeType(arguments[i + start], parameters[i].ParameterType);
                }
                return method.Invoke(method.IsStatic ? null : arguments[0], args);
            }));
        }
Пример #3
0
        override public ScriptList ListProperties()
        {
            var r = new ScriptList();

            r.AddRange(this.GetType().GetFields().Select((info) => info.Name));
            r.AddRange(properties.Select((p) => p.Key));
            return(r);
        }
Пример #4
0
        private static ScriptList children(ScriptObject obj)
        {
            var list = obj["@children"];

            if (list == null)
            {
                list             = new ScriptList();
                obj["@children"] = list;
            }

            return(list as ScriptList);
        }
Пример #5
0
 public static ScriptObject MakeSystemFunction(
     String name,
     ScriptList arguments,
     String help,
     Func <Context, ScriptList, Object> func)
 {
     return(new GenericScriptObject(
                "@name", name,
                "@arguments", arguments,
                "@help", help,
                "@function-body", func));
 }
Пример #6
0
        public static ScriptList Args(params Object[] objs)
        {
            var r = new ScriptList();

            foreach (var obj in objs)
            {
                if (obj is ScriptObject)
                {
                    r.Add(obj);
                }
                else if (obj is String)
                {
                    r.Add(Arg(obj.ToString()));
                }
                else
                {
                    throw new InvalidProgramException();
                }
            }
            return(r);
        }
Пример #7
0
        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);
        }
Пример #8
0
        private void evaluateNodeChild(bool callFunction, Object child, ScriptList arguments, Context context)
        {
            bool lazyArgument = false;
            var  prefix       = (child as ScriptObject).gsp("@prefix");

            if (callFunction && arguments.Count > 0 && (Function.IsFunction(arguments[0] as ScriptObject)))
            {
                var argumentInfo = Function.GetArgumentInfo(arguments[0] as ScriptObject, context, arguments.Count - 1);
                if (context.evaluationState != EvaluationState.Normal)
                {
                    return;
                }
                lazyArgument = argumentInfo["@lazy"] != null;
            }

            if (lazyArgument && prefix != ":" && prefix != "#")
            {
                arguments.Add(child);
            }
            else
            {
                var argument = Evaluate(context, child);
                if (context.evaluationState != EvaluationState.Normal)
                {
                    return;
                }
                if (prefix == "$" && argument is ScriptList)
                {
                    arguments.AddRange(argument as ScriptList);
                }
                else
                {
                    arguments.Add(argument);
                }
            }
        }
Пример #9
0
        private void SetupLoopFunctions()
        {
            AddFunction("map", "variable_name list code : Transform one list into another",
                        (context, arguments) =>
            {
                var vName  = ArgumentType <String>(arguments[0]);
                var list   = ArgumentType <System.Collections.IEnumerable>(arguments[1]);
                var code   = ArgumentType <ScriptObject>(arguments[2]);
                var result = new ScriptList();
                context.Scope.PushVariable(vName, null);
                foreach (var item in list)
                {
                    context.Scope.ChangeVariable(vName, item);
                    result.Add(Evaluate(context, code, true));
                    if (context.evaluationState == EvaluationState.UnwindingBreak)
                    {
                        context.Scope.PopVariable(vName);
                        return(context.UnBreak());
                    }
                }
                context.Scope.PopVariable(vName);
                return(result);
            },
                        Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)"),
                        Arguments.Arg("in"),
                        Arguments.Lazy("code"));

            AddFunction("mapi", "Like map, except the variable will hold the index.",
                        (context, arguments) =>
            {
                var vName  = ArgumentType <String>(arguments[0]);
                var from   = AutoBind.IntArgument(arguments[1]);
                var to     = AutoBind.IntArgument(arguments[2]);
                var code   = ArgumentType <ScriptObject>(arguments[3]);
                var result = new ScriptList();
                context.Scope.PushVariable(vName, null);
                for (int i = from; i < to; ++i)
                {
                    context.Scope.ChangeVariable(vName, i);
                    result.Add(Evaluate(context, code, true));
                    if (context.evaluationState == EvaluationState.UnwindingBreak)
                    {
                        context.Scope.PopVariable(vName);
                        return(context.UnBreak());
                    }
                }
                context.Scope.PopVariable(vName);
                return(result);
            },
                        Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)"),
                        Arguments.Arg("from"),
                        Arguments.Arg("to"),
                        Arguments.Lazy("code"));


            AddFunction("mapex",
                        "variable_name start code next : Like map, but the next element is the result of 'next'. Stops when next = null.",
                        (context, arguments) =>
            {
                var vName  = ArgumentType <String>(arguments[0]);
                var code   = ArgumentType <ScriptObject>(arguments[2]);
                var next   = ArgumentType <ScriptObject>(arguments[3]);
                var result = new ScriptList();
                var item   = arguments[1];
                context.Scope.PushVariable(vName, null);

                while (item != null)
                {
                    context.Scope.ChangeVariable(vName, item);
                    result.Add(Evaluate(context, code, true));
                    if (context.evaluationState == EvaluationState.UnwindingBreak)
                    {
                        context.Scope.PopVariable(vName);
                        return(context.UnBreak());
                    }
                    item = Evaluate(context, next, true);
                }

                context.Scope.PopVariable(vName);
                return(result);
            },
                        Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)"),
                        Arguments.Arg("start"),
                        Arguments.Lazy("code"),
                        Arguments.Lazy("next"));

            AddFunction("for",
                        "variable_name list code : Execute code for each item in list. Returns result of last run of code.",
                        (context, arguments) =>
            {
                var vName = ArgumentType <String>(arguments[0]);
                var list  = ArgumentType <System.Collections.IEnumerable>(arguments[1]);
                var func  = ArgumentType <ScriptObject>(arguments[2]);
                context.Scope.PushVariable(vName, null);
                Object result = null;
                foreach (var item in list)
                {
                    context.Scope.ChangeVariable(vName, item);
                    result = Evaluate(context, func, true);
                    if (context.evaluationState == EvaluationState.UnwindingBreak)
                    {
                        context.Scope.PopVariable(vName);
                        return(context.UnBreak());
                    }
                }

                context.Scope.PopVariable(vName);

                return(result);
            },
                        Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)"),
                        Arguments.Arg("list"),
                        Arguments.Lazy("code"));

            AddFunction("fori",
                        "variable_name list code : Execute code for each item in list. Returns result of last run of code.",
                        (context, arguments) =>
            {
                var vName = ArgumentType <String>(arguments[0]);
                var from  = AutoBind.IntArgument(arguments[1]);
                var to    = AutoBind.IntArgument(arguments[2]);
                var func  = ArgumentType <ScriptObject>(arguments[3]);
                context.Scope.PushVariable(vName, null);
                Object result = null;
                for (int i = from; i < to; ++i)
                {
                    context.Scope.ChangeVariable(vName, i);
                    result = Evaluate(context, func, true);
                    if (context.evaluationState == EvaluationState.UnwindingError)
                    {
                        return(result);
                    }
                    else if (context.evaluationState == EvaluationState.UnwindingBreak)
                    {
                        context.Scope.PopVariable(vName);
                        return(context.UnBreak());
                    }
                }

                context.Scope.PopVariable(vName);

                return(result);
            },
                        Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)"),
                        Arguments.Arg("from"),
                        Arguments.Arg("to"),
                        Arguments.Lazy("code"));

            AddFunction("while",
                        "condition code : Repeat code while condition evaluates to true.",
                        (context, arguments) =>
            {
                var cond = ArgumentType <ScriptObject>(arguments[0]);
                var code = ArgumentType <ScriptObject>(arguments[1]);

                while (context.evaluationState == EvaluationState.Normal && Evaluate(context, cond, true) != null)
                {
                    if (context.evaluationState == EvaluationState.Normal)
                    {
                        Evaluate(context, code, true);
                    }
                }
                if (context.evaluationState == EvaluationState.UnwindingBreak)
                {
                    return(context.UnBreak());
                }
                return(null);
            },
                        Arguments.Lazy("condition"),
                        Arguments.Lazy("code"));
        }
Пример #10
0
        private void SetupListFunctions()
        {
            AddFunction("length", "list : Returns length of list.",
                        (context, arguments) =>
            {
                var list = arguments[0] as ScriptList;
                return(list == null ? 0 : list.Count);
            }, Arguments.Arg("list"));

            AddFunction("count", "variable_name list code : Returns number of items in list for which code evaluated to true.",
                        (context, arguments) =>
            {
                var vName = ArgumentType <String>(arguments[0]);
                var list  = ArgumentType <ScriptList>(arguments[1]);
                var func  = ArgumentType <ScriptObject>(arguments[2]);

                context.Scope.PushVariable(vName, null);
                var result = (int)list.Count((o) =>
                {
                    context.Scope.ChangeVariable(vName, o);

                    return(Evaluate(context, func, true) != null);
                });
                context.Scope.PopVariable(vName);
                return(result);
            },
                        Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)"),
                        Arguments.Mutator(Arguments.Arg("in"), "(@list value)"),
                        Arguments.Lazy("code"));

            AddFunction("where", "variable_name list code : Returns new list containing only the items in list for which code evaluated to true.",
                        (context, arguments) =>
            {
                var vName = ArgumentType <String>(arguments[0]);
                var list  = ArgumentType <ScriptList>(arguments[1]);
                var func  = ArgumentType <ScriptObject>(arguments[2]);

                context.Scope.PushVariable(vName, null);
                var result = new ScriptList(list.Where((o) =>
                {
                    context.Scope.ChangeVariable(vName, o);
                    return(Evaluate(context, func, true) != null);
                }));
                context.Scope.PopVariable(vName);
                return(result);
            },
                        Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)"),
                        Arguments.Mutator(Arguments.Arg("in"), "(@list value)"),
                        Arguments.Lazy("code"));

            AddFunction("cat", "<n> : Combine N lists into one",
                        (context, arguments) =>
            {
                var result = new ScriptList();
                foreach (var arg in arguments[0] as ScriptList)
                {
                    if (arg is ScriptList)
                    {
                        result.AddRange(arg as ScriptList);
                    }
                    else
                    {
                        result.Add(arg);
                    }
                }
                return(result);
            }, Arguments.Repeat(Arguments.Optional("item")));

            AddFunction("last",
                        "list : Returns last item in list.",
                        (context, arguments) =>
            {
                return(ArgumentType <ScriptList>(arguments[0]).LastOrDefault());
            },
                        Arguments.Mutator(Arguments.Arg("list"), "(@list value)"));

            AddFunction("first",
                        "list : Returns first item in list.",
                        (context, arguments) =>
            {
                if (arguments[2] == null)
                {
                    return(ArgumentType <ScriptList>(arguments[0]).FirstOrDefault());
                }
                else
                {
                    var vName = ArgumentType <String>(arguments[1]);
                    var list  = ArgumentType <ScriptList>(arguments[0]);
                    var func  = ArgumentType <ScriptObject>(arguments[2]);

                    context.Scope.PushVariable(vName, null);
                    var result = list.FirstOrDefault((o) => {
                        context.Scope.ChangeVariable(vName, o);
                        return(Evaluate(context, func, true) != null);
                    });
                    context.Scope.PopVariable(vName);
                    return(result);
                }
            },
                        Arguments.Mutator(Arguments.Arg("list"), "(@list value)"),
                        Arguments.Optional(Arguments.Mutator(Arguments.Lazy("variable-name"), "(@identifier value)")),
                        Arguments.Optional(Arguments.Lazy("code")));

            AddFunction("index",
                        "list n : Returns nth element in list.",
                        (context, arguments) =>
            {
                var index = arguments[1] as int?;
                if (index == null || !index.HasValue)
                {
                    return(null);
                }
                if (index.Value < 0)
                {
                    return(null);
                }

                var list = ArgumentType <ScriptList>(arguments[0]);
                if (index.Value >= list.Count)
                {
                    return(null);
                }
                return(list[index.Value]);
            },
                        Arguments.Mutator(Arguments.Arg("list"), "(@list value)"),
                        Arguments.Arg("n"));


            //functions.Add("sub-list", Function.MakeSystemFunction("sub-list",
            //    Arguments.ParseArguments(this, "list list", "integer start", "integer ?length"),
            //    "list start length: Returns a elements in list between start and start+length.",
            //    (context, arguments) =>
            //    {
            //        var list = ArgumentType<ScriptList>(arguments[0]);
            //        var start = arguments[1] as int?;
            //        if (start == null || !start.HasValue) return new ScriptList();
            //        int? length = arguments[2] as int?;
            //        if (length == null || !length.HasValue) length = list.Count;

            //        if (start.Value < 0) { length -= start; start = 0; }
            //        if (start.Value >= list.Count) return new ScriptList();
            //        if (length.Value <= 0) return new ScriptList();
            //        if (length.Value + start.Value >= list.Count) length = list.Count - start.Value;

            //        return new ScriptList(list.GetRange(start.Value, length.Value));
            //    }));

            //functions.Add("sort", Function.MakeSystemFunction("sort",
            //    Arguments.ParseArguments(this, "string variable_name", "list in", "code code"),
            //    "vname list sort_func: Sorts elements according to sort func; sort func returns integer used to order items.",
            //    (context, arguments) =>
            //    {
            //        var vName = ScriptObject.AsString(arguments[0]);
            //        var list = ArgumentType<ScriptList>(arguments[1]);
            //        var sortFunc = ArgumentType<ScriptObject>(arguments[2]);

            //        var comparer = new ListSortComparer(this, vName, sortFunc, context);
            //        list.Sort(comparer);
            //        return list;
            //    }));

            //functions.Add("reverse", Function.MakeSystemFunction("reverse",
            //    Arguments.ParseArguments(this, "list list"),
            //    "list: Reverse the list.",
            //    (context, arguments) =>
            //    {
            //        var list = ArgumentType<ScriptList>(arguments[0]);
            //        list.Reverse();
            //        return list;
            //    }));

            AddFunction("reverse", "Reverse the elements of a list",
                        (context, arguments) =>
            {
                var r = AutoBind.ListArgument(arguments[0]);
                if (r == null)
                {
                    r = new ScriptList();
                }
                r.Reverse();
                return(r);
            }, Arguments.Arg("list"));

            AddFunction("array", "Create a list of items by running code N times",
                        (context, arguments) =>
            {
                var count = arguments[0] as int?;
                if (count == null || !count.HasValue)
                {
                    return(null);
                }
                var result = new ScriptList();
                for (int i = 0; i < count; ++i)
                {
                    result.Add(Evaluate(context, arguments[1], true));
                }
                return(result);
            },
                        Arguments.Arg("count"),
                        Arguments.Lazy("code"));
        }
Пример #11
0
        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();
        }
Пример #12
0
        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")));
        }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }