Exemplo n.º 1
0
 public void PostExport(Parsed.Story parsedStory, Runtime.Story runtimeStory)
 {
     foreach (var plugin in _plugins)
     {
         plugin.PostExport(parsedStory, runtimeStory);
     }
 }
 public void PostExport(Parsed.Fiction parsedFiction, Runtime.Story runtimeStory)
 {
     foreach (var plugin in _plugins)
     {
         plugin.PostExport(parsedFiction, runtimeStory);
     }
 }
Exemplo n.º 3
0
        private Runtime.Story CreateStory(Parsed.Fiction parsedFiction)
        {
            Runtime.Story runtimeStory = null;

            if (_pluginManager != null)
            {
                _pluginManager.PostParse(parsedFiction);
            }

            if (parsedFiction != null && !_hadParseError)
            {
                parsedFiction.countAllVisits = _options.countAllVisits;

                runtimeStory = parsedFiction.ExportRuntime();

                if (_pluginManager != null)
                {
                    _pluginManager.PostExport(parsedFiction, runtimeStory);
                }
            }
            else
            {
                runtimeStory = null;
            }
            return(runtimeStory);
        }
Exemplo n.º 4
0
        public Runtime.Story PostExport(Parsed.Story parsedStory, Runtime.Story runtimeStory)
        {
            object[] args = new object[] { parsedStory, runtimeStory };

            foreach (var plugin in _plugins)
            {
                typeof(IPlugin).InvokeMember("PostExport", BindingFlags.InvokeMethod, null, plugin, args);
            }

            return((Runtime.Story)args[1]);
        }
