1212static ExecResult exec_stmt (Interpreter * interp , Stmt * stmt , Env * env , LabelMap * labels );
1313static ExecResult exec_stmt_list (Interpreter * interp , StmtList * list , Env * env , LabelMap * labels );
1414
15+ // Thread worker for THR blocks
16+ #if PREFIX_HAS_THREADS
17+ typedef struct {
18+ Interpreter * interp ;
19+ Env * env ;
20+ Stmt * body ;
21+ Value thr_val ;
22+ } ThrStart ;
23+
24+ static int thr_worker (void * arg ) {
25+ ThrStart * start = (ThrStart * )arg ;
26+ LabelMap labels = {0 };
27+ ExecResult res = exec_stmt (start -> interp , start -> body , start -> env , & labels );
28+
29+ // Clean up labels
30+ for (size_t i = 0 ; i < labels .count ; i ++ ) value_free (labels .items [i ].key );
31+ free (labels .items );
32+
33+ if (res .status == EXEC_RETURN || res .status == EXEC_OK || res .status == EXEC_GOTO ) {
34+ value_free (res .value );
35+ }
36+ if (res .status == EXEC_ERROR && res .error ) {
37+ free (res .error );
38+ }
39+
40+ value_thr_set_finished (start -> thr_val , 1 );
41+ value_free (start -> thr_val );
42+ free (start -> interp );
43+ free (start );
44+ return 0 ;
45+ }
46+ #endif
47+
1548// ============ Helper functions ============
1649
1750static void * safe_malloc (size_t size ) {
@@ -182,6 +215,8 @@ int value_truthiness(Value v) {
182215 return v .as .s != NULL && v .as .s [0 ] != '\0' ;
183216 case VAL_FUNC :
184217 return 1 ; // Functions are always truthy
218+ case VAL_THR :
219+ return value_thr_is_running (v );
185220 default :
186221 return 0 ;
187222 }
@@ -196,6 +231,7 @@ static DeclType value_type_to_decl(ValueType vt) {
196231 case VAL_STR : return TYPE_STR ;
197232 case VAL_TNS : return TYPE_TNS ;
198233 case VAL_FUNC : return TYPE_FUNC ;
234+ case VAL_THR : return TYPE_THR ;
199235 default : return TYPE_UNKNOWN ;
200236 }
201237}
@@ -207,6 +243,7 @@ static ValueType decl_type_to_value(DeclType dt) {
207243 case TYPE_STR : return VAL_STR ;
208244 case TYPE_TNS : return VAL_TNS ;
209245 case TYPE_FUNC : return VAL_FUNC ;
246+ case TYPE_THR : return VAL_THR ;
210247 default : return VAL_NULL ;
211248 }
212249}
@@ -841,12 +878,12 @@ Value eval_expr(Interpreter* interp, Expr* expr, Env* env) {
841878 if (kw_used ) free (kw_used );
842879
843880 // Execute function body
844- LabelMap labels = {0 };
845- ExecResult res = exec_stmt (interp , user_func -> body , call_env , & labels );
881+ LabelMap local_labels = {0 };
882+ ExecResult res = exec_stmt (interp , user_func -> body , call_env , & local_labels );
846883
847884 // Clean up labels
848- for (size_t i = 0 ; i < labels .count ; i ++ ) value_free (labels .items [i ].key );
849- free (labels .items );
885+ for (size_t i = 0 ; i < local_labels .count ; i ++ ) value_free (local_labels .items [i ].key );
886+ free (local_labels .items );
850887
851888 env_free (call_env );
852889
@@ -881,11 +918,21 @@ Value eval_expr(Interpreter* interp, Expr* expr, Env* env) {
881918 case TYPE_INT : return value_int (0 );
882919 case TYPE_FLT : return value_flt (0.0 );
883920 case TYPE_STR : return value_str ("" );
921+ case TYPE_TNS :
922+ interp -> error = strdup ("TNS-returning function must return a value" );
923+ interp -> error_line = expr -> line ;
924+ interp -> error_col = expr -> column ;
925+ return value_null ();
884926 case TYPE_FUNC :
885927 interp -> error = strdup ("FUNC-returning function must return a value" );
886928 interp -> error_line = expr -> line ;
887929 interp -> error_col = expr -> column ;
888930 return value_null ();
931+ case TYPE_THR :
932+ interp -> error = strdup ("THR-returning function must return a value" );
933+ interp -> error_line = expr -> line ;
934+ interp -> error_col = expr -> column ;
935+ return value_null ();
889936 default :
890937 return value_null ();
891938 }
@@ -1507,7 +1554,10 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
15071554 snprintf (buf , sizeof (buf ), "Type mismatch: expected %s but got %s" ,
15081555 expected == TYPE_INT ? "INT" :
15091556 expected == TYPE_FLT ? "FLT" :
1510- expected == TYPE_STR ? "STR" : "FUNC" ,
1557+ expected == TYPE_STR ? "STR" :
1558+ expected == TYPE_TNS ? "TNS" :
1559+ expected == TYPE_FUNC ? "FUNC" :
1560+ expected == TYPE_THR ? "THR" : "UNKNOWN" ,
15111561 value_type_name (v ));
15121562 value_free (v );
15131563 return make_error (buf , stmt -> line , stmt -> column );
@@ -1705,6 +1755,57 @@ static ExecResult exec_stmt(Interpreter* interp, Stmt* stmt, Env* env, LabelMap*
17051755 return res ;
17061756 }
17071757
1758+ case STMT_THR : {
1759+ Value thr_val = value_thr_new ();
1760+ Value thr_for_worker = value_copy (thr_val );
1761+ if (!env_assign (env , stmt -> as .thr_stmt .name , thr_val , TYPE_THR , true)) {
1762+ value_free (thr_for_worker );
1763+ value_free (thr_val );
1764+ return make_error ("Cannot assign to THR identifier" , stmt -> line , stmt -> column );
1765+ }
1766+ value_free (thr_val );
1767+
1768+ #if PREFIX_HAS_THREADS
1769+ ThrStart * start = safe_malloc (sizeof (ThrStart ));
1770+ Interpreter * thr_interp = safe_malloc (sizeof (Interpreter ));
1771+ * thr_interp = (Interpreter ){0 };
1772+ thr_interp -> global_env = interp -> global_env ;
1773+ thr_interp -> functions = interp -> functions ;
1774+ thr_interp -> loop_depth = 0 ;
1775+ thr_interp -> error = NULL ;
1776+ thr_interp -> error_line = 0 ;
1777+ thr_interp -> error_col = 0 ;
1778+ thr_interp -> in_try_block = false;
1779+ thr_interp -> modules = interp -> modules ;
1780+ thr_interp -> shushed = interp -> shushed ;
1781+
1782+ start -> interp = thr_interp ;
1783+ start -> env = env ;
1784+ start -> body = stmt -> as .thr_stmt .body ;
1785+ start -> thr_val = thr_for_worker ;
1786+
1787+ if (thrd_create (& thr_for_worker .as .thr -> thread , thr_worker , start ) != thrd_success ) {
1788+ value_thr_set_finished (thr_for_worker , 1 );
1789+ value_free (thr_for_worker );
1790+ free (thr_interp );
1791+ free (start );
1792+ return make_error ("Failed to start THR" , stmt -> line , stmt -> column );
1793+ }
1794+ #else
1795+ LabelMap local_labels = {0 };
1796+ ExecResult res = exec_stmt (interp , stmt -> as .thr_stmt .body , env , & local_labels );
1797+ for (size_t i = 0 ; i < local_labels .count ; i ++ ) value_free (local_labels .items [i ].key );
1798+ free (local_labels .items );
1799+ if (res .status == EXEC_ERROR && res .error ) free (res .error );
1800+ if (res .status == EXEC_RETURN || res .status == EXEC_OK || res .status == EXEC_GOTO ) {
1801+ value_free (res .value );
1802+ }
1803+ value_thr_set_finished (thr_for_worker , 1 );
1804+ value_free (thr_for_worker );
1805+ #endif
1806+ return make_ok (value_null ());
1807+ }
1808+
17081809 case STMT_IF : {
17091810 Value cond = eval_expr (interp , stmt -> as .if_stmt .condition , env );
17101811 if (interp -> error ) {
0 commit comments