public virtual void Visit(ForBlock s) { block = new ForBlock(s.SourceSpan, block, s.Name, s.Index, s.Limit, s.Step, s.UserIndex, s.BreakLabel, s.ContinueLabel); TransformBlock(s); result = block; block = block.Parent; }
public static void Emit(byte[] instruction, CompilationContext context) { // 300R0000 VVVVVVVV // R: Register to use as loop counter. // V: Number of iterations to loop. // 310R0000 byte mode = instruction[StartOrEndIndex]; byte iterationRegisterIndex = instruction[IterationRegisterIndex]; switch (mode) { case LoopBegin: // Just start a new compilation block and parse the instruction itself at the end. context.BlockStack.Push(new OperationBlock(instruction)); return; case LoopEnd: break; default: throw new TamperCompilationException($"Invalid loop {mode} in Atmosphere cheat"); } // Use the loop begin instruction stored in the stack. instruction = context.CurrentBlock.BaseInstruction; CodeType codeType = InstructionHelper.GetCodeType(instruction); if (codeType != CodeType.StartEndLoop) { throw new TamperCompilationException($"Loop end does not match code type {codeType} in Atmosphere cheat"); } // Validate if the register in the beginning and end are the same. byte oldIterationRegisterIndex = instruction[IterationRegisterIndex]; if (iterationRegisterIndex != oldIterationRegisterIndex) { throw new TamperCompilationException($"The register used for the loop changed from {oldIterationRegisterIndex} to {iterationRegisterIndex} in Atmosphere cheat"); } Register iterationRegister = context.GetRegister(iterationRegisterIndex); ulong immediate = InstructionHelper.GetImmediate(instruction, IterationsImmediateIndex, IterationsImmediateSize); // Create a loop block with the current operations and nest it in the upper // block of the stack. ForBlock block = new ForBlock(immediate, iterationRegister, context.CurrentOperations); context.BlockStack.Pop(); context.CurrentOperations.Add(block); }
public ForBlock Build() { var forBlock = new ForBlock(_block); if (_reader.HasNext()) { _reader.Next(); var token = _reader.Current(); if (token.OperatorType != OperatorType.LeftParenthesis) { throwUnexceptedError(); } else { throwErrorIfHasNoNextOrNext("incompleted for block;"); throwErrorIfOperatorTypeNotMatch(OperatorType.Declare); forBlock.DeclareExpression = new DeclareExpressionBuilder(_reader, forBlock).Build(); forBlock.CheckExpression = new ExpressionBuilder(_reader, false, forBlock).Build(); if (!forBlock.CheckExpression.Root.OutputType.IsBool()) { throwError("second expression should be bool expression ,but it's not;"); } forBlock.OperateExpression.Root = new AstNodeBuilder(_reader, forBlock, _interceptChars).Build(); if (_reader.HasNext()) { forBlock.Body = new OrderedBlockBuilder(_reader, "for", forBlock).Build(); return(forBlock); } else { throwError("incompleted for block;"); } } } else { throwError("incompleted for block;"); } return(null); }
public void Visit(ForBlock s) { /* forprep (for index), (for limit), (for step) forContinue * forLoop: * block * local <index> * ... * end * forContinue: * forloop (for index), (for limit), (for step), <index> forLoop * forBreak: */ // For index variables should have been allocated sequentially. Allocation allocation = function.Local(s.Index); int A = allocation; allocation.Release(); // Prologue. function.InstructionAsBx(s.SourceSpan, Opcode.ForPrep, A, s.ContinueLabel); Label forLoop = new Label("forLoop"); function.Label(forLoop); // Enter block. Allocation blockBase = function.Top(); block = new BlockBuilder(block, s, blockBase); blockBase.Release(); function.DeclareLocal(s.UserIndex); BuildBlock(s); // End of block. block = block.Parent; // Epilogue. function.Label(s.ContinueLabel); function.InstructionAsBx(s.SourceSpan, Opcode.ForLoop, A, forLoop); function.Label(s.BreakLabel); }
public void Visit(ForBlock s) { Indent(); o.Write("for "); o.Write(s.UserIndex.Name); o.Write(" : "); o.Write(s.Index.Name); o.Write(", "); o.Write(s.Limit.Name); o.Write(", "); o.Write(s.Step.Name); o.Write(" : "); o.Write(s.BreakLabel.Name); o.Write(", "); o.Write(s.ContinueLabel.Name); o.WriteLine(); WriteBlock(s); Indent(); o.WriteLine("end"); }