Exemplo n.º 5
0
        CommandLineTool(string[] args)
        {
            // Set console's output encoding to UTF-8
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            if (ProcessArguments(args) == false)
            {
                ExitWithUsageInstructions();
            }

            if (opts.testMode)
            {
                opts.inputFile = "test.ink";
            }

            if (opts.inputFile == null)
            {
                ExitWithUsageInstructions();
            }

            string inputString      = null;
            string workingDirectory = Directory.GetCurrentDirectory();

            if (opts.outputFile == null)
            {
                opts.outputFile = Path.ChangeExtension(opts.inputFile, ".ink.json");
            }

            if (!Path.IsPathRooted(opts.outputFile))
            {
                opts.outputFile = Path.Combine(workingDirectory, opts.outputFile);
            }

            if (opts.stressTest)
            {
                StressTestContentGenerator stressTestContent = null;
                TimeOperation("Generating test content", () => {
                    stressTestContent = new StressTestContentGenerator(100);
                });

                Console.WriteLine("Generated ~{0}k of test ink", stressTestContent.sizeInKiloChars);

                inputString = stressTestContent.content;
            }
            else
            {
                try {
                    string fullFilename = opts.inputFile;
                    if (!Path.IsPathRooted(fullFilename))
                    {
                        fullFilename = Path.Combine(workingDirectory, fullFilename);
                    }

                    // Make the working directory the directory for the root ink file,
                    // so that relative paths for INCLUDE files are correct.
                    workingDirectory = Path.GetDirectoryName(fullFilename);
                    Directory.SetCurrentDirectory(workingDirectory);

                    // Now make the input file relative to the working directory,
                    // but just getting the file's actual name.
                    opts.inputFile = Path.GetFileName(fullFilename);

                    inputString = File.ReadAllText(opts.inputFile);
                }
                catch {
                    Console.WriteLine("Could not open file '" + opts.inputFile + "'");
                    Environment.Exit(ExitCodeError);
                }
            }

            InkParser parser = null;

            Parsed.Story  parsedStory = null;
            Runtime.Story story       = null;
            errors         = new List <string> ();
            warnings       = new List <string> ();
            authorMessages = new List <string> ();
            var pluginManager = new PluginManager(pluginNames);

            var inputIsJson = opts.inputFile.EndsWith(".json");

            // Loading a normal ink file (as opposed to an already compiled json file)
            if (!inputIsJson)
            {
                TimeOperation("Creating parser", () => {
                    parser = new InkParser(inputString, opts.inputFile, OnError);
                });

                TimeOperation("Parsing", () => {
                    parsedStory = parser.Parse();
                });

                TimeOperation("PostParsePlugins", () => {
                    pluginManager.PostParse(parsedStory);
                });

                if (parsedStory != null && errors.Count == 0)
                {
                    if (opts.countAllVisits)
                    {
                        parsedStory.countAllVisits = true;
                    }

                    TimeOperation("Exporting runtime", () => {
                        story = parsedStory.ExportRuntime(OnError);
                    });

                    TimeOperation("PostParsePlugins", () => {
                        pluginManager.PostExport(parsedStory, story);
                    });
                }
            }

            // Opening up a compiled json file for playing
            else
            {
                story = new Runtime.Story(inputString);

                // No purpose for loading an already compiled file other than to play it
                opts.playMode = true;
            }

            PrintAllMessages();

            if (story == null || errors.Count > 0)
            {
                Environment.Exit(ExitCodeError);
            }

            // JSON round trip testing
            //if (opts.testMode) {
            //    var jsonStr = story.ToJsonString ();
            //    Console.WriteLine (jsonStr);

            //    Console.WriteLine ("---------------------------------------------------");

            //    var reloadedStory = new Runtime.Story (jsonStr);
            //    var newJsonStr = reloadedStory.ToJsonString ();
            //    Console.WriteLine (newJsonStr);

            //    story = reloadedStory;
            //}

            // Play mode
            // Test mode may use "-tp" in commmand line args to specify that
            // the test script is also played
            if (opts.playMode)
            {
                _playing = true;

                // Always allow ink external fallbacks
                story.allowExternalFunctionFallbacks = true;

                var player = new CommandLinePlayer(story, false, parsedStory, opts.keepOpenAfterStoryFinish);

                //Capture a CTRL+C key combo so we can restore the console's foreground color back to normal when exiting
                Console.CancelKeyPress += OnExit;

                try {
                    player.Begin();
                } catch (Runtime.StoryException e) {
                    if (e.Message.Contains("Missing function binding"))
                    {
                        OnError(e.Message, ErrorType.Error);
                        PrintAllMessages();
                    }
                    else
                    {
                        throw e;
                    }
                } catch (System.Exception e) {
                    string storyPath = "<END>";
                    var    path      = story.state.currentPath;
                    if (path != null)
                    {
                        storyPath = path.ToString();
                    }
                    throw new System.Exception(e.Message + " (Internal story path: " + storyPath + ")", e);
                }
            }

            // Compile mode
            else
            {
                var jsonStr = story.ToJsonString();

                try {
                    File.WriteAllText(opts.outputFile, jsonStr, System.Text.Encoding.UTF8);
                } catch {
                    Console.WriteLine("Could not write to output file '" + opts.outputFile + "'");
                    Environment.Exit(ExitCodeError);
                }
            }
        }
