コード例 #1
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
        // Compiles an (optional) argument list and then calls it.
        private void MethodCall(Instruction instruction, string name, int length)
        {
            Signature signature = new Signature { Type = SignatureType.Getter, Arity = 0, Name = name, Length = length };

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

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

            // Parse the block argument, if any.
            if (Match(TokenType.LeftBrace))
            {
                // Include the block argument in the arity.
                signature.Type = SignatureType.Method;
                signature.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);

                // TODO: Use the name of the method the block is being provided to.
                fnCompiler.EndCompiler();
            }

            // TODO: Allow Grace-style mixfix methods?
            CallSignature(instruction, signature);
        }
コード例 #2
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
        public static ObjFn Compile(SophieVM 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 },
                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();
        }
コード例 #3
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
        // Compiles a method definition inside a class body. Returns the symbol in the
        // method table for the new method.
        private int Method(ClassCompiler classCompiler, bool isConstructor, SignatureFn signatureFn)
        {
            // Build the method signature.
            Signature signature = new Signature();
            SignatureFromToken(signature);

            classCompiler.MethodName = signature.Name;
            classCompiler.MethodLength = signature.Length;

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

            // Compile the method signature.
            signatureFn(methodCompiler, signature);

            // Include the full signature in debug messages in stack traces.

            Consume(TokenType.LeftBrace, "Expect '{' to begin method body.");
            methodCompiler.FinishBody(isConstructor);

            methodCompiler.EndCompiler();

            return SignatureSymbol(signature);
        }