Esempio n. 1
0
        public override void Accept(FunctionDeclaration node)
        {
            // Add the function name to the scope
            symbolTable.AddSymbol(node.Name.Value);

            // Begin a new scope
            symbolTable.InvokeInNewScope(() => {
                // Iterate over the function arguments
                foreach (var arg in node.Arguments)
                {
                    // Add the argument to the scope
                    symbolTable.AddSymbol(arg.Name.Value);
                }

                // Visit the children of the function declaration
                node.VisitChildren(this);
            });
        }
Esempio n. 2
0
        /*
         * 'fn' < name > < argument_list > < code_block >
         */
        FunctionDeclaration ParseFunctionDeclaration()
        {
            var node = new FunctionDeclaration(unit.Location);

            // Expect the 'fn' keyword
            unit.Expect(TokenClass.Keyword, "fn");

            // Read the name of the function
            node.Name = ParseName();

            // Read the argument list
            node.Arguments.AddRange(ParseDeclarationArgumentList());

            // Parse the function body
            node.Body = ParseBlock();

            // Return the function declaration
            return(node);
        }
Esempio n. 3
0
 public virtual void Accept(FunctionDeclaration node) => Update(node);
Esempio n. 4
0
        public override void Accept(FunctionDeclaration node)
        {
            // Add the function name to the scope
            Context.SymbolTable.AddSymbol(node.Name.Value);

            // Invoke the following action within a new scope
            Context.SymbolTable.InvokeInNewScope(() => {
                // Create an emitter for the function body
                var body = new Emitter();

                // Invoke the following action within a new context
                InvokeInNewContext(body, () => {
                    // Iterate over the arguments of the function
                    foreach (var arg in node.Arguments)
                    {
                        // Add the argument name to the scope
                        Context.SymbolTable.AddSymbol(arg.Name.Value);

                        // Test if the argument has a type hint
                        if (arg.HasTypeHint)
                        {
                            // Compile the type hint
                            arg.TypeHint.Visit(this);

                            // Create a name object for the argument name
                            var name = new IodineName(arg.Name.Value);

                            // Make the name constant
                            var constant = Context.Module.DefineConstant(name);

                            // Perform a behavior check on the object
                            Context.Emitter.Emit(
                                opcode: Opcode.CastLocal,
                                arg: constant
                                );
                        }
                    }

                    // Visit the children of the function
                    node.VisitChildren(this);
                });

                // Resolve the function body
                body.Resolve();

                // Create method flags
                var flags = MethodFlags.None;

                // TODO: Implement method flags

                // Iterate over the arguments of the function
                foreach (var arg in node.Arguments)
                {
                    // Create a string object with the name of the argument
                    var str = new IodineString(arg.Name.Value);

                    // Make the string object constant
                    var constant = Context.Module.DefineConstant(str);

                    // Load the constant argument name string
                    Context.Emitter.Emit(
                        opcode: Opcode.LoadConst,
                        arg: constant
                        );
                }

                // Build a tuple to hold [argument_count] elements
                Context.Emitter.Emit(
                    opcode: Opcode.BuildTuple,
                    arg: node.Arguments.Count
                    );

                // Enter a new scope to satisfy the C# compiler
                {
                    // Make the generated byte code constant
                    var constant = Context.Module.DefineConstant(body);

                    // Load the generated byte code as constant
                    Context.Emitter.Emit(
                        opcode: Opcode.LoadConst,
                        arg: constant
                        );
                }

                // Build the function
                Context.Emitter.Emit(
                    opcode: Opcode.BuildFunction,
                    arg: (int)flags
                    );
            });
        }