Exemplo n.º 6
0
        CommandLineTool(string[] args)
        {
            // Set console's output encoding to UTF-8
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            if (ProcessArguments(args) == false)
            {
                ExitWithUsageInstructions();
            }

            if (opts.inputFile == null)
            {
                ExitWithUsageInstructions();
            }

            string inputString      = null;
            string workingDirectory = Directory.GetCurrentDirectory();

            if (opts.outputFile == null)
            {
                opts.outputFile = Path.ChangeExtension(opts.inputFile, ".ink.json");
            }

            if (!Path.IsPathRooted(opts.outputFile))
            {
                opts.outputFile = Path.Combine(workingDirectory, opts.outputFile);
            }

            try {
                string fullFilename = opts.inputFile;
                if (!Path.IsPathRooted(fullFilename))
                {
                    fullFilename = Path.Combine(workingDirectory, fullFilename);
                }

                // Make the working directory the directory for the root ink file,
                // so that relative paths for INCLUDE files are correct.
                workingDirectory = Path.GetDirectoryName(fullFilename);
                Directory.SetCurrentDirectory(workingDirectory);

                // Now make the input file relative to the working directory,
                // but just getting the file's actual name.
                opts.inputFile = Path.GetFileName(fullFilename);

                inputString = File.ReadAllText(opts.inputFile);
            }
            catch {
                Console.WriteLine("Could not open file '" + opts.inputFile + "'");
                Environment.Exit(ExitCodeError);
            }

            var inputIsJson = opts.inputFile.EndsWith(".json", StringComparison.InvariantCultureIgnoreCase);

            if (inputIsJson && opts.stats)
            {
                Console.WriteLine("Cannot show stats for .json, only for .ink");
                Environment.Exit(ExitCodeError);
            }

            Parsed.Story  parsedStory = null;
            Runtime.Story story       = null;
            Compiler      compiler    = null;

            // Loading a normal ink file (as opposed to an already compiled json file)
            if (!inputIsJson)
            {
                compiler = new Compiler(inputString, new Compiler.Options {
                    sourceFilename = opts.inputFile,
                    pluginNames    = pluginNames,
                    countAllVisits = opts.countAllVisits,
                    errorHandler   = OnError,
                    fileHandler    = this
                });

                // Only want stats, don't need to code-gen
                if (opts.stats)
                {
                    parsedStory = compiler.Parse();

                    // Print any errors
                    PrintAllMessages();

                    // Generate stats, then print as JSON
                    var stats = Ink.Stats.Generate(compiler.parsedStory);

                    var writer = new Runtime.SimpleJson.Writer();

                    writer.WriteObjectStart();
                    writer.WriteProperty("words", stats.words);
                    writer.WriteProperty("knots", stats.knots);
                    writer.WriteProperty("stitches", stats.stitches);
                    writer.WriteProperty("functions", stats.functions);
                    writer.WriteProperty("choices", stats.choices);
                    writer.WriteProperty("gathers", stats.gathers);
                    writer.WriteProperty("diverts", stats.diverts);
                    writer.WriteObjectEnd();

                    Console.WriteLine(writer.ToString());

                    return;
                }

                // Full compile
                else
                {
                    story = compiler.Compile();
                }
            }

            // Opening up a compiled json file for playing
            else
            {
                story = new Runtime.Story(inputString);

                // No purpose for loading an already compiled file other than to play it
                opts.playMode = true;
            }

            PrintAllMessages();

            if (story == null || _errors.Count > 0)
            {
                Environment.Exit(ExitCodeError);
            }

            // Play mode
            if (opts.playMode)
            {
                _playing = true;

                // Always allow ink external fallbacks
                story.allowExternalFunctionFallbacks = true;

                var player = new CommandLinePlayer(story, false, compiler, opts.keepOpenAfterStoryFinish);

                //Capture a CTRL+C key combo so we can restore the console's foreground color back to normal when exiting
                Console.CancelKeyPress += OnExit;

                try {
                    player.Begin();
                } catch (Runtime.StoryException e) {
                    if (e.Message.Contains("Missing function binding"))
                    {
                        OnError(e.Message, ErrorType.Error);
                        PrintAllMessages();
                    }
                    else
                    {
                        throw e;
                    }
                } catch (System.Exception e) {
                    string storyPath = "<END>";
                    var    path      = story.state.currentPathString;
                    if (path != null)
                    {
                        storyPath = path.ToString();
                    }
                    throw new System.Exception(e.Message + " (Internal story path: " + storyPath + ")", e);
                }
            }

            // Compile mode
            else
            {
                var jsonStr = story.ToJson();

                try {
                    File.WriteAllText(opts.outputFile, jsonStr, System.Text.Encoding.UTF8);
                } catch {
                    Console.WriteLine("Could not write to output file '" + opts.outputFile + "'");
                    Environment.Exit(ExitCodeError);
                }
            }
        }
