Ink.Parsed.Story.ExportRuntime C# (CSharp) Method

ExportRuntime() public method

public ExportRuntime ( ErrorHandler errorHandler = null ) : Runtime.Story
errorHandler ErrorHandler
return Runtime.Story
        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;
		}

Usage Example

コード例 #1
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);
                }
            }
        }
All Usage Examples Of Ink.Parsed.Story::ExportRuntime