Example #1
0
        public static void GenerateCode(ElseIfHeader header, GeneratorContext builder)
        {
            string currentEndLabel = builder.DeclareLabel("endElif");

            builder.AddCode(header.Condition);
            builder.AddOp(new JumpLabelConditionalNegated(currentEndLabel), header.IfToken);

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

            string finalEndLabel = header.EndLabelHint;

            if (finalEndLabel == null)
            {
                throw new Exception("Encountered ElseIf Header without an end label!");
            }

            if (header.NextConditionalComponentHint == null)
            {
                builder.SetLabelToNext(finalEndLabel);

                if (header.RequiresScopeHint)
                {
                    builder.AddOp(new ScopeEnd(), header.ParentBlockHint.EndToken);
                }
            }
            else
            {
                builder.AddOp(new JumpLabel(finalEndLabel));
            }

            builder.SetLabelToNext(currentEndLabel);
        }
Example #2
0
        public static void GenerateCode(VariableAssignment assignment, GeneratorContext builder)
        {
            if (assignment.IsDeclaration)
            {
                if (assignment.HasValue)
                {
                    builder.AddCode(assignment.Value);
                }

                else
                {
                    builder.AddOp(new LiteralValue(assignment.DeclarationType.Default()), assignment.TypeToken);
                }

                builder.AddOp(new VariableCreate(assignment.Name), assignment.NameToken);
            }
            else
            {
                if (assignment.Indices.Count > 1)
                {
                    throw new NotImplementedException("Only one level of indexing is supported at the moment");
                }

                if (assignment.BuiltInFunctionHint != null)
                {
                    if (assignment.Indices.Count == 0)
                    {
                        builder.AddOp(new VariableGet(assignment.Name), assignment.NameToken);
                    }
                    else
                    {
                        builder.AddOp(new VariableGet(assignment.Name));
                        builder.AddCode(assignment.Indices[0].Index);
                        builder.AddOp(new ArrayElementGet());
                    }
                }

                if (assignment.Value != null)
                {
                    builder.AddCode(assignment.Value);
                }

                if (assignment.BuiltInFunctionHint != null)
                {
                    builder.AddOp(new CallBuiltIn(assignment.BuiltInFunctionHint), assignment.OperatorToken);
                }

                if (assignment.Indices.Count == 0)
                {
                    builder.AddOp(new VariableSet(assignment.Name), assignment.NameToken);
                }
                else
                {
                    builder.AddCode(assignment.Indices[0].Index);
                    builder.AddOp(new ArrayElementSet(assignment.Name),
                                  assignment.NameToken);
                }
            }
        }
Example #3
0
        public static void GenerateCode(FunctionCall call, GeneratorContext builder)
        {
            foreach (Expression arg in call.Arguments)
            {
                builder.AddCode(arg);
            }

            if (call.BuiltInFunctionHint != null)
            {
                builder.AddOp(new CallBuiltIn(call.BuiltInFunctionHint), call.NameToken);
            }

            else
            {
                builder.AddOp(new Call(call.UserFunctionHint), call.NameToken);
            }
        }
Example #4
0
        public static void GenerateCode(IfHeader header, GeneratorContext builder)
        {
            if (header.RequiresScopeHint)
            {
                builder.AddOp(new ScopeBegin(), header.IfToken);
            }

            string currentEndLabel = builder.DeclareLabel("endIf");

            string finalEndLabel = null;

            if (header.NextConditionalComponentHint != null)
            {
                finalEndLabel = builder.DeclareLabel("endConditional");
            }

            builder.AddCode(header.Condition);

            builder.AddOp(new JumpLabelConditionalNegated(currentEndLabel), header.IfToken);

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

            if (header.NextConditionalComponentHint != null)
            {
                IConditionalSubComponent current = header.NextConditionalComponentHint;
                while (current != null)
                {
                    current.EndLabelHint = finalEndLabel;
                    current = current.NextConditionalComponentHint;
                }

                builder.AddOp(new JumpLabel(finalEndLabel));
            }

            builder.SetLabelToNext(currentEndLabel);

            if (header.NextConditionalComponentHint == null &&
                header.RequiresScopeHint)
            {
                builder.AddOp(new ScopeEnd(), header.ParentBlockHint.EndToken);
            }
        }
Example #5
0
        public static void GenerateCode(Expressions.Types.Return statement, GeneratorContext builder)
        {
            if (statement.HasValue)
            {
                builder.AddCode(statement.Value);
            }

            builder.AddOp(new Types.Return(), statement.ReturnToken);
        }
