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