@@ -68,6 +68,7 @@ typedef enum {
6868 O_MAP ,
6969 O_CLASS ,
7070 O_OBJ ,
71+ O_USER ,
7172} py_obj_kind_t ;
7273
7374typedef enum {
@@ -172,6 +173,11 @@ struct _py_obj_base_t {
172173 py_obj_base_t * class ; // points to a O_CLASS object
173174 py_map_t * members ;
174175 } u_obj ;
176+ struct { // for O_USER
177+ const py_user_info_t * info ;
178+ machine_uint_t data1 ;
179+ machine_uint_t data2 ;
180+ } u_user ;
175181 };
176182};
177183
@@ -431,6 +437,34 @@ py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
431437 return o ;
432438}
433439
440+ py_obj_t py_obj_new_user (const py_user_info_t * info , machine_uint_t data1 , machine_uint_t data2 ) {
441+ py_obj_base_t * o = m_new (py_obj_base_t , 1 );
442+ o -> kind = O_USER ;
443+ // TODO should probably parse the info to turn strings to qstr's, and wrap functions in O_FUN_N objects
444+ // that'll take up some memory. maybe we can lazily do the O_FUN_N: leave it a ptr to a C function, and
445+ // only when the method is looked-up do we change that to the O_FUN_N object.
446+ o -> u_user .info = info ;
447+ o -> u_user .data1 = data1 ;
448+ o -> u_user .data2 = data2 ;
449+ return o ;
450+ }
451+
452+ void py_user_get_data (py_obj_t o , machine_uint_t * data1 , machine_uint_t * data2 ) {
453+ assert (IS_O (o , O_USER ));
454+ if (data1 != NULL ) {
455+ * data1 = ((py_obj_base_t * )o )-> u_user .data1 ;
456+ }
457+ if (data2 != NULL ) {
458+ * data2 = ((py_obj_base_t * )o )-> u_user .data2 ;
459+ }
460+ }
461+
462+ void py_user_set_data (py_obj_t o , machine_uint_t data1 , machine_uint_t data2 ) {
463+ assert (IS_O (o , O_USER ));
464+ ((py_obj_base_t * )o )-> u_user .data1 = data1 ;
465+ ((py_obj_base_t * )o )-> u_user .data2 = data2 ;
466+ }
467+
434468py_obj_t rt_str_join (py_obj_t self_in , py_obj_t arg ) {
435469 assert (IS_O (self_in , O_STR ));
436470 py_obj_base_t * self = self_in ;
@@ -812,6 +846,8 @@ const char *py_obj_get_type_str(py_obj_t o_in) {
812846 assert (IS_O (qn -> value , O_STR ));
813847 return qstr_str (((py_obj_base_t * )qn -> value )-> u_str );
814848 }
849+ case O_USER :
850+ return o -> u_user .info -> type_name ;
815851 default :
816852 assert (0 );
817853 return "UnknownType" ;
@@ -911,6 +947,9 @@ void py_obj_print(py_obj_t o_in) {
911947 printf ("}" );
912948 break ;
913949 }
950+ case O_USER :
951+ o -> u_user .info -> print (o_in );
952+ break ;
914953 default :
915954 printf ("<? %d>" , o -> kind );
916955 assert (0 );
@@ -1826,6 +1865,22 @@ void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
18261865 }
18271866 }
18281867 goto no_attr ;
1868+ } else if (IS_O (base , O_USER )) {
1869+ py_obj_base_t * o = base ;
1870+ const py_user_method_t * meth = & o -> u_user .info -> methods [0 ];
1871+ for (; meth -> name != NULL ; meth ++ ) {
1872+ if (strcmp (meth -> name , qstr_str (attr )) == 0 ) {
1873+ if (meth -> kind == 0 ) {
1874+ dest [1 ] = rt_make_function_1 (meth -> fun );
1875+ } else if (meth -> kind == 1 ) {
1876+ dest [1 ] = rt_make_function_2 (meth -> fun );
1877+ } else {
1878+ assert (0 );
1879+ }
1880+ dest [0 ] = base ;
1881+ return ;
1882+ }
1883+ }
18291884 }
18301885
18311886no_attr :
0 commit comments