galaaz 0.4.10 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/LICENSE +0 -0
  4. data/README.md +3123 -882
  5. data/Rakefile +62 -41
  6. data/bin/galaaz-bootstrap +137 -0
  7. data/bin/galaaz-jruby +14 -0
  8. data/bin/galaaz_jruby_env.inc.sh +6 -0
  9. data/bin/gbookdown +64 -0
  10. data/bin/gknit +223 -6
  11. data/bin/gknit-draft +105 -0
  12. data/bin/gknit-draft.rb +28 -0
  13. data/bin/gknit_Rscript +127 -0
  14. data/bin/grun +27 -1
  15. data/bin/gstudio +49 -4
  16. data/bin/{gstudio.rb → gstudio_irb.rb} +0 -0
  17. data/bin/gstudio_pry.rb +7 -0
  18. data/bin/install-tinytex +6 -0
  19. data/bin/run_all_rspec +43 -0
  20. data/bin/run_example +14 -0
  21. data/bin/run_old_rspec +19 -0
  22. data/bin/run_rspec +23 -0
  23. data/bin/run_rspec_subset +38 -0
  24. data/bin/run_slow_rspec +19 -0
  25. data/blogs/R-on-Rails-Planning-Document.md +940 -0
  26. data/blogs/README.md +100 -0
  27. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
  28. data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
  29. data/blogs/galaaz_ggplot/galaaz_ggplot.md +364 -0
  30. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
  31. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
  32. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
  33. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
  34. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
  35. data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
  36. data/blogs/galaaz_ggplot/midwest_external_png +0 -0
  37. data/blogs/gknit/gknit.Rmd +52 -55
  38. data/blogs/gknit/gknit.md +94 -94
  39. data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
  40. data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
  41. data/blogs/gknit/lst.rds +0 -0
  42. data/blogs/gknit/model.rb +1 -1
  43. data/blogs/gknit/stats.bib +0 -0
  44. data/blogs/manual/include_model_local_repro.Rmd +14 -0
  45. data/blogs/manual/include_model_local_repro.md +75 -0
  46. data/blogs/manual/lst.rds +0 -0
  47. data/blogs/manual/manual.Rmd +1582 -196
  48. data/blogs/manual/manual.log +1786 -0
  49. data/blogs/manual/manual.md +3107 -890
  50. data/blogs/manual/manual.tex +3018 -1086
  51. data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
  52. data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
  53. data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
  54. data/blogs/manual/model.rb +41 -0
  55. data/blogs/nse_dplyr/nse_dplyr.Rmd +277 -151
  56. data/blogs/nse_dplyr/nse_dplyr.log +928 -0
  57. data/blogs/nse_dplyr/nse_dplyr.md +457 -293
  58. data/blogs/oh_my/not_so.rb +0 -0
  59. data/blogs/oh_my/oh_my.Rmd +1234 -25
  60. data/blogs/oh_my/oh_my.log +804 -0
  61. data/blogs/oh_my/oh_my.md +1808 -228
  62. data/blogs/oh_my/oh_my.tex +821 -0
  63. data/blogs/oh_my/old.Rmd +15 -14
  64. data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
  65. data/blogs/ruby_plot/ruby_plot.log +885 -0
  66. data/blogs/ruby_plot/ruby_plot.md +71 -103
  67. data/blogs/ruby_plot/ruby_plot.tex +940 -0
  68. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
  69. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
  70. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
  71. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
  72. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
  73. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
  74. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
  75. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
  76. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
  77. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
  78. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
  79. data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
  80. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  81. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  82. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  83. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  84. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  85. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  86. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  87. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  88. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  89. data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  90. data/blogs/test/test.Rmd +14 -0
  91. data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
  92. data/examples/50Plots_MasterList/ScatterPlot.rb +0 -0
  93. data/examples/50Plots_MasterList/scatter_plot.rb +0 -0
  94. data/examples/Bibliography/master.bib +50 -0
  95. data/examples/Bibliography/stats.bib +72 -0
  96. data/examples/R/calc.R +0 -0
  97. data/examples/R/java_interop.R +0 -0
  98. data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
  99. data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +53 -0
  100. data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
  101. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +33 -0
  102. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +34 -0
  103. data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
  104. data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
  105. data/examples/islr/all.rb +13 -0
  106. data/examples/islr/ch2.spec.rb +37 -7
  107. data/examples/islr/ch3.spec.rb +11 -2
  108. data/examples/islr/ch3_boston.rb +27 -0
  109. data/examples/islr/ch3_multiple_regression.rb +0 -0
  110. data/examples/islr/ch6.spec.rb +24 -1
  111. data/examples/islr/x_y_rnorm.jpg +0 -0
  112. data/examples/latex_templates/Test-acm_article/Makefile +16 -0
  113. data/examples/latex_templates/Test-acm_article/Test-acm_article.Rmd +65 -0
  114. data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +1670 -0
  115. data/examples/latex_templates/Test-acm_article/sensys-abstract.cls +703 -0
  116. data/examples/latex_templates/Test-acm_article/sigproc.bib +59 -0
  117. data/examples/latex_templates/Test-acs_article/Test-acs_article.Rmd +260 -0
  118. data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +11 -0
  119. data/examples/latex_templates/Test-acs_article/acs-my_output.bib +11 -0
  120. data/examples/latex_templates/Test-acs_article/acstest.bib +17 -0
  121. data/examples/latex_templates/Test-aea_article/AEA.cls +1414 -0
  122. data/{blogs/gknit/marshal.dump → examples/latex_templates/Test-aea_article/BibFile.bib} +0 -0
  123. data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +108 -0
  124. data/examples/latex_templates/Test-aea_article/aea.bst +1269 -0
  125. data/examples/latex_templates/Test-aea_article/multicol.sty +853 -0
  126. data/examples/latex_templates/Test-aea_article/references.bib +0 -0
  127. data/examples/latex_templates/Test-aea_article/setspace.sty +546 -0
  128. data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +256 -0
  129. data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +3397 -0
  130. data/examples/latex_templates/Test-ams_article/Test-ams_article.Rmd +215 -0
  131. data/examples/latex_templates/Test-ams_article/amstest.bib +436 -0
  132. data/examples/latex_templates/Test-asa_article/Test-asa_article.Rmd +153 -0
  133. data/examples/latex_templates/Test-asa_article/agsm.bst +1353 -0
  134. data/examples/latex_templates/Test-asa_article/bibliography.bib +233 -0
  135. data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +2409 -0
  136. data/examples/latex_templates/Test-ieee_article/IEEEtran.cls +6346 -0
  137. data/examples/latex_templates/Test-ieee_article/Test-ieee_article.Rmd +175 -0
  138. data/examples/latex_templates/Test-ieee_article/mybibfile.bib +20 -0
  139. data/examples/latex_templates/Test-rjournal_article/RJournal.sty +335 -0
  140. data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +18 -0
  141. data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +52 -0
  142. data/examples/latex_templates/Test-springer_article/Test-springer_article.Rmd +65 -0
  143. data/examples/latex_templates/Test-springer_article/bibliography.bib +26 -0
  144. data/examples/latex_templates/Test-springer_article/spbasic.bst +1658 -0
  145. data/examples/latex_templates/Test-springer_article/spmpsci.bst +1512 -0
  146. data/examples/latex_templates/Test-springer_article/spphys.bst +1443 -0
  147. data/examples/latex_templates/Test-springer_article/svglov3.clo +113 -0
  148. data/examples/latex_templates/Test-springer_article/svjour3.cls +1431 -0
  149. data/examples/misc/baseball.csv +0 -0
  150. data/examples/misc/ggplot.rb +3 -2
  151. data/examples/misc/moneyball.rb +0 -0
  152. data/examples/misc/subsetting.rb +0 -0
  153. data/examples/multithread_shards_to_r/shards_to_r.rb +67 -0
  154. data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +73 -0
  155. data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +382 -0
  156. data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +164 -0
  157. data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +92 -0
  158. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +482 -0
  159. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +280 -0
  160. data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +386 -0
  161. data/examples/sthda_ggplot/README.md +0 -0
  162. data/examples/sthda_ggplot/RUN.md +41 -0
  163. data/examples/sthda_ggplot/all.rb +0 -0
  164. data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +0 -0
  165. data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +0 -0
  166. data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +2 -0
  167. data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +0 -0
  168. data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +0 -0
  169. data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +0 -0
  170. data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +0 -0
  171. data/examples/sthda_ggplot/one_variable_continuous/stat.rb +0 -0
  172. data/examples/sthda_ggplot/one_variable_discrete/bar.rb +0 -0
  173. data/examples/sthda_ggplot/qplots/box_violin_dot.rb +0 -0
  174. data/examples/sthda_ggplot/qplots/scatter_plots.rb +0 -0
  175. data/examples/sthda_ggplot/scatter_gg.rb +0 -0
  176. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +0 -0
  177. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +0 -0
  178. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +0 -0
  179. data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +0 -0
  180. data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +0 -0
  181. data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +0 -0
  182. data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +4 -3
  183. data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +0 -0
  184. data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +0 -0
  185. data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +0 -0
  186. data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +0 -0
  187. data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +0 -0
  188. data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +0 -0
  189. data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +0 -0
  190. data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +0 -0
  191. data/ext/new_bridge/Makefile +46 -0
  192. data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
  193. data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
  194. data/lib/R_interface/galaaz_device.R +20 -0
  195. data/lib/R_interface/include_engine.R +109 -0
  196. data/lib/R_interface/new_bridge_adapter.rb +824 -0
  197. data/lib/R_interface/r.rb +177 -25
  198. data/lib/R_interface/r_arrow.rb +113 -0
  199. data/lib/R_interface/r_libs.R +4 -4
  200. data/lib/R_interface/r_methods.rb +13 -116
  201. data/lib/R_interface/r_module_s.rb +0 -0
  202. data/lib/R_interface/rbinary_operators.rb +20 -2
  203. data/lib/R_interface/rclosure.rb +5 -1
  204. data/lib/R_interface/rdata_frame.rb +34 -70
  205. data/lib/R_interface/rdevice.rb +125 -0
  206. data/lib/R_interface/rdevices.R +0 -0
  207. data/lib/R_interface/renvironment.rb +10 -4
  208. data/lib/R_interface/rexpression.rb +5 -1
  209. data/lib/R_interface/rindexed_object.rb +41 -13
  210. data/lib/R_interface/rlanguage.rb +20 -62
  211. data/lib/R_interface/rlist.rb +115 -25
  212. data/lib/R_interface/rlogical_operators.rb +0 -0
  213. data/lib/R_interface/rmatrix.rb +2 -11
  214. data/lib/R_interface/rmd_indexed_object.rb +5 -1
  215. data/lib/R_interface/robject.rb +348 -290
  216. data/lib/R_interface/rpkg.rb +1 -0
  217. data/lib/R_interface/rsupport.rb +610 -331
  218. data/lib/R_interface/rsupport_scope.rb +2 -1
  219. data/lib/R_interface/rsymbol.rb +50 -0
  220. data/lib/R_interface/ruby_callback.rb +2 -3
  221. data/lib/R_interface/ruby_extensions.rb +225 -175
  222. data/lib/R_interface/runary_operators.rb +0 -0
  223. data/lib/R_interface/rvector.rb +147 -31
  224. data/lib/galaaz.rb +0 -0
  225. data/lib/galaaz_jruby.rb +22 -0
  226. data/lib/gknit/diagnostics.rb +50 -0
  227. data/lib/gknit/draft.rb +111 -0
  228. data/lib/gknit/include_engine.rb +15 -7
  229. data/lib/gknit/knitr_engine.rb +223 -107
  230. data/lib/gknit/rb_engine.rb +3 -3
  231. data/lib/gknit/ruby_engine.rb +0 -0
  232. data/lib/gknit.rb +3 -0
  233. data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
  234. data/lib/new_bridge/envelope.rb +51 -0
  235. data/lib/new_bridge/eval_result.rb +26 -0
  236. data/lib/new_bridge/framing.rb +39 -0
  237. data/lib/new_bridge/instance_pool_client.rb +38 -0
  238. data/lib/new_bridge/r_instance_manager.rb +404 -0
  239. data/lib/new_bridge/session_client.rb +530 -0
  240. data/lib/new_bridge/tcp_framed.rb +44 -0
  241. data/lib/new_bridge.rb +9 -0
  242. data/lib/util/exec_ruby.rb +95 -46
  243. data/lib/util/inline_file.rb +35 -30
  244. data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
  245. data/new_bridge_specs/eval_r_async_spec.rb +113 -0
  246. data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
  247. data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
  248. data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
  249. data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
  250. data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
  251. data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
  252. data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
  253. data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
  254. data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
  255. data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
  256. data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
  257. data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
  258. data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
  259. data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
  260. data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
  261. data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
  262. data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
  263. data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
  264. data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
  265. data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
  266. data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
  267. data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
  268. data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
  269. data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
  270. data/r_requires/ggplot.rb +0 -0
  271. data/r_requires/knitr.rb +0 -0
  272. data/specs/all.rb +15 -11
  273. data/specs/arrow_from_ruby_batches_spec.rb +50 -0
  274. data/specs/arrow_semantics_spec.rb +64 -0
  275. data/specs/bridge_concurrent_spec.rb +46 -0
  276. data/specs/bridge_nested_spec.rb +25 -0
  277. data/specs/dataframe_semantics_spec.rb +122 -0
  278. data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
  279. data/specs/dispatch_probe_cache_spec.rb +38 -0
  280. data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
  281. data/specs/dispatch_probe_fallback_spec.rb +18 -0
  282. data/specs/environment_semantics_spec.rb +89 -0
  283. data/specs/field_access_spec.rb +31 -0
  284. data/specs/figures/bg.jpeg +0 -0
  285. data/specs/figures/bg.png +0 -0
  286. data/specs/figures/bg.svg +168 -57
  287. data/specs/figures/dose_len.png +0 -0
  288. data/specs/figures/no_args.jpeg +0 -0
  289. data/specs/figures/no_args.png +0 -0
  290. data/specs/figures/no_args.svg +168 -57
  291. data/specs/figures/width_height.jpeg +0 -0
  292. data/specs/figures/width_height.png +0 -0
  293. data/specs/figures/width_height_units1.jpeg +0 -0
  294. data/specs/figures/width_height_units1.png +0 -0
  295. data/specs/figures/width_height_units2.jpeg +0 -0
  296. data/specs/figures/width_height_units2.png +0 -0
  297. data/specs/formula_semantics_spec.rb +81 -0
  298. data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
  299. data/specs/galaaz_util_inline_file_spec.rb +54 -0
  300. data/specs/gknit_cli_option_permutation_spec.rb +24 -0
  301. data/specs/gknit_include_engine_spec.rb +72 -0
  302. data/specs/gknit_install_timeout_report_spec.rb +69 -0
  303. data/specs/gknit_internal_error_report_spec.rb +57 -0
  304. data/specs/gknit_vector_map_output_spec.rb +59 -0
  305. data/specs/globalenv_guardrail_spec.rb +52 -0
  306. data/specs/language_expression_semantics_spec.rb +145 -0
  307. data/specs/list_semantics_spec.rb +111 -0
  308. data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
  309. data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
  310. data/specs/new_bridge_callback_timeout_spec.rb +69 -0
  311. data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
  312. data/specs/nil_null_spec.rb +42 -0
  313. data/specs/object_build_phase2_spec.rb +53 -0
  314. data/specs/phase1_callback_bridge_spec.rb +84 -0
  315. data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
  316. data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
  317. data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
  318. data/specs/plot_device_semantics_spec.rb +28 -0
  319. data/specs/plot_snapshot_semantics_spec.rb +58 -0
  320. data/specs/protocol_result_spec.rb +236 -0
  321. data/specs/r_batch_fail_fast_spec.rb +47 -0
  322. data/specs/r_bridge_bootstrap_spec.rb +11 -0
  323. data/specs/r_devices.spec.rb +1 -1
  324. data/specs/r_eval.spec.rb +16 -18
  325. data/specs/r_function.spec.rb +1 -1
  326. data/specs/r_instance_manager_spec.rb +285 -0
  327. data/specs/r_list_apply.spec.rb +15 -15
  328. data/specs/r_matrix.spec.rb +0 -0
  329. data/specs/r_nse.spec.rb +5 -5
  330. data/specs/r_object_send_dispatch_spec.rb +13 -0
  331. data/specs/r_vector_comparator_spec.rb +8 -0
  332. data/specs/r_vector_creation.spec.rb +0 -0
  333. data/specs/r_vector_functions.spec.rb +0 -0
  334. data/specs/r_vector_object.spec.rb +0 -0
  335. data/specs/r_vector_operators.spec.rb +0 -0
  336. data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
  337. data/specs/r_vector_subsetting.spec.rb +0 -0
  338. data/specs/range_helper_spec.rb +21 -0
  339. data/specs/rsupport_scope_spec.rb +28 -0
  340. data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
  341. data/specs/scalar_character_spec.rb +44 -0
  342. data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
  343. data/specs/session_env_bridge_spec.rb +25 -0
  344. data/specs/simplecov_bootstrap_spec.rb +10 -0
  345. data/specs/spec_helper.rb +10 -0
  346. data/specs/tmp.rb +41 -20
  347. data/specs/unboxing_recursion_regression_spec.rb +30 -0
  348. data/specs/unboxing_spec.rb +49 -0
  349. data/specs/verify_callbacks.rb +42 -0
  350. data/sty/galaaz.sty +0 -0
  351. data/version.rb +1 -1
  352. metadata +239 -71
  353. data/blogs/galaaz_ggplot/galaaz_ggplot.aux +0 -41
  354. data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -705
  355. data/blogs/galaaz_ggplot/galaaz_ggplot.out +0 -10
  356. data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
  357. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-latex/midwest_rb.pdf +0 -0
  358. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-latex/scatter_plot_rb.pdf +0 -0
  359. data/blogs/galaaz_ggplot/midwest.html +0 -188
  360. data/blogs/gknit/gknit.html +0 -2266
  361. data/blogs/gknit/gknit.pdf +0 -0
  362. data/blogs/gknit/gknit.tex +0 -1358
  363. data/blogs/manual/graph.rb +0 -29
  364. data/blogs/manual/manual.html +0 -2995
  365. data/blogs/manual/manual.pdf +0 -0
  366. data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
  367. data/blogs/nse_dplyr/nse_dplyr.html +0 -960
  368. data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
  369. data/blogs/nse_dplyr/nse_dplyr.tex +0 -1373
  370. data/blogs/oh_my/oh_my.html +0 -680
  371. data/blogs/ruby_plot/ruby_plot.Rmd_external_figs +0 -662
  372. data/blogs/ruby_plot/ruby_plot.html +0 -729
  373. data/blogs/ruby_plot/ruby_plot.pdf +0 -0
  374. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.svg +0 -57
  375. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.svg +0 -106
  376. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.svg +0 -110
  377. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.svg +0 -174
  378. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.svg +0 -236
  379. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.svg +0 -296
  380. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.svg +0 -236
  381. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.svg +0 -218
  382. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.svg +0 -128
  383. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.svg +0 -150
  384. data/examples/paper/paper.rb +0 -36
  385. data/specs/r_dataframe.spec.rb +0 -379
  386. data/specs/r_environment.spec.rb +0 -140
  387. data/specs/r_formula.spec.rb +0 -232
  388. data/specs/r_language.spec.rb +0 -112
  389. data/specs/r_list.spec.rb +0 -293
  390. data/specs/r_plots.spec.rb +0 -72
  391. data/specs/ruby_expression.spec.rb +0 -315
