Пример #1
0
        public static ScriptObject ParseChar(ParseState state)
        {
            var result = new GenericScriptObject("@type", "char", "@start", state.start, "@source", state);
            var token = "";

            state.Advance(); //skip opening '
            while (!state.AtEnd())
            {
                if (state.Next() == '\\')
                {
                    state.Advance();
                    if (state.Next() == 'n') token += "\n";
                    if (state.Next() == 't') token += "\t";
                    if (state.Next() == 'r') token += "\r";
                    else token += state.Next();
                }
                else if (state.Next() == '\'')
                {
                    result["@end"] = state.start;
                    result["@token"] = token;
                    state.Advance();
                    return result;
                }
                else
                {
                    token += state.Next();
                    state.Advance();
                }
            }

            result["@end"] = state.start;
            result["@token"] = token;
            return result;
        }
Пример #2
0
        public static GenericScriptObject BindXNAMath()
        {
            var xna = new GenericScriptObject();

            xna.SetProperty("v", Function.MakeSystemFunction("Vector3",
                Arguments.Args("x", "y", "z", Arguments.Optional("w")), "Create a new vector.",
                (context, arguments) =>
                {
                    if (arguments[3] == null)
                        return new Vector3(AutoBind.NumericArgument(arguments[0]),
                            AutoBind.NumericArgument(arguments[1]),
                            AutoBind.NumericArgument(arguments[2]));
                    else
                        return new Vector4(AutoBind.NumericArgument(arguments[0]),
                            AutoBind.NumericArgument(arguments[1]),
                            AutoBind.NumericArgument(arguments[2]),
                            AutoBind.NumericArgument(arguments[3]));
                }));

            xna.SetProperty("helper", AutoBind.GenerateLazyBindingObjectForStaticLibrary(typeof(MathHelper)));
            xna.SetProperty("matrix", AutoBind.GenerateLazyBindingObjectForStaticLibrary(typeof(Matrix)));
            xna.SetProperty("quat", AutoBind.GenerateLazyBindingObjectForStaticLibrary(typeof(Quaternion)));
            xna.SetProperty("v2", AutoBind.GenerateLazyBindingObjectForStaticLibrary(typeof(Vector2), true));
            xna.SetProperty("v3", AutoBind.GenerateLazyBindingObjectForStaticLibrary(typeof(Vector3), true));
            xna.SetProperty("v4", AutoBind.GenerateLazyBindingObjectForStaticLibrary(typeof(Vector4), true));
            xna.SetProperty("rect", AutoBind.GenerateLazyBindingObjectForStaticLibrary(typeof(Rectangle), true));

            return xna;
        }
Пример #3
0
        public static ScriptObject GenerateTypeBinding(System.Type type)
        {
            var r = new GenericScriptObject();

            r.SetProperty("@construct", Function.MakeSystemFunction("@construct",
                                                                    Arguments.Args(Arguments.Optional(Arguments.Repeat("argument"))),
                                                                    "Create a new instance of " + type.Name,
                                                                    (context, arguments) =>
            {
                return(Activator.CreateInstance(type, (arguments[0] as ScriptList).ToArray()));
            }));

            foreach (var method in type.GetMethods())
            {
                if (method.IsPublic)
                {
                    r.SetProperty(method.Name, GenerateMethodBinding(method));
                }
            }

            return(r);
        }
Пример #4
0
        public static MISP.GenericScriptObject GenerateBinding()
        {
            var gui = new MISP.GenericScriptObject();

            gui["create"] = MISP.Function.MakeSystemFunction("create", MISP.Arguments.Args(
                MISP.Arguments.Arg("type"), Arguments.Arg("rect"), Arguments.Arg("settings"), Arguments.Optional("hover")),
                "Create a ui element.",
                (context, arguments) =>
                {
                    var type = ScriptObject.AsString(arguments[0]);
                    var rect = arguments[1] as Rectangle?;
                    if (rect == null || !rect.HasValue) throw new InvalidOperationException("Second argument must be a rect.");
                    UIItem result = null;
                    if (type == "item") result = new UIItem(rect.Value);
                    else if (type == "slider") result = new VerticalSlider(rect.Value);
                    else throw new InvalidOperationException("Unknown element type.");
                    result.settings = arguments[2] as ScriptObject;
                    result.hoverSettings = arguments[3] as ScriptObject;
                    return result;
                });

            return gui;
        }
Пример #5
0
        public static ScriptObject GenerateLazyBindingObjectForStaticLibrary(System.Type type, bool generateConstructor = false)
        {
            var r = new GenericScriptObject();

            if (generateConstructor)
            {
                r.SetProperty("@construct", Function.MakeSystemFunction("@construct",
                                                                        Arguments.Args(Arguments.Optional(Arguments.Repeat("argument"))),
                                                                        "Create a new instance of " + type.Name,
                                                                        (context, arguments) =>
                {
                    return(Activator.CreateInstance(type, (arguments[0] as ScriptList).ToArray()));
                }));
            }

            foreach (var method in type.GetMethods())
            {
                if (method.IsPublic && method.IsStatic)
                {
                    r.SetProperty(TransformMethodName(method.Name), LazyBindStaticMethod(type, method.Name));
                }
            }
            return(r);
        }
