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); }
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); } } }
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); } }
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); } }
public static void GenerateCode(Expressions.Types.Return statement, GeneratorContext builder) { if (statement.HasValue) { builder.AddCode(statement.Value); } builder.AddOp(new Types.Return(), statement.ReturnToken); }
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); }
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); }
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);
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); } }
public static void GenerateCode(Indexer indexer, GeneratorContext builder) { builder.AddCode(indexer.SourceExpression); builder.AddCode(indexer.IndexExpression); builder.AddOp(new ArrayElementGet(), indexer.OpeningBracket); }
public static void GenerateCode(VariableReference reference, GeneratorContext builder) { builder.AddOp(new VariableGet(reference.Name), reference.Token); }
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); }
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(); }
public static void GenerateCode(LiteralGet literal, GeneratorContext builder) { builder.AddOp(new LiteralValue(literal.Value), literal.Token); }