@@ -178,7 +178,7 @@ tcc_read_cstring(ptr)
178178tcc_read_bytes(ptr , 5 )
179179# > [1] 68 65 6c 6c 6f
180180tcc_ptr_addr(ptr , hex = TRUE )
181- # > [1] "0x5dafff18bed0 "
181+ # > [1] "0x57e1a27400f0 "
182182tcc_ptr_is_null(ptr )
183183# > [1] FALSE
184184tcc_free(ptr )
@@ -209,11 +209,11 @@ through output parameters.
209209ptr_ref <- tcc_malloc(.Machine $ sizeof.pointer %|| % 8L )
210210target <- tcc_malloc(8 )
211211tcc_ptr_set(ptr_ref , target )
212- # > <pointer: 0x5dafff262a50 >
212+ # > <pointer: 0x57e19ec62480 >
213213tcc_data_ptr(ptr_ref )
214- # > <pointer: 0x5db00198a030 >
214+ # > <pointer: 0x57e19e05f410 >
215215tcc_ptr_set(ptr_ref , tcc_null_ptr())
216- # > <pointer: 0x5dafff262a50 >
216+ # > <pointer: 0x57e19ec62480 >
217217tcc_free(target )
218218# > NULL
219219tcc_free(ptr_ref )
@@ -441,7 +441,7 @@ ffi <- tcc_ffi() |>
441441
442442x <- as.integer(1 : 100 ) # to avoid ALTREP
443443.Internal(inspect(x ))
444- # > @5db002c5b160 13 INTSXP g0c0 [REF(65535)] 1 : 100 (compact)
444+ # > @57e1a0611640 13 INTSXP g0c0 [REF(65535)] 1 : 100 (compact)
445445ffi $ sum_array(x , length(x ))
446446# > [1] 5050
447447
457457# > [1] 11
458458
459459.Internal(inspect(x ))
460- # > @5db002c5b160 13 INTSXP g0c0 [REF(65535)] 11 : 110 (expanded)
460+ # > @57e1a0611640 13 INTSXP g0c0 [REF(65535)] 11 : 110 (expanded)
461461```
462462
463463## Advanced FFI features
@@ -484,15 +484,15 @@ ffi <- tcc_ffi() |>
484484
485485p1 <- ffi $ struct_point_new()
486486ffi $ struct_point_set_x(p1 , 0.0 )
487- # > <pointer: 0x5db001d8b2f0 >
487+ # > <pointer: 0x57e19ff258d0 >
488488ffi $ struct_point_set_y(p1 , 0.0 )
489- # > <pointer: 0x5db001d8b2f0 >
489+ # > <pointer: 0x57e19ff258d0 >
490490
491491p2 <- ffi $ struct_point_new()
492492ffi $ struct_point_set_x(p2 , 3.0 )
493- # > <pointer: 0x5db0024ee190 >
493+ # > <pointer: 0x57e19e089190 >
494494ffi $ struct_point_set_y(p2 , 4.0 )
495- # > <pointer: 0x5db0024ee190 >
495+ # > <pointer: 0x57e19e089190 >
496496
497497ffi $ distance(p1 , p2 )
498498# > [1] 5
@@ -537,9 +537,9 @@ ffi <- tcc_ffi() |>
537537
538538s <- ffi $ struct_flags_new()
539539ffi $ struct_flags_set_active(s , 1L )
540- # > <pointer: 0x5dafffa48a90 >
540+ # > <pointer: 0x57e19d142ee0 >
541541ffi $ struct_flags_set_level(s , 9L )
542- # > <pointer: 0x5dafffa48a90 >
542+ # > <pointer: 0x57e19d142ee0 >
543543ffi $ struct_flags_get_active(s )
544544# > [1] 1
545545ffi $ struct_flags_get_level(s )
@@ -890,28 +890,19 @@ tcc_callback_close(cb)
890890
891891### Stackful C coroutines: streaming BCF/VCF records with htslib
892892
893- A more experimental pattern is to use Rtinycc as a JIT compiler for
894- native iterators that keep their own C stack between calls from R. The
895- script
896- [ ` scripts/demo-streaming-bcf-reader-ffi.R ` ] ( scripts/demo-streaming-bcf-reader-ffi.R )
897- combines the stackful ` ucontext ` coroutine pattern from
898- [ ` scripts/demo-stackful-coroutine-ffi.R ` ] ( scripts/demo-stackful-coroutine-ffi.R )
899- with [ htslib] ( https://www.htslib.org/ ) to make a streaming BCF/VCF
900- reader. Each call from R resumes the native reader until the next
901- ` bcf1_t ` record is available, yields back to R, and then lets R copy the
902- current record into a regular list.
903-
904- The important safety rule is that the alternate coroutine stack does not
905- call R’s C API. htslib owns the file/header/record state, the coroutine
906- only yields status codes, and R objects are created after control has
907- returned to the normal R call stack.
908-
909- The README runs the demo when htslib is available on the build machine.
910- The example input is plain VCF text because htslib can stream VCF and
911- BCF through the same API; no ` bcftools ` conversion step is needed.
893+ Rtinycc can JIT-compile native iterators that keep their own C stack
894+ between R calls. This demo binds [ htslib] ( https://www.htslib.org/ )
895+ through a ` ucontext ` coroutine: R resumes the reader until the next
896+ ` bcf1_t ` , then copies the current fields into a regular list. The
897+ coroutine stack never calls R’s C API; R objects are created only after
898+ control returns to the normal R stack.
899+
900+ The demo uses plain VCF text, opened directly by htslib through the same
901+ API as BCF.
912902
913903``` r
914- cat(system2(R.home(" bin/Rscript" ), " scripts/demo-streaming-bcf-reader-ffi.R" , stdout = TRUE ), sep = " \n " )
904+ source(" scripts/demo-streaming-bcf-reader-ffi.R" )
905+ run_streaming_bcf_demo()
915906# > Rtinycc version: 0.1.10
916907# > Demo: stackful coroutine + htslib BCF/VCF API streaming reader
917908# > Note: htslib reads run on the alternate coroutine stack; R objects are built only after each yield.
@@ -926,9 +917,7 @@ cat(system2(R.home("bin/Rscript"), "scripts/demo-streaming-bcf-reader-ffi.R", st
926917# > done_after_collect=TRUE
927918```
928919
929- The README also displays the actual demo source below, rather than a
930- shortened pseudo-example. The full R script is foldable so the page
931- stays readable.
920+ The full demo source is foldable below.
932921
933922<details >
934923<summary >
@@ -1384,7 +1373,7 @@ make_demo_vcf <- function() {
13841373 vcf
13851374}
13861375
1387- if (identical(sys.nframe(), 0L ) ) {
1376+ run_streaming_bcf_demo <- function ( ) {
13881377 say(" Rtinycc version: " , as.character(utils :: packageVersion(" Rtinycc" )))
13891378 say(" Demo: stackful coroutine + htslib BCF/VCF API streaming reader" )
13901379 say(" Note: htslib reads run on the alternate coroutine stack; R objects are built only after each yield." )
@@ -1419,6 +1408,11 @@ if (identical(sys.nframe(), 0L)) {
14191408 }
14201409
14211410 say(" done_after_collect=" , isTRUE(ffi $ bcf_stream_done(reader $ ptr )))
1411+ invisible (NULL )
1412+ }
1413+
1414+ if (identical(sys.nframe(), 0L )) {
1415+ run_streaming_bcf_demo()
14221416}
14231417```
14241418
@@ -1774,7 +1768,7 @@ ffi <- tcc_ffi() |>
17741768 tcc_compile()
17751769
17761770ffi$struct_point_new()
1777- #> <pointer: 0x5db00115f320 >
1771+ #> <pointer: 0x57e19cff8f30 >
17781772ffi$enum_status_OK()
17791773#> [1] 0
17801774ffi$global_global_counter_get()
@@ -1891,11 +1885,11 @@ if (Sys.info()[["sysname"]] == "Linux") {
18911885# > # A tibble: 5 × 13
18921886# > expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time
18931887# > <bch:expr> <bch:t> <bch:t> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm>
1894- # > 1 read_tabl… 52.26ms 52.26ms 19 .1 6.33MB 19 .1 1 1 52.3ms
1895- # > 2 vroom_df_… 6.41ms 6.56ms 152 . 1.22MB 0 2 0 13.1ms
1896- # > 3 vroom_df_… 6.51ms 6.61ms 151 . 2.44MB 0 2 0 13.2ms
1897- # > 4 c_read_df 21.07ms 21.16ms 47.2 1.22MB 0 2 0 42.3ms
1898- # > 5 io_uring_… 20.18ms 20.66ms 48.4 1.22MB 0 2 0 41.3ms
1888+ # > 1 read_tabl… 49.73ms 49.73ms 20 .1 6.33MB 20 .1 1 1 49.7ms
1889+ # > 2 vroom_df_… 6.38ms 6.74ms 148 . 1.22MB 0 2 0 13.5ms
1890+ # > 3 vroom_df_… 6.58ms 6.92ms 145 . 2.44MB 0 2 0 13.8ms
1891+ # > 4 c_read_df 21.05ms 21.06ms 47.5 1.22MB 0 2 0 42.1ms
1892+ # > 5 io_uring_… 19.92ms 19.92ms 50.2 1.22MB 0 2 0 39.8ms
18991893# > # ℹ 4 more variables: result <list>, memory <list>, time <list>, gc <list>
19001894```
19011895
@@ -1997,9 +1991,9 @@ ffi <- tcc_ffi() |>
19971991
19981992b <- ffi $ struct_buf_new()
19991993ffi $ struct_buf_set_data_elt(b , 0L , 0xCAL )
2000- # > <pointer: 0x5db00ab77c60 >
1994+ # > <pointer: 0x57e1a847e840 >
20011995ffi $ struct_buf_set_data_elt(b , 1L , 0xFEL )
2002- # > <pointer: 0x5db00ab77c60 >
1996+ # > <pointer: 0x57e1a847e840 >
20031997ffi $ struct_buf_get_data_elt(b , 0L )
20041998# > [1] 202
20051999ffi $ struct_buf_get_data_elt(b , 1L )
0 commit comments