@@ -22,6 +22,7 @@
22
22
  ##########################################################################################
23
23
 
24
24
  require 'stringio'
25
+ require 'tmpdir'
25
26
 
26
27
  #----------------------------------------------------------------------------------------
27
28
  # Class RC is used only as a context for all ruby chunks in the rmarkdown file.
@@ -40,6 +41,24 @@ class RC
40
41
  @out_list = R.c(@out_list, obj)
41
42
  end
42
43
 
44
+ # In gknit, stdout is redirected to StringIO. Under JRuby, Kernel.puts can treat
45
+ # R::Vector as array-like (to_ary) and print one element per line. Normalize R
46
+ # objects to their R printed form first, so `puts vec` matches gstudio (`[1] ...`).
47
+ def normalize_output_arg(arg)
48
+ return arg.to_s if arg.is_a?(::R::Object)
49
+ return arg.map { |item| normalize_output_arg(item) } if arg.is_a?(::Array)
50
+ arg
51
+ end
52
+
53
+ def puts(*args)
54
+ return ::Kernel.puts if args.empty?
55
+ ::Kernel.puts(*args.map { |arg| normalize_output_arg(arg) })
56
+ end
57
+
58
+ def print(*args)
59
+ ::Kernel.print(*args.map { |arg| normalize_output_arg(arg) })
60
+ end
61
+
43
62
  def reset_outputs
