Inheritance: Parsed.Object
Exemplo n.º 1
0
        protected Parsed.Return ReturnStatement()
        {
            Whitespace ();

            var returnOrDone = Parse(Identifier);
            if (returnOrDone != "return") {
                return null;
            }

            Whitespace ();

            var expr = Parse(Expression);

            var returnObj = new Return (expr);
            return returnObj;
        }
Exemplo n.º 2
0
        public override Runtime.Object GenerateRuntimeObject()
        {
            Return foundReturn = null;

            if (isFunction)
            {
                CheckForDisallowedFunctionFlowControl();
            }

            // Non-functon: Make sure knots and stitches don't attempt to use Return statement
            else if (flowLevel == FlowLevel.Knot || flowLevel == FlowLevel.Stitch)
            {
                foundReturn = Find <Return> ();
                if (foundReturn != null)
                {
                    Error("Return statements can only be used in knots that are declared as functions: == function " + this.name + " ==", foundReturn);
                }
            }

            var container = new Runtime.Container();

            container.name = name;

            // Count visits on all knots and stitches
            container.visitsShouldBeCounted    = true;
            container.turnIndexShouldBeCounted = true;

            GenerateArgumentVariableAssignments(container);

            // Run through content defined for this knot/stitch:
            //  - First of all, any initial content before a sub-stitch
            //    or any weave content is added to the main content container
            //  - The first inner knot/stitch is automatically entered, while
            //    the others are only accessible by an explicit divert
            //       - The exception to this rule is if the knot/stitch takes
            //         parameters, in which case it can't be auto-entered.
            //  - Any Choices and Gathers (i.e. IWeavePoint) found are
            //    processsed by GenerateFlowContent.
            int contentIdx = 0;

            while (content != null && contentIdx < content.Count)
            {
                Parsed.Object obj = content [contentIdx];

                // Inner knots and stitches
                if (obj is FlowBase)
                {
                    var childFlow = (FlowBase)obj;

                    var childFlowRuntime = childFlow.runtimeObject;

                    // First inner stitch - automatically step into it
                    // 20/09/2016 - let's not auto step into knots
                    if (contentIdx == 0 && !childFlow.hasParameters &&
                        this.flowLevel == FlowLevel.Knot)
                    {
                        _startingSubFlowDivert = new Runtime.Divert();
                        container.AddContent(_startingSubFlowDivert);
                        _startingSubFlowRuntime = childFlowRuntime;
                    }

                    // Check for duplicate knots/stitches with same name
                    var namedChild = (Runtime.INamedContent)childFlowRuntime;
                    Runtime.INamedContent existingChild = null;
                    if (container.namedContent.TryGetValue(namedChild.name, out existingChild))
                    {
                        var errorMsg = string.Format("{0} already contains flow named '{1}' (at {2})",
                                                     this.GetType().Name,
                                                     namedChild.name,
                                                     (existingChild as Runtime.Object).debugMetadata);

                        Error(errorMsg, childFlow);
                    }

                    container.AddToNamedContentOnly(namedChild);
                }

                // Other content (including entire Weaves that were grouped in the constructor)
                // At the time of writing, all FlowBases have a maximum of one piece of "other content"
                // and it's always the root Weave
                else
                {
                    container.AddContent(obj.runtimeObject);
                }

                contentIdx++;
            }

            // CHECK FOR FINAL LOOSE ENDS!
            // Notes:
            //  - Functions don't need to terminate - they just implicitly return
            //  - If return statement was found, don't continue finding warnings for missing control flow,
            // since it's likely that a return statement has been used instead of a ->-> or something,
            // or the writer failed to mark the knot as a function.
            //  - _rootWeave may be null if it's a knot that only has stitches
            if (flowLevel != FlowLevel.Story && !this.isFunction && _rootWeave != null && foundReturn == null)
            {
                _rootWeave.ValidateTermination(WarningInTermination);
            }

            return(container);
        }