Beispiel #1
0
 private static object SetObjectProperty(Context context, Object obj, String name, Object value)
 {
     if (obj is ScriptObject)
     {
         try
         {
             (obj as ScriptObject)[name] = value;
         }
         catch (Exception e)
         {
             context.RaiseNewError("System Exception: " + e.Message, context.currentNode);
         }
     }
     else
     {
         var field = obj.GetType().GetField(ScriptObject.AsString(name));
         if (field != null) field.SetValue(obj, value);
         else
         {
             var prop = obj.GetType().GetProperty(ScriptObject.AsString(name));
             if (prop != null) prop.SetValue(obj, value, null);
         }
     }
     return value;
 }
Beispiel #2
0
        private Function defunImple(Context context, ScriptList arguments, bool addToScope)
        {
            var functionName = ArgumentType<String>(arguments[0]);

            List<ArgumentInfo> argumentInfo = null;
            try
            {
                argumentInfo = ArgumentInfo.ParseArguments(this, ArgumentType<ScriptList>(arguments[1]));
            }
            catch (ScriptError e)
            {
                context.RaiseNewError(e.Message, context.currentNode);
                return null;
            }

            var functionBody = ArgumentType<ParseNode>(arguments[2]);

            var newFunction = new Function(
                functionName,
                argumentInfo,
                "Script-defined function",
                functionBody,
                CopyScope(context.Scope));

            newFunction.shortHelp = ScriptObject.AsString(arguments[3]);

            if (addToScope) newFunction.declarationScope.PushVariable(newFunction.name, newFunction);

            return newFunction;
        }
Beispiel #3
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;
        }
Beispiel #4
0
        public static ScriptObject GetArgumentInfo(ScriptObject func, Context context, int index)
        {
            var arguments = func["@arguments"] as ScriptList;
            if (arguments == null) return null;

            if (index >= arguments.Count)
            {
                if (arguments.Count > 0 && (arguments[arguments.Count - 1] as ScriptObject)["@repeat"] != null)
                    return arguments[arguments.Count - 1] as ScriptObject;
                else
                {
                    context.RaiseNewError("Argument out of bounds", null);
                    return null;
                }
            }
            else
                return arguments[index] as ScriptObject;
        }
Beispiel #5
0
 private object LookupToken(Context context, String value)
 {
     //value = value.ToLowerInvariant();
     if (specialVariables.ContainsKey(value)) return specialVariables[value](context);
     if (context.Scope.HasVariable(value)) return context.Scope.GetVariable(value);
     if (functions.ContainsKey(value)) return functions[value];
     if (value.StartsWith("@") && functions.ContainsKey(value.Substring(1))) return functions[value.Substring(1)];
     context.RaiseNewError("Could not find value with name " + value + " in this context.", context.currentNode);
     return null;
 }
Beispiel #6
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);
            }
        }
Beispiel #7
0
 public Object EvaluateString(Context context, String str, String fileName, bool discardResults = false)
 {
     try
     {
         var root = Parser.ParseRoot(str, fileName);
         return Evaluate(context, root, false, discardResults);
     }
     catch (Exception e)
     {
         context.RaiseNewError("System Exception: " + e.Message, null);
         return null;
     }
 }
Beispiel #8
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;
        }
Beispiel #9
0
        private void SetupEnvironmentFunctions(Engine mispEngine)
        {
            mispEngine.AddFunction("save-environment", "", (context, arguments) =>
            {
                Engine.ReportSerializationError = (str) => Write(str + "\n");
                var file = new System.IO.StreamWriter(arguments[0].ToString());
                mispEngine.SerializeEnvironment(file, context.Scope);
                file.Close();
                return true;
            }, Arguments.Arg("file"));

            mispEngine.AddFunction("load-environment", "", (context, arguments) =>
            {
                var newContext = new Context();
                var newEngine = new Engine();

                PrepareEnvironment(newEngine);

                if (arguments[2] != null)
                {
                    newEngine.Evaluate(newContext, arguments[2], true, true);
                    if (newContext.evaluationState == EvaluationState.UnwindingError)
                    {
                        Write("Prime error:\n");
                        Write(MISP.Console.PrettyPrint2(newContext.errorObject, 0));
                        return false;
                    }
                }

                var result = newEngine.EvaluateString(newContext,
                    System.IO.File.ReadAllText(arguments[0].ToString()), arguments[0].ToString()) as ScriptObject;

                if (newContext.evaluationState != EvaluationState.UnwindingError)
                {
                    var environment = AddEnvironment(arguments[1].ToString(), newEngine, newContext);
                    if (environment.name == this.environment.name)
                        this.environment = environment;
                    SetupEnvironmentFunctions(newEngine);
                    var scope = new Scope();
                    foreach (var prop in result.ListProperties())
                        scope.PushVariable(prop as String, result.GetLocalProperty(prop as String));
                    newContext.ReplaceScope(scope);

                    Write("Loaded.\n");
                    return true;
                }
                else
                {
                    Write("Error:\n");
                    Write(MISP.Console.PrettyPrint2(newContext.errorObject, 0));
                    return false;
                }
            }, Arguments.Arg("file"), Arguments.Arg("name"), Arguments.Optional(Arguments.Lazy("prime")));
        }
Beispiel #10
0
 public void SetupNewEnvironment(String name)
 {
     var mispEngine = new Engine();
     var mispContext = new Context();
     PrepareEnvironment(mispEngine);
     var environment = AddEnvironment(name, mispEngine, mispContext);
     mispContext.limitExecutionTime = false;
 }
Beispiel #11
0
 public Environment AddEnvironment(String name, Engine engine, Context context)
 {
     environments.Upsert(name, new Environment { engine = engine, context = context, name = name });
     return environments[name];
 }
Beispiel #12
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;
        }
Beispiel #13
0
 private static Object MutateArgument(Object argument, ScriptObject argumentDescripter, Engine engine, Context context)
 {
     var mutator = argumentDescripter["@mutator"];
     if (mutator == null) return argument;
     context.Scope.PushVariable("value", argument);
     var result = engine.Evaluate(context, mutator, true);
     context.Scope.PopVariable("value");
     return result;
 }