Exemplo n.º 7
0
        public Runtime.Story ExportRuntime(ErrorHandler errorHandler = null)
        {
            _errorHandler = errorHandler;

            // Find all constants before main export begins, so that VariableReferences know
            // whether to generate a runtime variable reference or the literal value
            constants = new Dictionary <string, Expression> ();
            foreach (var constDecl in FindAll <ConstantDeclaration> ())
            {
                // Check for duplicate definitions
                Parsed.Expression existingDefinition = null;
                if (constants.TryGetValue(constDecl.constantName, out existingDefinition))
                {
                    if (!existingDefinition.Equals(constDecl.expression))
                    {
                        var errorMsg = string.Format("CONST '{0}' has been redefined with a different value. Multiple definitions of the same CONST are valid so long as they contain the same value. Initial definition was on {1}.", constDecl.constantName, existingDefinition.debugMetadata);
                        Error(errorMsg, constDecl, isWarning: false);
                    }
                }

                constants [constDecl.constantName] = constDecl.expression;
            }

            // List definitions are treated like constants too - they should be usable
            // from other variable declarations.
            _listDefs = new Dictionary <string, ListDefinition> ();
            foreach (var listDef in FindAll <ListDefinition> ())
            {
                _listDefs [listDef.identifier?.name] = listDef;
            }

            externals = new Dictionary <string, ExternalDeclaration> ();

            // Resolution of weave point names has to come first, before any runtime code generation
            // since names have to be ready before diverts start getting created.
            // (It used to be done in the constructor for a weave, but didn't allow us to generate
            // errors when name resolution failed.)
            ResolveWeavePointNaming();

            // Get default implementation of runtimeObject, which calls ContainerBase's generation method
            var rootContainer = runtimeObject as Runtime.Container;

            // Export initialisation of global variables
            // TODO: We *could* add this as a declarative block to the story itself...
            var variableInitialisation = new Runtime.Container();

            variableInitialisation.AddContent(Runtime.ControlCommand.EvalStart());

            // Global variables are those that are local to the story and marked as global
            var runtimeLists = new List <Runtime.ListDefinition> ();

            foreach (var nameDeclPair in variableDeclarations)
            {
                var varName = nameDeclPair.Key;
                var varDecl = nameDeclPair.Value;
                if (varDecl.isGlobalDeclaration)
                {
                    if (varDecl.listDefinition != null)
                    {
                        _listDefs[varName] = varDecl.listDefinition;
                        variableInitialisation.AddContent(varDecl.listDefinition.runtimeObject);
                        runtimeLists.Add(varDecl.listDefinition.runtimeListDefinition);
                    }
                    else
                    {
                        varDecl.expression.GenerateIntoContainer(variableInitialisation);
                    }

                    var runtimeVarAss = new Runtime.VariableAssignment(varName, isNewDeclaration: true);
                    runtimeVarAss.isGlobal = true;
                    variableInitialisation.AddContent(runtimeVarAss);
                }
            }

            variableInitialisation.AddContent(Runtime.ControlCommand.EvalEnd());
            variableInitialisation.AddContent(Runtime.ControlCommand.End());

            if (variableDeclarations.Count > 0)
            {
                variableInitialisation.name = "global decl";
                rootContainer.AddToNamedContentOnly(variableInitialisation);
            }

            // Signal that it's safe to exit without error, even if there are no choices generated
            // (this only happens at the end of top level content that isn't in any particular knot)
            rootContainer.AddContent(Runtime.ControlCommand.Done());

            // Replace runtimeObject with Story object instead of the Runtime.Container generated by Parsed.ContainerBase
            var runtimeStory = new Runtime.Story(rootContainer, runtimeLists);

            runtimeObject = runtimeStory;

            if (_hadError)
            {
                return(null);
            }

            // Optimisation step - inline containers that can be
            FlattenContainersIn(rootContainer);

            // Now that the story has been fulled parsed into a hierarchy,
            // and the derived runtime hierarchy has been built, we can
            // resolve referenced symbols such as variables and paths.
            // e.g. for paths " -> knotName --> stitchName" into an INKPath (knotName.stitchName)
            // We don't make any assumptions that the INKPath follows the same
            // conventions as the script format, so we resolve to actual objects before
            // translating into an INKPath. (This also allows us to choose whether
            // we want the paths to be absolute)
            ResolveReferences(this);

            if (_hadError)
            {
                return(null);
            }

            runtimeStory.ResetState();

            return(runtimeStory);
        }
