@@ -121,6 +121,18 @@ RtAny rt_box_function(void *fn) {
121121 return result ;
122122}
123123
124+ RtAny rt_box_struct (RtArena * arena , void * struct_data , size_t struct_size , int struct_type_id ) {
125+ RtAny result ;
126+ result .tag = RT_ANY_STRUCT ;
127+ /* Allocate space in the arena and copy struct data */
128+ void * copy = rt_arena_alloc (arena , struct_size );
129+ memcpy (copy , struct_data , struct_size );
130+ result .value .obj = copy ;
131+ /* Store struct type ID in element_tag (repurposed for structs) */
132+ result .element_tag = (RtAnyTag )struct_type_id ;
133+ return result ;
134+ }
135+
124136/* ============================================================================
125137 * Unboxing Functions
126138 * ============================================================================ */
@@ -222,6 +234,20 @@ void *rt_unbox_function(RtAny value) {
222234 return value .value .fn ;
223235}
224236
237+ void * rt_unbox_struct (RtAny value , int expected_type_id ) {
238+ if (value .tag != RT_ANY_STRUCT ) {
239+ rt_any_type_error ("struct" , value );
240+ }
241+ /* Check struct type ID matches */
242+ int actual_type_id = (int )value .element_tag ;
243+ if (actual_type_id != expected_type_id ) {
244+ fprintf (stderr , "Type error: struct type mismatch (expected type id %d, got %d)\n" ,
245+ expected_type_id , actual_type_id );
246+ exit (1 );
247+ }
248+ return value .value .obj ;
249+ }
250+
225251/* ============================================================================
226252 * Type Checking Functions
227253 * ============================================================================ */
@@ -241,6 +267,15 @@ bool rt_any_is_byte(RtAny value) { return value.tag == RT_ANY_BYTE; }
241267bool rt_any_is_array (RtAny value ) { return value .tag == RT_ANY_ARRAY ; }
242268bool rt_any_is_function (RtAny value ) { return value .tag == RT_ANY_FUNCTION ; }
243269
270+ bool rt_any_is_struct_type (RtAny value , int expected_type_id ) {
271+ if (value .tag != RT_ANY_STRUCT ) {
272+ return false;
273+ }
274+ /* Check if the struct type ID matches */
275+ int actual_type_id = (int )value .element_tag ;
276+ return actual_type_id == expected_type_id ;
277+ }
278+
244279RtAnyTag rt_any_get_tag (RtAny value ) {
245280 return value .tag ;
246281}
@@ -261,6 +296,7 @@ const char *rt_any_tag_name(RtAnyTag tag) {
261296 case RT_ANY_BYTE : return "byte" ;
262297 case RT_ANY_ARRAY : return "array" ;
263298 case RT_ANY_FUNCTION : return "function" ;
299+ case RT_ANY_STRUCT : return "struct" ;
264300 default : return "unknown" ;
265301 }
266302}
@@ -333,6 +369,12 @@ bool rt_any_equals(RtAny a, RtAny b) {
333369 }
334370 case RT_ANY_FUNCTION :
335371 return a .value .fn == b .value .fn ;
372+ case RT_ANY_STRUCT :
373+ /* For structs, compare type ID and pointer (identity comparison) */
374+ if (a .element_tag != b .element_tag ) {
375+ return false; /* Different struct types */
376+ }
377+ return a .value .obj == b .value .obj ;
336378 default :
337379 return false;
338380 }
@@ -392,6 +434,8 @@ char *rt_any_to_string(RtArena *arena, RtAny value) {
392434 return rt_arena_strdup (arena , buffer );
393435 case RT_ANY_FUNCTION :
394436 return rt_arena_strdup (arena , "[function]" );
437+ case RT_ANY_STRUCT :
438+ return rt_arena_strdup (arena , "[struct]" );
395439 default :
396440 return rt_arena_strdup (arena , "[unknown]" );
397441 }
@@ -439,6 +483,11 @@ RtAny rt_any_promote(RtArena *target_arena, RtAny value) {
439483 case RT_ANY_FUNCTION :
440484 break ;
441485
486+ case RT_ANY_STRUCT :
487+ /* Structs are arena-allocated; for now shallow copy pointer.
488+ * Full deep copy would require storing struct size metadata. */
489+ break ;
490+
442491 default :
443492 break ;
444493 }
0 commit comments