Example #6
0
        public static void GenerateCode(LiteralArrayGet literal, GeneratorContext builder)
        {
            foreach (Expression element in literal.Elements)
            {
                builder.AddCode(element);
            }

            builder.AddOp(new ArrayValue(literal.Elements.Count), literal.StartToken);
        }
Example #7
0
        public static void GenerateCode(OperatorCall call, GeneratorContext builder)
        {
            if (call.LeftInput != null)
            {
                builder.AddCode(call.LeftInput);
            }
            if (call.RightInput != null)
            {
                builder.AddCode(call.RightInput);
            }

            builder.AddOp(new CallBuiltIn(call.BuiltInFunctionHint), call.OperatorToken);
        }
Example #8
0
        public static void GenerateCode(FunctionHeader header, GeneratorContext builder)
        {
            foreach (string name in header.ParameterNames.Reverse())
            {
                builder.AddOp(new VariableCreate(name), header.NameToken);
            }

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

            // This is hacky, and might be cleaned up someday
            List <Op> sheet         = builder.Operations;
            bool      returnMissing = sheet.Count == 0 || !(sheet[^ 1] is Types.Return);
Example #9
0
        public static void GenerateCode(ElseHeader header, GeneratorContext builder)
        {
            foreach (Expression statement in header.ParentBlockHint.Statements)
            {
                builder.AddCode(statement);
            }

            string conditionalEndLabel = header.EndLabelHint;

            if (conditionalEndLabel == null)
            {
                throw new Exception("Encountered Else Header without an end label!");
            }

            builder.SetLabelToNext(conditionalEndLabel);

            if (header.RequiresScopeHint)
            {
                builder.AddOp(new ScopeEnd(), header.ParentBlockHint.EndToken);
            }
        }
Example #10
0
 public static void GenerateCode(Indexer indexer, GeneratorContext builder)
 {
     builder.AddCode(indexer.SourceExpression);
     builder.AddCode(indexer.IndexExpression);
     builder.AddOp(new ArrayElementGet(), indexer.OpeningBracket);
 }
Example #11
0
 public static void GenerateCode(VariableReference reference, GeneratorContext builder)
 {
     builder.AddOp(new VariableGet(reference.Name), reference.Token);
 }
Example #12
0
        public static void GenerateCode(Command command, GeneratorContext builder)
        {
            string label = null;

            switch (command.Keyword)
            {
            case Keywords.End:
                // End keywords were used to make the tree. They exist as
                // statements beyond that only so that the tree (and editor
                // functions that depend on the tree) are aware of them.
                return;

            case Keywords.Break:

                if (builder.BreakLabels.Count == 0)
                {
                    builder.ThrowError("Encountered break statement outside of loop");
                }

                label = builder.BreakLabels.Peek();
                break;

            case Keywords.Continue:

                if (builder.ContinueLabels.Count == 0)
                {
                    builder.ThrowError("Encountered continue statement outside of loop");
                }

                label = builder.ContinueLabels.Peek();
                break;

            default:
                builder.ThrowError("Encountered unexpected command expression");
                break;
            }

            if (label == null)
            {
                throw new Exception("Missing label");
            }


            Header ancestor = command.ParentBlockHint.Header;

            while (true)
            {
                // There might be intermediate if blocks that have scopes that
                // need ending. Also, the loop iteration we are breaking/skipping
                // might have one too.

                if (ancestor.RequiresScopeHint)
                {
                    builder.AddOp(new ScopeEnd(), command.Token);
                }

                if (ancestor is LoopHeader loopHeader)
                {
                    if (command.Keyword == Keywords.Continue &&
                        loopHeader.IsRange)
                    {
                        // For from-to loops, the increment is done at the end
                        // of the loop, and needs to be done here too. (loop-in
                        // loops do the incrementing at the beginning)
                        builder.AddOp(new Increment(loopHeader.IndexNameHint),
                                      command.Token);
                    }

                    break;
                }

                // The parent of a header is the block it is a header of
                // (confusing, when one puts it that way)

                // So to get the parent block of the current block we need
                // the parent of the parent

                ancestor = command.ParentBlockHint.ParentBlockHint?.Header;
            }

            if (ancestor == null)
            {
                throw new Exception("Unable to locate continue command loop header");
            }

            builder.AddOp(new JumpLabel(label), command.Token);
        }
Example #13
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();
        }
Example #14
0
 public static void GenerateCode(LiteralGet literal, GeneratorContext builder)
 {
     builder.AddOp(new LiteralValue(literal.Value), literal.Token);
 }