@@ -55,6 +55,12 @@ typedef struct
5555 bool is_immutable ;
5656} Local ;
5757
58+ typedef struct
59+ {
60+ u8 index ;
61+ bool islocal ;
62+ } Upvalue ;
63+
5864typedef enum
5965{
6066 TYPE_FUNCTION ,
@@ -67,9 +73,10 @@ typedef struct Compiler
6773 ObjFunction * function ;
6874 FunctionType type ;
6975
70- Local locals [UINT8_COUNT ];
71- int local_count ;
72- int scope_depth ;
76+ Local locals [UINT8_COUNT ];
77+ int local_count ;
78+ Upvalue upvalues [UINT8_COUNT ];
79+ int scope_depth ;
7380} Compiler ;
7481
7582static bool immutable_globals [UINT8_MAX ];
@@ -303,6 +310,43 @@ static int resolve_local(Compiler* compiler, Token* name)
303310 return -1 ;
304311}
305312
313+ static int add_upvalue (Compiler * compiler , u8 index , bool islocal )
314+ {
315+ int upvalue_count = compiler -> function -> upvalue_count ;
316+ for (int i = 0 ; i < upvalue_count ; i ++ )
317+ {
318+ Upvalue * upvalue = & compiler -> upvalues [i ];
319+ if (upvalue -> index == index && upvalue -> islocal == islocal )
320+ return i ;
321+ }
322+
323+ if (upvalue_count == UINT8_COUNT )
324+ {
325+ error ("Too many closure variables in function" );
326+ return 0 ;
327+ }
328+
329+ compiler -> upvalues [upvalue_count ].islocal = islocal ;
330+ compiler -> upvalues [upvalue_count ].index = index ;
331+ return compiler -> function -> upvalue_count ++ ;
332+ }
333+
334+ static int resolve_upvalue (Compiler * compiler , Token * name )
335+ {
336+ if (compiler -> enclosing == NULL )
337+ return -1 ;
338+
339+ int local = resolve_local (compiler -> enclosing , name );
340+ if (local != -1 )
341+ return add_upvalue (compiler , (u8 )local , true);
342+
343+ int upvalue = resolve_upvalue (compiler -> enclosing , name );
344+ if (upvalue != -1 )
345+ return add_upvalue (compiler , (u8 )upvalue , false);
346+
347+ return -1 ;
348+ }
349+
306350static void add_local (Token name , bool is_immutable )
307351{
308352 if (current -> local_count == UINT8_COUNT )
@@ -503,6 +547,11 @@ static void named_variable(Token name, bool can_assign)
503547 get_op = OP_GET_LOCAL ;
504548 set_op = OP_SET_LOCAL ;
505549 }
550+ else if ((arg = resolve_upvalue (current , & name )) != -1 )
551+ {
552+ get_op = OP_GET_UPVALUE ;
553+ set_op = OP_SET_UPVALUE ;
554+ }
506555 else
507556 {
508557 arg = identifier_constant (& name );
@@ -680,6 +729,12 @@ static void function(FunctionType type)
680729
681730 ObjFunction * function = end_compiler ();
682731 emit_bytes (OP_CLOSURE , make_constant (OBJ_VAL (function )));
732+
733+ for (int i = 0 ; i < function -> upvalue_count ; i ++ )
734+ {
735+ emit_byte (compiler .upvalues [i ].islocal ? 1 : 1 );
736+ emit_byte (compiler .upvalues [i ].index );
737+ }
683738}
684739
685740static void fun_declaration ()
0 commit comments