Exemplo n.º 8
0
        CommandLineTool(string[] args)
        {
            // Set console's output encoding to UTF-8
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            if (ProcessArguments (args) == false) {
                ExitWithUsageInstructions ();
            }

            if (opts.testMode) {
                opts.inputFile = "test.ink";
            }

            if (opts.inputFile == null) {
                ExitWithUsageInstructions ();
            }

            string inputString = null;
            string workingDirectory = Directory.GetCurrentDirectory();

            if (opts.outputFile == null)
                opts.outputFile = Path.ChangeExtension (opts.inputFile, ".ink.json");

            if( !Path.IsPathRooted(opts.outputFile) )
                opts.outputFile = Path.Combine (workingDirectory, opts.outputFile);

            if (opts.stressTest) {

                StressTestContentGenerator stressTestContent = null;
                TimeOperation ("Generating test content", () => {
                    stressTestContent = new StressTestContentGenerator (100);
                });

                Console.WriteLine ("Generated ~{0}k of test ink", stressTestContent.sizeInKiloChars);

                inputString = stressTestContent.content;

            } else {
                try {
                    string fullFilename = opts.inputFile;
                    if(!Path.IsPathRooted(fullFilename)) {
                        fullFilename = Path.Combine(workingDirectory, fullFilename);
                    }

                    // Make the working directory the directory for the root ink file,
                    // so that relative paths for INCLUDE files are correct.
                    workingDirectory = Path.GetDirectoryName(fullFilename);
                    Directory.SetCurrentDirectory(workingDirectory);

                    // Now make the input file relative to the working directory,
                    // but just getting the file's actual name.
                    opts.inputFile = Path.GetFileName(fullFilename);

                    inputString = File.ReadAllText(opts.inputFile);
                }
                catch {
                    Console.WriteLine ("Could not open file '" + opts.inputFile+"'");
                    Environment.Exit (ExitCodeError);
                }
            }

            InkParser parser = null;
            Parsed.Story parsedStory = null;
            Runtime.Story story = null;
            errors = new List<string> ();
            warnings = new List<string> ();
            authorMessages = new List<string> ();
            var pluginManager = new PluginManager (pluginNames);

            var inputIsJson = opts.inputFile.EndsWith (".json");

            // Loading a normal ink file (as opposed to an already compiled json file)
            if (!inputIsJson) {
                TimeOperation ("Creating parser", () => {
                    parser = new InkParser (inputString, opts.inputFile, OnError);
                });

                TimeOperation ("Parsing", () => {
                    parsedStory = parser.Parse ();
                });

                TimeOperation ("PostParsePlugins", () => {
                    pluginManager.PostParse(parsedStory);
                });

                if (parsedStory != null) {

                    if (opts.countAllVisits) {
                        parsedStory.countAllVisits = true;
                    }

                    TimeOperation ("Exporting runtime", () => {
                        story = parsedStory.ExportRuntime (OnError);
                    });

                    TimeOperation ("PostParsePlugins", () => {
                        pluginManager.PostExport(parsedStory, story);
                    });

                }

            }

            // Opening up a compiled json file for playing
            else {
                story = new Runtime.Story (inputString);

                // No purpose for loading an already compiled file other than to play it
                opts.playMode = true;
            }

            PrintAllMessages ();

            if (story == null || errors.Count > 0) {
                Environment.Exit (ExitCodeError);
            }

            // JSON round trip testing
            //            if (opts.testMode) {
            //                var jsonStr = story.ToJsonString (indented:true);
            //                Console.WriteLine (jsonStr);
            //
            //                Console.WriteLine ("---------------------------------------------------");
            //
            //                var reloadedStory = new Runtime.Story (jsonStr);
            //                var newJsonStr = reloadedStory.ToJsonString (indented: true);
            //                Console.WriteLine (newJsonStr);
            //
            //                story = reloadedStory;
            //            }

            // Play mode
            // Test mode may use "-tp" in commmand line args to specify that
            // the test script is also played
            if (opts.playMode) {

                _playing = true;

                // Always allow ink external fallbacks
                story.allowExternalFunctionFallbacks = true;

                var player = new CommandLinePlayer (story, false, parsedStory, opts.keepOpenAfterStoryFinish);

                //Capture a CTRL+C key combo so we can restore the console's foreground color back to normal when exiting
                Console.CancelKeyPress += OnExit;

                try {
                    player.Begin ();
                } catch (Runtime.StoryException e) {
                    if (e.Message.Contains ("Missing function binding")) {
                        OnError (e.Message, ErrorType.Error);
                        PrintAllMessages ();
                    } else {
                        throw e;
                    }
                }
            }

            // Compile mode
            else {

                var jsonStr = story.ToJsonString ();

                try {
                    File.WriteAllText (opts.outputFile, jsonStr, System.Text.Encoding.UTF8);
                } catch {
                    Console.WriteLine ("Could not write to output file '" + opts.outputFile+"'");
                    Environment.Exit (ExitCodeError);
                }
            }
        }
