@@ -1044,6 +1044,252 @@ static inline int32_t zrtl_array_get_i32(ZrtlArrayConstPtr arr, int32_t index) {
10441044 return ZRTL_ARRAY_DATA (arr , int32_t )[index ];
10451045}
10461046
1047+ /* ============================================================
1048+ * Async/Await Support
1049+ * ============================================================
1050+ *
1051+ * This section provides the C ABI for async functions that can be
1052+ * called from Zyntax-based languages. Native async functions return
1053+ * a ZrtlPromise which can be polled until completion.
1054+ *
1055+ * # Promise ABI Convention
1056+ *
1057+ * Async functions return a pointer to ZrtlPromise:
1058+ * async fn foo(a: i32) -> i64 => ZrtlPromise* foo(int32_t a)
1059+ *
1060+ * The poll function returns an i64:
1061+ * - 0 = Pending (operation not complete, poll again)
1062+ * - positive = Ready(value) - operation completed successfully
1063+ * - negative = Failed(error_code) - operation failed
1064+ *
1065+ * # Usage Example (C)
1066+ *
1067+ * // Define async state machine
1068+ * typedef struct {
1069+ * ZrtlStateMachineHeader header;
1070+ * int32_t counter;
1071+ * int32_t target;
1072+ * } CounterState;
1073+ *
1074+ * // Poll function
1075+ * int64_t counter_poll(void* state) {
1076+ * CounterState* s = (CounterState*)state;
1077+ * if (s->counter >= s->target) {
1078+ * s->header.state = ZRTL_ASYNC_COMPLETED;
1079+ * return s->counter; // Ready(counter)
1080+ * }
1081+ * s->counter++;
1082+ * return 0; // Pending
1083+ * }
1084+ *
1085+ * // Create async function
1086+ * ZrtlPromise* async_count_to(int32_t target) {
1087+ * CounterState* state = malloc(sizeof(CounterState));
1088+ * state->header = ZRTL_STATE_MACHINE_INIT;
1089+ * state->counter = 0;
1090+ * state->target = target;
1091+ *
1092+ * ZrtlPromise* promise = malloc(sizeof(ZrtlPromise));
1093+ * promise->state_machine = state;
1094+ * promise->poll_fn = counter_poll;
1095+ * return promise;
1096+ * }
1097+ *
1098+ * // Await (blocking)
1099+ * int64_t result = zrtl_promise_block_on(async_count_to(100));
1100+ */
1101+
1102+ /* Async state values */
1103+ typedef enum {
1104+ ZRTL_ASYNC_INITIAL = 0 , /* Initial state, not started */
1105+ ZRTL_ASYNC_RESUME1 = 1 , /* Resumed after first await */
1106+ ZRTL_ASYNC_RESUME2 = 2 , /* Resumed after second await */
1107+ ZRTL_ASYNC_RESUME3 = 3 ,
1108+ ZRTL_ASYNC_RESUME4 = 4 ,
1109+ ZRTL_ASYNC_RESUME5 = 5 ,
1110+ ZRTL_ASYNC_RESUME6 = 6 ,
1111+ ZRTL_ASYNC_RESUME7 = 7 ,
1112+ ZRTL_ASYNC_COMPLETED = 0xFFFFFFFE , /* Completed successfully */
1113+ ZRTL_ASYNC_FAILED = 0xFFFFFFFF , /* Failed with error */
1114+ } ZrtlAsyncState ;
1115+
1116+ /* State machine header - must be first field in async state structs */
1117+ typedef struct {
1118+ uint32_t state ; /* Current async state (ZrtlAsyncState) */
1119+ uint32_t _reserved ; /* Reserved for alignment */
1120+ } ZrtlStateMachineHeader ;
1121+
1122+ /* Initial value for state machine header */
1123+ #define ZRTL_STATE_MACHINE_INIT { ZRTL_ASYNC_INITIAL, 0 }
1124+
1125+ /* Poll function signature: takes state pointer, returns i64 ABI result */
1126+ typedef int64_t (* ZrtlPollFn )(void * state_machine );
1127+
1128+ /* Promise structure - returned by async functions */
1129+ typedef struct {
1130+ void * state_machine ; /* Pointer to the state machine */
1131+ ZrtlPollFn poll_fn ; /* Poll function */
1132+ } ZrtlPromise ;
1133+
1134+ /* Poll result values */
1135+ #define ZRTL_POLL_PENDING 0
1136+
1137+ /* Check if poll result is pending */
1138+ #define ZRTL_POLL_IS_PENDING (result ) ((result) == 0)
1139+
1140+ /* Check if poll result is ready (positive = success) */
1141+ #define ZRTL_POLL_IS_READY (result ) ((result) > 0)
1142+
1143+ /* Check if poll result is failed (negative = error) */
1144+ #define ZRTL_POLL_IS_FAILED (result ) ((result) < 0)
1145+
1146+ /* Extract error code from failed result */
1147+ #define ZRTL_POLL_ERROR_CODE (result ) ((int32_t)(result))
1148+
1149+ /* Poll a promise once */
1150+ static inline int64_t zrtl_promise_poll (ZrtlPromise * promise ) {
1151+ if (!promise || !promise -> poll_fn ) return -1 ;
1152+ return promise -> poll_fn (promise -> state_machine );
1153+ }
1154+
1155+ /* Block until promise completes (busy-wait) */
1156+ static inline int64_t zrtl_promise_block_on (ZrtlPromise * promise ) {
1157+ if (!promise ) return -1 ;
1158+ int64_t result ;
1159+ while ((result = zrtl_promise_poll (promise )) == ZRTL_POLL_PENDING ) {
1160+ /* Spin - could add yield here for better CPU usage */
1161+ }
1162+ return result ;
1163+ }
1164+
1165+ /* Free a promise and its state machine */
1166+ static inline void zrtl_promise_free (ZrtlPromise * promise ) {
1167+ if (promise ) {
1168+ if (promise -> state_machine ) {
1169+ zrtl_free (promise -> state_machine );
1170+ }
1171+ zrtl_free (promise );
1172+ }
1173+ }
1174+
1175+ /* Check if state machine is finished */
1176+ static inline int zrtl_state_is_finished (const ZrtlStateMachineHeader * header ) {
1177+ return header -> state >= ZRTL_ASYNC_COMPLETED ;
1178+ }
1179+
1180+ /* Advance state machine to next resume point */
1181+ static inline void zrtl_state_advance (ZrtlStateMachineHeader * header ) {
1182+ if (header -> state < ZRTL_ASYNC_COMPLETED ) {
1183+ header -> state ++ ;
1184+ }
1185+ }
1186+
1187+ /* Mark state machine as completed */
1188+ static inline void zrtl_state_complete (ZrtlStateMachineHeader * header ) {
1189+ header -> state = ZRTL_ASYNC_COMPLETED ;
1190+ }
1191+
1192+ /* Mark state machine as failed */
1193+ static inline void zrtl_state_fail (ZrtlStateMachineHeader * header ) {
1194+ header -> state = ZRTL_ASYNC_FAILED ;
1195+ }
1196+
1197+ /* ============================================================
1198+ * Promise Combinators
1199+ * ============================================================
1200+ *
1201+ * These helpers allow combining multiple promises.
1202+ *
1203+ * - zrtl_promise_all: Wait for all promises to complete
1204+ * - zrtl_promise_race: Wait for first promise to complete
1205+ */
1206+
1207+ /* Promise array for combinators */
1208+ typedef struct {
1209+ ZrtlPromise * * promises ; /* Array of promise pointers */
1210+ uint32_t count ; /* Number of promises */
1211+ int64_t * results ; /* Results array (for all) */
1212+ uint32_t completed ; /* Number completed (for all) */
1213+ int32_t winner ; /* Index of first completed (for race), -1 if none */
1214+ } ZrtlPromiseGroup ;
1215+
1216+ /* Create a promise group for Promise.all */
1217+ static inline ZrtlPromiseGroup * zrtl_promise_group_new (uint32_t count ) {
1218+ ZrtlPromiseGroup * group = (ZrtlPromiseGroup * )zrtl_alloc (sizeof (ZrtlPromiseGroup ));
1219+ if (!group ) return NULL ;
1220+
1221+ group -> promises = (ZrtlPromise * * )zrtl_alloc (sizeof (ZrtlPromise * ) * count );
1222+ group -> results = (int64_t * )zrtl_alloc (sizeof (int64_t ) * count );
1223+ group -> count = count ;
1224+ group -> completed = 0 ;
1225+ group -> winner = -1 ;
1226+
1227+ if (!group -> promises || !group -> results ) {
1228+ if (group -> promises ) zrtl_free (group -> promises );
1229+ if (group -> results ) zrtl_free (group -> results );
1230+ zrtl_free (group );
1231+ return NULL ;
1232+ }
1233+
1234+ for (uint32_t i = 0 ; i < count ; i ++ ) {
1235+ group -> promises [i ] = NULL ;
1236+ group -> results [i ] = 0 ;
1237+ }
1238+
1239+ return group ;
1240+ }
1241+
1242+ /* Add a promise to the group */
1243+ static inline void zrtl_promise_group_add (ZrtlPromiseGroup * group , uint32_t index , ZrtlPromise * promise ) {
1244+ if (group && index < group -> count ) {
1245+ group -> promises [index ] = promise ;
1246+ }
1247+ }
1248+
1249+ /* Poll all promises (Promise.all pattern) - returns 1 when all complete */
1250+ static inline int zrtl_promise_all_poll (ZrtlPromiseGroup * group ) {
1251+ if (!group ) return 1 ;
1252+
1253+ for (uint32_t i = 0 ; i < group -> count ; i ++ ) {
1254+ if (group -> results [i ] == ZRTL_POLL_PENDING && group -> promises [i ]) {
1255+ int64_t result = zrtl_promise_poll (group -> promises [i ]);
1256+ if (result != ZRTL_POLL_PENDING ) {
1257+ group -> results [i ] = result ;
1258+ group -> completed ++ ;
1259+ }
1260+ }
1261+ }
1262+
1263+ return group -> completed >= group -> count ;
1264+ }
1265+
1266+ /* Poll for first completion (Promise.race pattern) - returns winner index or -1 */
1267+ static inline int32_t zrtl_promise_race_poll (ZrtlPromiseGroup * group ) {
1268+ if (!group || group -> winner >= 0 ) return group ? group -> winner : -1 ;
1269+
1270+ for (uint32_t i = 0 ; i < group -> count ; i ++ ) {
1271+ if (group -> promises [i ]) {
1272+ int64_t result = zrtl_promise_poll (group -> promises [i ]);
1273+ if (result != ZRTL_POLL_PENDING ) {
1274+ group -> results [i ] = result ;
1275+ group -> winner = (int32_t )i ;
1276+ return group -> winner ;
1277+ }
1278+ }
1279+ }
1280+
1281+ return -1 ; /* None completed yet */
1282+ }
1283+
1284+ /* Free a promise group (does NOT free individual promises) */
1285+ static inline void zrtl_promise_group_free (ZrtlPromiseGroup * group ) {
1286+ if (group ) {
1287+ if (group -> promises ) zrtl_free (group -> promises );
1288+ if (group -> results ) zrtl_free (group -> results );
1289+ zrtl_free (group );
1290+ }
1291+ }
1292+
10471293/* ============================================================
10481294 * Test Harness Macros
10491295 * ============================================================
0 commit comments