@@ -107,6 +107,67 @@ static mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) {
107107 return o ;
108108}
109109
110+ static mp_obj_t code_colines_iter (mp_obj_t );
111+ static mp_obj_t code_colines_next (mp_obj_t );
112+ typedef struct _mp_obj_colines_iter_t {
113+ mp_obj_base_t base ;
114+ mp_fun_1_t iternext ;
115+ const mp_raw_code_t * rc ;
116+ mp_uint_t bc ;
117+ mp_uint_t source_line ;
118+ const byte * ci ;
119+ } mp_obj_colines_iter_t ;
120+
121+ static mp_obj_t code_colines_iter (mp_obj_t self_in ) {
122+ mp_obj_code_t * self = MP_OBJ_TO_PTR (self_in );
123+ mp_obj_colines_iter_t * iter = mp_obj_malloc (mp_obj_colines_iter_t , & mp_type_polymorph_iter );
124+ iter -> iternext = code_colines_next ;
125+ iter -> rc = self -> rc ;
126+ iter -> bc = 0 ;
127+ iter -> source_line = 1 ;
128+ iter -> ci = self -> rc -> prelude .line_info ;
129+ return MP_OBJ_FROM_PTR (iter );
130+ }
131+ static MP_DEFINE_CONST_FUN_OBJ_1 (code_colines_obj , code_colines_iter ) ;
132+
133+ static mp_obj_t code_colines_next (mp_obj_t iter_in ) {
134+ mp_obj_colines_iter_t * iter = MP_OBJ_TO_PTR (iter_in );
135+ const byte * ci_end = iter -> rc -> prelude .line_info_top ;
136+
137+ mp_uint_t start = iter -> bc ;
138+ mp_uint_t line_no = iter -> source_line ;
139+ bool another = true;
140+
141+ while (another && iter -> ci < ci_end ) {
142+ another = false;
143+ mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo (& iter -> ci );
144+ iter -> bc += decoded .bc_increment ;
145+ iter -> source_line += decoded .line_increment ;
146+
147+ if (decoded .bc_increment == 0 ) {
148+ line_no = iter -> source_line ;
149+ another = true;
150+ } else if (decoded .line_increment == 0 ) {
151+ another = true;
152+ }
153+ }
154+
155+ if (another ) {
156+ mp_uint_t prelude_size = (iter -> rc -> prelude .opcodes - (const byte * )iter -> rc -> fun_data );
157+ mp_uint_t bc_end = iter -> rc -> fun_data_len - prelude_size ;
158+ if (iter -> bc >= bc_end ) {
159+ return MP_OBJ_STOP_ITERATION ;
160+ } else {
161+ iter -> bc = bc_end ;
162+ }
163+ }
164+
165+ mp_uint_t end = iter -> bc ;
166+ mp_obj_t next [3 ] = {MP_OBJ_NEW_SMALL_INT (start ), MP_OBJ_NEW_SMALL_INT (end ), MP_OBJ_NEW_SMALL_INT (line_no )};
167+
168+ return mp_obj_new_tuple (MP_ARRAY_SIZE (next ), next );
169+ }
170+
110171static void code_attr (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
111172 if (dest [0 ] != MP_OBJ_NULL ) {
112173 // not load attribute
@@ -143,6 +204,10 @@ static void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
143204 }
144205 dest [0 ] = o -> lnotab ;
145206 break ;
207+ case MP_QSTR_co_lines :
208+ dest [0 ] = MP_OBJ_FROM_PTR (& code_colines_obj );
209+ dest [1 ] = self_in ;
210+ break ;
146211 }
147212}
148213
0 commit comments