private void CreateGenerator_GetEnumerator(FunctionDefinition node, Structure enumeratorType, bool generic) { // Get the generator class. Class genClass = node.GeneratorClass; // Use the GetEnumerator name for the most specific version. string name = "GetEnumerator"; Function contract = null; if(!generic && node.IsGenericIterator) { name = GenSym(); contract = FindFirstConstract(currentModule.GetEnumerableIface(), "GetEnumerator"); } // Create the function type. FunctionType functionType = FunctionType.Create(ReferenceType.Create(enumeratorType), new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false); // Create the method. Method method = new Method(name, MemberFlags.Public, genClass); method.SetFunctionType(functionType); genClass.AddFunction(name, method); // Set the explicit contract. if(contract != null) method.SetExplicitContract(contract); // Create the method block. BasicBlock block = new BasicBlock(method); block.SetName("top"); // Return this. builder.SetBlock(block); builder.CreateLoadArg(0); builder.CreateRet(); }
private void CreateGenerator_Current(FunctionDefinition node, bool generic) { // Get the generator class. Class genClass = node.GeneratorClass; // Use the get_Current name for the most specific version. string name = "get_Current"; Function contract = null; if(!generic && node.IsGenericIterator) { name = GenSym(); contract = FindFirstConstract(currentModule.GetEnumeratorIface(), "get_Current"); } // Select the current type. IChelaType currentType = node.YieldType; if(!generic) currentType = ReferenceType.Create(currentModule.GetObjectClass()); // Create the function type. FunctionType functionType = FunctionType.Create(currentType, new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false); // Create the method. Method method = new Method(name, MemberFlags.Public, genClass); method.SetFunctionType(functionType); genClass.AddFunction(name, method); // Set the explicit contract. if(contract != null) method.SetExplicitContract(contract); // Create the method block. BasicBlock block = new BasicBlock(method); block.SetName("top"); // Create the return and error blocks. BasicBlock retBlock = new BasicBlock(method); retBlock.SetName("ret"); BasicBlock errorBlock = new BasicBlock(method); errorBlock.SetName("error"); // Make sure reset was called before the first Current. builder.SetBlock(block); builder.CreateLoadArg(0); builder.CreateLoadField(node.GeneratorState); builder.CreateLoadInt32(0); builder.CreateCmpEQ(); builder.CreateBr(errorBlock, retBlock); // Raise an error if reset wasn't called. builder.SetBlock(errorBlock); Class excpt = (Class)ExtractClass(node, currentModule.GetLangMember("InvalidOperationException")); builder.CreateLoadString("IEnumerator.MoveNext must be called before than IEnumerator.Current."); builder.CreateNewObject(excpt, GetExceptionCtor(node, excpt), 1); builder.CreateThrow(); // Load the yielded value. builder.SetBlock(retBlock); builder.CreateLoadArg(0); builder.CreateLoadField(node.YieldedValue); // Cast the yielded value. Cast(node, null, node.YieldType, currentType); // Return. builder.CreateRet(); }