예제 #1
0
        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;
        }
예제 #2
0
        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);
        }
예제 #3
0
        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;
        }
예제 #4
0
        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();
        }
예제 #5
0
        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;
        }
예제 #6
0
        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;
        }