@@ -1282,6 +1282,7 @@ typedef struct {
12821282 int next_func_id ;
12831283 Thr * * thrs ;
12841284 char * * thr_ids ;
1285+ int * thr_state ; // 0 = none, 1 = in_progress, 2 = done
12851286 size_t thr_count ;
12861287 size_t thr_cap ;
12871288 int next_thr_id ;
@@ -1303,6 +1304,7 @@ static void ser_ctx_free(SerCtx* ctx) {
13031304 free (ctx -> func_state );
13041305 free (ctx -> thrs );
13051306 free (ctx -> thr_ids );
1307+ free (ctx -> thr_state );
13061308}
13071309
13081310static const char * ser_env_id (SerCtx * ctx , Env * env , int * state ) {
@@ -1357,24 +1359,28 @@ static const char* ser_func_id(SerCtx* ctx, Func* func, int* state) {
13571359 return ctx -> func_ids [ctx -> func_count - 1 ];
13581360}
13591361
1360- static const char * ser_thr_id (SerCtx * ctx , Thr * thr ) {
1362+ static const char * ser_thr_id (SerCtx * ctx , Thr * thr , int * state ) {
13611363 for (size_t i = 0 ; i < ctx -> thr_count ; i ++ ) {
13621364 if (ctx -> thrs [i ] == thr ) {
1365+ if (state ) * state = ctx -> thr_state [i ];
13631366 return ctx -> thr_ids [i ];
13641367 }
13651368 }
13661369 if (ctx -> thr_count + 1 > ctx -> thr_cap ) {
13671370 size_t new_cap = ctx -> thr_cap == 0 ? 4 : ctx -> thr_cap * 2 ;
13681371 ctx -> thrs = realloc (ctx -> thrs , new_cap * sizeof (Thr * ));
13691372 ctx -> thr_ids = realloc (ctx -> thr_ids , new_cap * sizeof (char * ));
1370- if (!ctx -> thrs || !ctx -> thr_ids ) { fprintf (stderr , "Out of memory\n" ); exit (1 ); }
1373+ ctx -> thr_state = realloc (ctx -> thr_state , new_cap * sizeof (int ));
1374+ if (!ctx -> thrs || !ctx -> thr_ids || !ctx -> thr_state ) { fprintf (stderr , "Out of memory\n" ); exit (1 ); }
13711375 ctx -> thr_cap = new_cap ;
13721376 }
13731377 ctx -> next_thr_id ++ ;
13741378 char buf [32 ];
13751379 snprintf (buf , sizeof (buf ), "t%d" , ctx -> next_thr_id );
13761380 ctx -> thrs [ctx -> thr_count ] = thr ;
13771381 ctx -> thr_ids [ctx -> thr_count ] = strdup (buf );
1382+ ctx -> thr_state [ctx -> thr_count ] = 0 ;
1383+ if (state ) * state = 0 ;
13781384 ctx -> thr_count ++ ;
13791385 return ctx -> thr_ids [ctx -> thr_count - 1 ];
13801386}
@@ -1386,6 +1392,78 @@ static void json_obj_field(JsonBuf* jb, bool* first, const char* key) {
13861392 jb_append_char (jb , ':' );
13871393}
13881394
1395+ typedef struct {
1396+ Thr * target ;
1397+ Map * * seen_maps ;
1398+ size_t seen_map_count ;
1399+ size_t seen_map_cap ;
1400+ Tensor * * seen_tensors ;
1401+ size_t seen_tensor_count ;
1402+ size_t seen_tensor_cap ;
1403+ } ThrContainCtx ;
1404+
1405+ static int thr_contain_seen_map (ThrContainCtx * ctx , Map * map ) {
1406+ for (size_t i = 0 ; i < ctx -> seen_map_count ; i ++ ) {
1407+ if (ctx -> seen_maps [i ] == map ) return 1 ;
1408+ }
1409+ if (ctx -> seen_map_count + 1 > ctx -> seen_map_cap ) {
1410+ size_t new_cap = ctx -> seen_map_cap == 0 ? 4 : ctx -> seen_map_cap * 2 ;
1411+ ctx -> seen_maps = realloc (ctx -> seen_maps , new_cap * sizeof (Map * ));
1412+ if (!ctx -> seen_maps ) { fprintf (stderr , "Out of memory\n" ); exit (1 ); }
1413+ ctx -> seen_map_cap = new_cap ;
1414+ }
1415+ ctx -> seen_maps [ctx -> seen_map_count ++ ] = map ;
1416+ return 0 ;
1417+ }
1418+
1419+ static int thr_contain_seen_tensor (ThrContainCtx * ctx , Tensor * tns ) {
1420+ for (size_t i = 0 ; i < ctx -> seen_tensor_count ; i ++ ) {
1421+ if (ctx -> seen_tensors [i ] == tns ) return 1 ;
1422+ }
1423+ if (ctx -> seen_tensor_count + 1 > ctx -> seen_tensor_cap ) {
1424+ size_t new_cap = ctx -> seen_tensor_cap == 0 ? 4 : ctx -> seen_tensor_cap * 2 ;
1425+ ctx -> seen_tensors = realloc (ctx -> seen_tensors , new_cap * sizeof (Tensor * ));
1426+ if (!ctx -> seen_tensors ) { fprintf (stderr , "Out of memory\n" ); exit (1 ); }
1427+ ctx -> seen_tensor_cap = new_cap ;
1428+ }
1429+ ctx -> seen_tensors [ctx -> seen_tensor_count ++ ] = tns ;
1430+ return 0 ;
1431+ }
1432+
1433+ static int value_contains_thr_rec (ThrContainCtx * ctx , Value v ) {
1434+ if (!ctx || !ctx -> target ) return 0 ;
1435+ switch (v .type ) {
1436+ case VAL_THR :
1437+ return v .as .thr == ctx -> target ;
1438+ case VAL_MAP :
1439+ if (!v .as .map ) return 0 ;
1440+ if (thr_contain_seen_map (ctx , v .as .map )) return 0 ;
1441+ for (size_t i = 0 ; i < v .as .map -> count ; i ++ ) {
1442+ if (value_contains_thr_rec (ctx , v .as .map -> items [i ].key )) return 1 ;
1443+ if (value_contains_thr_rec (ctx , v .as .map -> items [i ].value )) return 1 ;
1444+ }
1445+ return 0 ;
1446+ case VAL_TNS :
1447+ if (!v .as .tns ) return 0 ;
1448+ if (thr_contain_seen_tensor (ctx , v .as .tns )) return 0 ;
1449+ for (size_t i = 0 ; i < v .as .tns -> length ; i ++ ) {
1450+ if (value_contains_thr_rec (ctx , v .as .tns -> data [i ])) return 1 ;
1451+ }
1452+ return 0 ;
1453+ default :
1454+ return 0 ;
1455+ }
1456+ }
1457+
1458+ static int value_contains_thr (Value v , Thr * target ) {
1459+ ThrContainCtx ctx = {0 };
1460+ ctx .target = target ;
1461+ int found = value_contains_thr_rec (& ctx , v );
1462+ free (ctx .seen_maps );
1463+ free (ctx .seen_tensors );
1464+ return found ;
1465+ }
1466+
13891467static void ser_loc (JsonBuf * jb , int line , int col ) {
13901468 jb_append_char (jb , '{' );
13911469 bool first = true;
@@ -1404,7 +1482,7 @@ static void ser_expr(JsonBuf* jb, SerCtx* ctx, Interpreter* interp, Expr* expr);
14041482static void ser_stmt (JsonBuf * jb , SerCtx * ctx , Interpreter * interp , Stmt * stmt );
14051483static void ser_value (JsonBuf * jb , SerCtx * ctx , Interpreter * interp , Value v );
14061484
1407- static void ser_env (JsonBuf * jb , SerCtx * ctx , Interpreter * interp , Env * env ) {
1485+ static void ser_env (JsonBuf * jb , SerCtx * ctx , Interpreter * interp , Env * env , Thr * omit_thr ) {
14081486 if (!env ) {
14091487 jb_append_str (jb , "null" );
14101488 return ;
@@ -1445,6 +1523,9 @@ static void ser_env(JsonBuf* jb, SerCtx* ctx, Interpreter* interp, Env* env) {
14451523 for (size_t i = 0 ; i < env -> count ; i ++ ) {
14461524 EnvEntry * entry = & env -> entries [i ];
14471525 if (!entry -> initialized && !entry -> alias_target ) continue ;
1526+ if (omit_thr && entry -> initialized && !entry -> alias_target && value_contains_thr (entry -> value , omit_thr )) {
1527+ continue ;
1528+ }
14481529 if (!val_first ) jb_append_char (jb , ',' );
14491530 val_first = false;
14501531 jb_append_json_string (jb , entry -> name );
@@ -1458,7 +1539,7 @@ static void ser_env(JsonBuf* jb, SerCtx* ctx, Interpreter* interp, Env* env) {
14581539 jb_append_json_string (jb , entry -> alias_target );
14591540 json_obj_field (jb , & pf , "env" );
14601541 Env * owner = env_find_owner (env , entry -> alias_target );
1461- ser_env (jb , ctx , interp , owner ? owner : env );
1542+ ser_env (jb , ctx , interp , owner ? owner : env , omit_thr );
14621543 json_obj_field (jb , & pf , "value_type" );
14631544 jb_append_json_string (jb , decl_type_name (entry -> decl_type ));
14641545 jb_append_char (jb , '}' );
@@ -1505,7 +1586,7 @@ static void ser_env(JsonBuf* jb, SerCtx* ctx, Interpreter* interp, Env* env) {
15051586 jb_append_char (jb , ']' );
15061587
15071588 json_obj_field (jb , & def_first , "parent" );
1508- ser_env (jb , ctx , interp , env -> parent );
1589+ ser_env (jb , ctx , interp , env -> parent , omit_thr );
15091590
15101591 jb_append_char (jb , '}' );
15111592 jb_append_char (jb , '}' );
@@ -2271,7 +2352,7 @@ static void ser_value(JsonBuf* jb, SerCtx* ctx, Interpreter* interp, Value v) {
22712352 json_obj_field (jb , & df , "body" );
22722353 ser_stmt (jb , ctx , interp , fn -> body );
22732354 json_obj_field (jb , & df , "closure" );
2274- ser_env (jb , ctx , interp , fn -> closure );
2355+ ser_env (jb , ctx , interp , fn -> closure , NULL );
22752356 jb_append_char (jb , '}' );
22762357 jb_append_char (jb , '}' );
22772358 for (size_t i = 0 ; i < ctx -> func_count ; i ++ ) {
@@ -2284,7 +2365,9 @@ static void ser_value(JsonBuf* jb, SerCtx* ctx, Interpreter* interp, Value v) {
22842365 Value thv = value_null ();
22852366 thv .type = VAL_THR ;
22862367 thv .as .thr = th ;
2287- const char * id = ser_thr_id (ctx , th );
2368+ int state = 0 ;
2369+ const char * id = ser_thr_id (ctx , th , & state );
2370+ (void )state ;
22882371 jb_append_char (jb , '{' );
22892372 bool first = true;
22902373 json_obj_field (jb , & first , "t" );
@@ -2300,9 +2383,9 @@ static void ser_value(JsonBuf* jb, SerCtx* ctx, Interpreter* interp, Value v) {
23002383 json_obj_field (jb , & first , "finished" );
23012384 jb_append_str (jb , value_thr_get_finished (thv ) ? "true" : "false" );
23022385 json_obj_field (jb , & first , "stop" );
2303- jb_append_str (jb , value_thr_get_finished (thv ) ? "true" : "false" );
2386+ jb_append_str (jb , value_thr_get_stop_requested (thv ) ? "true" : "false" );
23042387 json_obj_field (jb , & first , "env" );
2305- ser_env (jb , ctx , interp , th -> env );
2388+ ser_env (jb , ctx , interp , th -> env , th );
23062389 json_obj_field (jb , & first , "block" );
23072390 if (th -> body ) ser_stmt (jb , ctx , interp , th -> body );
23082391 else jb_append_str (jb , "null" );
@@ -2465,12 +2548,14 @@ static Expr* deser_expr(JsonValue* obj, UnserCtx* ctx, Interpreter* interp, cons
24652548 JsonValue * val = json_obj_get (obj , "value" );
24662549 const char * lt = (lit_type && lit_type -> type == JSON_STR ) ? lit_type -> as .str : "INT" ;
24672550 if (strcmp (lt , "BOOL" ) == 0 ) {
2468- if (val && val -> type == JSON_BOOL ) return expr_bool (val -> as .boolean != 0 , line , col );
2469- if (val && val -> type == JSON_STR ) {
2470- if (strcmp (val -> as .str , "TRUE" ) == 0 || strcmp (val -> as .str , "true" ) == 0 ) return expr_bool (true, line , col );
2471- if (strcmp (val -> as .str , "FALSE" ) == 0 || strcmp (val -> as .str , "false" ) == 0 ) return expr_bool (false, line , col );
2472- }
2473- return expr_bool (false, line , col );
2551+ if (!val ) { * err = "UNSER: invalid BOOL value" ; return NULL ; }
2552+ if (val -> type == JSON_BOOL ) return expr_bool (val -> as .boolean != 0 , line , col );
2553+ if (val -> type == JSON_STR ) {
2554+ if (strcmp (val -> as .str , "TRUE" ) == 0 || strcmp (val -> as .str , "true" ) == 0 ) return expr_bool (true, line , col );
2555+ if (strcmp (val -> as .str , "FALSE" ) == 0 || strcmp (val -> as .str , "false" ) == 0 ) return expr_bool (false, line , col );
2556+ }
2557+ * err = "UNSER: invalid BOOL value" ;
2558+ return NULL ;
24742559 }
24752560 if (strcmp (lt , "INT" ) == 0 ) {
24762561 int64_t i = 0 ;
@@ -2866,12 +2951,14 @@ static Value deser_val(JsonValue* obj, UnserCtx* ctx, Interpreter* interp, const
28662951 }
28672952 if (strcmp (tp , "BOOL" ) == 0 ) {
28682953 JsonValue * v = json_obj_get (obj , "v" );
2869- if (v && v -> type == JSON_BOOL ) return value_bool (v -> as .boolean != 0 );
2870- if (v && v -> type == JSON_STR ) {
2954+ if (!v ) { * err = "UNSER: invalid BOOL value" ; return value_null (); }
2955+ if (v -> type == JSON_BOOL ) return value_bool (v -> as .boolean != 0 );
2956+ if (v -> type == JSON_STR ) {
28712957 if (strcmp (v -> as .str , "TRUE" ) == 0 || strcmp (v -> as .str , "true" ) == 0 ) return value_bool (true);
28722958 if (strcmp (v -> as .str , "FALSE" ) == 0 || strcmp (v -> as .str , "false" ) == 0 ) return value_bool (false);
28732959 }
2874- return value_bool (false);
2960+ * err = "UNSER: invalid BOOL value" ;
2961+ return value_null ();
28752962 }
28762963 if (strcmp (tp , "FLT" ) == 0 ) {
28772964 JsonValue * v = json_obj_get (obj , "v" );
@@ -2899,14 +2986,22 @@ static Value deser_val(JsonValue* obj, UnserCtx* ctx, Interpreter* interp, const
28992986 return value_null ();
29002987 }
29012988 size_t ndim = shape -> as .arr .count ;
2902- size_t * shp = malloc (sizeof (size_t ) * (ndim > 0 ? ndim : 1 ));
2903- if (!shp ) { * err = "Out of memory" ; return value_null (); }
2989+ if (ndim == 0 ) { * err = "UNSER: invalid TNS shape" ; return value_null (); }
2990+ // Compute expected element count and validate dims
2991+ size_t expected_total = 1 ;
29042992 for (size_t i = 0 ; i < ndim ; i ++ ) {
29052993 JsonValue * it = shape -> as .arr .items [i ];
2906- size_t sv = (size_t )((it && it -> type == JSON_NUM ) ? it -> as .num : 0 );
2907- shp [i ] = sv ;
2994+ if (!it || it -> type != JSON_NUM ) { * err = "UNSER: invalid TNS shape" ; return value_null (); }
2995+ size_t sv = (size_t )it -> as .num ;
2996+ if (sv == 0 ) { * err = "UNSER: invalid TNS shape" ; return value_null (); }
2997+ if (expected_total > 0 && sv > 0 && expected_total > (SIZE_MAX / sv )) { * err = "UNSER: TNS size overflow" ; return value_null (); }
2998+ expected_total *= sv ;
29082999 }
29093000 size_t total = flat -> as .arr .count ;
3001+ if (expected_total != total ) { * err = "UNSER: invalid TNS element count" ; return value_null (); }
3002+ size_t * shp = malloc (sizeof (size_t ) * ndim );
3003+ if (!shp ) { * err = "Out of memory" ; return value_null (); }
3004+ for (size_t i = 0 ; i < ndim ; i ++ ) shp [i ] = (size_t )shape -> as .arr .items [i ]-> as .num ;
29103005 Value * items = malloc (sizeof (Value ) * (total > 0 ? total : 1 ));
29113006 if (!items ) { free (shp ); * err = "Out of memory" ; return value_null (); }
29123007 DeclType elem_type = TYPE_UNKNOWN ;
@@ -3046,16 +3141,24 @@ static Value deser_val(JsonValue* obj, UnserCtx* ctx, Interpreter* interp, const
30463141 }
30473142 }
30483143 Value thr = value_thr_new ();
3049- value_thr_set_finished (thr , 1 );
3050- value_thr_set_paused (thr , json_obj_get (obj , "paused" ) && json_obj_get (obj , "paused" )-> type == JSON_BOOL ? json_obj_get (obj , "paused" )-> as .boolean : 0 );
3144+ // Set lifecycle flags from serialized form. Default to not finished/not stopped/not started.
3145+ JsonValue * finished_j = json_obj_get (obj , "finished" );
3146+ JsonValue * stop_j = json_obj_get (obj , "stop" );
3147+ JsonValue * paused_j = json_obj_get (obj , "paused" );
3148+ int finished_flag = (finished_j && finished_j -> type == JSON_BOOL ) ? finished_j -> as .boolean : 0 ;
3149+ int stop_flag = (stop_j && stop_j -> type == JSON_BOOL ) ? stop_j -> as .boolean : 0 ;
3150+ int paused_flag = (paused_j && paused_j -> type == JSON_BOOL ) ? paused_j -> as .boolean : 0 ;
3151+ value_thr_set_finished (thr , finished_flag );
3152+ value_thr_set_stop_requested (thr , stop_flag );
3153+ value_thr_set_paused (thr , paused_flag );
30513154 value_thr_set_started (thr , 0 );
30523155 thr .as .thr -> body = NULL ;
30533156 thr .as .thr -> env = NULL ;
3157+ if (id ) unser_thr_set (ctx , id , thr .as .thr );
30543158 JsonValue * blk = json_obj_get (obj , "block" );
30553159 JsonValue * envv = json_obj_get (obj , "env" );
30563160 if (blk && blk -> type == JSON_OBJ ) thr .as .thr -> body = deser_stmt (blk , ctx , interp , err );
30573161 if (envv && envv -> type == JSON_OBJ ) thr .as .thr -> env = deser_env (envv , ctx , interp , err );
3058- if (id ) unser_thr_set (ctx , id , thr .as .thr );
30593162 return thr ;
30603163 }
30613164
0 commit comments