44
63
  @out_list = nil
45
64
  end
@@ -59,6 +78,39 @@ RCbinding = RChunk.get_binding
59
78
 
60
79
  module GalaazUtil
61
80
 
81
+ # Read a logical-ish knitr option directly from the options list on the R side.
82
+ # This avoids wrapper-shape differences when values arrive as handles/lists via NewBridge.
83
+ def self.knitr_option_trueish?(options, key, default: true)
84
+ return default unless options && options.respond_to?(:r_interop)
85
+
86
+ key_esc = key.to_s.gsub("'", "\\\\'")
87
+ txt = R.bridge.eval_r("as.character(#{options.r_interop}[['#{key_esc}']])").to_s
88
+ token = txt.sub(/\A\[\d+\]\s*/, '').gsub('"', '').strip.upcase
89
+ return true if token == 'TRUE'
90
+ return false if token == 'FALSE'
91
+ return default if token == '' || token == 'NA' || token == 'NULL'
92
+ return token.to_f != 0.0 if token.match?(/\A-?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?\z/)
93
+
94
+ default
95
+ rescue StandardError
96
+ default
97
+ end
98
+
99
+ # Knitr chunk options are often R logical NA ("inherit global default"). Those must not be
100
+ # treated as false (see R::Vector#unboxed_get: NA → nil). Defaults match knitr: eval/echo/include/message/warning TRUE.
101
+ def self.knitr_logical_trueish?(opt)
102
+ return true if opt.nil?
103
+ return opt if opt == true || opt == false
104
+
105
+ raw = opt.unboxed_get(0) if opt.respond_to?(:unboxed_get)
106
+ return true if raw.nil?
107
+ return raw if raw == true || raw == false
108
+ return raw != 0 if raw.is_a?(Numeric)
109
+ return !raw.to_s.strip.casecmp('FALSE').zero? if raw.respond_to?(:to_s)
110
+
111
+ true
112
+ end
113
+
62
114
  #----------------------------------------------------------------------------------------
