Beispiel #1
0
        /// <summary>
        /// Loads a script from disk.
        /// Returns null if the script does not exist.
        /// </summary>
        /// <param name="path">The path to the script, including the filename but not the extension.</param>
        /// <returns></returns>
        public static PythonScript Load(string path)
        {
            var scriptFilename = Path.Combine(path + ".script");
            var pythonFilename = Path.Combine(path + ".py");
            var moduleName     = Path.GetFileName(path);

            if (!File.Exists(pythonFilename))
            {
                return(null);
            }
            var text            = File.ReadAllText(pythonFilename);
            var externalScripts = new List <PythonScript>();

            if (File.Exists(scriptFilename))
            {
                foreach (var externalScriptPath in File.ReadAllLines(scriptFilename))
                {
                    var externalScript = PythonScript.Load(externalScriptPath);
                    if (externalScript == null)
                    {
                        throw new ScriptException("Cannot find script file: " + Path.GetFullPath(externalScriptPath + ".py"));
                    }
                    externalScripts.Add(externalScript);
                }
            }
            return(new PythonScript(moduleName, text, externalScripts.ToArray()));
        }
Beispiel #2
0
 /// <summary>
 /// Compiles and caches a script, or returns the cached script if it exists.
 /// </summary>
 /// <param name="source">The script to search for.</param>
 /// <returns>The compiled code.</returns>
 private static CompiledCode GetCompiledScript(PythonScript source)
 {
     if (!compiledScripts.ContainsKey(source))
     {
         compiledScripts.Add(source, Compile(source));
     }
     return(compiledScripts[source]);
 }
Beispiel #3
0
        /// <summary>
        /// Calls a script function.
        /// </summary>
        /// <param name="script">The script containing the function.</param>
        /// <param name="function">The name of the function.</param>
        /// <param name="args">Arguments to pass to the function.</param>
        /// <returns>The return value.</returns>
        public static T CallFunction <T>(PythonScript script, string function, params object[] args)
        {
            var preCode = new List <string>();

            preCode.Add("from FrEee.Modding import Mod;");
            preCode.Add("if not galaxy is None:");
            preCode.Add("\tMod.Current = galaxy.Mod;");
            var arglist = new List <string>();

            for (var i = 0; i < args.Length; i++)
            {
                arglist.Add("arg" + i);
            }
            var code           = string.Join("\n", preCode.ToArray()) + "\n" + script.ModuleName + "." + function + "(" + string.Join(", ", arglist) + ")";
            var variables      = args.ToDictionary(arg => "arg" + args.IndexOf(arg));
            var sc             = new ScriptCode("functionCall", code, new PythonScript[] { script }.Concat(script.ExternalScripts).ToArray());
            var functionCall   = GetCodeScript(sc);
            var compiledScript = GetCompiledScript(functionCall);

            UpdateScope(variables);
            try
            {
                return(compiledScript.Execute <T>(scope));
            }
            catch (Exception ex)
            {
                if (ex.Data.Values.Count > 0)
                {
                    dynamic info      = ex.Data.Values.Cast <dynamic>().First();
                    var     debugInfo = info[0].DebugInfo;
                    if (debugInfo != null)
                    {
                        int startLine = debugInfo.StartLine;
                        int endLine   = debugInfo.StartLine;
                        throw new ScriptException(ex, string.Join("\n", functionCall.FullText.Split('\n').Skip(startLine - 1).Take(endLine - startLine + 1).ToArray()));
                    }
                    else
                    {
                        throw new ScriptException(ex, "(unknown code)");
                    }
                }
                else
                {
                    throw new ScriptException(ex, "(unknown code)");
                }
            }
        }
Beispiel #4
0
        public ObjectFormula <T> CreateReferenceEnumerableFormula <T>(object context)
            where T : IReferenceEnumerable
        {
            var typename = typeof(T).Name;

            if (typename.Contains("`"))
            {
                typename = typename.Substring(0, typename.IndexOf('`'));
            }
            var f       = new ObjectFormula <T>($"{typename}[{string.Join(", ", typeof(T).GetGenericArguments().Select(x => x.Name).ToArray())}]({Value.TrimStart('=')})", context, true);
            var import  = $"from {typeof(T).Namespace} import {typename};";
            var imports = new List <string>();

            imports.Add(import);
            foreach (var genparm in typeof(T).GetGenericArguments())
            {
                var typename2 = genparm.Name;
                if (typename2.Contains("`"))
                {
                    typename2 = typename.Substring(0, typename2.IndexOf('`'));
                }
                imports.Add($"from {genparm.Namespace} import {typename2};");
            }
            var script = new PythonScript("Import", string.Join("\n", imports));

            if (f.ExternalScripts == null)
            {
                f.ExternalScripts = new PythonScript[] { script }
            }
            ;
            else
            {
                f.ExternalScripts = f.ExternalScripts.Append(script).ToArray();
            }
            return(f);
        }