Пример #6
0
        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;
        }
Пример #7
0
 public static ScriptObject ParseToken(ParseState state)
 {
     var result = new GenericScriptObject("@type", "token", "@start", state.start, "@source", state);
     while (!state.AtEnd() && !(" \t\r\n:.)]}".Contains(state.Next()))) state.Advance();
     result["@end"] = state.start;
     result["@token"] = state.source.Substring(asInt(result["@start"]),
         asInt(result["@end"]) - asInt(result["@start"]));
     if (String.IsNullOrEmpty(result.gsp("@token"))) throw new ParseError("Empty token", state.currentLine);
     return result;
 }
Пример #8
0
        public static ScriptObject ParseStringExpression(ParseState state, bool isRoot = false)
        {
            var result = new GenericScriptObject("@type", "stringexpression", "@start", state.start, "@source", state);
            if (!isRoot) state.Advance(); //Skip opening quote
            string piece = "";
            int piece_start = state.start;
            while (!state.AtEnd())
            {
                if (state.Next() == '}' && piece.Length == 0)
                {
                    state.Advance(1);
                }
                else if (state.Next() == '(')
                {
                    if (piece.Length > 0) children(result).Add(
                        new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                            "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    children(result).Add(ParseNode(state));
                    piece = "";
                }
                else if (state.Next() == '\\')
                {
                    if (piece.Length == 0) piece_start = state.start;
                    state.Advance(); //skip the slash.
                    piece += state.Next();
                    state.Advance();
                }
                else if (!isRoot && state.Next() == '"')
                {
                    if (piece.Length > 0) children(result).Add(
                        new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                            "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    state.Advance();
                    result["@end"] = state.start;
                    if (children(result).Count == 1 && isType(children(result)[0] as ScriptObject, "string"))
                        return child(result, 0) as ScriptObject;
                    return result;
                }
                else
                {
                    if (piece.Length == 0) piece_start = state.start;
                    piece += state.Next();
                    state.Advance();
                }

            }

            if (isRoot)
            {
                if (piece.Length > 0) children(result).Add(new GenericScriptObject("@type", "string", "@start", piece_start,
                    "@source", state, "@token", state.source.Substring(piece_start, state.start - piece_start)));
                if (children(result).Count == 1) return child(result, 0) as ScriptObject;
                return result;
            }

            throw new ParseError("Unexpected end of script inside string expression.", state.currentLine);
        }
Пример #9
0
        public static ScriptObject ParseNumber(ParseState state)
        {
            var result = new GenericScriptObject("@type", "number", "@start", state.start, "@source", state);
            bool foundDot = false;

            while (!state.AtEnd())
            {
                if (state.Next() == '-')
                {
                    if (asInt(result["@start"]) != state.start) break;
                    state.Advance();
                    continue;
                }
                if (state.Next() >= '0' && state.Next() <= '9')
                {
                    state.Advance();
                    continue;
                }
                else if (state.Next() == '.')
                {
                    if (foundDot) break;
                    foundDot = true;
                    state.Advance();
                    continue;
                }
                break;
            }

            result["@end"] = state.start;
            result["@token"] = state.source.Substring(asInt(result["@start"]), asInt(result["@end"]) - asInt(result["@start"]));
            return result;
        }
Пример #10
0
 public static ScriptObject ParseNode(ParseState state, String start = "(", String end = ")")
 {
     var result = new GenericScriptObject("@type", "node", "@start", state.start, "@source", state);
     if (!state.MatchNext(start)) throw new ParseError("Expected " + start, state.currentLine);
     state.Advance(start.Length);
     while (!state.AtEnd() && !state.MatchNext(end))
     {
         DevourWhitespace(state);
         if (state.Next() == '}')
             return result;
         if (!state.AtEnd() && !state.MatchNext(end))
         {
             var expression = ParseExpression(state);
             if (isType(expression, "memberaccess")) expression = ReorderMemberAccessNode(expression);
             children(result).Add(expression);
         }
         DevourWhitespace(state);
     }
     if (end != null) state.Advance(end.Length);
     return result;
 }
Пример #11
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);
        }
Пример #12
0
        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"));
        }