63
115
  # Executes the ruby code with the given options.
64
116
  # @param options [R::List] An R list of options
@@ -78,15 +130,30 @@ module GalaazUtil
78
130
  def self.exec_ruby(options)
79
131
 
80
132
  # RubyChunk.init
81
-
82
- # read the chunk code
83
- code = R.paste(options.code, collapse: "\n") >> 0
84
-
133
+
134
+ # Read chunk code via a temp file (avoids result-protocol limits on long strings). Use Dir.tmpdir
135
+ # so gknit works without /dev/shm (macOS, sandboxes, minimal containers).
136
+ chunk_code_file = File.join(Dir.tmpdir, "galaaz_chunk_code_#{Process.pid}_#{Thread.current.object_id}.txt")
137
+ path_lit = ::R::Support.parse_arg(chunk_code_file)
138
+ begin
139
+ R.bridge.eval_r("writeLines(paste(#{options.r_interop}[['code']], collapse='\\n'), #{path_lit})")
140
+ code = File.read(chunk_code_file)
141
+ ensure
142
+ File.unlink(chunk_code_file) if chunk_code_file && File.file?(chunk_code_file)
143
+ end
144
+ # If the string arrived with literal \n (e.g. from R→Ruby transport), convert to real newlines so eval does not hit "unexpected backslash"
145
+ code = code.gsub("\\n", "\n") if code.is_a?(String)
85
146
  # the output should be a list with the proper structure to pass to
