@@ -179,6 +179,8 @@ struct _py_obj_base_t {
179
179
};
180
180
181
181
static qstr q_append ;
182
+ static qstr q_pop ;
183
+ static qstr q_sort ;
182
184
static qstr q_join ;
183
185
static qstr q_format ;
184
186
static qstr q___build_class__ ;
@@ -189,6 +191,7 @@ static qstr q_KeyError;
189
191
static qstr q_NameError ;
190
192
static qstr q_TypeError ;
191
193
static qstr q_SyntaxError ;
194
+ static qstr q_ValueError ;
192
195
193
196
py_obj_t py_const_none ;
194
197
py_obj_t py_const_false ;
@@ -786,6 +789,24 @@ py_obj_t rt_str_format(int n_args, const py_obj_t* args) {
786
789
return py_obj_new_str (qstr_from_str_take (vstr -> buf ));
787
790
}
788
791
792
+ uint get_index (py_obj_base_t * base , py_obj_t index ) {
793
+ // assumes base is O_TUPLE or O_LIST
794
+ // TODO False and True are considered 0 and 1 for indexing purposes
795
+ int len = base -> u_tuple_list .len ;
796
+ if (IS_SMALL_INT (index )) {
797
+ int i = FROM_SMALL_INT (index );
798
+ if (i < 0 ) {
799
+ i += len ;
800
+ }
801
+ if (i < 0 || i >= len ) {
802
+ nlr_jump (py_obj_new_exception_2 (q_IndexError , "%s index out of range" , py_obj_get_type_str (base ), NULL ));
803
+ }
804
+ return i ;
805
+ } else {
806
+ nlr_jump (py_obj_new_exception_2 (q_TypeError , "%s indices must be integers, not %s" , py_obj_get_type_str (base ), py_obj_get_type_str (index )));
807
+ }
808
+ }
809
+
789
810
py_obj_t rt_list_append (py_obj_t self_in , py_obj_t arg ) {
790
811
assert (IS_O (self_in , O_LIST ));
791
812
py_obj_base_t * self = self_in ;
@@ -797,6 +818,47 @@ py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
797
818
return py_const_none ; // return None, as per CPython
798
819
}
799
820
821
+ py_obj_t rt_list_pop (py_obj_t self_in , py_obj_t arg ) {
822
+ assert (IS_O (self_in , O_LIST ));
823
+ py_obj_base_t * self = self_in ;
824
+ uint index = get_index (self , arg );
825
+ py_obj_t ret = self -> u_tuple_list .items [index ];
826
+ self -> u_tuple_list .len -= 1 ;
827
+ memcpy (self -> u_tuple_list .items + index , self -> u_tuple_list .items + index + 1 , (self -> u_tuple_list .len - index ) * sizeof (py_obj_t ));
828
+ return ret ;
829
+ }
830
+
831
+ // TODO make this conform to CPython's definition of sort
832
+ static void py_quicksort (py_obj_t * head , py_obj_t * tail , py_obj_t key_fn ) {
833
+ while (head < tail ) {
834
+ py_obj_t * h = head - 1 ;
835
+ py_obj_t * t = tail ;
836
+ py_obj_t v = rt_call_function_1 (key_fn , tail [0 ]); // get pivot using key_fn
837
+ for (;;) {
838
+ do ++ h ; while (rt_compare_op (RT_COMPARE_OP_LESS , rt_call_function_1 (key_fn , h [0 ]), v ) == py_const_true );
839
+ do -- t ; while (h < t && rt_compare_op (RT_COMPARE_OP_LESS , v , rt_call_function_1 (key_fn , t [0 ])) == py_const_true );
840
+ if (h >= t ) break ;
841
+ py_obj_t x = h [0 ];
842
+ h [0 ] = t [0 ];
843
+ t [0 ] = x ;
844
+ }
845
+ py_obj_t x = h [0 ];
846
+ h [0 ] = tail [0 ];
847
+ tail [0 ] = x ;
848
+ py_quicksort (head , t , key_fn );
849
+ head = h + 1 ;
850
+ }
851
+ }
852
+
853
+ py_obj_t rt_list_sort (py_obj_t self_in , py_obj_t key_fn ) {
854
+ assert (IS_O (self_in , O_LIST ));
855
+ py_obj_base_t * self = self_in ;
856
+ if (self -> u_tuple_list .len > 1 ) {
857
+ py_quicksort (self -> u_tuple_list .items , self -> u_tuple_list .items + self -> u_tuple_list .len - 1 , key_fn );
858
+ }
859
+ return py_const_none ; // return None, as per CPython
860
+ }
861
+
800
862
py_obj_t rt_gen_instance_next (py_obj_t self_in ) {
801
863
py_obj_t ret = rt_iternext (self_in );
802
864
if (ret == py_const_stop_iteration ) {
@@ -839,6 +901,8 @@ static py_code_t *unique_codes;
839
901
py_obj_t fun_str_join ;
840
902
py_obj_t fun_str_format ;
841
903
py_obj_t fun_list_append ;
904
+ py_obj_t fun_list_pop ;
905
+ py_obj_t fun_list_sort ;
842
906
py_obj_t fun_gen_instance_next ;
843
907
844
908
py_obj_t py_builtin___repl_print__ (py_obj_t o ) {
@@ -938,6 +1002,8 @@ FILE *fp_write_code = NULL;
938
1002
939
1003
void rt_init (void ) {
940
1004
q_append = qstr_from_str_static ("append" );
1005
+ q_pop = qstr_from_str_static ("pop" );
1006
+ q_sort = qstr_from_str_static ("sort" );
941
1007
q_join = qstr_from_str_static ("join" );
942
1008
q_format = qstr_from_str_static ("format" );
943
1009
q___build_class__ = qstr_from_str_static ("__build_class__" );
@@ -948,6 +1014,7 @@ void rt_init(void) {
948
1014
q_NameError = qstr_from_str_static ("NameError" );
949
1015
q_TypeError = qstr_from_str_static ("TypeError" );
950
1016
q_SyntaxError = qstr_from_str_static ("SyntaxError" );
1017
+ q_ValueError = qstr_from_str_static ("ValueError" );
951
1018
952
1019
py_const_none = py_obj_new_const ("None" );
953
1020
py_const_false = py_obj_new_const ("False" );
@@ -972,6 +1039,8 @@ void rt_init(void) {
972
1039
fun_str_join = rt_make_function_2 (rt_str_join );
973
1040
fun_str_format = rt_make_function_var (1 , rt_str_format );
974
1041
fun_list_append = rt_make_function_2 (rt_list_append );
1042
+ fun_list_pop = rt_make_function_2 (rt_list_pop );
1043
+ fun_list_sort = rt_make_function_2 (rt_list_sort );
975
1044
fun_gen_instance_next = rt_make_function_1 (rt_gen_instance_next );
976
1045
977
1046
#ifdef WRITE_CODE
@@ -1280,24 +1349,6 @@ py_obj_t rt_unary_op(int op, py_obj_t arg) {
1280
1349
return py_const_none ;
1281
1350
}
1282
1351
1283
- uint get_index (py_obj_base_t * base , py_obj_t index ) {
1284
- // assumes base is O_TUPLE or O_LIST
1285
- // TODO False and True are considered 0 and 1 for indexing purposes
1286
- int len = base -> u_tuple_list .len ;
1287
- if (IS_SMALL_INT (index )) {
1288
- int i = FROM_SMALL_INT (index );
1289
- if (i < 0 ) {
1290
- i += len ;
1291
- }
1292
- if (i < 0 || i >= len ) {
1293
- nlr_jump (py_obj_new_exception_2 (q_IndexError , "%s index out of range" , py_obj_get_type_str (base ), NULL ));
1294
- }
1295
- return i ;
1296
- } else {
1297
- nlr_jump (py_obj_new_exception_2 (q_TypeError , "%s indices must be integers, not %s" , py_obj_get_type_str (base ), py_obj_get_type_str (index )));
1298
- }
1299
- }
1300
-
1301
1352
py_obj_t rt_binary_op (int op , py_obj_t lhs , py_obj_t rhs ) {
1302
1353
DEBUG_OP_printf ("binary %d %p %p\n" , op , lhs , rhs );
1303
1354
if (op == RT_BINARY_OP_SUBSCR ) {
@@ -1804,13 +1855,28 @@ py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1804
1855
nlr_jump (py_obj_new_exception_2 (q_TypeError , "function takes %d positional arguments but %d were given" , (const char * )(machine_int_t )n_args_fun , (const char * )(machine_int_t )n_args ));
1805
1856
}
1806
1857
1858
+ // args are in reverse order in the array; keyword arguments come first, value then key
1859
+ // eg: (value1, key1, value0, key0, arg1, arg0)
1860
+ py_obj_t rt_call_function_n_kw (py_obj_t fun , uint n_args , uint n_kw , const py_obj_t * args ) {
1861
+ // TODO
1862
+ assert (0 );
1863
+ return py_const_none ;
1864
+ }
1865
+
1807
1866
// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1808
1867
// if n_args==0 then there are only self/NULL and fun
1809
- py_obj_t rt_call_method_n (int n_args , const py_obj_t * args ) {
1810
- DEBUG_OP_printf ("call method %p(self=%p, n_args=%d )\n" , args [n_args + 1 ], args [n_args ], n_args );
1868
+ py_obj_t rt_call_method_n (uint n_args , const py_obj_t * args ) {
1869
+ DEBUG_OP_printf ("call method %p(self=%p, n_args=%u )\n" , args [n_args + 1 ], args [n_args ], n_args );
1811
1870
return rt_call_function_n (args [n_args + 1 ], n_args + ((args [n_args ] == NULL ) ? 0 : 1 ), args );
1812
1871
}
1813
1872
1873
+ // args contains: kw_val(n_kw-1) kw_key(n_kw-1) ... kw_val(0) kw_key(0) arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1874
+ py_obj_t rt_call_method_n_kw (uint n_args , uint n_kw , const py_obj_t * args ) {
1875
+ uint n = n_args + 2 * n_kw ;
1876
+ DEBUG_OP_printf ("call method %p(self=%p, n_args=%u, n_kw=%u)\n" , args [n + 1 ], args [n ], n_args , n_kw );
1877
+ return rt_call_function_n_kw (args [n + 1 ], n_args + ((args [n ] == NULL ) ? 0 : 1 ), n_kw , args );
1878
+ }
1879
+
1814
1880
// items are in reverse order
1815
1881
py_obj_t rt_build_tuple (int n_args , py_obj_t * items ) {
1816
1882
py_obj_base_t * o = m_new (py_obj_base_t , 1 );
@@ -1900,6 +1966,22 @@ py_obj_t rt_store_set(py_obj_t set, py_obj_t item) {
1900
1966
return set ;
1901
1967
}
1902
1968
1969
+ // unpacked items are stored in order into the array pointed to by items
1970
+ void rt_unpack_sequence (py_obj_t seq_in , uint num , py_obj_t * items ) {
1971
+ if (IS_O (seq_in , O_TUPLE ) || IS_O (seq_in , O_LIST )) {
1972
+ py_obj_base_t * seq = seq_in ;
1973
+ if (seq -> u_tuple_list .len < num ) {
1974
+ nlr_jump (py_obj_new_exception_2 (q_ValueError , "need more than %d values to unpack" , (void * )seq -> u_tuple_list .len , NULL ));
1975
+ } else if (seq -> u_tuple_list .len > num ) {
1976
+ nlr_jump (py_obj_new_exception_2 (q_ValueError , "too many values to unpack (expected %d)" , (void * )(machine_uint_t )num , NULL ));
1977
+ }
1978
+ memcpy (items , seq -> u_tuple_list .items , num * sizeof (py_obj_t ));
1979
+ } else {
1980
+ // TODO call rt_getiter and extract via rt_iternext
1981
+ nlr_jump (py_obj_new_exception_2 (q_TypeError , "'%s' object is not iterable" , py_obj_get_type_str (seq_in ), NULL ));
1982
+ }
1983
+ }
1984
+
1903
1985
py_obj_t rt_build_map (int n_args ) {
1904
1986
py_obj_base_t * o = m_new (py_obj_base_t , 1 );
1905
1987
o -> kind = O_MAP ;
@@ -1925,6 +2007,10 @@ py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1925
2007
DEBUG_OP_printf ("load attr %s\n" , qstr_str (attr ));
1926
2008
if (IS_O (base , O_LIST ) && attr == q_append ) {
1927
2009
return build_bound_method (base , fun_list_append );
2010
+ } else if (IS_O (base , O_LIST ) && attr == q_pop ) {
2011
+ return build_bound_method (base , fun_list_pop );
2012
+ } else if (IS_O (base , O_LIST ) && attr == q_sort ) {
2013
+ return build_bound_method (base , fun_list_sort );
1928
2014
} else if (IS_O (base , O_CLASS )) {
1929
2015
py_obj_base_t * o = base ;
1930
2016
py_map_elem_t * elem = py_qstr_map_lookup (o -> u_class .locals , attr , false);
@@ -1977,6 +2063,14 @@ void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1977
2063
dest [1 ] = fun_list_append ;
1978
2064
dest [0 ] = base ;
1979
2065
return ;
2066
+ } else if (IS_O (base , O_LIST ) && attr == q_pop ) {
2067
+ dest [1 ] = fun_list_pop ;
2068
+ dest [0 ] = base ;
2069
+ return ;
2070
+ } else if (IS_O (base , O_LIST ) && attr == q_sort ) {
2071
+ dest [1 ] = fun_list_sort ;
2072
+ dest [0 ] = base ;
2073
+ return ;
1980
2074
} else if (IS_O (base , O_OBJ )) {
1981
2075
// logic: look in obj members then class locals (TODO check this against CPython)
1982
2076
py_obj_base_t * o = base ;
0 commit comments