コード例 #1
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        private Function CreateGenerator_MoveNext(FunctionDefinition node)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(ChelaType.GetBoolType(),
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method("MoveNext", MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            method.DefinitionNode = node;
            genClass.AddFunction("MoveNext", method);

            // Swap the exception contexts.
            method.SwapExceptionContexts(currentFunction);

            // Store the old function.
            Function oldFunction = currentFunction;
            currentFunction = method;

            // Create the jump table block.
            BasicBlock jmpBlock = CreateBasicBlock();
            jmpBlock.SetName("jmp");

            // Generate the main code.
            BasicBlock topBlock = CreateBasicBlock();
            topBlock.SetName("top");
            builder.SetBlock(topBlock);

            // Prepare returning.
            LexicalScope topScope = (LexicalScope) node.GetScope();
            PrepareReturning(node, currentFunction, topScope);

            // Create the function body.
            VisitList(node.GetChildren());

            // Finish returning.
            FinishReturn(node, currentFunction);

            // Create the state jump table.
            builder.SetBlock(jmpBlock);

            // Load the current state.
            builder.CreateLoadArg(0);
            builder.CreateLoadField(node.GeneratorState);

            // Build the jump table.
            int numstates = node.Yields.Count*2+3;
            int[] stateConstants = new int[numstates];
            BasicBlock[] stateEntries = new BasicBlock[numstates];

            // The default case is return.
            stateConstants[0] = -1;
            stateEntries[0] = currentFunction.ReturnBlock;

            // The first state is the top block.
            stateConstants[1] = 0;
            stateEntries[1] = topBlock;

            // The second state is the return block.
            stateConstants[2] = 1;
            stateEntries[2] = currentFunction.ReturnBlock;

            // The next states are the yield merges followed by yield disposes.
            for(int i = 0; i < node.Yields.Count; ++i)
            {
                ReturnStatement yieldStmnt = node.Yields[i];

                // Emit the merge state.
                int stateId = i*2+2;
                int entryIndex = stateId+1;
                stateConstants[entryIndex] = stateId;
                stateEntries[entryIndex] = yieldStmnt.MergeBlock;

                // Emit the dispose state.
                stateConstants[entryIndex+1] = stateId+1;
                stateEntries[entryIndex+1] = yieldStmnt.DisposeBlock;
            }

            builder.CreateSwitch(stateConstants, stateEntries);

            // Restore the old function.
            currentFunction = oldFunction;

            return method;
        }