86
- # function engine_output. We first add the souce code from the block to
87
- # the list
88
- out_list = R.list(R.structure(R.list(src: code), class: 'source')) if
89
- options.echo >> 0
147
+ # function engine_output. We first add the source code from the block to
148
+ # the list. Pass src as a character vector of lines (not one string with \n)
149
+ # so knitr preserves line breaks and indentation in the rendered chunk.
150
+ if knitr_option_trueish?(options, 'echo', default: true)
151
+ src_lines = code.lines.map(&:chomp)
152
+ src_lines = [" "] if src_lines.empty?
153
+ out_list = R.list(R.structure(R.list(src: R.c(*src_lines)), class: 'source'))
154
+ else
155
+ out_list = R.list
156
+ end
90
157
 
91
158
  begin
92
159
 
@@ -98,8 +165,8 @@ module GalaazUtil
98
165
  # Execute the Ruby code in the scope of class RubyChunk. This is done
99
166
  # so that instance variables created in one chunk can be used again on
100
167
  # another chunk
101
- # RubyChunk.instance_eval(code) if (options[["eval"]] >> 0)
102
- eval(code, RCbinding, __FILE__, __LINE__ + 1) if (options[["eval"]] >> 0)
168
+ # RChunk.instance_eval(code) if (options[["eval"]].unboxed_get(0))
169
+ eval(code, RCbinding, __FILE__, __LINE__ + 1) if knitr_option_trueish?(options, 'eval', default: true)
103
170
 
104
171
  # add the returned value to the list
105
172
  # this should have captured everything in the evaluation code
@@ -109,23 +176,29 @@ module GalaazUtil
109
176
  out_list = R.c(out_list, out)
110
177
 
111
178
  rescue StandardError => e
179
+ begin
180
+ label = options['label'].unboxed_get(0).to_s
181
+ GknitDiagnostics.record(chunk_label: label, error: e) if defined?(GknitDiagnostics)
182
+ rescue StandardError
183
+ nil
184
+ end
112
185
 
113
- # print the error message
114
- if (options.message >> 0)
115
- message = R.list(R.structure(R.list(message: e.message), class: 'message'))
116
- out_list = R.c(out_list, message)
186
+ # Use R's simpleMessage/simpleWarning so knitr's engine_output can call conditionMessage() on them
187
+ # g_simpleMessage transforms "; " to newlines then calls simpleMessage (defined in R engine setup)
188
+ if knitr_option_trueish?(options, 'message', default: true)
189
+ msg_cond = R.g_simpleMessage(e.message.to_s)
190
+ out_list = R.c(out_list, msg_cond)
117
191
  end
118
192
 
119
- # Print the backtrace of the error message
120
- if (options.warning >> 0)
193
+ if knitr_option_trueish?(options, 'warning', default: true)
121
194
  bt = ""
122
195
  e.backtrace.each { |line| bt << line + "\n"}
123
- warning = R.list(R.structure(R.list(message: bt), class: 'message'))
124
- out_list = R.c(out_list, warning)
196
+ warn_cond = R.g_simpleWarning(bt)
197
+ out_list = R.c(out_list, warn_cond)
125
198
  end
126
199
 
127
200
  rescue SyntaxError => e
128
- STDERR.puts "A syntax error occured in ruby block '#{options.label >> 0}'"
201
+ STDERR.puts "A syntax error occured in ruby block '#{options['label'].unboxed_get(0)}'"
129
202
  raise SyntaxError.new(e)
130
203
 
131
204
  ensure
@@ -133,34 +206,10 @@ module GalaazUtil
133
206
  $stdout = STDOUT
134
207
  end
135
208
 
136
- (options.include >> 0)? out_list : R.list
137
-
138
- end
139
-
140
- #----------------------------------------------------------------------------------------
141
- # Used by old gknit. Will eventually be replaced by exe_ruby
142
- #----------------------------------------------------------------------------------------
143
-
144
- def self.exec_ruby_tor(code)
145
-
146
- # the output should be a list with the proper structure to pass to
147
- # function engine_output.
148
- out_list = R.list(R.structure(R.list(src: code), class: 'source'))
149
-
150
- # Set up standard output as a StringIO object.
151
- $stdout = StringIO.new
152
- RubyChunk.instance_eval(code)
153
-
154
- # this should have captured everything in the evaluation code
155
- # it is not working since at least RC10.
156
- out = $stdout.string
157
-
158
- out_list = R.c(out_list, out)
209
+ # include=FALSE must still execute code (knitr semantics). Output suppression is handled
210
+ # at engine emission stage, not here.
211
+ out_list
159
212
 
160
- # return $stdout to standard output
161
- $stdout = STDOUT
162
- R::Support.parse_arg(out_list)
163
-
164
213
  end
165
214
 
166
215
  end
@@ -24,22 +24,20 @@
24
24
  module GalaazUtil
25
25
 
26
26
  #========================================================================================
