public override AstNode Visit(FunctionDefinition node) { // Process attributes. ProcessAttributes(node); // Ignore pure declarations. if(node.GetChildren() == null) return node; // Update the scope. PushScope(node.GetScope()); // Visit the children. VisitList(node.GetChildren()); // Restore the scope. PopScope(); return node; }
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); }
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; }
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; }