예제 #1
0
		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);
		}
예제 #2
0
		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);
		}
예제 #3
0
		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);
		}
예제 #4
0
		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);
		}
예제 #5
0
		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
		}