@@ -1516,6 +1516,58 @@ pub fn standard_vm() -> VM {
15161516 Ok ( Value :: bool ( !args[ 0 ] . is_truthy ( ) ) )
15171517 } ) ) ;
15181518
1519+ // Math helper functions
1520+ vm. define_global ( "abs" , native ( "abs" , |args| {
1521+ if args. len ( ) != 1 { return Err ( "abs expects 1 argument" . to_string ( ) ) ; }
1522+ if let Some ( i) = args[ 0 ] . as_int ( ) {
1523+ Ok ( Value :: int ( i. abs ( ) ) )
1524+ } else if let Some ( f) = args[ 0 ] . as_float ( ) {
1525+ Ok ( Value :: float ( f. abs ( ) ) )
1526+ } else {
1527+ Err ( "abs expects a number" . to_string ( ) )
1528+ }
1529+ } ) ) ;
1530+
1531+ vm. define_global ( "even?" , native ( "even?" , |args| {
1532+ if args. len ( ) != 1 { return Err ( "even? expects 1 argument" . to_string ( ) ) ; }
1533+ if let Some ( i) = args[ 0 ] . as_int ( ) {
1534+ Ok ( Value :: bool ( i % 2 == 0 ) )
1535+ } else {
1536+ Err ( "even? expects an integer" . to_string ( ) )
1537+ }
1538+ } ) ) ;
1539+
1540+ vm. define_global ( "odd?" , native ( "odd?" , |args| {
1541+ if args. len ( ) != 1 { return Err ( "odd? expects 1 argument" . to_string ( ) ) ; }
1542+ if let Some ( i) = args[ 0 ] . as_int ( ) {
1543+ Ok ( Value :: bool ( i % 2 != 0 ) )
1544+ } else {
1545+ Err ( "odd? expects an integer" . to_string ( ) )
1546+ }
1547+ } ) ) ;
1548+
1549+ vm. define_global ( "positive?" , native ( "positive?" , |args| {
1550+ if args. len ( ) != 1 { return Err ( "positive? expects 1 argument" . to_string ( ) ) ; }
1551+ if let Some ( i) = args[ 0 ] . as_int ( ) {
1552+ Ok ( Value :: bool ( i > 0 ) )
1553+ } else if let Some ( f) = args[ 0 ] . as_float ( ) {
1554+ Ok ( Value :: bool ( f > 0.0 ) )
1555+ } else {
1556+ Err ( "positive? expects a number" . to_string ( ) )
1557+ }
1558+ } ) ) ;
1559+
1560+ vm. define_global ( "negative?" , native ( "negative?" , |args| {
1561+ if args. len ( ) != 1 { return Err ( "negative? expects 1 argument" . to_string ( ) ) ; }
1562+ if let Some ( i) = args[ 0 ] . as_int ( ) {
1563+ Ok ( Value :: bool ( i < 0 ) )
1564+ } else if let Some ( f) = args[ 0 ] . as_float ( ) {
1565+ Ok ( Value :: bool ( f < 0.0 ) )
1566+ } else {
1567+ Err ( "negative? expects a number" . to_string ( ) )
1568+ }
1569+ } ) ) ;
1570+
15191571 // List operations
15201572 vm. define_global ( "list" , native ( "list" , |args| Ok ( Value :: list ( args. to_vec ( ) ) ) ) ) ;
15211573
@@ -2242,6 +2294,100 @@ pub fn standard_vm() -> VM {
22422294 }
22432295 } ) ) ;
22442296
2297+ vm. define_global ( "pmap" , native ( "pmap" , |args| {
2298+ use rayon:: prelude:: * ;
2299+
2300+ if args. len ( ) != 2 {
2301+ return Err ( "pmap expects 2 arguments (function list)" . to_string ( ) ) ;
2302+ }
2303+
2304+ // Get the function
2305+ let func = & args[ 0 ] ;
2306+
2307+ // Get the list
2308+ let items = args[ 1 ] . as_list ( )
2309+ . ok_or_else ( || "pmap expects a list as second argument" . to_string ( ) ) ?;
2310+
2311+ // Check if function is a native function
2312+ let native_func = func. as_native_function ( )
2313+ . ok_or_else ( || "pmap currently only supports native functions" . to_string ( ) ) ?;
2314+
2315+ // Convert items to SharedValue for thread-safe processing
2316+ let shared_items: Result < Vec < _ > , String > = items. iter ( )
2317+ . map ( |v| v. make_shared ( ) )
2318+ . collect ( ) ;
2319+ let shared_items = shared_items?;
2320+
2321+ // Process in parallel using Rayon
2322+ let results: Result < Vec < _ > , String > = shared_items
2323+ . par_iter ( )
2324+ . map ( |shared_val| {
2325+ // Convert back to Rc-based Value for function call
2326+ let val = Value :: from_shared ( shared_val) ;
2327+
2328+ // Apply function
2329+ ( native_func. func ) ( & [ val] )
2330+ } )
2331+ . collect ( ) ;
2332+
2333+ let results = results?;
2334+
2335+ // Return as list
2336+ Ok ( Value :: list ( results) )
2337+ } ) ) ;
2338+
2339+ vm. define_global ( "pfilter" , native ( "pfilter" , |args| {
2340+ use rayon:: prelude:: * ;
2341+
2342+ if args. len ( ) != 2 {
2343+ return Err ( "pfilter expects 2 arguments (predicate list)" . to_string ( ) ) ;
2344+ }
2345+
2346+ // Get the predicate function
2347+ let pred = & args[ 0 ] ;
2348+
2349+ // Get the list
2350+ let items = args[ 1 ] . as_list ( )
2351+ . ok_or_else ( || "pfilter expects a list as second argument" . to_string ( ) ) ?;
2352+
2353+ // Check if predicate is a native function
2354+ let native_pred = pred. as_native_function ( )
2355+ . ok_or_else ( || "pfilter currently only supports native functions" . to_string ( ) ) ?;
2356+
2357+ // Convert items to SharedValue for thread-safe processing
2358+ let shared_items: Result < Vec < _ > , String > = items. iter ( )
2359+ . map ( |v| v. make_shared ( ) )
2360+ . collect ( ) ;
2361+ let shared_items = shared_items?;
2362+
2363+ // Filter in parallel using Rayon
2364+ let results: Result < Vec < _ > , String > = shared_items
2365+ . par_iter ( )
2366+ . filter_map ( |shared_val| {
2367+ // Convert back to Rc-based Value for function call
2368+ let val = Value :: from_shared ( shared_val) ;
2369+
2370+ // Apply predicate
2371+ match ( native_pred. func ) ( & [ val. clone ( ) ] ) {
2372+ Ok ( result) => {
2373+ // Check if result is truthy (not nil and not false)
2374+ if result. is_nil ( ) || ( result. as_bool ( ) == Some ( false ) ) {
2375+ None
2376+ } else {
2377+ Some ( Ok ( val) )
2378+ }
2379+ }
2380+ Err ( e) => Some ( Err ( e) ) ,
2381+ }
2382+ } )
2383+ . collect ( ) ;
2384+
2385+ let results = results?;
2386+
2387+ // Return as list
2388+ Ok ( Value :: list ( results) )
2389+ } ) ) ;
2390+
22452391 vm
22462392}
22472393
0 commit comments