/// <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 }
/// <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); }