public override AstNode Visit(FunctionDefinition node) { // Visit the prototype. node.GetPrototype().Accept(this); return node; }
private void DefineGeneratorBody(FunctionDefinition node) { // Get entry function. Function entryFunction = node.GetFunction(); // Rebase his locals. entryFunction.RebaseLocals(); // Create the generator class. Scope spaceScope = entryFunction.GetParentScope(); Class generatorClass = new Class(GenSym(), MemberFlags.Internal, spaceScope); node.GeneratorClass = generatorClass; // Use the same generic prototype as the entry point function. generatorClass.SetGenericPrototype(entryFunction.GetGenericPrototype()); // Add the generator class to the same scope as the function. if(spaceScope.IsClass() || spaceScope.IsStructure()) { Structure parentClass = (Structure)spaceScope; parentClass.AddType(generatorClass); } else if(spaceScope.IsNamespace()) { Namespace parentSpace = (Namespace)spaceScope; parentSpace.AddMember(generatorClass); } else { Error(node, "Cannot create generator class in {0}", spaceScope.GetFullName()); } // Add the enumerable interface. Structure enumerableIface = null; if(node.IsEnumerable) { enumerableIface = currentModule.GetEnumerableIface(); if(node.IsGenericIterator) { enumerableIface = currentModule.GetEnumerableGIface(); GenericInstance gargs = new GenericInstance(enumerableIface.GetGenericPrototype(), new IChelaType[]{node.YieldType}); enumerableIface = (Structure)enumerableIface.InstanceGeneric(gargs, currentModule); } generatorClass.AddInterface(enumerableIface); } // Add the enumerator interface. Structure enumeratorIface = currentModule.GetEnumeratorIface(); if(node.IsGenericIterator) { enumeratorIface = currentModule.GetEnumeratorGIface(); GenericInstance gargs = new GenericInstance(enumeratorIface.GetGenericPrototype(), new IChelaType[]{node.YieldType}); enumeratorIface = (Structure)enumeratorIface.InstanceGeneric(gargs, currentModule); } generatorClass.AddInterface(enumeratorIface); // Create the yielded field. FieldVariable yieldedValue = new FieldVariable("yielded", MemberFlags.Private, node.YieldType, generatorClass); generatorClass.AddField(yieldedValue); node.YieldedValue = yieldedValue; // Create the generator state variable. FieldVariable generatorState = new FieldVariable("state", MemberFlags.Private, ChelaType.GetIntType(), generatorClass); generatorClass.AddField(generatorState); node.GeneratorState = generatorState; // Encapsulate the locals in fields. foreach(LocalVariable local in entryFunction.GetLocals()) { if(!local.IsPseudoLocal) continue; // Variables containing arguments must be public. MemberFlags access = MemberFlags.Private; if(local.ArgumentIndex >= 0) access = MemberFlags.Public; // Create the field to hold the state. FieldVariable localField = new FieldVariable(GenSym(), access, local.GetVariableType(), generatorClass); generatorClass.AddField(localField); local.ActualVariable = localField; } // Create an instance of the generator class. Structure generatorClassInstance = generatorClass.GetClassInstance(); if(generatorClass.GetGenericPrototype().GetPlaceHolderCount() != 0) { // Create an instance using the same placeholders. GenericPrototype proto = generatorClass.GetGenericPrototype(); int numargs = proto.GetPlaceHolderCount(); IChelaType[] protoInstance = new IChelaType[numargs]; for(int i = 0; i < numargs; ++i) protoInstance[i] = proto.GetPlaceHolder(i); // Instance the generic class. GenericInstance instance = new GenericInstance(proto, protoInstance); generatorClassInstance = (Structure)generatorClassInstance.InstanceGeneric(instance, currentModule); } node.GeneratorClassInstance = generatorClassInstance; // Create the trivial constructor. Function ctor = CreateTrivialConstructor(generatorClass, generatorClassInstance); if(generatorClass.IsGeneric()) ctor = FindFirstConstructor(generatorClassInstance); // Create a local to hold the created closure. LexicalScope topScope = (LexicalScope)node.GetScope(); LocalVariable closureLocal = new LocalVariable("closure", topScope, ReferenceType.Create(generatorClassInstance)); // Create the entry point content. BasicBlock entryBlock = CreateBasicBlock(); entryBlock.SetName("entry"); builder.SetBlock(entryBlock); // Create the closure and store it in his local. builder.CreateNewObject(generatorClassInstance, ctor, 0); builder.CreateStoreLocal(closureLocal); // Load the closure. builder.CreateLoadLocal(closureLocal); // Store the arguments into the closure. FunctionPrototype prototype = node.GetPrototype(); AstNode argument = prototype.GetArguments(); byte index = 0; while(argument != null) { FunctionArgument argNode = (FunctionArgument) argument; // TODO: Forbid ref, out, stream arguments here. // Store the argument in the closure. LocalVariable argVar = argNode.GetVariable(); if(argVar != null) { // Load the closure builder.CreateDup1(); // Load the argument. builder.CreateLoadArg(index); // Store it into the field. builder.CreateStoreField((FieldVariable)argVar.ActualVariable); } // Process the next argument. argument = argument.GetNext(); index++; } // Encapsulate the argument variables. foreach(ArgumentVariable argVar in node.ArgumentVariables) { if(!argVar.IsPseudoArgument) continue; // Create the argument field. FieldVariable argField = new FieldVariable(GenSym(), MemberFlags.Public, argVar.GetVariableType(), generatorClass); generatorClass.AddField(argField); argVar.ActualVariable = argField; // Store the self field. if(!currentFunction.IsStatic() && argVar.GetArgumentIndex() == 0) node.GeneratorSelf = argField; // Load the closure. builder.CreateDup1(); // Load the argument. builder.CreateLoadArg((byte)argVar.GetArgumentIndex()); // Store it into the closure. builder.CreateStoreField(argField); } // Return the generator. builder.CreateRet(); // Notify the yields about their states. int stateIndex = 2; foreach(ReturnStatement yieldStmtn in node.Yields) { yieldStmtn.YieldState = stateIndex; stateIndex += 2; } // Implement IEnumerator. if(node.IsEnumerable) { // Create the object GetEnumerator method. CreateGenerator_GetEnumerator(node, currentModule.GetEnumeratorIface(), false); // Create the generic GetEnumerator method if(node.IsGenericIterator) CreateGenerator_GetEnumerator(node, enumeratorIface, true); } // Create the Current property. CreateGenerator_Current(node, false); if(node.IsGenericIterator) CreateGenerator_Current(node, true); // Create the Reset method. CreateGenerator_Reset(node); // Create the MoveNext method. Function moveNext = CreateGenerator_MoveNext(node); // Create the Dispose method. CreateGenerator_Dispose(node, moveNext); // Fix the inheritance. generatorClass.FixInheritance(); }
private void DefineFunctionBody(FunctionDefinition node, Function function, LexicalScope topScope) { // Create the top basic block. BasicBlock topBlock = CreateBasicBlock(); topBlock.SetName("top"); builder.SetBlock(topBlock); // Prepare returning. PrepareReturning(node, function, topScope); // Store the arguments into local variables. FunctionPrototype prototype = node.GetPrototype(); AstNode argument = prototype.GetArguments(); byte index = 0; while(argument != null) { FunctionArgument argNode = (FunctionArgument) argument; LocalVariable argVar = argNode.GetVariable(); if(argVar != null && !argVar.IsPseudoScope()) { // Load the argument. builder.CreateLoadArg(index); // Store it into the local. builder.CreateStoreLocal(argVar); } // Process the next argument. argument = argument.GetNext(); index++; } // Generate constructor initialization. if(function.IsConstructor()) { Method ctor = (Method)function; ConstructorInitializer ctorInit = prototype.GetConstructorInitializer(); if(ctorInit != null) ctorInit.Accept(this); else CreateImplicitBaseConstructor(node, ctor); // Initialize some field. if(ctor.IsCtorLeaf()) { Structure building = (Structure)ctor.GetParentScope(); GenerateFieldInitializations(node, building); } } else if(function.IsStaticConstructor()) { // Generate static field initialization. Scope parent = function.GetParentScope(); Structure pbuilding = parent as Structure; if(pbuilding != null) GenerateStaticFieldInitializations(node, function, pbuilding); } // Visit his children. VisitList(node.GetChildren()); // Finish return. FinishReturn(node, function); }
public override AstNode Visit(FunctionDefinition node) { // Begin the node. builder.BeginNode(node); // Process attributes. ProcessAttributes(node); // Get the prototype. FunctionPrototype prototype = node.GetPrototype(); // Get the function. Function function = prototype.GetFunction(); // Ignore functions without a body. if(node.GetChildren() == null) return builder.EndNode(); // Store the old function. // TODO: Add closures Function oldFunction = currentFunction; currentFunction = function; // Update the securiry. if(function.IsUnsafe()) PushUnsafe(); // Get the function lexical scope. LexicalScope topScope = (LexicalScope)node.GetScope(); // Update the scope. PushScope(topScope); // Define the generator or function body if(node.IsGenerator) DefineGeneratorBody(node); else DefineFunctionBody(node, function, topScope); // Restore the scope. PopScope(); // Restore the security. if(function.IsUnsafe()) PopUnsafe(); // Restore the current function. currentFunction = oldFunction; return builder.EndNode(); }
public override AstNode Visit(FunctionDefinition node) { // Get the prototype. FunctionPrototype prototype = node.GetPrototype(); // Visit the prototype. prototype.Accept(this); // Set the node type. node.SetNodeType(prototype.GetNodeType()); // Get and link the function with the definition. Function function = prototype.GetFunction(); node.SetFunction(function); // Create finalizers as macros. AstNode children = node.GetChildren(); if(prototype.GetDestructorName() != null && children != null) { TokenPosition position = node.GetPosition(); // Get the base finalizer. Expression baseFinalizer = new MemberAccess(new BaseExpression(position), "Finalize", position); // Invoke it. AstNode baseInvoke = new CallExpression(baseFinalizer, null, position); FinallyStatement finalStmnt = new FinallyStatement(baseInvoke, position); // Try the finalizer, always invoke the parent finalizer. TryStatement tryStmnt = new TryStatement(children, null, finalStmnt, position); node.SetChildren(tryStmnt); } return node; }
public override AstNode Visit(FunctionDefinition node) { // Process attributes. ProcessAttributes(node); // Get the prototype. FunctionPrototype prototype = node.GetPrototype(); // Get the function. Function function = prototype.GetFunction(); // Store the definition node in the function. if(function.DefinitionNode != null) Error(node, "multiples definition of a function."); function.DefinitionNode = node; // Check for declarations, interfaces. MemberFlags instanceFlags = function.GetFlags() & MemberFlags.InstanceMask; if(instanceFlags == MemberFlags.Abstract || instanceFlags == MemberFlags.Contract || function.IsExternal()) { if(node.GetChildren() != null) Error(node, "abstract/extern functions cannot have a definition body."); return node; } else { if(node.GetChildren() == null) Error(node, "functions must have a definition."); } // Store the old function. // TODO: Add closures Function oldFunction = currentFunction; currentFunction = function; // Create the function lexical scope. LexicalScope topScope = CreateLexicalScope(node); node.SetScope(topScope); // Use the prototype scope. Scope protoScope = prototype.GetScope(); if(protoScope != null) PushScope(protoScope); // Update the scope. PushScope(topScope); // Push the security. if(function.IsUnsafe()) PushUnsafe(); // Declare the argument variables. AstNode argument = prototype.GetArguments(); int index = 0; while(argument != null) { // Cast the argument node. FunctionArgument argNode = (FunctionArgument)argument; // Set the argument name. string name = argument.GetName(); ArgumentData argData = function.GetArguments()[index++]; argData.Name = name; // Create the argument variable. if(name != null && name != "" && name != "this") { // Create the argument local variable LocalVariable argLocal = new LocalVariable(name, topScope, argNode.GetNodeType()); argLocal.Type = LocalType.Argument; argLocal.ArgumentIndex = index; // Store it in the argument node. argNode.SetVariable(argLocal); } else if(name == "this") { // Create the this argument. node.ArgumentVariables.Add( new ArgumentVariable(0, "this", topScope, argument.GetNodeType()) ); } argument = argument.GetNext(); } // Check the constructor initializer. if(function.IsConstructor()) CheckConstructorInit(node); // Visit his children. VisitList(node.GetChildren()); // Restore the security. if(function.IsUnsafe()) PopUnsafe(); // Restore the scope. PopScope(); // Restore the prototype scope. if(protoScope != null) PopScope(); // Restore the current function. currentFunction = oldFunction; return node; }
private void CheckConstructorInit(FunctionDefinition node) { // Get the prototype. FunctionPrototype prototype = node.GetPrototype(); // Get the constructor initializer. ConstructorInitializer ctorInit = prototype.GetConstructorInitializer(); // Get the function. Method function = (Method)prototype.GetFunction(); // Special check for the implicit constructor. if(ctorInit == null) { CheckDefaultConstructorInit(node, function); return; } // Get the base constructor. Structure building = (Structure)function.GetParentScope(); FunctionGroup ctorGroup; if(ctorInit.IsBaseCall()) { Structure baseBuilding = building.GetBase(); if(baseBuilding == null) Error(node, "cannot invoke base constructor in Object definition."); ctorGroup = baseBuilding.GetConstructor(); } else { ctorGroup = building.GetConstructor(); } // Store the constructor group. ctorInit.SetConstructorGroup(ctorGroup); // Visit the constructor initializer ctorInit.Accept(this); // Set the parent constructor. function.SetCtorParent((Method)ctorInit.GetConstructor()); // Make sure the construction invocation is acyclic. if(!function.IsCtorLeaf()) CheckConstructorCycles(node, function); }