Exemplo n.º 1
0
        public static LoopHeader Loop(MatchIterator iterator)
        {
            Expression array;

            iterator.AssertKeyword(Keywords.Loop);
            Token loop = (Token)iterator.Current;

            if (iterator.AtEnd())
            {
                LoopHeader result = new LoopHeader(loop);
                return(result);
            }

            iterator.AssertExpression(out Expression firstExpression);

            if (iterator.AtEnd())
            {
                // Actually checking that this expression is an array is for
                // a later step, when the messenger is available.
                array = firstExpression;
                LoopHeader result = new LoopHeader(loop, array);
                return(result);
            }

            if (iterator.NextIsKeyword(Keywords.In, out Token inToken))
            {
                // Again, actually checking that this is indeed just a name
                // has to wait for a later stage.
                Expression name = firstExpression;

                iterator.AssertExpression(out array);
                iterator.AssertEnd();

                LoopHeader result = new LoopHeader(loop, name, inToken, array);
                return(result);
            }

            if (iterator.NextIsKeyword(Keywords.From, out Token from))
            {
                Expression name = firstExpression;

                iterator.AssertExpression(out Expression start);
                iterator.AssertKeyword(Keywords.To, out Token to);
                iterator.AssertExpression(out Expression end);
                iterator.AssertEnd();

                LoopHeader result = new LoopHeader(
                    loop, name, from, start, to, end);
                return(result);
            }

            throw iterator.UnexpectedEnd();
        }
Exemplo n.º 2
0
 private Color GetColor(SprakExpression item)
 {
     return(item switch
     {
         Block block => GetColor(block.Header),
         Command _ => Colors.Blue,
         FunctionCall _ => Colors.Orange,
         FunctionHeader _ => Colors.Blue,
         IfHeader _ => Colors.DarkRed,
         LiteralArrayGet _ => Colors.Yellow,
         LiteralGet _ => Colors.Yellow,
         LoopHeader _ => Colors.Red,
         MainHeader _ => Colors.Orange,
         OperatorCall _ => Colors.Green,
         Return _ => Colors.Blue,
         VariableAssignment _ => Colors.Orange,
         VariableReference _ => Colors.Yellow,
         _ => Colors.Black
     });
Exemplo n.º 3
0
        public static void GenerateCode(LoopHeader header, GeneratorContext builder)
        {
            bool requiresOuterScope = !header.IsInfinite;
            bool requiresInnerScope = header.RequiresScopeHint;

            if (requiresOuterScope)
            {
                builder.AddOp(new ScopeBegin(), header.LoopToken);
            }

            string endLabel = builder.DeclareLabel("LoopEnd");

            builder.BreakLabels.Push(endLabel);

            string continueLabel = builder.DeclareLabel("LoopContinue");

            builder.ContinueLabels.Push(continueLabel);

            string indexName = null;

            if (header.IsInfinite)
            {
                builder.SetLabelToNext(continueLabel);
            }

            else if (header.IsRange)
            {
                builder.PushIndex();
                indexName = header.Name;

                // For the end expression, don't use a variable if a literal could be used instead
                // Actually, it would be better if this were generalized to statements that translate to a single
                // op, but that is an optimization for another day.
                Op endOp;

                if (header.RangeEnd is LiteralGet end)
                {
                    endOp = new LiteralValue(end.Value);
                }

                else
                {
                    string endName = builder.GetIndexedName("end");
                    builder.AddCode(header.RangeEnd);
                    builder.AddOp(new VariableCreate(endName), header.LoopToken);

                    endOp = new VariableGet(endName);
                }

                builder.AddCode(header.RangeStart);
                builder.AddOp(new VariableCreate(indexName), header.NameToken);

                builder.SetLabelToNext(continueLabel);

                builder.AddOp(new VariableGet(indexName), header.NameToken);
                builder.AddOp(endOp);
                builder.AddOp(new GreaterThan(), header.FromToken);
                builder.AddOp(new JumpLabelConditional(endLabel), header.FromToken);
            }
            else
            {
                builder.PushIndex();
                indexName = builder.GetIndexedName("index");
                string arrayName   = builder.GetIndexedName("array");
                string countName   = builder.GetIndexedName("count");
                string currentName = header.Name ?? "@";

                builder.AddCode(header.Array);
                builder.AddOp(new VariableCreate(arrayName), header.LoopToken);

                builder.AddOp(new ArrayCount(arrayName), header.LoopToken);
                builder.AddOp(new VariableCreate(countName), header.LoopToken);

                builder.AddOp(new LiteralValue(new SprakNumber(0)), header.LoopToken);
                builder.AddOp(new VariableCreate(indexName), header.LoopToken);

                builder.AddOp(new LiteralValue(SprakUnit.Value), header.LoopToken);
                builder.AddOp(new VariableCreate(currentName), header.LoopToken);

                builder.SetLabelToNext(continueLabel);

                builder.AddOp(new VariableGet(indexName), header.LoopToken);
                builder.AddOp(new VariableGet(countName), header.LoopToken);
                builder.AddOp(new GreaterThanOrEqualTo(), header.LoopToken);
                builder.AddOp(new JumpLabelConditional(endLabel), header.LoopToken);

                builder.AddOp(new VariableGet(arrayName), header.InToken);
                builder.AddOp(new VariableGet(indexName), header.InToken);
                builder.AddOp(new ArrayElementGet(), header.InToken);
                builder.AddOp(new VariableSet(currentName), header.InToken);

                builder.AddOp(new Increment(indexName), header.InToken);
            };

            // This is used by the continue command, currently.
            header.IndexNameHint = indexName;

            if (requiresInnerScope)
            {
                builder.AddOp(new ScopeBegin(), header.LoopToken);
            }

            foreach (Expression statement in header.ParentBlockHint.Statements)
            {
                builder.AddCode(statement);
            }

            if (requiresInnerScope)
            {
                builder.AddOp(new ScopeEnd(), header.EndToken);
            }

            if (header.IsRange)
            {
                builder.AddOp(new Increment(indexName), header.EndToken);
            }

            builder.AddOp(new JumpLabel(continueLabel), header.EndToken);
            builder.SetLabelToNext(endLabel);

            if (!header.IsInfinite)
            {
                builder.PopIndex();
            }

            if (requiresOuterScope)
            {
                builder.AddOp(new ScopeEnd(), header.EndToken);
            }

            builder.BreakLabels.Pop();
            builder.ContinueLabels.Pop();
        }