Beispiel #5
0
        /// <summary>
        /// Runs a script.
        /// </summary>
        /// <param name="script">The script code to run.</param>
        /// <param name="variables">Read/write variables to inject into the script.</param>
        /// <param name="readOnlyVariables">Read-only variables to inject into the script.</param>
        public static void RunScript(PythonScript script, IDictionary <string, object> variables = null, IDictionary <string, object> readOnlyVariables = null)
        {
            var preCommands  = new List <string>();
            var postCommands = new List <string>();

            preCommands.Add("import clr");
            preCommands.Add("clr.AddReference('System.Core')");
            preCommands.Add("import System");
            preCommands.Add("clr.ImportExtensions(System.Linq)");
            preCommands.Add("clr.AddReference('FrEee.Core')");
            preCommands.Add("import FrEee");
            preCommands.Add("import FrEee.Utility");
            preCommands.Add("clr.ImportExtensions(FrEee.Utility.Extensions)");
            preCommands.Add("from FrEee.Modding import Mod");
            preCommands.Add("from FrEee.Game.Objects.Space import Galaxy");
            preCommands.Add("from FrEee.Game.Objects.Civilization import Empire");
            var code =
                string.Join("\n", preCommands.ToArray()) + "\n" +
                script.Text + "\n" +
                string.Join("\n", postCommands.ToArray());
            var external = new List <PythonScript>(script.ExternalScripts);

            if (Mod.Current != null)
            {
                external.Add(Mod.Current.GlobalScript);
            }
            var sc             = new ScriptCode("runner", code, external.ToArray());
            var runner         = GetCodeScript(sc);
            var compiledScript = GetCompiledScript(runner);
            var allVariables   = new Dictionary <string, object>();

            if (variables != null)
            {
                foreach (var v in variables)
                {
                    allVariables.Add(v.Key, v.Value);
                }
            }
            if (readOnlyVariables != null)
            {
                foreach (var v in readOnlyVariables)
                {
                    allVariables.Add(v.Key, v.Value);
                }
            }
            UpdateScope(allVariables);
            try
            {
                compiledScript.Execute(scope);
                if (variables != null)
                {
                    var newvals = RetrieveVariablesFromScope(scope, variables.Keys);
                    foreach (var kvp in variables)
                    {
                        newvals[kvp.Key].CopyTo(kvp.Value);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex.Data.Values.Count > 0)
                {
                    Array info      = ex.Data.Values.Cast <dynamic>().First();
                    var   debugInfo = info.Cast <dynamic>().FirstOrDefault(o => o.DebugInfo != null)?.DebugInfo;
                    if (debugInfo != null)
                    {
                        int startLine = debugInfo.StartLine;
                        int endLine   = debugInfo.StartLine;
                        throw new ScriptException(ex, string.Join("\n", runner.FullText.Split('\n').Skip(startLine - 1).Take(endLine - startLine + 1).ToArray()));
                    }
                    else
                    {
                        throw new ScriptException(ex, "(unknown code)");
                    }
                }
                else
                {
                    throw new ScriptException(ex, "(unknown code)");
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Evaluates a script expression.
        /// </summary>
        /// <param name="expression">The script code to run.</param>
        /// <param name="readOnlyVariables">Variables to inject into the script.</param>
        /// <returns>Any .</returns>
        public static T EvaluateExpression <T>(string expression, IDictionary <string, object> readOnlyVariables = null)
        {
            var script = new PythonScript("expression", expression);

            return(RunScript <T>(script, null, readOnlyVariables));
        }
Beispiel #7
0
        /// <summary>
        /// Compiles a script.
        /// </summary>
        /// <returns></returns>
        public static CompiledCode Compile(PythonScript script)
        {
            var compiledScript = engine.CreateScriptSourceFromString(script.FullText);

            return(compiledScript.Compile());
        }