@@ -227,6 +227,28 @@ typedef uint32_t ZrtlTypeTag;
227227/* Destructor function type for boxed values */
228228typedef void (* ZrtlDropFn )(void * data );
229229
230+ /* ============================================================
231+ * Memory management helpers (defined early - used by other helpers)
232+ * ============================================================ */
233+
234+ /* Allocate memory (use platform malloc) */
235+ static inline void * zrtl_alloc (size_t size ) {
236+ extern void * malloc (size_t );
237+ return malloc (size );
238+ }
239+
240+ /* Free memory (use platform free) */
241+ static inline void zrtl_free (void * ptr ) {
242+ extern void free (void * );
243+ free (ptr );
244+ }
245+
246+ /* Reallocate memory */
247+ static inline void * zrtl_realloc (void * ptr , size_t size ) {
248+ extern void * realloc (void * , size_t );
249+ return realloc (ptr , size );
250+ }
251+
230252/* Dynamic boxed value */
231253typedef struct {
232254 ZrtlTypeTag tag ; /* Type tag identifying the type */
@@ -573,18 +595,186 @@ typedef uint16_t (*ZrtlRegisterTypeFn)(const ZrtlTypeInfo* info);
573595 * Common type definitions for runtime functions
574596 * ============================================================ */
575597
576- /* Zyntax string type (UTF-8, length-prefixed) */
577- typedef struct {
578- int32_t length ; /* Length in bytes (not including null terminator) */
579- char * data ; /* UTF-8 encoded string data */
580- } ZrtlString ;
598+ /* ============================================================
599+ * ZrtlString - Canonical String Format
600+ * ============================================================
601+ *
602+ * IMPORTANT: Zyntax uses a length-prefixed inline string format.
603+ * This is NOT a struct with a pointer - it's a contiguous memory block:
604+ *
605+ * Memory layout: [length: i32][utf8_bytes...]
606+ * - First 4 bytes: length as little-endian i32 (byte count, NOT char count)
607+ * - Remaining bytes: UTF-8 encoded string data
608+ * - NO null terminator (use length to determine end)
609+ *
610+ * Example: "Hello" is stored as:
611+ * [0x05, 0x00, 0x00, 0x00, 'H', 'e', 'l', 'l', 'o']
612+ * ^--- length = 5 ---^ ^--- UTF-8 bytes ---^
613+ *
614+ * In C, strings are passed as `int32_t*` pointing to the length field.
615+ * Use the helper macros below to access string data.
616+ */
617+
618+ /* String pointer type - points to the length header */
619+ typedef int32_t * ZrtlStringPtr ;
620+ typedef const int32_t * ZrtlStringConstPtr ;
621+
622+ /* Get string length from a ZrtlStringPtr */
623+ #define ZRTL_STRING_LENGTH (str_ptr ) (*(str_ptr))
624+
625+ /* Get pointer to UTF-8 bytes from a ZrtlStringPtr */
626+ #define ZRTL_STRING_DATA (str_ptr ) ((const char*)((str_ptr) + 1))
627+
628+ /* Get mutable pointer to UTF-8 bytes */
629+ #define ZRTL_STRING_DATA_MUT (str_ptr ) ((char*)((str_ptr) + 1))
630+
631+ /* Calculate total allocation size for a string of given byte length */
632+ #define ZRTL_STRING_ALLOC_SIZE (byte_len ) (sizeof(int32_t) + (byte_len))
633+
634+ /* Create a new string from C string (null-terminated) */
635+ static inline ZrtlStringPtr zrtl_string_new (const char * cstr ) {
636+ extern size_t strlen (const char * );
637+ extern void * memcpy (void * , const void * , size_t );
638+
639+ if (!cstr ) return NULL ;
640+
641+ int32_t len = (int32_t )strlen (cstr );
642+ ZrtlStringPtr ptr = (ZrtlStringPtr )zrtl_alloc (ZRTL_STRING_ALLOC_SIZE (len ));
643+ if (!ptr ) return NULL ;
644+
645+ * ptr = len ;
646+ memcpy (ZRTL_STRING_DATA_MUT (ptr ), cstr , len );
647+ return ptr ;
648+ }
649+
650+ /* Create a new string from bytes with known length */
651+ static inline ZrtlStringPtr zrtl_string_from_bytes (const char * bytes , int32_t len ) {
652+ extern void * memcpy (void * , const void * , size_t );
653+
654+ if (len < 0 ) return NULL ;
655+
656+ ZrtlStringPtr ptr = (ZrtlStringPtr )zrtl_alloc (ZRTL_STRING_ALLOC_SIZE (len ));
657+ if (!ptr ) return NULL ;
658+
659+ * ptr = len ;
660+ if (bytes && len > 0 ) {
661+ memcpy (ZRTL_STRING_DATA_MUT (ptr ), bytes , len );
662+ }
663+ return ptr ;
664+ }
665+
666+ /* Create an empty string */
667+ static inline ZrtlStringPtr zrtl_string_empty (void ) {
668+ ZrtlStringPtr ptr = (ZrtlStringPtr )zrtl_alloc (sizeof (int32_t ));
669+ if (ptr ) * ptr = 0 ;
670+ return ptr ;
671+ }
672+
673+ /* Free a ZrtlString */
674+ static inline void zrtl_string_free (ZrtlStringPtr str ) {
675+ if (str ) zrtl_free (str );
676+ }
677+
678+ /* Copy a ZrtlString */
679+ static inline ZrtlStringPtr zrtl_string_copy (ZrtlStringConstPtr str ) {
680+ extern void * memcpy (void * , const void * , size_t );
681+
682+ if (!str ) return zrtl_string_empty ();
683+
684+ int32_t len = ZRTL_STRING_LENGTH (str );
685+ size_t total_size = ZRTL_STRING_ALLOC_SIZE (len );
686+ ZrtlStringPtr copy = (ZrtlStringPtr )zrtl_alloc (total_size );
687+ if (!copy ) return NULL ;
581688
582- /* Zyntax array type */
689+ memcpy (copy , str , total_size );
690+ return copy ;
691+ }
692+
693+ /* Print a ZrtlString to stdout */
694+ static inline void zrtl_string_print (ZrtlStringConstPtr str ) {
695+ extern int putchar (int );
696+
697+ if (!str ) return ;
698+
699+ int32_t len = ZRTL_STRING_LENGTH (str );
700+ const char * data = ZRTL_STRING_DATA (str );
701+
702+ for (int32_t i = 0 ; i < len ; i ++ ) {
703+ putchar ((unsigned char )data [i ]);
704+ }
705+ }
706+
707+ /* Compare two ZrtlStrings for equality */
708+ static inline int zrtl_string_equals (ZrtlStringConstPtr a , ZrtlStringConstPtr b ) {
709+ extern int memcmp (const void * , const void * , size_t );
710+
711+ if (a == b ) return 1 ;
712+ if (!a || !b ) return 0 ;
713+
714+ int32_t len_a = ZRTL_STRING_LENGTH (a );
715+ int32_t len_b = ZRTL_STRING_LENGTH (b );
716+
717+ if (len_a != len_b ) return 0 ;
718+
719+ return memcmp (ZRTL_STRING_DATA (a ), ZRTL_STRING_DATA (b ), len_a ) == 0 ;
720+ }
721+
722+ /* ============================================================
723+ * ZrtlStringView - Non-owning String Reference (for SDK use)
724+ * ============================================================
725+ *
726+ * For SDK code that needs to work with string data without
727+ * dealing with the inline format, use ZrtlStringView.
728+ * This is NOT the format used by the compiler - only for SDK convenience.
729+ */
583730typedef struct {
584- int32_t length ; /* Number of elements */
585- int32_t capacity ; /* Allocated capacity */
586- void * data ; /* Pointer to element data */
587- } ZrtlArray ;
731+ const char * data ; /* Pointer to UTF-8 bytes */
732+ int32_t length ; /* Length in bytes */
733+ } ZrtlStringView ;
734+
735+ /* Create a view from a ZrtlStringPtr */
736+ static inline ZrtlStringView zrtl_string_view (ZrtlStringConstPtr str ) {
737+ ZrtlStringView view = { NULL , 0 };
738+ if (str ) {
739+ view .length = ZRTL_STRING_LENGTH (str );
740+ view .data = ZRTL_STRING_DATA (str );
741+ }
742+ return view ;
743+ }
744+
745+ /* ============================================================
746+ * ZrtlArray - Canonical Array Format
747+ * ============================================================
748+ *
749+ * Arrays use a similar inline format for the header:
750+ *
751+ * Memory layout: [capacity: i32][length: i32][elem0, elem1, ...]
752+ * - First 4 bytes: allocated capacity
753+ * - Next 4 bytes: current length (number of elements)
754+ * - Remaining: element data
755+ *
756+ * Arrays are passed as `int32_t*` pointing to the capacity field.
757+ */
758+
759+ /* Array pointer type - points to the capacity header */
760+ typedef int32_t * ZrtlArrayPtr ;
761+ typedef const int32_t * ZrtlArrayConstPtr ;
762+
763+ /* Get array capacity */
764+ #define ZRTL_ARRAY_CAPACITY (arr_ptr ) ((arr_ptr)[0])
765+
766+ /* Get array length */
767+ #define ZRTL_ARRAY_LENGTH (arr_ptr ) ((arr_ptr)[1])
768+
769+ /* Get pointer to array elements (typed) */
770+ #define ZRTL_ARRAY_DATA (arr_ptr , elem_type ) ((elem_type*)((arr_ptr) + 2))
771+
772+ /* Header size in i32 units */
773+ #define ZRTL_ARRAY_HEADER_SIZE 2
774+
775+ /* Calculate allocation size for array */
776+ #define ZRTL_ARRAY_ALLOC_SIZE (capacity , elem_size ) \
777+ (sizeof(int32_t) * ZRTL_ARRAY_HEADER_SIZE + (capacity) * (elem_size))
588778
589779/* Zyntax optional type */
590780typedef struct {
@@ -605,73 +795,57 @@ typedef struct {
605795#define ZRTL_TYPE_END /* End type definition */
606796
607797/* ============================================================
608- * Memory management helpers
798+ * Array creation helpers
609799 * ============================================================ */
610800
611- /* Allocate memory (use platform malloc) */
612- static inline void * zrtl_alloc (size_t size ) {
613- extern void * malloc (size_t );
614- return malloc (size );
615- }
801+ /* Create a new array with given capacity (for i32 elements) */
802+ static inline ZrtlArrayPtr zrtl_array_new_i32 (int32_t initial_capacity ) {
803+ int32_t cap = initial_capacity > 0 ? initial_capacity : 8 ;
804+ size_t size = ZRTL_ARRAY_ALLOC_SIZE (cap , sizeof (int32_t ));
805+ ZrtlArrayPtr ptr = (ZrtlArrayPtr )zrtl_alloc (size );
806+ if (!ptr ) return NULL ;
616807
617- /* Free memory (use platform free) */
618- static inline void zrtl_free (void * ptr ) {
619- extern void free (void * );
620- free (ptr );
808+ ZRTL_ARRAY_CAPACITY (ptr ) = cap ;
809+ ZRTL_ARRAY_LENGTH (ptr ) = 0 ;
810+ return ptr ;
621811}
622812
623- /* Reallocate memory */
624- static inline void * zrtl_realloc (void * ptr , size_t size ) {
625- extern void * realloc (void * , size_t );
626- return realloc (ptr , size );
813+ /* Free an array */
814+ static inline void zrtl_array_free (ZrtlArrayPtr arr ) {
815+ if (arr ) zrtl_free (arr );
627816}
628817
629- /* ============================================================
630- * String helpers
631- * ============================================================ */
818+ /* Push an i32 element to array (may reallocate, returns new ptr) */
819+ static inline ZrtlArrayPtr zrtl_array_push_i32 ( ZrtlArrayPtr arr , int32_t value ) {
820+ if (! arr ) return NULL ;
632821
633- /* Create a ZrtlString from a C string */
634- static inline ZrtlString zrtl_string_from_cstr (const char * cstr ) {
635- extern size_t strlen (const char * );
636- extern void * memcpy (void * , const void * , size_t );
822+ int32_t cap = ZRTL_ARRAY_CAPACITY (arr );
823+ int32_t len = ZRTL_ARRAY_LENGTH (arr );
637824
638- ZrtlString str ;
639- str . length = ( int32_t ) strlen ( cstr );
640- str . data = ( char * ) zrtl_alloc ( str . length + 1 ) ;
641- memcpy ( str . data , cstr , str . length + 1 );
642- return str ;
643- }
825+ /* Check if we need to grow */
826+ if ( len + ZRTL_ARRAY_HEADER_SIZE >= cap ) {
827+ int32_t new_cap = cap * 2 ;
828+ size_t new_size = ZRTL_ARRAY_ALLOC_SIZE ( new_cap , sizeof ( int32_t ) );
829+ ZrtlArrayPtr new_arr = ( ZrtlArrayPtr ) zrtl_realloc ( arr , new_size ) ;
830+ if (! new_arr ) return NULL ;
644831
645- /* Free a ZrtlString */
646- static inline void zrtl_string_free (ZrtlString * str ) {
647- if (str -> data ) {
648- zrtl_free (str -> data );
649- str -> data = NULL ;
650- str -> length = 0 ;
832+ arr = new_arr ;
833+ ZRTL_ARRAY_CAPACITY (arr ) = new_cap ;
651834 }
652- }
653835
654- /* ============================================================
655- * Array helpers
656- * ============================================================ */
836+ /* Add element */
837+ ZRTL_ARRAY_DATA ( arr , int32_t )[ len ] = value ;
838+ ZRTL_ARRAY_LENGTH ( arr ) = len + 1 ;
657839
658- /* Create a new array with given element size */
659- static inline ZrtlArray zrtl_array_new (size_t element_size , int32_t initial_capacity ) {
660- ZrtlArray arr ;
661- arr .length = 0 ;
662- arr .capacity = initial_capacity > 0 ? initial_capacity : 8 ;
663- arr .data = zrtl_alloc (element_size * arr .capacity );
664840 return arr ;
665841}
666842
667- /* Free an array */
668- static inline void zrtl_array_free (ZrtlArray * arr ) {
669- if (arr -> data ) {
670- zrtl_free (arr -> data );
671- arr -> data = NULL ;
672- arr -> length = 0 ;
673- arr -> capacity = 0 ;
843+ /* Get element from array */
844+ static inline int32_t zrtl_array_get_i32 (ZrtlArrayConstPtr arr , int32_t index ) {
845+ if (!arr || index < 0 || index >= ZRTL_ARRAY_LENGTH (arr )) {
846+ return 0 ;
674847 }
848+ return ZRTL_ARRAY_DATA (arr , int32_t )[index ];
675849}
676850
677851#ifdef __cplusplus
0 commit comments