EndCompiler() 개인적인 메소드

private EndCompiler ( string debugName ) : ObjFn
debugName string
리턴 Wren.Core.Objects.ObjFn
예제 #1
0
        public static ObjFn Compile(WrenVM vm, ObjModule module, string sourcePath, string source, bool printErrors)
        {
            Parser parser = new Parser
            {
                vm = vm,
                Module = module,
                SourcePath = sourcePath,
                Source = source,
                TokenStart = 0,
                CurrentChar = 0,
                CurrentLine = 1,
                Current = { Type = TokenType.Error, Start = 0, Length = 0, Line = 0 },
                SkipNewlines = true,
                PrintErrors = printErrors,
                HasError = false,
                Raw = ""
            };

            Compiler compiler = new Compiler(parser, null, true);

            // Read the first token.
            compiler.NextToken();

            compiler.IgnoreNewlines();

            while (!compiler.Match(TokenType.Eof))
            {
                compiler.Definition();

                // If there is no newline, it must be the end of the block on the same line.
                if (!compiler.MatchLine())
                {
                    compiler.Consume(TokenType.Eof, "Expect end of file.");
                    break;
                }
            }

            compiler.Emit(Instruction.NULL);
            compiler.Emit(Instruction.RETURN);

            // See if there are any implicitly declared module-level variables that never
            // got an explicit definition.
            // TODO: It would be nice if the error was on the line where it was used.
            for (int i = 0; i < parser.Module.Variables.Count; i++)
            {
                ModuleVariable t = parser.Module.Variables[i];
                if (t.Container == Obj.Undefined)
                {
                    compiler.Error(string.Format("Variable '{0}' is used but not defined.", t.Name));
                }
            }

            return compiler.EndCompiler("(script)");
        }
예제 #2
0
        private void CreateConstructor(Signature signature, int initializerSymbol)
        {
            Compiler methodCompiler = new Compiler(_parser, this, false);

            methodCompiler.Emit(_enclosingClass.IsForeign ? Instruction.FOREIGN_CONSTRUCT : Instruction.CONSTRUCT);
            methodCompiler.EmitShortArg(Instruction.CALL_0 + signature.Arity, initializerSymbol);
            methodCompiler.Emit(Instruction.RETURN);

            methodCompiler.EndCompiler("");
        }
예제 #3
0
        // Compiles a method definition inside a class body. Returns the symbol in the
        // method table for the new method.
        private bool Method(ClassCompiler classCompiler, int classSlot)
        {

            bool isForeign = Match(TokenType.Foreign);
            classCompiler.IsStaticMethod = Match(TokenType.Static);

            SignatureFn signatureFn = GetRule(_parser.Current.Type).Method;
            NextToken();

            if (signatureFn == null)
            {
                Error("Expect method definition.");
                return false;
            }

            // Build the method signature.
            Signature signature = SignatureFromToken(new Signature(), SignatureType.Getter);
            classCompiler.Signature = signature;

            Compiler methodCompiler = new Compiler(_parser, this, false);
            signatureFn(methodCompiler, signature);

            if (classCompiler.IsStaticMethod && signature.Type == SignatureType.Initializer)
            {
                Error("A constructor cannot be static.");
            }

            String fullSignature = SignatureToString(signature);

            if (isForeign)
            {
                int constant = AddConstant(Obj.MakeString(fullSignature));

                EmitShortArg(Instruction.CONSTANT, constant);
            }
            else
            {
                Consume(TokenType.LeftBrace, "Expect '{' to begin method body.");
                methodCompiler.FinishBody(signature.Type == SignatureType.Initializer);
                methodCompiler.EndCompiler(fullSignature);
            }

            // Define the method. For a constructor, this defines the instance
            // initializer method.
            int methodSymbol = SignatureSymbol(signature);
            DefineMethod(classSlot, classCompiler.IsStaticMethod, methodSymbol);

            if (signature.Type == SignatureType.Initializer)
            {
                signature.Type = SignatureType.Method;
                int constructorSymbol = SignatureSymbol(signature);
                CreateConstructor(signature, methodSymbol);
                DefineMethod(classSlot, true, constructorSymbol);
            }

            return true;
        }
