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 }
private void CompileIncrement(Parser parser, ByteBuffer buffer, Increment increment, bool outputUsed) { if (!outputUsed) { throw new Exception("This should have been optimized into a += or -="); } if (increment.Root is Variable) { // OpCode re-use be damned. This should be not one, but two top-level op codes. // INCREMENT_INLINE and INCREMENT_POP (depending on whether outputUsed is true) // In fact, the code here in its current form is actually WRONG because someString++ will have // a '1' appended to it when it really should be an error if the variable is not an integer. // Same for the others below. Ideally the DUPLICATE_STACK_TOP op should be removed. Variable variable = (Variable)increment.Root; int scopeId = variable.LocalScopeId; this.CompileExpression(parser, buffer, increment.Root, true); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(variable.FirstToken, OpCode.ASSIGN_LOCAL, scopeId); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(variable.FirstToken, OpCode.ASSIGN_LOCAL, scopeId); } } else if (increment.Root is BracketIndex) { BracketIndex bracketIndex = (BracketIndex)increment.Root; this.CompileExpression(parser, buffer, bracketIndex.Root, true); this.CompileExpression(parser, buffer, bracketIndex.Index, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(bracketIndex.BracketToken, OpCode.INDEX); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 1); } else { buffer.Add(increment.IncrementToken, OpCode.STACK_INSERTION_FOR_INCREMENT); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 0); } } else if (increment.Root is DotStep) { DotStep dotStep = (DotStep)increment.Root; this.CompileExpression(parser, buffer, dotStep.Root, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(dotStep.DotToken, OpCode.DEREF_DOT, parser.GetId(dotStep.StepToken.Value)); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_STEP, parser.GetId(dotStep.StepToken.Value), 1); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_STEP, parser.GetId(dotStep.StepToken.Value), 0); buffer.Add(increment.IncrementToken, OpCode.STACK_SWAP_POP); } } else { throw new ParserException(increment.IncrementToken, "Cannot apply " + (increment.IsIncrement ? "++" : "--") + " to this sort of expression."); } }
private void CompileIntegerConstant(Parser parser, ByteBuffer buffer, IntegerConstant intConst, bool outputUsed) { if (!outputUsed) throw new ParserException(intConst.FirstToken, "This expression does nothing."); buffer.Add(intConst.FirstToken, OpCode.LITERAL, parser.GetIntConstant(intConst.Value)); }