private void CompileDoWhileLoop(Parser parser, ByteBuffer buffer, DoWhileLoop doWhileLoop) { ByteBuffer loopBody = new ByteBuffer(); this.Compile(parser, loopBody, doWhileLoop.Code); loopBody.ResolveContinues(true); // continues should jump to the condition, hence the true. ByteBuffer condition = new ByteBuffer(); this.CompileExpression(parser, condition, doWhileLoop.Condition, true); loopBody.Concat(condition); loopBody.Add(doWhileLoop.Condition.FirstToken, OpCode.JUMP_IF_TRUE, -loopBody.Size - 1); loopBody.ResolveBreaks(); buffer.Concat(loopBody); }
private void CompileWhileLoop(Parser parser, ByteBuffer buffer, WhileLoop whileLoop) { ByteBuffer loopBody = new ByteBuffer(); this.Compile(parser, loopBody, whileLoop.Code); ByteBuffer condition = new ByteBuffer(); this.CompileExpression(parser, condition, whileLoop.Condition, true); condition.Add(whileLoop.Condition.FirstToken, OpCode.JUMP_IF_FALSE, loopBody.Size + 1); condition.Concat(loopBody); condition.Add(null, OpCode.JUMP, -condition.Size - 1); condition.ResolveBreaks(); condition.ResolveContinues(); buffer.Concat(condition); }
private void CompileSwitchStatement(Parser parser, ByteBuffer buffer, SwitchStatement switchStatement) { this.CompileExpression(parser, buffer, switchStatement.Condition, true); ByteBuffer chunkBuffer = new ByteBuffer(); Dictionary<int, int> chunkIdsToOffsets = new Dictionary<int, int>(); Dictionary<int, int> integersToChunkIds = new Dictionary<int,int>(); Dictionary<string, int> stringsToChunkIds = new Dictionary<string,int>(); int defaultChunkId = -1; foreach (SwitchStatement.Chunk chunk in switchStatement.Chunks) { int chunkId = chunk.ID; if (chunk.Cases.Length == 1 && chunk.Cases[0] == null) { defaultChunkId = chunkId; } else { foreach (Expression expression in chunk.Cases) { if (switchStatement.UsesIntegers) { integersToChunkIds[((IntegerConstant)expression).Value] = chunkId; } else { stringsToChunkIds[((StringConstant)expression).Value] = chunkId; } } } chunkIdsToOffsets[chunkId] = chunkBuffer.Size; this.Compile(parser, chunkBuffer, chunk.Code); } chunkBuffer.ResolveBreaks(); int switchId = parser.RegisterByteCodeSwitch(switchStatement.FirstToken, chunkIdsToOffsets, integersToChunkIds, stringsToChunkIds, switchStatement.UsesIntegers); int defaultOffsetLength = defaultChunkId == -1 ? chunkBuffer.Size : chunkIdsToOffsets[defaultChunkId]; buffer.Add(switchStatement.FirstToken, switchStatement.UsesIntegers ? OpCode.SWITCH_INT : OpCode.SWITCH_STRING, switchId, defaultOffsetLength); buffer.Concat(chunkBuffer); }
private void CompileForLoop(Parser parser, ByteBuffer buffer, ForLoop forLoop) { this.Compile(parser, buffer, forLoop.Init); ByteBuffer codeBuffer = new ByteBuffer(); this.Compile(parser, codeBuffer, forLoop.Code); codeBuffer.ResolveContinues(true); // resolve continues as jump-to-end before you add the step instructions. this.Compile(parser, codeBuffer, forLoop.Step); ByteBuffer forBuffer = new ByteBuffer(); this.CompileExpression(parser, forBuffer, forLoop.Condition, true); forBuffer.Add(forLoop.Condition.FirstToken, OpCode.JUMP_IF_FALSE, codeBuffer.Size + 1); // +1 to go past the jump I'm about to add. forBuffer.Concat(codeBuffer); forBuffer.Add(null, OpCode.JUMP, -forBuffer.Size - 1); forBuffer.ResolveBreaks(); buffer.Concat(forBuffer); }
private void CompileForEachLoop(Parser parser, ByteBuffer buffer, ForEachLoop forEachLoop) { buffer.Add(null, OpCode.LITERAL, parser.GetIntConstant(0)); buffer.Add(null, OpCode.LITERAL, parser.GetIntConstant(forEachLoop.IterationVariableId)); this.CompileExpression(parser, buffer, forEachLoop.IterationExpression, true); buffer.Add(forEachLoop.IterationExpression.FirstToken, OpCode.VERIFY_TYPE_IS_ITERABLE); ByteBuffer body = new ByteBuffer(); ByteBuffer body2 = new Crayon.ByteBuffer(); this.Compile(parser, body2, forEachLoop.Code); body.Add(forEachLoop.FirstToken, OpCode.ITERATION_STEP, body2.Size + 1); body2.Add(null, OpCode.JUMP, -body2.Size - 2); body.Concat(body2); body.ResolveBreaks(); body.ResolveContinues(); buffer.Concat(body); buffer.Add(null, OpCode.POP); // list buffer.Add(null, OpCode.POP); // var ID buffer.Add(null, OpCode.POP); // index }