예제 #4
0
        // Compiles an (optional) argument list and then calls it.
        private void MethodCall(Instruction instruction, Signature signature)
        {
            Signature called = new Signature { Type = SignatureType.Getter, Arity = 0, Name = signature.Name, Length = signature.Length };

            // Parse the argument list, if any.
            if (Match(TokenType.LeftParen))
            {
                called.Type = SignatureType.Method;

                // Allow empty an argument list.
                if (Peek() != TokenType.RightParen)
                {
                    FinishArgumentList(called);
                }
                Consume(TokenType.RightParen, "Expect ')' after arguments.");
            }

            // Parse the block argument, if any.
            if (Match(TokenType.LeftBrace))
            {
                // Include the block argument in the arity.
                called.Type = SignatureType.Method;
                called.Arity++;

                Compiler fnCompiler = new Compiler(_parser, this, true);

                // Make a dummy signature to track the arity.
                Signature fnSignature = new Signature { Arity = 0 };

                // Parse the parameter list, if any.
                if (Match(TokenType.Pipe))
                {
                    fnCompiler.FinishParameterList(fnSignature);
                    Consume(TokenType.Pipe, "Expect '|' after function parameters.");
                }

                fnCompiler._numParams = fnSignature.Arity;

                fnCompiler.FinishBody(false);

                String blockName = SignatureToString(called) + " block argument";
                fnCompiler.EndCompiler(blockName);
            }

            // TODO: Allow Grace-style mixfix methods?

            // If this is a super() call for an initializer, make sure we got an actual
            // argument list.
            if (signature.Type == SignatureType.Initializer)
            {
                if (called.Type != SignatureType.Method)
                {
                    Error("A superclass constructor must have an argument list.");
                }

                called.Type = SignatureType.Initializer;
            }

            CallSignature(instruction, called);
        }
예제 #5
0
        // Compiles a method definition inside a class body. Returns the symbol in the
        // method table for the new method.
        private bool Method(ClassCompiler classCompiler, int classSlot, out bool hasConstructor)
        {
            hasConstructor = false;

            bool isForeign = Match(TokenType.TOKEN_FOREIGN);
            classCompiler.isStaticMethod = Match(TokenType.TOKEN_STATIC);

            SignatureFn signatureFn = GetRule(parser.current.type).method;
            NextToken();

            if (signatureFn == null)
            {
                Error("Expect method definition.");
                return false;
            }

            // Build the method signature.
            Signature signature = SignatureFromToken(SignatureType.SIG_GETTER);
            classCompiler.signature = signature;

            Compiler methodCompiler = new Compiler(parser, this, false);
            signatureFn(methodCompiler, signature);

            if (classCompiler.isStaticMethod && signature.Type == SignatureType.SIG_INITIALIZER)
            {
                Error("A constructor cannot be static.");
            }

            String fullSignature = SignatureToString(signature);

            if (isForeign)
            {
                int constant = AddConstant(new Value(fullSignature));

                EmitShortArg(Instruction.CONSTANT, constant);
            }
            else
            {
                Consume(TokenType.TOKEN_LEFT_BRACE, "Expect '{' to begin method body.");
                methodCompiler.FinishBody(signature.Type == SignatureType.SIG_INITIALIZER);
                methodCompiler.EndCompiler(fullSignature);
            }

            // Define the method. For a constructor, this defines the instance
            // initializer method.
            int methodSymbol = SignatureSymbol(signature);
            DefineMethod(classSlot, classCompiler.isStaticMethod, methodSymbol);

            if (signature.Type == SignatureType.SIG_INITIALIZER)
            {
                signature.Type = SignatureType.SIG_METHOD;
                int constructorSymbol = SignatureSymbol(signature);
                CreateConstructor(signature, methodSymbol);
                DefineMethod(classSlot, true, constructorSymbol);

                hasConstructor = true;
            }

            return true;
        }
예제 #6
0
        // Compiles an (optional) argument list and then calls it.
        private void MethodCall(Instruction instruction, Signature signature)
        {
            Signature called = new Signature { Type = SignatureType.SIG_GETTER, Arity = 0, Name = signature.Name, Length = signature.Length };

            // Parse the argument list, if any.
            if (Match(TokenType.TOKEN_LEFT_PAREN))
            {
                called.Type = SignatureType.SIG_METHOD;

                // Allow empty an argument list.
                if (Peek() != TokenType.TOKEN_RIGHT_PAREN)
                {
                    FinishArgumentList(called);
                }
                Consume(TokenType.TOKEN_RIGHT_PAREN, "Expect ')' after arguments.");
            }

            // Parse the block argument, if any.
            if (Match(TokenType.TOKEN_LEFT_BRACE))
            {
                // Include the block argument in the arity.
                called.Type = SignatureType.SIG_METHOD;
                called.Arity++;

                Compiler fnCompiler = new Compiler(parser, this, true);

                // Make a dummy signature to track the arity.
                Signature fnSignature = new Signature { Arity = 0 };

                // Parse the parameter list, if any.
                if (Match(TokenType.TOKEN_PIPE))
                {
                    fnCompiler.FinishParameterList(fnSignature);
                    Consume(TokenType.TOKEN_PIPE, "Expect '|' after function parameters.");
                }

                fnCompiler.numParams = fnSignature.Arity;

                fnCompiler.FinishBody(false);

                String blockName = SignatureToString(called) + " block argument";
                fnCompiler.EndCompiler(blockName);
            }

            // TODO: Allow Grace-style mixfix methods?

            // If this is a super() call for an initializer, make sure we got an actual
            // argument list.
            if (signature.Type == SignatureType.SIG_INITIALIZER)
            {
                if (called.Type != SignatureType.SIG_METHOD)
                {
                    Error("A superclass constructor must have an argument list.");
                }

                called.Type = SignatureType.SIG_INITIALIZER;
            }

            CallSignature(instruction, called);
        }