Exemplo n.º 9
0
        CommandLineTool(string[] args)
        {
            if (ProcessArguments(args) == false)
            {
                ExitWithUsageInstructions();
            }

            if (opts.testMode)
            {
                opts.inputFile = "test.ink";
            }

            if (opts.inputFile == null)
            {
                ExitWithUsageInstructions();
            }

            if (opts.outputFile == null)
            {
                opts.outputFile = Path.ChangeExtension(opts.inputFile, ".ink.json");
            }

            string inputString   = null;
            string rootDirectory = System.IO.Directory.GetCurrentDirectory();

            if (opts.workingDirectory != null)
            {
                rootDirectory = Path.GetFullPath(opts.workingDirectory);
            }

            if (opts.stressTest)
            {
                StressTestContentGenerator stressTestContent = null;
                TimeOperation("Generating test content", () => {
                    stressTestContent = new StressTestContentGenerator(100);
                });

                Console.WriteLine("Generated ~{0}k of test ink", stressTestContent.sizeInKiloChars);

                inputString = stressTestContent.content;
            }
            else
            {
                try {
                    string fullFilename = opts.inputFile;
                    if (!Path.IsPathRooted(fullFilename))
                    {
                        fullFilename = Path.Combine(rootDirectory, fullFilename);
                    }

                    inputString = File.ReadAllText(fullFilename);
                }
                catch {
                    Console.WriteLine("Could not open file '" + opts.inputFile + "'");
                    Environment.Exit(ExitCodeError);
                }
            }

            InkParser parser = null;

            Parsed.Story  parsedStory = null;
            Runtime.Story story       = null;
            errors         = new List <string> ();
            warnings       = new List <string> ();
            authorMessages = new List <string> ();
            var pluginManager = new PluginManager(pluginNames);

            var inputIsJson = opts.inputFile.EndsWith(".json");

            // Loading a normal ink file (as opposed to an already compiled json file)
            if (!inputIsJson)
            {
                TimeOperation("Creating parser", () => {
                    parser = new InkParser(inputString, opts.inputFile, rootDirectory, OnError);
                });

                TimeOperation("Parsing", () => {
                    parsedStory = parser.Parse();
                });

                TimeOperation("PostParsePlugins", () => {
                    pluginManager.PostParse(parsedStory);
                });

                if (parsedStory != null)
                {
                    if (opts.countAllVisits)
                    {
                        parsedStory.countAllVisits = true;
                    }

                    TimeOperation("Exporting runtime", () => {
                        story = parsedStory.ExportRuntime(OnError);
                    });

                    TimeOperation("PostParsePlugins", () => {
                        pluginManager.PostExport(parsedStory, story);
                    });
                }
            }

            // Opening up a compiled json file for playing
            else
            {
                story = Runtime.Story.CreateWithJson(inputString);

                // No purpose for loading an already compiled file other than to play it
                opts.playMode = true;
            }

            PrintMessages(authorMessages, ConsoleColor.Green);
            PrintMessages(warnings, ConsoleColor.Blue);
            PrintMessages(errors, ConsoleColor.Red);

            if (story == null)
            {
                Environment.Exit(ExitCodeError);
            }

            // JSON round trip testing
//            if (opts.testMode) {
//                var jsonStr = story.ToJsonString (indented:true);
//                Console.WriteLine (jsonStr);
//
//                Console.WriteLine ("---------------------------------------------------");
//
//                var reloadedStory = Runtime.Story.CreateWithJson (jsonStr);
//                var newJsonStr = reloadedStory.ToJsonString (indented: true);
//                Console.WriteLine (newJsonStr);
//
//                story = reloadedStory;
//            }

            // Play mode
            // Test mode may use "-tp" in commmand line args to specify that
            // the test script is also played
            if (opts.playMode)
            {
                // Always allow ink external fallbacks
                story.allowExternalFunctionFallbacks = true;

                var player = new CommandLinePlayer(story, false, parsedStory);
                player.Begin();
            }

            // Compile mode
            else
            {
                var jsonStr = story.ToJsonString(opts.indentedJson);

                try {
                    File.WriteAllText(opts.outputFile, jsonStr, System.Text.Encoding.UTF8);
                } catch {
                    Console.WriteLine("Could write to output file '" + opts.outputFile + "'");
                    Environment.Exit(ExitCodeError);
                }
            }
        }
