@@ -66,6 +66,7 @@ typedef struct
6666typedef enum
6767{
6868 TYPE_FUNCTION ,
69+ TYPE_METHOD ,
6970 TYPE_SCRIPT ,
7071} FunctionType ;
7172
@@ -81,10 +82,17 @@ typedef struct Compiler
8182 int scope_depth ;
8283} Compiler ;
8384
85+ typedef struct ClassCompiler
86+ {
87+ struct ClassCompiler * enclosing ;
88+ Token name ;
89+ } ClassCompiler ;
90+
8491static bool immutable_globals [UINT8_MAX ];
8592
86- Parser parser ;
87- Compiler * current = NULL ;
93+ Parser parser ;
94+ Compiler * current = NULL ;
95+ ClassCompiler * current_class = NULL ;
8896
8997static Chunk * current_chunk ()
9098{
@@ -241,8 +249,16 @@ static void init_compiler(Compiler* compiler, FunctionType type)
241249 local -> depth = 0 ;
242250 local -> is_captured = false;
243251 local -> is_immutable = false;
244- local -> name .start = "" ;
245- local -> name .length = 0 ;
252+ if (type != TYPE_FUNCTION )
253+ {
254+ local -> name .start = "this" ;
255+ local -> name .length = 4 ;
256+ }
257+ else
258+ {
259+ local -> name .start = "" ;
260+ local -> name .length = 0 ;
261+ }
246262}
247263
248264static ObjFunction * end_compiler ()
@@ -617,6 +633,16 @@ static void variable(bool can_assign)
617633 named_variable (parser .previous , can_assign );
618634}
619635
636+ static void this_ (bool can_assign )
637+ {
638+ if (current_class == NULL )
639+ {
640+ error ("Can't use 'this' outside of a class" );
641+ return ;
642+ }
643+ variable (false);
644+ }
645+
620646static void unary (bool can_assign )
621647{
622648 TokenType operator_type = parser .previous .type ;
@@ -642,7 +668,7 @@ ParseRule rules[] = {
642668 [TOKEN_LEFT_BRACE ] = { NULL , NULL , PREC_NONE },
643669 [TOKEN_RIGHT_BRACE ] = { NULL , NULL , PREC_NONE },
644670 [TOKEN_COMMA ] = { NULL , NULL , PREC_NONE },
645- [TOKEN_DOT ] = { NULL , dot , PREC_NONE },
671+ [TOKEN_DOT ] = { NULL , dot , PREC_NONE },
646672 [TOKEN_MINUS ] = { unary , binary , PREC_TERM },
647673 [TOKEN_PLUS ] = { NULL , binary , PREC_TERM },
648674 [TOKEN_SEMICOLON ] = { NULL , NULL , PREC_NONE },
@@ -659,19 +685,19 @@ ParseRule rules[] = {
659685 [TOKEN_STRING ] = { string , NULL , PREC_NONE },
660686 [TOKEN_NUMBER ] = { number , NULL , PREC_NONE },
661687 [TOKEN_IDENTIFIER ] = { variable , NULL , PREC_NONE },
662- [TOKEN_AND ] = { NULL , and_ , PREC_AND },
688+ [TOKEN_AND ] = { NULL , and_ , PREC_AND },
663689 [TOKEN_CLASS ] = { NULL , NULL , PREC_NONE },
664690 [TOKEN_ELSE ] = { NULL , NULL , PREC_NONE },
665691 [TOKEN_FALSE ] = { literal , NULL , PREC_NONE },
666692 [TOKEN_FOR ] = { NULL , NULL , PREC_NONE },
667693 [TOKEN_FUN ] = { NULL , NULL , PREC_NONE },
668694 [TOKEN_IF ] = { NULL , NULL , PREC_NONE },
669695 [TOKEN_NIL ] = { literal , NULL , PREC_NONE },
670- [TOKEN_OR ] = { NULL , or_ , PREC_OR },
696+ [TOKEN_OR ] = { NULL , or_ , PREC_OR },
671697 [TOKEN_PRINT ] = { NULL , NULL , PREC_NONE },
672698 [TOKEN_RETURN ] = { NULL , NULL , PREC_NONE },
673699 [TOKEN_SUPER ] = { NULL , NULL , PREC_NONE },
674- [TOKEN_THIS ] = { NULL , NULL , PREC_NONE },
700+ [TOKEN_THIS ] = { this_ , NULL , PREC_NONE },
675701 [TOKEN_TRUE ] = { literal , NULL , PREC_NONE },
676702 [TOKEN_VAR ] = { NULL , NULL , PREC_NONE },
677703 [TOKEN_WHILE ] = { NULL , NULL , PREC_NONE },
@@ -769,7 +795,7 @@ static void method()
769795 consume (TOKEN_IDENTIFIER , "Expect method name." );
770796 u8 constant = identifier_constant (& parser .previous );
771797
772- FunctionType type = TYPE_FUNCTION ;
798+ FunctionType type = TYPE_METHOD ;
773799 function (type );
774800
775801 emit_bytes (OP_METHOD , constant );
@@ -784,6 +810,9 @@ static void class_declaration()
784810 emit_bytes (OP_CLASS , name_constant );
785811 define_variable (name_constant , true);
786812
813+ ClassCompiler class_compiler = {.name = parser .previous , .enclosing = current_class };
814+ current_class = & class_compiler ;
815+
787816 named_variable (class_name , false);
788817 consume (TOKEN_LEFT_BRACE , "Expected '{' after class name" );
789818 while (!check (TOKEN_RIGHT_BRACE ) && !check (TOKEN_EOF ))
@@ -792,6 +821,8 @@ static void class_declaration()
792821 }
793822 consume (TOKEN_RIGHT_BRACE , "Expected '}' after class body" );
794823 emit_byte (OP_POP );
824+
825+ current_class = current_class -> enclosing ;
795826}
796827
797828static void fun_declaration ()
0 commit comments