Ejemplo n.º 1
0
        ForInStatement ParseForInStatement()
        {
            var statement = new ForInStatement(_current.m_line);

            statement.name_list = ParseNameList();
            if (NextToken().m_type != (int)TokenType.IN)
            {
                throw NewParserException("expect 'in' in for-in-statement", _current);
            }
            // 这个结构特殊,返回的是迭代器,
            statement.exp_list = ParseExpList();

            if (NextToken().m_type != (int)TokenType.DO)
            {
                throw NewParserException("expect 'do' to start for-in-body", _current);
            }
            statement.block = ParseBlock();
            if (NextToken().m_type != (int)TokenType.END)
            {
                throw NewParserException("expect 'end' to complete for-in-body", _current);
            }

            return(statement);
        }
Ejemplo n.º 2
0
        void HandleForInStatement(ForInStatement tree)
        {
            EnterBlock();

            var         f = GetCurrentFunction();
            Instruction code;

            // init iterator function
            HandleExpList(tree.exp_list, 3);
            var func_register  = GenerateRegisterId();
            var table_register = GenerateRegisterId();
            var index_register = GenerateRegisterId();

            EnterLoop();
            {
                EnterBlock();

                // alloca registers for names
                int name_start = GetNextRegisterId();
                HandleNameList(tree.name_list);
                int name_end = GetNextRegisterId();

                // allocate temp registers for call iterator function
                int temp_func  = name_start;
                int temp_table = name_start + 1;
                int temp_index = name_start + 2;

                // call iterate function
                Action <int, int> move = (int dst, int src) =>
                {
                    var l_code = Instruction.AB(OpType.OpType_Move, dst, src);
                    f.AddInstruction(l_code, tree.name_list.line);
                };
                move(temp_func, func_register);
                move(temp_table, table_register);
                move(temp_index, index_register);

                code = Instruction.ABC(OpType.OpType_Call, temp_func, 2, 0);
                f.AddInstruction(code, tree.exp_list.line);

                code = Instruction.A(OpType.OpType_FillNilFromTopToA, name_end);
                f.AddInstruction(code, tree.exp_list.line);

                // jump to loop tail when the first name value is nil
                code = Instruction.ABx(OpType.OpType_JmpNil, name_start, 0);
                int index = f.AddInstruction(code, tree.exp_list.line);
                AddLoopJumpInfo(JumpType.JumpTail, index);

                // index = name1
                move(index_register, name_start);

                HandleBlock(tree.block);

                LeaveBlock();
                // jump to loop head
                code  = Instruction.Bx(OpType.OpType_Jmp, 0);
                index = f.AddInstruction(code, -1);
                AddLoopJumpInfo(JumpType.JumpHead, index);
            }

            LeaveLoop();

            LeaveBlock();
        }