public override Ink.Runtime.Object GenerateRuntimeObject()
        {
            ParsedFiction.AddExternal(this);

            // No runtime code exists for an external, only metadata
            return(null);
        }
Exemplo n.º 2
0
        public override Runtime.Object GenerateRuntimeObject()
        {
            var container = new Runtime.Container();

            if (content != null)
            {
                foreach (var obj in content)
                {
                    var contentObjRuntime = obj.runtimeObject;

                    // Some objects (e.g. author warnings) don't generate runtime objects
                    if (contentObjRuntime)
                    {
                        container.AddContent(contentObjRuntime);
                    }
                }
            }

            if (dontFlatten)
            {
                ParsedFiction.DontFlattenContainer(container);
            }

            return(container);
        }
Exemplo n.º 3
0
        public override void GenerateIntoContainer(Runtime.Container container)
        {
            var runtimeRawList = new Runtime.InkList();

            if (itemNameList != null)
            {
                foreach (var itemName in itemNameList)
                {
                    var nameParts = itemName.Split('.');

                    string listName     = null;
                    string listItemName = null;
                    if (nameParts.Length > 1)
                    {
                        listName     = nameParts [0];
                        listItemName = nameParts [1];
                    }
                    else
                    {
                        listItemName = nameParts [0];
                    }

                    var listItem = ParsedFiction.ResolveListItem(listName, listItemName, this);
                    if (listItem == null)
                    {
                        if (listName == null)
                        {
                            Error("Could not find list definition that contains item '" + itemName + "'");
                        }
                        else
                        {
                            Error("Could not find list item " + itemName);
                        }
                    }
                    else
                    {
                        if (listName == null)
                        {
                            listName = ((ListDefinition)listItem.parent).name;
                        }
                        var item = new Runtime.InkListItem(listName, listItem.name);

                        if (runtimeRawList.ContainsKey(item))
                        {
                            Warning("Duplicate of item '" + itemName + "' in list.");
                        }
                        else
                        {
                            runtimeRawList [item] = listItem.seriesValue;
                        }
                    }
                }
            }

            container.AddContent(new Runtime.ListValue(runtimeRawList));
        }
        public override void GenerateIntoContainer(Runtime.Container container)
        {
            Expression constantValue = null;

            // If it's a constant reference, just generate the literal expression value
            // It's okay to access the constants at code generation time, since the
            // first thing the ExportRuntime function does it search for all the constants
            // in the story hierarchy, so they're all available.
            if (ParsedFiction.constants.TryGetValue(name, out constantValue))
            {
                constantValue.GenerateConstantIntoContainer(container);
                isConstantReference = true;
                return;
            }

            _runtimeVarRef = new Runtime.VariableReference(name);

            // List item reference?
            // Path might be to a list (listName.listItemName or just listItemName)
            if (path.Count == 1 || path.Count == 2)
            {
                string listItemName = null;
                string listName     = null;

                if (path.Count == 1)
                {
                    listItemName = path [0];
                }
                else
                {
                    listName     = path [0];
                    listItemName = path [1];
                }

                var listItem = ParsedFiction.ResolveListItem(listName, listItemName, this);
                if (listItem)
                {
                    isListItemReference = true;
                }
            }

            container.AddContent(_runtimeVarRef);
        }
        public override void GenerateIntoContainer(Runtime.Container container)
        {
            var foundList = ParsedFiction.ResolveList(name);

            bool usingProxyDivert = false;

            if (isChoiceCount)
            {
                if (arguments.Count > 0)
                {
                    Error("The CHOICE_COUNT() function shouldn't take any arguments");
                }

                container.AddContent(Runtime.ControlCommand.ChoiceCount());
            }
            else if (isTurns)
            {
                if (arguments.Count > 0)
                {
                    Error("The TURNS() function shouldn't take any arguments");
                }

                container.AddContent(Runtime.ControlCommand.Turns());
            }
            else if (isTurnsSince || isReadCount)
            {
                var divertTarget         = arguments [0] as DivertTarget;
                var variableDivertTarget = arguments [0] as VariableReference;

                if (arguments.Count != 1 || (divertTarget == null && variableDivertTarget == null))
                {
                    Error("The " + name + "() function should take one argument: a divert target to the target knot, stitch, gather or choice you want to check. e.g. TURNS_SINCE(-> myKnot)");
                    return;
                }

                if (divertTarget)
                {
                    _divertTargetToCount = divertTarget;
                    AddContent(_divertTargetToCount);

                    _divertTargetToCount.GenerateIntoContainer(container);
                }
                else
                {
                    _variableReferenceToCount = variableDivertTarget;
                    AddContent(_variableReferenceToCount);

                    _variableReferenceToCount.GenerateIntoContainer(container);
                }

                if (isTurnsSince)
                {
                    container.AddContent(Runtime.ControlCommand.TurnsSince());
                }
                else
                {
                    container.AddContent(Runtime.ControlCommand.ReadCount());
                }
            }
            else if (isRandom)
            {
                if (arguments.Count != 2)
                {
                    Error("RANDOM should take 2 parameters: a minimum and a maximum integer");
                }

                // We can type check single values, but not complex expressions
                for (int arg = 0; arg < arguments.Count; arg++)
                {
                    if (arguments [arg] is Number)
                    {
                        var num = arguments [arg] as Number;
                        if (!(num.value is int))
                        {
                            string paramName = arg == 0 ? "minimum" : "maximum";
                            Error("RANDOM's " + paramName + " parameter should be an integer");
                        }
                    }

                    arguments [arg].GenerateIntoContainer(container);
                }

                container.AddContent(Runtime.ControlCommand.Random());
            }
            else if (isSeedRandom)
            {
                if (arguments.Count != 1)
                {
                    Error("SEED_RANDOM should take 1 parameter - an integer seed");
                }

                var num = arguments [0] as Number;
                if (num && !(num.value is int))
                {
                    Error("SEED_RANDOM's parameter should be an integer seed");
                }

                arguments [0].GenerateIntoContainer(container);

                container.AddContent(Runtime.ControlCommand.SeedRandom());
            }
            else if (isListRange)
            {
                if (arguments.Count != 3)
                {
                    Error("LIST_RANGE should take 3 parameters - a list, a min and a max");
                }

                for (int arg = 0; arg < arguments.Count; arg++)
                {
                    arguments [arg].GenerateIntoContainer(container);
                }

                container.AddContent(Runtime.ControlCommand.ListRange());
            }
            else if (isListRandom)
            {
                if (arguments.Count != 1)
                {
                    Error("LIST_RANDOM should take 1 parameter - a list");
                }

                arguments [0].GenerateIntoContainer(container);

                container.AddContent(Runtime.ControlCommand.ListRandom());
            }
            else if (Runtime.NativeFunctionCall.CallExistsWithName(name))
            {
                var nativeCall = Runtime.NativeFunctionCall.CallWithName(name);

                if (nativeCall.numberOfParameters != arguments.Count)
                {
                    var msg = name + " should take " + nativeCall.numberOfParameters + " parameter";
                    if (nativeCall.numberOfParameters > 1)
                    {
                        msg += "s";
                    }
                    Error(msg);
                }

                for (int arg = 0; arg < arguments.Count; arg++)
                {
                    arguments [arg].GenerateIntoContainer(container);
                }

                container.AddContent(Runtime.NativeFunctionCall.CallWithName(name));
            }
            else if (foundList != null)
            {
                if (arguments.Count > 1)
                {
                    Error("Can currently only construct a list from one integer (or an empty list from a given list definition)");
                }

                // List item from given int
                if (arguments.Count == 1)
                {
                    container.AddContent(new Runtime.StringValue(name));
                    arguments [0].GenerateIntoContainer(container);
                    container.AddContent(Runtime.ControlCommand.ListFromInt());
                }

                // Empty list with given origin.
                else
                {
                    var list = new Runtime.InkList();
                    list.SetInitialOriginName(name);
                    container.AddContent(new Runtime.ListValue(list));
                }
            }

            // Normal function call
            else
            {
                container.AddContent(_proxyDivert.runtimeObject);
                usingProxyDivert = true;
            }

            // Don't attempt to resolve as a divert if we're not doing a normal function call
            if (!usingProxyDivert)
            {
                content.Remove(_proxyDivert);
            }

            // Function calls that are used alone on a tilda-based line:
            //  ~ func()
            // Should tidy up any returned value from the evaluation stack,
            // since it's unused.
            if (shouldPopReturnedValue)
            {
                container.AddContent(Runtime.ControlCommand.PopEvaluatedValue());
            }
        }