27
- # Opens the given filename for reading and returns the file content so that it can be
28
- # printed as a code chunk in rmarkdown
29
- # @param filename [String] the name of the file to be found. If the file has no
30
- # extension then '.rb' is assumed
31
- # @param relative [String] containing either 'require_relative ' or 'require '. In the
32
- # first case looks on the current directory, on the latter, searches the $LOAD_PATH
33
- # @param pwd [String] Directory to look at when 'require_relative ', by default, its
34
- # the pwd directory
27
+ # Resolves the path of the file (same logic as inline_file) and returns it. Does not
28
+ # read the file. Use this when the content will be read by R (e.g. readLines) to avoid
29
+ # embedding file content in R code.
30
+ # @param filename [String] same as inline_file
31
+ # @param relative [String] same as inline_file
32
+ # @param pwd [String] same as inline_file
33
+ # @return [String] resolved absolute path
35
34
  #========================================================================================
36
-
37
- def self.inline_file(filename, relative, pwd = Dir.pwd)
35
+ def self.inline_file_path(filename, relative, pwd = Dir.pwd)
36
+ f = filename.dup
37
+ f << ".rb" if File.extname(f) == ""
38
+ file = "#{pwd}/#{f}"
38
39
 
39
- filename << ".rb" if File.extname(filename) == ""
40
- file = "#{pwd}/#{filename}"
41
-
42
- if (relative == false)
40
+ if (relative == false) && !R.file__exists(file).unboxed_get(0)
43
41
  $LOAD_PATH.each do |path|
44
42
  begin
45
43
  files = Dir.entries(path)
@@ -48,28 +46,35 @@ module GalaazUtil
48
46
  end
49
47
 
50
48
  if files != nil
51
- file = "#{path}/#{filename}"
52
- # break if File.exist?(file)
53
- break if (R.file__exists(file) >> 0)
49
+ file = "#{path}/#{f}"
50
+ break if (R.file__exists(file).unboxed_get(0))
54
51
  end
55
52
  end
56
53
  end
57
54
 
58
- # There is a bug(?) in > RC15 that when the bellow command
59
- # is called, there is a call to R Polyglot eval passing to_i
60
- # if File.exist?(file)
61
- if (R.file__exists(file) >> 0)
62
- code = ""
63
- File.open(file, "r") do |fileObj|
64
- while (line = fileObj.gets)
65
- code << line
66
- end
55
+ raise Errno::ENOENT, "file #{filename} not found in #{$LOAD_PATH}" unless R.file__exists(file).unboxed_get(0)
56
+ file
57
+ end
58
+
59
+ #========================================================================================
60
+ # Opens the given filename for reading and returns the file content so that it can be
61
+ # printed as a code chunk in rmarkdown
62
+ # @param filename [String] the name of the file to be found. If the file has no
63
+ # extension then '.rb' is assumed
64
+ # @param relative [String] containing either 'require_relative ' or 'require '. In the
65
+ # first case looks on the current directory, on the latter, searches the $LOAD_PATH
66
+ # @param pwd [String] Directory to look at when 'require_relative ', by default, its
67
+ # the pwd directory
68
+ #========================================================================================
69
+
70
+ def self.inline_file(filename, relative, pwd = Dir.pwd)
71
+ file = inline_file_path(filename, relative, pwd)
72
+ code = ""
73
+ File.open(file, "r") do |fileObj|
74
+ while (line = fileObj.gets)
75
+ code << line
67
76
  end
68
-
69
- else
70
- raise Errno::ENOENT, "file #{filename} not found in #{$LOAD_PATH}"
71
77
  end
72
-
73
78
  code
74
79
  end