Exemplo n.º 10
0
Arquivo: Story.cs Projeto: inkle/ink
        public Runtime.Story ExportRuntime(ErrorHandler errorHandler = null)
		{
            _errorHandler = errorHandler;

            // Find all constants before main export begins, so that VariableReferences know
            // whether to generate a runtime variable reference or the literal value
            constants = new Dictionary<string, Expression> ();
            foreach (var constDecl in FindAll<ConstantDeclaration> ()) {

                // Check for duplicate definitions
                Parsed.Expression existingDefinition = null;
                if (constants.TryGetValue (constDecl.constantName, out existingDefinition)) {
                    if (!existingDefinition.Equals (constDecl.expression)) {
                        var errorMsg = string.Format ("CONST '{0}' has been redefined with a different value. Multiple definitions of the same CONST are valid so long as they contain the same value. Initial definition was on {1}.", constDecl.constantName, existingDefinition.debugMetadata);
                        Error (errorMsg, constDecl, isWarning:false);
                    }
                }

                constants [constDecl.constantName] = constDecl.expression;
            }

            externals = new Dictionary<string, ExternalDeclaration> ();

			// Get default implementation of runtimeObject, which calls ContainerBase's generation method
            var rootContainer = runtimeObject as Runtime.Container;

            // Export initialisation of global variables
            // TODO: We *could* add this as a declarative block to the story itself...
            var variableInitialisation = new Runtime.Container ();
            variableInitialisation.AddContent (Runtime.ControlCommand.EvalStart ());

            // Global variables are those that are local to the story and marked as global
            foreach (var nameDeclPair in variableDeclarations) {
                var varName = nameDeclPair.Key;
                var varDecl = nameDeclPair.Value;
                if (varDecl.isGlobalDeclaration) {
                    varDecl.expression.GenerateIntoContainer (variableInitialisation);
                    var runtimeVarAss = new Runtime.VariableAssignment (varName, isNewDeclaration:true);
                    runtimeVarAss.isGlobal = true;
                    variableInitialisation.AddContent (runtimeVarAss);
                }
            }

            variableInitialisation.AddContent (Runtime.ControlCommand.EvalEnd ());
            variableInitialisation.AddContent (Runtime.ControlCommand.End ());

            if (variableDeclarations.Count > 0) {
                variableInitialisation.name = "global decl";
                rootContainer.AddToNamedContentOnly (variableInitialisation);
            }

            // Signal that it's safe to exit without error, even if there are no choices generated
            // (this only happens at the end of top level content that isn't in any particular knot)
            rootContainer.AddContent (Runtime.ControlCommand.Done ());

			// Replace runtimeObject with Story object instead of the Runtime.Container generated by Parsed.ContainerBase
            var runtimeStory = new Runtime.Story (rootContainer);
			runtimeObject = runtimeStory;

            if (hadError)
                return null;

            // Optimisation step - inline containers that can be
            FlattenContainersIn (rootContainer);

			// Now that the story has been fulled parsed into a hierarchy,
			// and the derived runtime hierarchy has been built, we can
			// resolve referenced symbols such as variables and paths.
			// e.g. for paths " -> knotName --> stitchName" into an INKPath (knotName.stitchName)
			// We don't make any assumptions that the INKPath follows the same
			// conventions as the script format, so we resolve to actual objects before
			// translating into an INKPath. (This also allows us to choose whether
			// we want the paths to be absolute)
			ResolveReferences (this);

            if (hadError)
                return null;

            runtimeStory.ResetState ();

			return runtimeStory;
		}
