private void CreateGenerator_Reset(FunctionDefinition node) { // Get the generator class. Class genClass = node.GeneratorClass; // Create the function type. FunctionType functionType = FunctionType.Create(ChelaType.GetVoidType(), new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false); // Create the method. Method method = new Method("Reset", MemberFlags.Public, genClass); method.SetFunctionType(functionType); genClass.AddFunction("Reset", method); // Create the top block. BasicBlock top = new BasicBlock(method); builder.SetBlock(top); // Throw an exception. Class excpt = (Class)ExtractClass(node, currentModule.GetLangMember("InvalidOperationException")); builder.CreateLoadString("IEnumerator.Reset cannot be called in generators."); builder.CreateNewObject(excpt, GetExceptionCtor(node, excpt), 1); builder.CreateThrow(); }
private Method CreateTrivialConstructor(Structure building, Structure buildingInstance) { // Create the constructor function type. FunctionType type = FunctionType.Create(ChelaType.GetVoidType(), new IChelaType[]{ReferenceType.Create(buildingInstance)}, false); // Create the constructor. Method ctor = new Method(".ctor", MemberFlags.Public | MemberFlags.Constructor, building); ctor.SetFunctionType(type); building.AddFunction(".ctor", ctor); // Create the constructor block. BasicBlock top = new BasicBlock(ctor); top.SetName("top"); top.Append(new Instruction(OpCode.RetVoid, null)); return ctor; }
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 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; }
private void CreateGenerator_Dispose(FunctionDefinition node, Function moveNext) { // Get the generator class. Class genClass = node.GeneratorClass; // Create the function type. FunctionType functionType = FunctionType.Create(ChelaType.GetVoidType(), new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false); // Create the method. Method method = new Method("Dispose", MemberFlags.Public, genClass); method.SetFunctionType(functionType); genClass.AddFunction("Dispose", method); // Create the top block. BasicBlock top = new BasicBlock(method); builder.SetBlock(top); // Create the return and dispose blocks. BasicBlock justReturn = new BasicBlock(method); BasicBlock disposeAndReturn = new BasicBlock(method); // Load the current state. builder.CreateLoadArg(0); builder.CreateDup1(); builder.CreateDup1(); builder.CreateLoadField(node.GeneratorState); builder.CreateDup1(); builder.CreateLoadInt32(1); builder.CreateCmpEQ(); builder.CreateBr(justReturn, disposeAndReturn); // Dispose and return implementation. builder.SetBlock(disposeAndReturn); // Increase the state. builder.CreateLoadInt32(1); builder.CreateAdd(); builder.CreateStoreField(node.GeneratorState); // Call move next. builder.CreateCall(moveNext, 1); builder.CreateRetVoid(); // Just return implementation. builder.SetBlock(justReturn); builder.CreateRetVoid(); }
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(); }
private void CreateDefaultStaticConstructor(StructDefinition node) { // Get the structure. Structure building = node.GetStructure(); // Check for an user defined constructor. if(building.GetStaticConstructor() != null) return; // Get the static initialization fields. List<FieldDeclaration> staticInitedField = new List<FieldDeclaration> (); bool isUnsafe = false; foreach(FieldDeclaration decl in building.GetFieldInitializations()) { Variable variable = decl.GetVariable(); if(variable.IsStatic()) { staticInitedField.Add(decl); if(variable.IsUnsafe()) isUnsafe = true; } } // If there aren't field to initialize, don't create the static constructor. if(staticInitedField.Count == 0) return; // Begin the node. builder.BeginNode(node); // Create the static constructor function type. FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType()); // Create the constructor method. MemberFlags flags = MemberFlags.StaticConstructor; if(isUnsafe) flags |= MemberFlags.Unsafe; Method constructor = new Method("<sctor>", flags, building); constructor.SetFunctionType(ctorType); // Store it. building.AddFunction("<sctor>", constructor); // Create the constructor scope. LexicalScope ctorScope = CreateLexicalScope(node, constructor); PushScope(ctorScope); // Create the top basic block. BasicBlock topBlock = new BasicBlock(constructor); builder.SetBlock(topBlock); // Initialize the static fields. GenerateStaticFieldInitializations(node, staticInitedField); // Restore the scope. PopScope(); // Return void. builder.CreateRetVoid(); // End the node. builder.EndNode(); }
private void CreateDefaultConstructor(StructDefinition node) { // Get the structure. Structure building = node.GetStructure(); // Check for an user defined constructor. if(building.GetConstructor() != null) return; // Instance the building. GenericPrototype contGenProto = building.GetGenericPrototype(); int templateArgs = contGenProto.GetPlaceHolderCount(); Structure buildingInstance = building; if(templateArgs != 0) { IChelaType[] thisArgs = new IChelaType[templateArgs]; for(int i = 0; i < templateArgs; ++i) thisArgs[i] = contGenProto.GetPlaceHolder(i); buildingInstance = (Structure)building.InstanceGeneric( new GenericInstance(contGenProto, thisArgs), currentModule); } // Create the default constructor function type. List<IChelaType> arguments = new List<IChelaType> (); arguments.Add(ReferenceType.Create(buildingInstance)); FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType(), arguments); // Create the constructor method. MemberFlags flags = MemberFlags.Public | MemberFlags.Constructor; Method constructor = new Method(building.GetName(), flags, building); constructor.SetFunctionType(ctorType); // Store it. building.AddFunction("<ctor>", constructor); node.SetDefaultConstructor(constructor); }
public override AstNode Visit(DelegateDefinition node) { // Check the security. bool isUnsafe = (node.GetFlags() & MemberFlags.SecurityMask) == MemberFlags.Unsafe; if(isUnsafe) PushUnsafe(); // Get the delegate building. Structure building = node.GetStructure(); // Use the generic prototype. // Use the generic scope. PseudoScope genScope = node.GetGenericScope(); if(genScope != null) PushScope(genScope); // Visit the argument list. VisitList(node.GetArguments()); // Visit the return type. Expression returnTypeExpr = node.GetReturnType(); returnTypeExpr.Accept(this); IChelaType returnType = returnTypeExpr.GetNodeType(); returnType = ExtractActualType(returnTypeExpr, returnType); // Use references for class/interface. if(returnType.IsPassedByReference()) returnType = ReferenceType.Create(returnType); // Create the invoke function type. List<IChelaType> arguments = new List<IChelaType> (); // Add the argument types. AstNode argNode = node.GetArguments(); while(argNode != null) { arguments.Add(argNode.GetNodeType()); argNode = argNode.GetNext(); } // Create the function type. FunctionType functionType = FunctionType.Create(returnType, arguments); // Check the type security. if(functionType.IsUnsafe()) UnsafeError(node, "safe delegate with unsafe type."); // Create the invoke type. List<IChelaType> invokeArguments = new List<IChelaType> (); invokeArguments.Add(ReferenceType.Create(building)); for(int i = 0; i < arguments.Count; ++i) invokeArguments.Add(arguments[i]); FunctionType invokeType = FunctionType.Create(returnType, invokeArguments); // Create the constructor type. List<IChelaType> ctorArguments = new List<IChelaType> (); ctorArguments.Add(ReferenceType.Create(building)); ctorArguments.Add(ReferenceType.Create(currentModule.TypeMap(ChelaType.GetObjectType()))); ctorArguments.Add(ReferenceType.Create(functionType)); FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType(), ctorArguments); // Create the constructor method. Method ctorMethod = new Method("<ctor>", MemberFlags.Public | MemberFlags.Runtime | MemberFlags.Constructor, building); ctorMethod.SetFunctionType(ctorType); building.AddFunction("<ctor>", ctorMethod); // Create the invoke function. Method invokeMethod = new Method("Invoke", MemberFlags.Public | MemberFlags.Runtime, building); invokeMethod.SetFunctionType(invokeType); building.AddFunction("Invoke", invokeMethod); // Restore the scope. if(genScope != null) PopScope(); // Restore the security level. if(isUnsafe) PushUnsafe(); return node; }