75
80
 
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Benchmark-only spec for Phase 5.5 deep unboxing performance.
4
+ # Run:
5
+ # bin/run_rspec specs/new_bridge/benchmark_phase5_5_unboxing_spec.rb --format documentation
6
+ #
7
+ # Optional env:
8
+ # BENCH_ITERS=5 # default: 5
9
+ # BENCH_TARGET_DEPTH=100 # default: 100 (nested list depth)
10
+
11
+
12
+ require_relative '../lib/R_interface/r'
13
+
14
+ RSpec.describe 'Phase 5.5 benchmark deep unboxing (R.bridge seam)' do
15
+ before(:all) do
16
+ skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
17
+ end
18
+
19
+ def measure_seconds
20
+ t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
21
+ yield
22
+ Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0
23
+ end
24
+
25
+ def stats(arr)
26
+ return { avg: 0.0, min: 0.0, max: 0.0 } if arr.empty?
27
+
28
+ {
29
+ avg: arr.sum / arr.size.to_f,
30
+ min: arr.min,
31
+ max: arr.max
32
+ }
33
+ end
34
+
35
+ it 'benchmarks unpack time for a nested list of depth 100' do
36
+ bridge = R.bridge
37
+ expect(bridge).to respond_to(:unbox_walk)
38
+ expect(bridge).to respond_to(:unbox_materialize)
39
+
40
+ iters = (ENV['BENCH_ITERS'] || '5').to_i
41
+ target_depth = (ENV['BENCH_TARGET_DEPTH'] || '100').to_i
42
+
43
+ deep = nil
44
+ build_s = measure_seconds do
45
+ deep = R.list(1)
46
+ target_depth.times { deep = R.list(deep) }
47
+ end
48
+
49
+ walk_times = []
50
+ materialize_times = []
51
+ unbox_times = []
52
+ walk_statuses = []
53
+ materialize_statuses = []
54
+ unbox_statuses = []
55
+
56
+ iters.times do
57
+ walk_times << measure_seconds do
58
+ result = bridge.unbox_walk(deep.r_interop,
59
+ max_depth: R::Support::MAX_UNBOX_DEPTH,
60
+ max_nodes: 300_000)
61
+ walk_statuses << result[:status]
62
+ end
63
+
64
+ materialize_times << measure_seconds do
65
+ result = bridge.unbox_materialize(deep.r_interop,
66
+ max_depth: R::Support::MAX_UNBOX_DEPTH,
67
+ max_nodes: 300_000)
68
+ materialize_statuses << result[:status]
69
+ end
70
+
71
+ unbox_times << measure_seconds do
72
+ begin
73
+ deep >> nil
74
+ unbox_statuses << :ok
75
+ rescue StandardError => e
76
+ unbox_statuses << :"error:#{e.class}"
77
+ end
78
+ end
79
+ end
80
+
81
+ w = stats(walk_times)
82
+ m = stats(materialize_times)
83
+ u = stats(unbox_times)
84
+
85
+ puts "\n[BENCH] nested-depth benchmark"
86
+ puts "[BENCH] target_depth=#{target_depth} max_unbox_depth=#{R::Support::MAX_UNBOX_DEPTH} iters=#{iters}"
87
+ puts format('[BENCH] build_once %.3fs', build_s)
88
+ puts format('[BENCH] unbox_walk avg=%.3fs min=%.3fs max=%.3fs statuses=%s',
89
+ w[:avg], w[:min], w[:max], walk_statuses.inspect)
90
+ puts format('[BENCH] materialize avg=%.3fs min=%.3fs max=%.3fs statuses=%s',
91
+ m[:avg], m[:min], m[:max], materialize_statuses.inspect)
92
+ puts format('[BENCH] deep >> nil avg=%.3fs min=%.3fs max=%.3fs statuses=%s',
93
+ u[:avg], u[:min], u[:max], unbox_statuses.inspect)
94
+ end
95
+ end
96
+
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Async Ruby→R completion (+eval_r_async+, +R.eval_r_async+, +R::Async+).
4
+ # Run: bin/run_all_rspec new_bridge_specs/eval_r_async_spec.rb
5
+
6
+ require 'thread'
7
+
8
+ require_relative '../lib/new_bridge'
9
+ require_relative '../lib/R_interface/r'
10
+
11
+ RSpec.describe 'NewBridge::SessionClient#eval_r_async' do
12
+ cpp = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
13
+
14
+ before(:all) do
15
+ skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
16
+ @client = NewBridge::SessionClient.new(source_path: cpp)
17
+ @client.start
18
+ end
19
+
20
+ after(:all) { @client&.stop }
21
+
22
+ it 'returns call_id immediately and completes with success payload' do
23
+ done = Queue.new
24
+ cid = @client.eval_r_async('42L', timeout: nil) do |result|
25
+ done.push(result)
26
+ end
27
+ expect(cid).to match(/\A[0-9a-f-]{36}\z/i)
28
+
29
+ r = done.pop
30
+ expect(r).to be_ok
31
+ expect(r.value['kind']).to eq('integer')
32
+ expect(r.value['value']).to eq(42)
33
+ end
34
+
35
+ it 'runs Ruby work before R completion when R sleeps' do
36
+ order = Queue.new
37
+ @client.eval_r_async('({ Sys.sleep(0.15); 1L })', timeout: nil) do |result|
38
+ order.push [:r_done, result.ok?]
39
+ end
40
+ order.push [:ruby_after_start]
41
+ sleep 0.05
42
+ order.push [:ruby_mid]
43
+
44
+ expect(order.pop).to eq([:ruby_after_start])
45
+ expect(order.pop).to eq([:ruby_mid])
46
+ expect(order.pop).to eq([:r_done, true])
47
+ end
48
+
49
+ it 'completes with failure on Ruby-side timeout' do
50
+ done = Queue.new
51
+ @client.eval_r_async('({ Sys.sleep(0.3); 1L })', timeout: 0.05) do |result|
52
+ done.push(result)
53
+ end
54
+ r = done.pop
55
+ expect(r).not_to be_ok
56
+ expect(r.error).to be_a(NewBridge::SessionClient::TimeoutError)
57
+ end
58
+
59
+ it 'completes with failure on R error' do
60
+ done = Queue.new
61
+ @client.eval_r_async('stop("galaaz_async_test_error")', timeout: nil) do |result|
62
+ done.push(result)
63
+ end
64
+ r = done.pop
65
+ expect(r).not_to be_ok
66
+ expect(r.error).to be_a(NewBridge::SessionClient::RProcessError)
67
+ expect(r.error.message).to match(/galaaz_async_test_error/)
68
+ end
69
+
70
+ it 'raises without a block' do
71
+ expect { @client.eval_r_async('1L') }.to raise_error(ArgumentError, /block/)
72
+ end
73
+ end
74
+
75
+ RSpec.describe 'R.eval_r_async and R::Async (integration)' do
76
+ before(:all) do
77
+ skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
78
+ end
79
+
80
+ it 'formats scalar like sync eval_r' do
81
+ done = Queue.new
82
+ R.eval_r_async('({ Sys.sleep(0.05); 7L })', timeout: nil) do |result|
83
+ done.push(result)
84
+ end
85
+ r = done.pop
86
+ expect(r).to be_ok
87
+ expect(r.value).to eq('[1] 7')
88
+ end
89
+
90
+ it 'R::Async returns an R::Object for rnorm(1)' do
91
+ done = Queue.new
92
+ R::Async.rnorm(1) do |result|
93
+ done.push(result)
94
+ end
95
+ r = done.pop
96
+ expect(r).to be_ok
97
+ expect(r.value).to be_a(R::Object)
98
+ end
99
+
100
+ it 'R::Async accepts timeout: and fails when R is too slow' do
101
+ done = Queue.new
102
+ R::Async.Sys__sleep(0.3, timeout: 0.05) do |result|
103
+ done.push(result)
104
+ end
105
+ r = done.pop
106
+ expect(r).not_to be_ok
107
+ expect(r.error).to be_a(NewBridge::SessionClient::TimeoutError)
108
+ end
109
+
110
+ it 'raises when R::Async is called without a block' do
111
+ expect { R::Async.rnorm(1) }.to raise_error(ArgumentError, /block/)
112
+ end
113
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 5.1 concurrent semantics on the R.bridge seam.
4
+ # Run:
5
+ # bin/run_rspec specs/new_bridge/integration_phase5_1_concurrent_spec.rb
6
+
7
+
8
+ require_relative '../lib/R_interface/r'
9
+
10
+ RSpec.describe 'Phase 5.1 integration concurrent (R.bridge seam)' do
11
+ it 'serializes concurrent eval_r_with_result calls and returns correct results' do
12
+ bridge = R.bridge
13
+ n_threads = 5
14
+ rounds_per_thread = 10
15
+ results_mutex = Mutex.new
16
+ results = []
17
+ errors = []
18
+
19
+ threads = n_threads.times.map do |thread_id|
20
+ Thread.new do
21
+ rounds_per_thread.times do |round|
22
+ expected_value = (thread_id * 1000) + round
23
+ assignment = "g2_v_t#{thread_id}_r#{round} <- #{expected_value}L"
24
+ env = bridge.eval_r_with_result(assignment)
25
+ results_mutex.synchronize do
26
+ if env && env[:type] == :scalar_integer && env[:value] == expected_value
27
+ results << { thread_id: thread_id, round: round, value: env[:value] }
28
+ else
29
+ errors << { thread_id: thread_id, round: round, env: env, expected: expected_value }
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ threads.each(&:join)
37
+
38
+ expect(errors).to eq([])
39
+ expect(results.size).to eq(n_threads * rounds_per_thread)
40
+
41
+ seen = {}
42
+ results.each do |r|
43
+ key = [r[:thread_id], r[:round]]
44
+ expect(seen[key]).to be_nil
45
+ seen[key] = true
46
+ expect(r[:value]).to eq((r[:thread_id] * 1000) + r[:round])
47
+ end
48
+ end
49
+ end
50
+
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 5.1 seam check for eval/handle roundtrip semantics (no callbacks).
4
+ # Run:
5
+ # bin/run_rspec specs/new_bridge/integration_phase5_1_eval_spec.rb
6
+
7
+
8
+ require_relative '../lib/R_interface/r'
9
+
10
+ RSpec.describe 'Phase 5.1 integration eval semantics (no callbacks)' do
11
+ it 'evaluates scalar expression through R::Support.eval' do
12
+ value = R::Support.eval('1L + 2L')
13
+ expect(value).to eq(3)
14
+ end
15
+ end
16
+
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 5.1 seam check for basic R module call path (no callbacks).
4
+ # Run:
5
+ # bin/run_rspec specs/new_bridge/integration_phase5_1_r_api_spec.rb
6
+
7
+
8
+ require_relative '../lib/R_interface/r'
9
+
10
+ RSpec.describe 'Phase 5.1 integration basic R API (no callbacks)' do
11
+ it 'supports simple R function dispatch through R::Support' do
12
+ result = R.sum(R.c(1, 2, 3))
13
+ expect(result).to be_a(R::Object)
14
+ expect(result.to_ruby).to eq(6)
15
+ end
16
+
17
+ it 'supports handle-producing calls and follow-up scalar access' do
18
+ vec = R.c(10, 20, 30)
19
+ expect(vec).to be_a(R::Object)
20
+
21
+ size = R.length(vec)
22
+ expect(size.to_ruby).to eq(3)
23
+ end
24
+ end
25
+
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 5.1 smoke: verify R.bridge seam can route to NewBridge adapter.
4
+ # Run: bundle exec rspec specs/new_bridge/integration_phase5_1_smoke_spec.rb
5
+
6
+
7
+ require_relative '../lib/R_interface/r'
8
+
9
+ RSpec.describe 'Phase 5.1 integration smoke (R.bridge seam)' do
10
+ before(:all) do
11
+ skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
12
+ end
13
+
14
+ it 'routes R.bridge to NewBridgeAdapter by default' do
15
+ expect(R.bridge).to be_a(R::NewBridgeAdapter)
16
+ expect(R.bridge.ready?).to eq(true)
17
+ end
18
+
19
+ it 'supports basic eval_r through seam' do
20
+ out = R.bridge.eval_r('1L + 1L')
21
+ expect(out).to include('2')
22
+ end
23
+
24
+ it 'supports basic eval_r_with_result through seam' do
25
+ env = R.bridge.eval_r_with_result('g2_v_p51 <- 123L')
26
+ expect(env).not_to be_nil
27
+ expect(env[:type]).to eq(:scalar_integer)
28
+ expect(env[:value]).to eq(123)
29
+ end
30
+ end
31
+
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 5.2 data.frame unboxing compatibility.
4
+ # Run:
5
+ # bin/run_rspec specs/new_bridge/integration_phase5_2_dataframe_unboxing_spec.rb
6
+
7
+
8
+ require_relative '../lib/R_interface/r'
9
+
10
+ RSpec.describe 'Phase 5.2 integration data.frame unboxing' do
11
+ it 'unboxes a tiny data.frame handle returned by R::Support into a Ruby hash' do
12
+ df = R.data__frame(x: R.c(1, 2), y: R.c('a', 'b'))
13
+ ruby = df.to_ruby
14
+ expect(ruby).to be_a(Hash)
15
+ expect(ruby['x']).to eq([1, 2])
16
+ expect(ruby['y']).to eq(['a', 'b'])
17
+ end
18
+ end
19
+
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 5.2 decoding/unboxing compatibility for eval handles.
4
+ # Run:
5
+ # bin/run_rspec specs/new_bridge/integration_phase5_2_handle_eval_unboxing_spec.rb
6
+
7
+
8
+ require_relative '../lib/R_interface/r'
9
+
10
+ RSpec.describe 'Phase 5.2 integration handle eval unboxing' do
11
+ it 'unboxes a vector handle returned by R::Support.eval' do
12
+ vec = R.c(7, 8, 9)
13
+ out = R::Support.eval(vec)
14
+ expect(out).to be_a(R::Object)
15
+ expect(out.to_ruby).to eq([7, 8, 9])
16
+ end
17
+
18
+ it 'unboxes a character vector handle returned by R::Support.eval' do
19
+ vec = R.c('a', 'b')
20
+ out = R::Support.eval(vec)
21
+ expect(out).to be_a(R::Object)
22
+ expect(out.to_ruby).to eq(['a', 'b'])
23
+ end
24
+ end
25
+