Example #1
0
        override public void GetSource(TranslateRule context, Element element, Location location)
        {
            ElementOrigin origin = ElementOrigin.GetElementOrigin(element);

            if (origin == null)
            {
                throw new SyntaxErrorException("Could not get the type source.", location);
            }

            IndexedVar typeVar = origin.OriginVar(context.VarCollection, null, Name + " origin");

            typeVar.Type          = this;
            element.SupportedType = typeVar;
        }
        void ParseStatement(ScopeGroup getter, ScopeGroup scope, Node statement, IndexedVar returnVar)
        {
            switch (statement)
            {
            // Method
            case MethodNode methodNode:
                Element method = ParseMethod(getter, scope, methodNode, false);
                return;

            // Variable set
            case VarSetNode varSetNode:
                ParseVarset(getter, scope, varSetNode);
                return;

            // Foreach
            case ForEachNode forEachNode:
            {
                ContinueSkip.Setup();

                ScopeGroup forGroup = scope.Child();

                Element array = ParseExpression(getter, scope, forEachNode.Array);

                IndexedVar index = IndexedVar.AssignInternalVarExt(VarCollection, scope, $"'{forEachNode.Variable.VariableName}' for index", IsGlobal);

                int offset = 0;

                Element getVariableReference()
                {
                    return(Element.Part <V_ValueInArray>(array, indexer()));
                }

                Element indexer()
                {
                    if (offset == 0)
                    {
                        return(index.GetVariable());
                    }
                    else
                    {
                        return(index.GetVariable() + getOffset());
                    }
                }

                V_Number getOffset()
                {
                    return(new V_Number(offset));
                }

                IndexedVar    arrayVar = null;
                ElementOrigin origin   = ElementOrigin.GetElementOrigin(array);
                if (origin == null && forEachNode.Variable.Type != null)
                {
                    throw new SyntaxErrorException("Could not get the type source.", forEachNode.Variable.Location);
                }
                if (origin != null)
                {
                    arrayVar = origin.OriginVar(VarCollection, null, null);
                }

                // Reset the counter.
                Actions.AddRange(index.SetVariable(0));

                // The action the for loop starts on.
                int forStartIndex = ContinueSkip.GetSkipCount();

                A_SkipIf skipCondition = new A_SkipIf()
                {
                    ParameterValues = new IWorkshopTree[2]
                };
                skipCondition.ParameterValues[0] =
                    !(index.GetVariable() < Element.Part <V_CountOf>(array)
                      );
                Actions.Add(skipCondition);

                List <A_SkipIf> rangeSkips = new List <A_SkipIf>();
                for (; offset < forEachNode.Repeaters; offset++)
                {
                    if (offset > 0)
                    {
                        //variable.Reference = getVariableReference();

                        A_SkipIf skipper = new A_SkipIf()
                        {
                            ParameterValues = new Element[2]
                        };
                        skipper.ParameterValues[0] = !(
                            index.GetVariable() + getOffset() < Element.Part <V_CountOf>(array)
                            );
                        rangeSkips.Add(skipper);
                        Actions.Add(skipper);
                    }

                    // Parse the for's block. Use a child to prevent conflicts with repeaters.
                    ScopeGroup tempChild = forGroup.Child();

                    Var variable;
                    if (arrayVar != null)
                    {
                        variable = arrayVar.CreateChild(tempChild, forEachNode.Variable.VariableName, new Element[] { indexer() }, forEachNode.Variable);
                        if (forEachNode.Variable.Type != null)
                        {
                            variable.Type = ParserData.GetDefinedType(forEachNode.Variable.Type, forEachNode.Variable.Location);
                        }
                    }
                    else
                    {
                        variable = new ElementReferenceVar(forEachNode.Variable.VariableName, tempChild, forEachNode, getVariableReference());
                    }

                    ParseBlock(tempChild, tempChild, forEachNode.Block, false, returnVar);
                    tempChild.Out(this);
                }
                // Take the foreach out of scope.
                forGroup.Out(this);

                // Increment the index
                Actions.AddRange(index.SetVariable(index.GetVariable() + forEachNode.Repeaters));

                // Add the for's finishing elements
                ContinueSkip.SetSkipCount(forStartIndex);
                Actions.Add(Element.Part <A_Loop>());

                rangeSkips.ForEach(var => var.ParameterValues[1] = new V_Number(GetSkipCount(var)));

                // Set the skip
                if (skipCondition != null)
                {
                    skipCondition.ParameterValues[1] = new V_Number(GetSkipCount(skipCondition));
                }

                ContinueSkip.ResetSkip();
                return;
            }

            // For
            case ForNode forNode:
            {
                ContinueSkip.Setup();

                ScopeGroup forContainer = scope.Child();

                // Set the variable
                if (forNode.VarSetNode != null)
                {
                    ParseVarset(getter, scope, forNode.VarSetNode);
                }
                if (forNode.DefineNode != null)
                {
                    ParseDefine(getter, forContainer, forNode.DefineNode);
                }

                ScopeGroup forGroup = forContainer.Child();

                // The action the for loop starts on.
                int forStartIndex = ContinueSkip.GetSkipCount();

                A_SkipIf skipCondition = null;
                // Skip if the condition is false.
                if (forNode.Expression != null)     // If it has an expression
                {
                    skipCondition = new A_SkipIf()
                    {
                        ParameterValues = new IWorkshopTree[2]
                    };
                    skipCondition.ParameterValues[0] = !(ParseExpression(forGroup, forGroup, forNode.Expression));
                    Actions.Add(skipCondition);
                }

                // Parse the for's block.
                ParseBlock(forGroup, forGroup, forNode.Block, false, returnVar);

                // Parse the statement
                if (forNode.Statement != null)
                {
                    ParseVarset(forGroup, forGroup, forNode.Statement);
                }

                // Take the for out of scope.
                forGroup.Out(this);

                ContinueSkip.SetSkipCount(forStartIndex);
                Actions.Add(Element.Part <A_Loop>());

                // Set the skip
                if (skipCondition != null)
                {
                    skipCondition.ParameterValues[1] = new V_Number(GetSkipCount(skipCondition));
                }

                // Take the defined variable in the for out of scope
                forContainer.Out(this);

                ContinueSkip.ResetSkip();
                return;
            }

            // While
            case WhileNode whileNode:
            {
                ContinueSkip.Setup();

                // The action the while loop starts on.
                int whileStartIndex = ContinueSkip.GetSkipCount();

                A_SkipIf skipCondition = new A_SkipIf()
                {
                    ParameterValues = new IWorkshopTree[2]
                };
                skipCondition.ParameterValues[0] = !(ParseExpression(getter, scope, whileNode.Expression));
                Actions.Add(skipCondition);

                ScopeGroup whileGroup = scope.Child();

                ParseBlock(whileGroup, whileGroup, whileNode.Block, false, returnVar);

                // Take the while out of scope.
                whileGroup.Out(this);

                ContinueSkip.SetSkipCount(whileStartIndex);
                Actions.Add(Element.Part <A_Loop>());

                skipCondition.ParameterValues[1] = new V_Number(GetSkipCount(skipCondition));

                ContinueSkip.ResetSkip();
                return;
            }

            // If
            case IfNode ifNode:
            {
                A_SkipIf if_SkipIf = new A_SkipIf()
                {
                    ParameterValues = new IWorkshopTree[2]
                };
                if_SkipIf.ParameterValues[0] = !(ParseExpression(getter, scope, ifNode.IfData.Expression));

                Actions.Add(if_SkipIf);

                var ifScope = scope.Child();

                // Parse the if body.
                ParseBlock(ifScope, ifScope, ifNode.IfData.Block, false, returnVar);

                // Take the if out of scope.
                ifScope.Out(this);

                // Determines if the "Skip" action after the if block will be created.
                // Only if there is if-else or else statements.
                bool addIfSkip = ifNode.ElseIfData.Length > 0 || ifNode.ElseBlock != null;

                // Create the "Skip" action.
                A_Skip if_Skip = new A_Skip();
                if (addIfSkip)
                {
                    Actions.Add(if_Skip);
                }

                // Update the initial SkipIf's skip count now that we know the number of actions the if block has.
                if_SkipIf.ParameterValues[1] = new V_Number(GetSkipCount(if_SkipIf));

                // Parse else-ifs
                A_Skip[] elseif_Skips = new A_Skip[ifNode.ElseIfData.Length];     // The ElseIf's skips
                for (int i = 0; i < ifNode.ElseIfData.Length; i++)
                {
                    // Create the SkipIf action for the else if.
                    A_SkipIf elseif_SkipIf = new A_SkipIf()
                    {
                        ParameterValues = new IWorkshopTree[2]
                    };
                    elseif_SkipIf.ParameterValues[0] = !(ParseExpression(getter, scope, ifNode.ElseIfData[i].Expression));

                    Actions.Add(elseif_SkipIf);

                    // Parse the else-if body.
                    var elseifScope = scope.Child();
                    ParseBlock(elseifScope, elseifScope, ifNode.ElseIfData[i].Block, false, returnVar);

                    // Take the else-if out of scope.
                    elseifScope.Out(this);

                    // Determines if the "Skip" action after the else-if block will be created.
                    // Only if there is additional if-else or else statements.
                    bool addIfElseSkip = i < ifNode.ElseIfData.Length - 1 || ifNode.ElseBlock != null;

                    // Create the "Skip" action for the else-if.
                    if (addIfElseSkip)
                    {
                        elseif_Skips[i] = new A_Skip();
                        Actions.Add(elseif_Skips[i]);
                    }

                    // Set the SkipIf's parameters.
                    elseif_SkipIf.ParameterValues[1] = new V_Number(GetSkipCount(elseif_SkipIf));
                }

                // Parse else body.
                if (ifNode.ElseBlock != null)
                {
                    var elseScope = scope.Child();
                    ParseBlock(elseScope, elseScope, ifNode.ElseBlock, false, returnVar);

                    // Take the else out of scope.
                    elseScope.Out(this);
                }

                // Replace dummy skip with real skip now that we know the length of the if, if-else, and else's bodies.
                // Replace if's dummy.
                if (addIfSkip)
                {
                    if_Skip.ParameterValues = new IWorkshopTree[]
                    {
                        new V_Number(GetSkipCount(if_Skip))
                    }
                }
                ;

                // Replace else-if's dummy.
                for (int i = 0; i < elseif_Skips.Length; i++)
                {
                    if (elseif_Skips[i] != null)
                    {
                        elseif_Skips[i].ParameterValues = new IWorkshopTree[]
                        {
                            new V_Number(GetSkipCount(elseif_Skips[i]))
                        };
                    }
                }

                return;
            }

            // Return
            case ReturnNode returnNode:

                if (returnNode.Value != null)
                {
                    Element result = ParseExpression(getter, scope, returnNode.Value);
                    if (returnVar != null)
                    {
                        Actions.AddRange(returnVar.SetVariable(result));
                    }
                }

                A_Skip returnSkip = new A_Skip();
                Actions.Add(returnSkip);
                Actions.Add(Element.Part <A_Skip>(new V_Number(-1)));
                ReturnSkips.Add(returnSkip);
                return;

            case DeleteNode deleteNode:
                DefinedClass.Delete(ParseExpression(getter, scope, deleteNode.Delete), this);
                return;

            // Define
            case DefineNode defineNode:
                ParseDefine(getter, scope, defineNode);
                return;

            case ExpressionTreeNode expressionTree:
                new ParseExpressionTree(this, getter, scope, expressionTree);
                return;

            default:
                throw new SyntaxErrorException("Expected statement.", statement.Location);
            }
        }