Пример #13
0
        public static ScriptObject ParseExpression(ParseState state)
        {
            ScriptObject result = null;
            var          prefix = ParsePrefix(state);

            if (state.Next() == '"')
            {
                if (prefix == "$")
                {
                    prefix = "";
                    result = ParseBasicString(state);
                }
                else
                {
                    result = ParseStringExpression(state);
                }
            }
            else if (state.Next() == '(')
            {
                result = ParseNode(state);
            }
            else if (state.Next() == '\'')
            {
                result = ParseChar(state);
            }
            else if ("-0123456789".Contains(state.Next()))
            {
                result = ParseNumber(state);
                if (result["@token"].ToString() == "-") //A lone - sign is not a valid number. Interpret it as a token.
                {
                    result["@type"] = "token";
                }
            }
            else
            {
                if (" \t\r\n:.)}".Contains(state.Next()) &&
                    !String.IsNullOrEmpty(prefix))
                {
                    //The prefix is a token.
                    result           = new GenericScriptObject("@type", "token", "@start", state.start - 1, "@source", state);
                    result["@end"]   = state.start;
                    result["@token"] = prefix;
                    prefix           = "";
                }
                else
                {
                    result = ParseToken(state);
                }
            }

            if (!state.AtEnd() && (state.Next() == '.' || state.Next() == ':'))
            {
                var final_result = new GenericScriptObject("@type", "memberaccess", "@start", result["@start"],
                                                           "@source", state);
                children(final_result).Add(result);
                final_result["@token"] = new String(state.Next(), 1);
                state.Advance();
                children(final_result).Add(ParseExpression(state));
                result = final_result;
            }

            result["@prefix"] = prefix;
            if (!PrefixCheck.CheckPrefix(result))
            {
                throw new ParseError("Illegal prefix on expression of type " + result["@type"], state.currentLine);
            }
            return(result);
        }
Пример #14
0
        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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        public static ScriptObject ParseExpression(ParseState state)
        {
            ScriptObject result = null;
            var prefix = ParsePrefix(state);
            if (state.Next() == '"')
            {
                result = ParseStringExpression(state);
            }
            else if (state.Next() == '(')
            {
                result = ParseNode(state);
            }
            else if (state.Next() == '\'')
            {
                result = ParseChar(state);
            }
            else if ("-0123456789".Contains(state.Next()))
            {
                result = ParseNumber(state);
                if (result["@token"].ToString() == "-") //A lone - sign is not a valid number. Interpret it as a token.
                    result["@type"] = "token";
            }
            else
            {
                if (" \t\r\n:.)}".Contains(state.Next())
                    && !String.IsNullOrEmpty(prefix))
                {
                    //The prefix is a token.
                    result = new GenericScriptObject("@type", "token", "@start", state.start - 1, "@source", state);
                    result["@end"] = state.start;
                    result["@token"] = prefix;
                    prefix = "";
                }
                else
                    result = ParseToken(state);
            }

            if (!state.AtEnd() && (state.Next() == '.' || state.Next() == ':'))
            {
                var final_result = new GenericScriptObject("@type", "memberaccess", "@start", result["@start"],
                    "@source", state);
                children(final_result).Add(result);
                final_result["@token"] = new String(state.Next(), 1);
                state.Advance();
                children(final_result).Add(ParseExpression(state));
                result = final_result;
            }

            result["@prefix"] = prefix;
            if (!PrefixCheck.CheckPrefix(result))
                throw new ParseError("Illegal prefix on expression of type " + result["@type"], state.currentLine);
            return result;
        }
Пример #17
0
        public static ScriptObject ParseStringExpression(ParseState state, bool isRoot = false)
        {
            var result = new GenericScriptObject("@type", "stringexpression", "@start", state.start, "@source", state);

            if (!isRoot)
            {
                state.Advance();          //Skip opening quote
            }
            string piece       = "";
            int    piece_start = state.start;

            while (!state.AtEnd())
            {
                if (state.Next() == '}' && piece.Length == 0)
                {
                    state.Advance(1);
                }
                else if (state.Next() == '(')
                {
                    if (piece.Length > 0)
                    {
                        children(result).Add(
                            new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                                                    "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    }
                    children(result).Add(ParseNode(state));
                    piece = "";
                }
                else if (state.Next() == '\\')
                {
                    if (piece.Length == 0)
                    {
                        piece_start = state.start;
                    }
                    state.Advance(); //skip the slash.
                    piece += state.Next();
                    state.Advance();
                }
                else if (!isRoot && state.Next() == '"')
                {
                    if (piece.Length > 0)
                    {
                        children(result).Add(
                            new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                                                    "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    }
                    state.Advance();
                    result["@end"] = state.start;
                    if (children(result).Count == 1 && isType(children(result)[0] as ScriptObject, "string"))
                    {
                        return(child(result, 0) as ScriptObject);
                    }
                    return(result);
                }
                else
                {
                    if (piece.Length == 0)
                    {
                        piece_start = state.start;
                    }
                    piece += state.Next();
                    state.Advance();
                }
            }

            if (isRoot)
            {
                if (piece.Length > 0)
                {
                    children(result).Add(new GenericScriptObject("@type", "string", "@start", piece_start,
                                                                 "@source", state, "@token", state.source.Substring(piece_start, state.start - piece_start)));
                }
                if (children(result).Count == 1)
                {
                    return(child(result, 0) as ScriptObject);
                }
                return(result);
            }

            throw new ParseError("Unexpected end of script inside string expression.", state.currentLine);
        }
Пример #18
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 result = Convert.ToInt32(node.gsp("@token"));
                }
                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;
        }
Пример #19
0
        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"));
        }