Exemplo n.º 11
0
        public Runtime.Story ExportRuntime(ErrorHandler errorHandler = null)
        {
            _errorHandler = errorHandler;

            // Find all constants before main export begins, so that VariableReferences know
            // whether to generate a runtime variable reference or the literal value
            constants = new Dictionary <string, Expression> ();
            foreach (var constDecl in FindAll <ConstantDeclaration> ())
            {
                constants [constDecl.constantName] = constDecl.expression;
            }

            externals = new Dictionary <string, ExternalDeclaration> ();

            // Get default implementation of runtimeObject, which calls ContainerBase's generation method
            var rootContainer = runtimeObject as Runtime.Container;

            // Export initialisation of global variables
            // TODO: We *could* add this as a declarative block to the story itself...
            var variableInitialisation = new Runtime.Container();

            variableInitialisation.AddContent(Runtime.ControlCommand.EvalStart());

            // Global variables are those that are local to the story and marked as global
            foreach (var nameDeclPair in variableDeclarations)
            {
                var varName = nameDeclPair.Key;
                var varDecl = nameDeclPair.Value;
                if (varDecl.isGlobalDeclaration)
                {
                    varDecl.expression.GenerateIntoContainer(variableInitialisation);
                    var runtimeVarAss = new Runtime.VariableAssignment(varName, isNewDeclaration: true);
                    runtimeVarAss.isGlobal = true;
                    variableInitialisation.AddContent(runtimeVarAss);
                }
            }

            variableInitialisation.AddContent(Runtime.ControlCommand.EvalEnd());
            variableInitialisation.AddContent(Runtime.ControlCommand.End());

            if (variableDeclarations.Count > 0)
            {
                variableInitialisation.name = "global decl";
                rootContainer.AddToNamedContentOnly(variableInitialisation);
            }

            // Signal that it's safe to exit without error, even if there are no choices generated
            // (this only happens at the end of top level content that isn't in any particular knot)
            rootContainer.AddContent(Runtime.ControlCommand.Done());

            // Replace runtimeObject with Story object instead of the Runtime.Container generated by Parsed.ContainerBase
            var runtimeStory = new Runtime.Story(rootContainer);

            runtimeObject = runtimeStory;

            if (hadError)
            {
                return(null);
            }

            // Now that the story has been fulled parsed into a hierarchy,
            // and the derived runtime hierarchy has been built, we can
            // resolve referenced symbols such as variables and paths.
            // e.g. for paths " -> knotName --> stitchName" into an INKPath (knotName.stitchName)
            // We don't make any assumptions that the INKPath follows the same
            // conventions as the script format, so we resolve to actual objects before
            // translating into an INKPath. (This also allows us to choose whether
            // we want the paths to be absolute)
            ResolveReferences(this);

            if (hadError)
            {
                return(null);
            }

            runtimeStory.ResetState();

            return(runtimeStory);
        }