Esempio n. 1
0
        /// <summary>
        /// Declares a method (a function in a class).
        /// Possible todo: merge this with FunctionDeclaration, as they share a lot of code.
        /// </summary>
        private void MethodDeclaration(string fnType, ELoxFunctionType fnType2)
        {
            Tokens.Consume(IDENTIFIER, $"Expect {fnType} name.");
            if (Tokens.Previous().Lexeme == "init")
            {
                fnType2 = ELoxFunctionType.TYPE_INITIALIZER;
            }
            string      fnName     = Tokens.Previous().Lexeme;
            int         fnLine     = LineOfLastToken;
            LoxCompiler fnCompiler = new LoxCompiler(Tokens, fnType2, fnName, this, _CurrentClass);

            fnCompiler.FunctionBody();
            fnCompiler.EndCompiler();
            EmitOpcode(fnLine, OP_LOAD_FUNCTION);
            EmitData(fnLine, (byte)fnCompiler.Arity);
            // EmitConstantIndex(MakeBitStrConstant(fnName), _FixupConstants); // has fixup
            AddFixup(fnLine, fnCompiler);
            EmitData(fnLine, (byte)fnCompiler._UpvalueCount);
            for (int i = 0; i < fnCompiler._UpvalueCount; i++)
            {
                EmitData(fnLine, (byte)(fnCompiler._UpvalueData[i].IsLocal ? 1 : 0));
                EmitData(fnLine, (byte)(fnCompiler._UpvalueData[i].Index));
            }
            EmitOpcode(fnLine, OP_METHOD);
            EmitConstantIndex(fnLine, MakeBitStrConstant(fnName), _FixupConstants); // has fixup
        }
Esempio n. 2
0
 private LoxCompiler(TokenList tokens, ELoxFunctionType type, string name, LoxCompiler enclosing, LoxCompilerClass enclosingClass)
     : base(tokens, name)
 {
     _FunctionType      = type;
     Arity              = 0;
     _Chunk             = new GearsChunk(name);
     _Rules             = new List <Rule>();
     _EnclosingCompiler = enclosing;
     _CurrentClass      = enclosingClass;
     // stack slot zero is used for 'this' reference in methods, and is empty for script/functions:
     if (type != ELoxFunctionType.TYPE_FUNCTION)
     {
         _LocalVarData[_LocalCount++] = new LoxCompilerLocal("this", 0);
     }
     else
     {
         _LocalVarData[_LocalCount++] = new LoxCompilerLocal(string.Empty, 0);
     }
 }
Esempio n. 3
0
 /// <summary>
 /// Attempts to compile the passed source, tokenizing first.
 /// If compilation is successful, compiler.Chunk will be set.
 /// If compilation fails, status will be the error message.
 /// </summary>
 public static bool TryCompileFromSource(string path, string source, out GearsChunk chunk, out string status)
 {
     try {
         TokenList   tokens   = new LoxTokenizer(path, source).ScanTokens();
         LoxCompiler compiler = new LoxCompiler(tokens, ELoxFunctionType.TYPE_SCRIPT, path, null, null);
         if (compiler.Compile())
         {
             chunk  = compiler._Chunk;
             status = null;
             return(true);
         }
         status = $"LoxCompiler: uncaught error while compiling {path}.";
         chunk  = null;
         return(false);
     }
     catch (CompilerException e) {
         chunk  = null;
         status = $"LoxCompiler at {e.TargetSite.DeclaringType.Name}.{e.TargetSite.Name} {path} {e}";
         return(false);
     }
 }
Esempio n. 4
0
        /// <summary>
        /// function    → IDENTIFIER "(" parameters? ")" block ;
        /// parameters  → IDENTIFIER( "," IDENTIFIER )* ;
        /// </summary>
        private void FunctionDeclaration(string fnType, ELoxFunctionType fnType2)
        {
            int global = ParseVariable($"Expect {fnType} name.");

            MarkInitialized();
            string      fnName     = Tokens.Previous().Lexeme;
            int         fnLine     = LineOfLastToken;
            LoxCompiler fnCompiler = new LoxCompiler(Tokens, fnType2, fnName, this, _CurrentClass);

            fnCompiler.FunctionBody();
            fnCompiler.EndCompiler();
            EmitOpcode(fnLine, OP_LOAD_FUNCTION);
            EmitData(fnLine, (byte)fnCompiler.Arity);
            // EmitConstantIndex(MakeBitStrConstant(fnName), _FixupConstants); // has fixup
            AddFixup(fnLine, fnCompiler);
            // EmitOpcode(OP_CLOSURE);
            EmitData(fnLine, (byte)fnCompiler._UpvalueCount);
            for (int i = 0; i < fnCompiler._UpvalueCount; i++)
            {
                EmitData(fnLine, (byte)(fnCompiler._UpvalueData[i].IsLocal ? 1 : 0));
                EmitData(fnLine, (byte)(fnCompiler._UpvalueData[i].Index));
            }
            DefineVariable(fnLine, global);
        }
Esempio n. 5
0
 private void AddFixup(int line, LoxCompiler fn)
 {
     _FixupFns.Add(fn);
     fn._OriginAddress = _Chunk.SizeCode;
     EmitData(line, 0, 0); // fn jump - to fix up
 }