galaaz 0.5.0 → 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 (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/LICENSE +0 -0
  4. data/README.md +1360 -636
  5. data/Rakefile +61 -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 +84 -13
  11. data/bin/gknit-draft.rb +0 -0
  12. data/bin/gstudio +5 -3
  13. data/bin/gstudio_irb.rb +0 -0
  14. data/bin/gstudio_pry.rb +0 -0
  15. data/bin/install-tinytex +6 -0
  16. data/bin/run_all_rspec +43 -0
  17. data/bin/run_example +14 -0
  18. data/bin/run_old_rspec +19 -0
  19. data/bin/run_rspec +23 -0
  20. data/bin/run_rspec_subset +38 -0
  21. data/bin/run_slow_rspec +19 -0
  22. data/blogs/R-on-Rails-Planning-Document.md +940 -0
  23. data/blogs/README.md +100 -0
  24. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
  25. data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
  26. data/blogs/galaaz_ggplot/galaaz_ggplot.md +115 -155
  27. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
  28. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
  29. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
  30. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
  31. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
  32. data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
  33. data/blogs/galaaz_ggplot/midwest_external_png +0 -0
  34. data/blogs/gknit/gknit.Rmd +47 -52
  35. data/blogs/gknit/gknit.md +1430 -0
  36. data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
  37. data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
  38. data/blogs/gknit/lst.rds +0 -0
  39. data/blogs/gknit/model.rb +1 -1
  40. data/blogs/gknit/stats.bib +0 -0
  41. data/blogs/manual/include_model_local_repro.Rmd +14 -0
  42. data/blogs/manual/include_model_local_repro.md +75 -0
  43. data/blogs/manual/lst.rds +0 -0
  44. data/blogs/manual/manual.Rmd +852 -239
  45. data/blogs/manual/manual.log +1786 -0
  46. data/blogs/manual/manual.md +1360 -636
  47. data/blogs/manual/manual.tex +1883 -1161
  48. data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
  49. data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
  50. data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
  51. data/blogs/manual/model.rb +1 -1
  52. data/blogs/nse_dplyr/nse_dplyr.Rmd +84 -111
  53. data/blogs/nse_dplyr/nse_dplyr.log +928 -0
  54. data/blogs/nse_dplyr/nse_dplyr.md +198 -229
  55. data/blogs/oh_my/not_so.rb +0 -0
  56. data/blogs/oh_my/oh_my.Rmd +1234 -25
  57. data/blogs/oh_my/oh_my.log +804 -0
  58. data/blogs/oh_my/oh_my.md +1663 -86
  59. data/blogs/oh_my/oh_my.tex +821 -0
  60. data/blogs/oh_my/old.Rmd +15 -14
  61. data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
  62. data/blogs/ruby_plot/ruby_plot.log +885 -0
  63. data/blogs/ruby_plot/ruby_plot.md +71 -102
  64. data/blogs/ruby_plot/ruby_plot.tex +940 -0
  65. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
  66. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
  67. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
  68. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
  69. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
  70. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
  71. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
  72. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
  73. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
  74. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
  75. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
  76. data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
  77. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  78. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  79. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  80. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  81. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  82. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  83. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  84. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  85. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  86. data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  87. data/blogs/test/test.Rmd +14 -0
  88. data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
  89. data/examples/50Plots_MasterList/ScatterPlot.rb +0 -0
  90. data/examples/50Plots_MasterList/scatter_plot.rb +0 -0
  91. data/examples/Bibliography/master.bib +0 -0
  92. data/examples/Bibliography/stats.bib +0 -0
  93. data/examples/R/calc.R +0 -0
  94. data/examples/R/java_interop.R +0 -0
  95. data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
  96. data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +53 -0
  97. data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
  98. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +33 -0
  99. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +34 -0
  100. data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
  101. data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
  102. data/examples/islr/all.rb +13 -0
  103. data/examples/islr/ch2.spec.rb +37 -7
  104. data/examples/islr/ch3.spec.rb +11 -2
  105. data/examples/islr/ch3_boston.rb +27 -0
  106. data/examples/islr/ch3_multiple_regression.rb +0 -0
  107. data/examples/islr/ch6.spec.rb +24 -1
  108. data/examples/islr/x_y_rnorm.jpg +0 -0
  109. data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +0 -0
  110. data/examples/latex_templates/Test-acm_article/sigproc.bib +0 -0
  111. data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +0 -0
  112. data/examples/latex_templates/Test-acs_article/acs-my_output.bib +0 -0
  113. data/examples/latex_templates/Test-aea_article/BibFile.bib +0 -0
  114. data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +0 -0
  115. data/examples/latex_templates/Test-aea_article/references.bib +0 -0
  116. data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +0 -0
  117. data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +0 -0
  118. data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +0 -0
  119. data/examples/latex_templates/Test-ieee_article/mybibfile.bib +0 -0
  120. data/examples/latex_templates/Test-rjournal_article/RJournal.sty +0 -0
  121. data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +0 -0
  122. data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +0 -0
  123. data/examples/misc/baseball.csv +0 -0
  124. data/examples/misc/ggplot.rb +3 -2
  125. data/examples/misc/moneyball.rb +0 -0
  126. data/examples/misc/subsetting.rb +0 -0
  127. data/examples/multithread_shards_to_r/shards_to_r.rb +67 -0
  128. data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +0 -0
  129. data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +0 -0
  130. data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +0 -0
  131. data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +0 -0
  132. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +0 -0
  133. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +0 -0
  134. data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +0 -0
  135. data/examples/sthda_ggplot/README.md +0 -0
  136. data/examples/sthda_ggplot/RUN.md +41 -0
  137. data/examples/sthda_ggplot/all.rb +0 -0
  138. data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +0 -0
  139. data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +0 -0
  140. data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +2 -0
  141. data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +0 -0
  142. data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +0 -0
  143. data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +0 -0
  144. data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +0 -0
  145. data/examples/sthda_ggplot/one_variable_continuous/stat.rb +0 -0
  146. data/examples/sthda_ggplot/one_variable_discrete/bar.rb +0 -0
  147. data/examples/sthda_ggplot/qplots/box_violin_dot.rb +0 -0
  148. data/examples/sthda_ggplot/qplots/scatter_plots.rb +0 -0
  149. data/examples/sthda_ggplot/scatter_gg.rb +0 -0
  150. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +0 -0
  151. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +0 -0
  152. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +0 -0
  153. data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +0 -0
  154. data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +0 -0
  155. data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +0 -0
  156. data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +4 -3
  157. data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +0 -0
  158. data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +0 -0
  159. data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +0 -0
  160. data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +0 -0
  161. data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +0 -0
  162. data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +0 -0
  163. data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +0 -0
  164. data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +0 -0
  165. data/ext/new_bridge/Makefile +46 -0
  166. data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
  167. data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
  168. data/lib/R_interface/galaaz_device.R +20 -0
  169. data/lib/R_interface/include_engine.R +109 -0
  170. data/lib/R_interface/new_bridge_adapter.rb +824 -0
  171. data/lib/R_interface/r.rb +177 -25
  172. data/lib/R_interface/r_arrow.rb +113 -0
  173. data/lib/R_interface/r_libs.R +3 -3
  174. data/lib/R_interface/r_methods.rb +13 -126
  175. data/lib/R_interface/r_module_s.rb +0 -0
  176. data/lib/R_interface/rbinary_operators.rb +20 -2
  177. data/lib/R_interface/rclosure.rb +5 -1
  178. data/lib/R_interface/rdata_frame.rb +34 -70
  179. data/lib/R_interface/rdevice.rb +125 -0
  180. data/lib/R_interface/rdevices.R +0 -0
  181. data/lib/R_interface/renvironment.rb +10 -4
  182. data/lib/R_interface/rexpression.rb +5 -1
  183. data/lib/R_interface/rindexed_object.rb +41 -13
  184. data/lib/R_interface/rlanguage.rb +20 -62
  185. data/lib/R_interface/rlist.rb +115 -25
  186. data/lib/R_interface/rlogical_operators.rb +0 -0
  187. data/lib/R_interface/rmatrix.rb +2 -11
  188. data/lib/R_interface/rmd_indexed_object.rb +5 -1
  189. data/lib/R_interface/robject.rb +348 -290
  190. data/lib/R_interface/rpkg.rb +0 -0
  191. data/lib/R_interface/rsupport.rb +609 -328
  192. data/lib/R_interface/rsupport_scope.rb +2 -1
  193. data/lib/R_interface/rsymbol.rb +50 -0
  194. data/lib/R_interface/ruby_callback.rb +2 -3
  195. data/lib/R_interface/ruby_extensions.rb +225 -175
  196. data/lib/R_interface/runary_operators.rb +0 -0
  197. data/lib/R_interface/rvector.rb +147 -31
  198. data/lib/galaaz.rb +0 -0
  199. data/lib/galaaz_jruby.rb +22 -0
  200. data/lib/gknit/diagnostics.rb +50 -0
  201. data/lib/gknit/draft.rb +23 -17
  202. data/lib/gknit/include_engine.rb +15 -7
  203. data/lib/gknit/knitr_engine.rb +223 -74
  204. data/lib/gknit/rb_engine.rb +3 -3
  205. data/lib/gknit/ruby_engine.rb +0 -0
  206. data/lib/gknit.rb +1 -0
  207. data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
  208. data/lib/new_bridge/envelope.rb +51 -0
  209. data/lib/new_bridge/eval_result.rb +26 -0
  210. data/lib/new_bridge/framing.rb +39 -0
  211. data/lib/new_bridge/instance_pool_client.rb +38 -0
  212. data/lib/new_bridge/r_instance_manager.rb +404 -0
  213. data/lib/new_bridge/session_client.rb +530 -0
  214. data/lib/new_bridge/tcp_framed.rb +44 -0
  215. data/lib/new_bridge.rb +9 -0
  216. data/lib/util/exec_ruby.rb +95 -20
  217. data/lib/util/inline_file.rb +35 -30
  218. data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
  219. data/new_bridge_specs/eval_r_async_spec.rb +113 -0
  220. data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
  221. data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
  222. data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
  223. data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
  224. data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
  225. data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
  226. data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
  227. data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
  228. data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
  229. data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
  230. data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
  231. data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
  232. data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
  233. data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
  234. data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
  235. data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
  236. data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
  237. data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
  238. data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
  239. data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
  240. data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
  241. data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
  242. data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
  243. data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
  244. data/r_requires/ggplot.rb +0 -0
  245. data/r_requires/knitr.rb +0 -0
  246. data/specs/all.rb +15 -11
  247. data/specs/arrow_from_ruby_batches_spec.rb +50 -0
  248. data/specs/arrow_semantics_spec.rb +64 -0
  249. data/specs/bridge_concurrent_spec.rb +46 -0
  250. data/specs/bridge_nested_spec.rb +25 -0
  251. data/specs/dataframe_semantics_spec.rb +122 -0
  252. data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
  253. data/specs/dispatch_probe_cache_spec.rb +38 -0
  254. data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
  255. data/specs/dispatch_probe_fallback_spec.rb +18 -0
  256. data/specs/environment_semantics_spec.rb +89 -0
  257. data/specs/field_access_spec.rb +31 -0
  258. data/specs/figures/bg.jpeg +0 -0
  259. data/specs/figures/bg.png +0 -0
  260. data/specs/figures/bg.svg +168 -57
  261. data/specs/figures/dose_len.png +0 -0
  262. data/specs/figures/no_args.jpeg +0 -0
  263. data/specs/figures/no_args.png +0 -0
  264. data/specs/figures/no_args.svg +168 -57
  265. data/specs/figures/width_height.jpeg +0 -0
  266. data/specs/figures/width_height.png +0 -0
  267. data/specs/figures/width_height_units1.jpeg +0 -0
  268. data/specs/figures/width_height_units1.png +0 -0
  269. data/specs/figures/width_height_units2.jpeg +0 -0
  270. data/specs/figures/width_height_units2.png +0 -0
  271. data/specs/formula_semantics_spec.rb +81 -0
  272. data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
  273. data/specs/galaaz_util_inline_file_spec.rb +54 -0
  274. data/specs/gknit_cli_option_permutation_spec.rb +24 -0
  275. data/specs/gknit_include_engine_spec.rb +72 -0
  276. data/specs/gknit_install_timeout_report_spec.rb +69 -0
  277. data/specs/gknit_internal_error_report_spec.rb +57 -0
  278. data/specs/gknit_vector_map_output_spec.rb +59 -0
  279. data/specs/globalenv_guardrail_spec.rb +52 -0
  280. data/specs/language_expression_semantics_spec.rb +145 -0
  281. data/specs/list_semantics_spec.rb +111 -0
  282. data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
  283. data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
  284. data/specs/new_bridge_callback_timeout_spec.rb +69 -0
  285. data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
  286. data/specs/nil_null_spec.rb +42 -0
  287. data/specs/object_build_phase2_spec.rb +53 -0
  288. data/specs/phase1_callback_bridge_spec.rb +84 -0
  289. data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
  290. data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
  291. data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
  292. data/specs/plot_device_semantics_spec.rb +28 -0
  293. data/specs/plot_snapshot_semantics_spec.rb +58 -0
  294. data/specs/protocol_result_spec.rb +236 -0
  295. data/specs/r_batch_fail_fast_spec.rb +47 -0
  296. data/specs/r_bridge_bootstrap_spec.rb +11 -0
  297. data/specs/r_devices.spec.rb +1 -1
  298. data/specs/r_eval.spec.rb +16 -18
  299. data/specs/r_function.spec.rb +1 -1
  300. data/specs/r_instance_manager_spec.rb +285 -0
  301. data/specs/r_list_apply.spec.rb +15 -15
  302. data/specs/r_matrix.spec.rb +0 -0
  303. data/specs/r_nse.spec.rb +5 -5
  304. data/specs/r_object_send_dispatch_spec.rb +13 -0
  305. data/specs/r_vector_comparator_spec.rb +8 -0
  306. data/specs/r_vector_creation.spec.rb +0 -0
  307. data/specs/r_vector_functions.spec.rb +0 -0
  308. data/specs/r_vector_object.spec.rb +0 -0
  309. data/specs/r_vector_operators.spec.rb +0 -0
  310. data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
  311. data/specs/r_vector_subsetting.spec.rb +0 -0
  312. data/specs/range_helper_spec.rb +21 -0
  313. data/specs/rsupport_scope_spec.rb +28 -0
  314. data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
  315. data/specs/scalar_character_spec.rb +44 -0
  316. data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
  317. data/specs/session_env_bridge_spec.rb +25 -0
  318. data/specs/simplecov_bootstrap_spec.rb +10 -0
  319. data/specs/spec_helper.rb +10 -0
  320. data/specs/tmp.rb +0 -0
  321. data/specs/unboxing_recursion_regression_spec.rb +30 -0
  322. data/specs/unboxing_spec.rb +49 -0
  323. data/specs/verify_callbacks.rb +42 -0
  324. data/sty/galaaz.sty +0 -0
  325. data/version.rb +1 -1
  326. metadata +194 -64
  327. data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -520
  328. data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
  329. data/blogs/galaaz_ggplot/midwest.html +0 -188
  330. data/blogs/gknit/gknit.html +0 -2266
  331. data/blogs/gknit/gknit.pdf +0 -0
  332. data/blogs/manual/manual.html +0 -4638
  333. data/blogs/manual/manual.pdf +0 -0
  334. data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
  335. data/blogs/nse_dplyr/nse_dplyr.html +0 -878
  336. data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
  337. data/blogs/oh_my/oh_my.html +0 -568
  338. data/blogs/ruby_plot/ruby_plot.html +0 -544
  339. data/blogs/ruby_plot/ruby_plot.pdf +0 -0
  340. data/examples/latex_templates/Test-acs_article/Test-acs_article.pdf +0 -0
  341. data/examples/latex_templates/Test-aea_article/Test-aea_article.pdf +0 -0
  342. data/examples/latex_templates/Test-amq_article/Test-amq_article.pdf +0 -0
  343. data/examples/latex_templates/Test-amq_article/pics/Figure2.pdf +0 -0
  344. data/examples/latex_templates/Test-asa_article/Test-asa_article.pdf +0 -0
  345. data/examples/latex_templates/Test-ieee_article/Test-ieee_article.pdf +0 -0
  346. data/examples/latex_templates/Test-rjournal_article/RJwrapper.pdf +0 -0
  347. data/examples/latex_templates/Test-springer_article/Test-springer_article.pdf +0 -0
  348. data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.pdf +0 -0
  349. data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.pdf +0 -0
  350. data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.pdf +0 -0
  351. data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.pdf +0 -0
  352. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.pdf +0 -0
  353. data/specs/r_dataframe.spec.rb +0 -379
  354. data/specs/r_environment.spec.rb +0 -140
  355. data/specs/r_formula.spec.rb +0 -232
  356. data/specs/r_language.spec.rb +0 -112
  357. data/specs/r_list.spec.rb +0 -293
  358. data/specs/r_plots.spec.rb +0 -72
  359. data/specs/ruby_expression.spec.rb +0 -316
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 3: R -> Ruby callbacks via CALL/RET.
4
+ # Run: bundle exec rspec specs/new_bridge/phase3_callbacks_spec.rb
5
+
6
+ root = File.expand_path('../..', __dir__)
7
+ $LOAD_PATH.unshift(File.join(root, 'lib')) unless $LOAD_PATH.include?(File.join(root, 'lib'))
8
+
9
+ require 'new_bridge'
10
+
11
+ RSpec.describe 'NewBridge Phase 3 (CALL/RET callbacks)' do
12
+ let(:phase1_cpp) { File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__) }
13
+ let(:instance_id) { 'instance-a' }
14
+
15
+ before(:all) do
16
+ skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
17
+ cpp = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
18
+ @client = NewBridge::SessionClient.new(source_path: cpp)
19
+ @client.start
20
+ end
21
+
22
+ after(:all) do
23
+ @client&.stop
24
+ end
25
+
26
+ def with_client(instance_id: 'instance-a')
27
+ yield @client, instance_id
28
+ end
29
+
30
+ it 'callback ping: Ruby callback returns a scalar' do
31
+ with_client(instance_id: instance_id) do |c, iid|
32
+ cb_call_id = c.register_callback do |payload|
33
+ payload.to_i + 1
34
+ end
35
+
36
+ out = c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', '41', 500)",
37
+ session_id: 'sess-a', instance_id: iid)
38
+
39
+ expect(out['kind']).to eq('double')
40
+ expect(out['value']).to eq(42)
41
+ end
42
+ end
43
+
44
+ it 'callback error propagation: Ruby callback raises' do
45
+ with_client(instance_id: instance_id) do |c, iid|
46
+ cb_call_id = c.register_callback do |_payload|
47
+ raise 'boom'
48
+ end
49
+
50
+ expect do
51
+ c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', '0', 500)",
52
+ session_id: 'sess-a', instance_id: iid)
53
+ end.to raise_error(NewBridge::SessionClient::RProcessError, /boom|evaluation error/)
54
+ end
55
+ end
56
+
57
+ it 'callback timeout: Ruby callback does not respond in time' do
58
+ with_client(instance_id: instance_id) do |c, iid|
59
+ cb_call_id = c.register_callback do |_payload|
60
+ sleep 0.2
61
+ 999
62
+ end
63
+
64
+ expect do
65
+ c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', '0', 50)",
66
+ session_id: 'sess-a', instance_id: iid, timeout: 2)
67
+ end.to raise_error(NewBridge::SessionClient::RProcessError, /evaluation error|timeout/)
68
+ end
69
+ end
70
+ end
71
+
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 4.2: hardening coverage (edge cases + stress) on current bridge API.
4
+ # Run: bundle exec rspec specs/new_bridge/phase4_2_hardening_spec.rb
5
+
6
+ root = File.expand_path('../..', __dir__)
7
+ $LOAD_PATH.unshift(File.join(root, 'lib')) unless $LOAD_PATH.include?(File.join(root, 'lib'))
8
+
9
+ require 'new_bridge'
10
+
11
+ RSpec.describe 'NewBridge Phase 4.2 (Hardening Coverage)' do
12
+ let(:phase1_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
+ cpp = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
17
+ @client = NewBridge::SessionClient.new(source_path: cpp)
18
+ @client.start
19
+ end
20
+
21
+ after(:all) do
22
+ @client&.stop
23
+ end
24
+
25
+ describe 'edge cases: envelope + eval error paths' do
26
+ it 'rejects msgpack payload that is not a map' do
27
+ bytes = MessagePack.pack(['not', 'a', 'map'])
28
+ expect do
29
+ NewBridge::Envelope.decode(bytes)
30
+ end.to raise_error(NewBridge::Envelope::Error, /expected a map/)
31
+ end
32
+
33
+ it 'rejects malformed envelope bytes' do
34
+ expect do
35
+ NewBridge::Envelope.decode("\x81\xA4type".b)
36
+ end.to raise_error(NewBridge::Envelope::Error)
37
+ end
38
+
39
+ it 'rejects envelope with unknown keys on encode' do
40
+ expect do
41
+ NewBridge::Envelope.encode(
42
+ 'call_id' => 'abc',
43
+ 'type' => 'REQ',
44
+ 'bogus' => 'x'
45
+ )
46
+ end.to raise_error(NewBridge::Envelope::InvalidEnvelope, /unknown keys/)
47
+ end
48
+
49
+ it 'rejects empty envelope bytes' do
50
+ expect do
51
+ NewBridge::Envelope.decode(''.b)
52
+ end.to raise_error(NewBridge::Envelope::InvalidEnvelope, /empty envelope/)
53
+ end
54
+
55
+ it 'raises on invalid R syntax' do
56
+ expect do
57
+ @client.eval_r('x <-')
58
+ end.to raise_error(NewBridge::SessionClient::RProcessError)
59
+ end
60
+
61
+ it 'raises on empty R code payload' do
62
+ expect do
63
+ @client.eval_r('')
64
+ end.to raise_error(NewBridge::SessionClient::RProcessError)
65
+ end
66
+
67
+ it 'returns nil JSON value for NA integer scalar' do
68
+ out = @client.eval_r('as.integer(NA)')
69
+ expect(out['kind']).to eq('integer')
70
+ expect(out['value']).to be_nil
71
+ end
72
+
73
+ it 'returns nil JSON value for NA logical scalar' do
74
+ out = @client.eval_r('as.logical(NA)')
75
+ expect(out['kind']).to eq('logical')
76
+ expect(out['value']).to be_nil
77
+ end
78
+
79
+ it 'returns nil JSON value for NA double scalar' do
80
+ out = @client.eval_r('as.numeric(NA)')
81
+ expect(out['kind']).to eq('double')
82
+ expect(out['value']).to be_nil
83
+ end
84
+
85
+ it 'raises on non scalar results' do
86
+ expect do
87
+ @client.eval_r('1:3')
88
+ end.to raise_error(NewBridge::SessionClient::RProcessError, /length-1 scalar/)
89
+ end
90
+
91
+ it 'handles very short timeout from Ruby side' do
92
+ expect do
93
+ @client.eval_r('Sys.sleep(0.2); 1L', timeout: 0.05)
94
+ end.to raise_error(NewBridge::SessionClient::TimeoutError)
95
+ end
96
+ end
97
+
98
+ describe 'concurrency and stress on one instance' do
99
+ it 'handles 50 concurrent requests with unique sessions' do
100
+ threads = 50.times.map do |i|
101
+ Thread.new do
102
+ sid = "p42-conc-#{i}"
103
+ @client.eval_r("v <- #{i}L; v", session_id: sid)['value']
104
+ end
105
+ end
106
+
107
+ values = threads.map(&:value)
108
+ expect(values.sort).to eq((0..49).to_a)
109
+ end
110
+
111
+ it 'handles repeated calls in same session without leaking type info' do
112
+ sid = 'p42-same-session'
113
+ 20.times do |i|
114
+ @client.eval_r("x <- #{i}L", session_id: sid)
115
+ end
116
+ out = @client.eval_r('x', session_id: sid)
117
+ expect(out['kind']).to eq('integer')
118
+ expect(out['value']).to eq(19)
119
+ end
120
+
121
+ it 'supports larger payload code strings' do
122
+ big = 'a' * 20_000
123
+ code = "nchar('#{big}')"
124
+ out = @client.eval_r(code)
125
+ expect(out['value']).to eq(20_000)
126
+ end
127
+
128
+ it 'keeps nested callback recursion stable for depth 5' do
129
+ cb_call_id = @client.register_callback do |_payload, call_id|
130
+ acc = 0
131
+ 5.times do |i|
132
+ r = @client.eval_r("#{i}L + 1L", parent_id: call_id)
133
+ acc += r['value']
134
+ end
135
+ acc
136
+ end
137
+
138
+ out = @client.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', 'unused', 5000)")
139
+ expect(out['kind']).to eq('double')
140
+ expect(out['value']).to eq(15)
141
+ end
142
+
143
+ it 'handles 200 sequential requests without state corruption' do
144
+ sid = 'p42-seq'
145
+ 200.times do |i|
146
+ @client.eval_r("k <- #{i}L", session_id: sid)
147
+ end
148
+ out = @client.eval_r('k', session_id: sid)
149
+ expect(out['value']).to eq(199)
150
+ end
151
+
152
+ it 'supports concurrent requests to the same session deterministically for last write readback' do
153
+ sid = 'p42-same-session-concurrent'
154
+ threads = 20.times.map do |i|
155
+ Thread.new { @client.eval_r("x <- #{i}L", session_id: sid) }
156
+ end
157
+ threads.each(&:join)
158
+ out = @client.eval_r('x', session_id: sid)
159
+ expect(out['kind']).to eq('integer')
160
+ expect(out['value']).to be_between(0, 19).inclusive
161
+ end
162
+ end
163
+
164
+ describe 'multi-instance hardening on current pool API' do
165
+ before(:all) do
166
+ cpp = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
167
+ @pool = NewBridge::InstancePoolClient.new(
168
+ source_path: cpp,
169
+ instances: ['p42-a', 'p42-b']
170
+ ).start
171
+ end
172
+
173
+ after(:all) do
174
+ @pool&.stop
175
+ end
176
+
177
+ it 'maintains session isolation across instances with same session_id' do
178
+ @pool.eval_r('x <- 101L', session_id: 'same-sid', instance_id: 'p42-a')
179
+ @pool.eval_r('x <- 202L', session_id: 'same-sid', instance_id: 'p42-b')
180
+
181
+ a = @pool.eval_r('x', session_id: 'same-sid', instance_id: 'p42-a')
182
+ b = @pool.eval_r('x', session_id: 'same-sid', instance_id: 'p42-b')
183
+
184
+ expect(a['value']).to eq(101)
185
+ expect(b['value']).to eq(202)
186
+ end
187
+
188
+ it 'handles 80 pool requests under mixed concurrency' do
189
+ threads = 8.times.map do |t|
190
+ Thread.new do
191
+ inst = t.even? ? 'p42-a' : 'p42-b'
192
+ 10.times.map do |i|
193
+ n = (t * 10) + i
194
+ sid = "p42-pool-#{t}-#{i}"
195
+ @pool.eval_r("z <- #{n}L; z", session_id: sid, instance_id: inst)['value']
196
+ end
197
+ end
198
+ end
199
+
200
+ values = threads.flat_map(&:value)
201
+ expect(values.sort).to eq((0..79).to_a)
202
+ end
203
+
204
+ it 'raises when routing to unknown instance_id' do
205
+ expect do
206
+ @pool.eval_r('1L + 1L', session_id: 'x', instance_id: 'unknown-instance')
207
+ end.to raise_error(KeyError)
208
+ end
209
+
210
+ it 'keeps instance local state isolated after updates on both instances' do
211
+ @pool.eval_r('counter <- 1L', session_id: 'iso', instance_id: 'p42-a')
212
+ @pool.eval_r('counter <- 10L', session_id: 'iso', instance_id: 'p42-b')
213
+
214
+ @pool.eval_r('counter <- counter + 1L', session_id: 'iso', instance_id: 'p42-a')
215
+ @pool.eval_r('counter <- counter + 1L', session_id: 'iso', instance_id: 'p42-b')
216
+
217
+ a = @pool.eval_r('counter', session_id: 'iso', instance_id: 'p42-a')
218
+ b = @pool.eval_r('counter', session_id: 'iso', instance_id: 'p42-b')
219
+ expect(a['value']).to eq(2)
220
+ expect(b['value']).to eq(11)
221
+ end
222
+
223
+ it 'continues serving healthy instances after an unknown-instance routing error' do
224
+ expect do
225
+ @pool.eval_r('1L', session_id: 'err', instance_id: 'nope')
226
+ end.to raise_error(KeyError)
227
+
228
+ ok = @pool.eval_r('7L + 5L', session_id: 'ok', instance_id: 'p42-a')
229
+ expect(ok['value']).to eq(12)
230
+ end
231
+ end
232
+
233
+ describe 'rapid lifecycle checks' do
234
+ it 'supports repeated start/stop cycles' do
235
+ 5.times do
236
+ c = NewBridge::SessionClient.new(source_path: phase1_cpp)
237
+ c.start
238
+ out = c.eval_r('2L + 3L')
239
+ expect(out['value']).to eq(5)
240
+ c.stop
241
+ end
242
+ end
243
+
244
+ it 'allows stop to be called multiple times safely' do
245
+ c = NewBridge::SessionClient.new(source_path: phase1_cpp)
246
+ c.start
247
+ c.stop
248
+ expect { c.stop }.not_to raise_error
249
+ end
250
+ end
251
+ end
252
+
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 4.3: local R instance management API (first slice).
4
+ # Run: bundle exec rspec specs/new_bridge/phase4_3_r_instance_manager_spec.rb
5
+
6
+ root = File.expand_path('../..', __dir__)
7
+ $LOAD_PATH.unshift(File.join(root, 'lib')) unless $LOAD_PATH.include?(File.join(root, 'lib'))
8
+
9
+ require 'new_bridge'
10
+
11
+ RSpec.describe 'NewBridge Phase 4.3 (RInstanceManager - local)' do
12
+ before(:all) do
13
+ skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
14
+ phase1_cpp = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
15
+ @mgr = NewBridge::RInstanceManager.new(source_path: phase1_cpp)
16
+ @mgr.spawn_local(instance_id: 'mgr-a', version: 'v-current')
17
+ @mgr.spawn_local(instance_id: 'mgr-b', version: 'v-legacy')
18
+ end
19
+
20
+ after(:all) do
21
+ @mgr&.stop
22
+ end
23
+
24
+ it 'evaluates code in isolated instances with routing by instance_id' do
25
+ @mgr.eval_r('x <- 11L', session_id: 'shared-sid', instance_id: 'mgr-a')
26
+ @mgr.eval_r('x <- 22L', session_id: 'shared-sid', instance_id: 'mgr-b')
27
+
28
+ a = @mgr.eval_r('x', session_id: 'shared-sid', instance_id: 'mgr-a')
29
+ b = @mgr.eval_r('x', session_id: 'shared-sid', instance_id: 'mgr-b')
30
+
31
+ expect(a['value']).to eq(11)
32
+ expect(b['value']).to eq(22)
33
+ end
34
+
35
+ it 'raises on spawning an existing instance_id' do
36
+ expect do
37
+ @mgr.spawn_local(instance_id: 'mgr-a')
38
+ end.to raise_error(ArgumentError, /instance already exists/)
39
+ end
40
+
41
+ it 'exposes instance metadata including version labels' do
42
+ list = @mgr.instances
43
+ ids = list.map { |h| h[:id] }
44
+ expect(ids).to include('mgr-a', 'mgr-b')
45
+
46
+ a = list.find { |h| h[:id] == 'mgr-a' }
47
+ b = list.find { |h| h[:id] == 'mgr-b' }
48
+ expect(a[:version]).to eq('v-current')
49
+ expect(b[:version]).to eq('v-legacy')
50
+ expect(a[:status]).to eq(:healthy)
51
+ expect(b[:provider]).to eq('local')
52
+ end
53
+
54
+ it 'routes eval by version with eval_with_version' do
55
+ out = @mgr.eval_with_version('10L + 5L', version: 'v-current', session_id: 'ver-sess')
56
+ expect(out['value']).to eq(15)
57
+ end
58
+
59
+ it 'returns one result per version with eval_all_versions' do
60
+ results = @mgr.eval_all_versions('3L + 4L', session_id: 'all-vers')
61
+ expect(results.keys.sort).to eq(%w[v-current v-legacy])
62
+ expect(results['v-current']['value']).to eq(7)
63
+ expect(results['v-legacy']['value']).to eq(7)
64
+ end
65
+
66
+ it 'stops instances on demand' do
67
+ @mgr.stop('mgr-a')
68
+ expect(@mgr.instance_ids).not_to include('mgr-a')
69
+
70
+ expect do
71
+ @mgr.eval_r('1L + 1L', session_id: 's', instance_id: 'mgr-a')
72
+ end.to raise_error(KeyError)
73
+
74
+ # remaining instance still works
75
+ out = @mgr.eval_r('2L + 2L', session_id: 's', instance_id: 'mgr-b')
76
+ expect(out['value']).to eq(4)
77
+ end
78
+
79
+ it 'raises when eval_with_version targets unknown version' do
80
+ expect do
81
+ @mgr.eval_with_version('1L + 1L', version: 'no-such-version')
82
+ end.to raise_error(KeyError, /no instance for version/)
83
+ end
84
+ end
85
+
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Phase 4: Nested Ruby->R during R callback waits.
4
+ # Run: bundle exec rspec specs/new_bridge/phase4_nested_callbacks_spec.rb
5
+
6
+ root = File.expand_path('../..', __dir__)
7
+ $LOAD_PATH.unshift(File.join(root, 'lib')) unless $LOAD_PATH.include?(File.join(root, 'lib'))
8
+
9
+ require 'new_bridge'
10
+
11
+ RSpec.describe 'NewBridge Phase 4 (Nested callbacks)' do
12
+ let(:phase1_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
+ cpp = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
17
+ @client = NewBridge::SessionClient.new(source_path: cpp)
18
+ @client.start
19
+ end
20
+
21
+ after(:all) do
22
+ @client&.stop
23
+ end
24
+
25
+ def with_client
26
+ yield @client
27
+ end
28
+
29
+ it 'deep recursion: Ruby callback calls back into R and returns correct value' do
30
+ with_client do |c|
31
+ # Register callback that does nested eval_r into R
32
+ cb_call_id = c.register_callback do |_payload, call_id|
33
+ # Nested call into R - this tests the core Phase 4 scenario
34
+ nested_result = c.eval_r('41L + 1L', parent_id: call_id)
35
+ nested_result['value'] # Return 42
36
+ end
37
+
38
+ # R calls the callback via galaaz_callback_call_phase3
39
+ out = c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', 'unused', 5000)")
40
+
41
+ expect(out['kind']).to eq('double')
42
+ expect(out['value']).to eq(42)
43
+ end
44
+ end
45
+
46
+ it 'error unwinding: Ruby callback raises, error propagates correctly' do
47
+ with_client do |c|
48
+ cb_call_id = c.register_callback do |_payload, _call_id|
49
+ raise 'callback error from Ruby'
50
+ end
51
+
52
+ # Note: Error message is generic because R_tryEval catches Rcpp::stop
53
+ # The important thing is that an error is raised, not the specific message
54
+ expect do
55
+ c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', 'unused', 5000)")
56
+ end.to raise_error(NewBridge::SessionClient::RProcessError)
57
+ end
58
+ end
59
+
60
+ it 'timeout: Ruby callback sleeps too long, raises timeout' do
61
+ with_client do |c|
62
+ cb_call_id = c.register_callback do |_payload, _call_id|
63
+ sleep 0.5 # Sleep longer than callback timeout
64
+ 999
65
+ end
66
+
67
+ # The callback times out after 50ms, but the Ruby sleep is 500ms
68
+ # Note: Error message is generic because R_tryEval catches Rcpp::stop
69
+ expect do
70
+ c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', 'unused', 50)", timeout: 2)
71
+ end.to raise_error(NewBridge::SessionClient::RProcessError)
72
+ end
73
+ end
74
+
75
+ it 'nested ordering: multiple nested calls complete correctly' do
76
+ with_client do |c|
77
+ call_count = 0
78
+
79
+ cb_call_id = c.register_callback do |_payload, call_id|
80
+ call_count += 1
81
+ # Multiple nested calls
82
+ r1 = c.eval_r('10L + 1L', parent_id: call_id)
83
+ r2 = c.eval_r('20L + 2L', parent_id: call_id)
84
+ r3 = c.eval_r('30L + 3L', parent_id: call_id)
85
+
86
+ r1['value'] + r2['value'] + r3['value'] # 11 + 22 + 33 = 66
87
+ end
88
+
89
+ out = c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', 'unused', 5000)")
90
+
91
+ expect(out['value']).to eq(66)
92
+ expect(call_count).to eq(1)
93
+ end
94
+ end
95
+
96
+ # dplyr/rlang fancy errors can lose their causal message under nested callback
97
+ # stacks (path_trim_prefix/strsplit). Gatekeeper wraps nested evals so Ruby
98
+ # still sees "object 'a' not found".
99
+ it 'preserves causal dplyr error messages under nested eval', :slow do
100
+ with_client do |c|
101
+ probe = c.eval_r("isTRUE(requireNamespace('dplyr', quietly = TRUE))")
102
+ skip 'dplyr not installed' unless probe['value'] == true
103
+
104
+ nested_msg = nil
105
+ cb_call_id = c.register_callback do |_payload, call_id|
106
+ begin
107
+ c.eval_r(
108
+ "__G_EVAL_WITH_RESULT__tmp <- { library(dplyr); mutate(data.frame(x = 1:3), y = a + x) }",
109
+ parent_id: call_id
110
+ )
111
+ rescue NewBridge::SessionClient::RProcessError => e
112
+ nested_msg = e.message.to_s
113
+ end
114
+ 1.0
115
+ end
116
+
117
+ c.eval_r("galaaz_callback_call_phase3('#{cb_call_id}', 'unused', 15000)", timeout: 30)
118
+
119
+ expect(nested_msg).to match(/object 'a' not found/)
120
+ expect(nested_msg).not_to match(/strsplit|path_trim_prefix/)
121
+ end
122
+ end
123
+ end
data/r_requires/ggplot.rb CHANGED
File without changes
data/r_requires/knitr.rb CHANGED
File without changes
data/specs/all.rb CHANGED
@@ -23,14 +23,20 @@
23
23
 
24
24
  require_relative 'r_eval.spec'
25
25
 
26
- # Specification for Functions
27
- require_relative 'r_function.spec'
26
+ # Nil/null: nil.is__null and nil.isTRUE (R NULL → Ruby nil)
27
+ require_relative 'nil_null_spec'
28
+
29
+ # Unboxing: single scalar/list, nested list, depth limit
30
+ require_relative 'unboxing_spec'
31
+
32
+ # Field access: obj.name uses R [[ not $ (avoids "$ operator is invalid for atomic vectors")
33
+ require_relative 'field_access_spec'
28
34
 
29
- # Specification for Ruby expressions
30
- require_relative 'ruby_expression.spec'
35
+ # Scalar character: bridge unescapes \n and \" so Ruby gets real newlines/quotes
36
+ require_relative 'scalar_character_spec'
31
37
 
32
- # Specification for R::Environment
33
- require_relative 'r_environment.spec'
38
+ # Specification for Functions
39
+ require_relative 'r_function.spec'
34
40
 
35
41
  # Specification for R::Vector
36
42
  require_relative 'r_vector_creation.spec'
@@ -40,21 +46,19 @@ require_relative 'r_vector_functions.spec'
40
46
  require_relative 'r_vector_operators.spec'
41
47
 
42
48
  # Specification for R::Lists
43
- require_relative 'r_list.spec'
44
49
  require_relative 'r_list_apply.spec'
45
50
 
46
51
  # Specification for R::Matrix
47
52
  require_relative 'r_matrix.spec'
48
53
 
49
- # Specification for R::Dataframes
50
- require_relative 'r_dataframe.spec'
51
-
52
54
  # Specification for language features
53
55
  require_relative 'r_function.spec'
54
- require_relative 'r_formula.spec'
55
56
 
56
57
  # Test file generation
57
58
  require_relative 'r_devices.spec'
58
59
 
60
+ # Phase 1: NewBridge callback stub + galaaz_bridge_env (see Documentation/Gknit_Generic_Output_Phased_Plan.md)
61
+ require_relative 'phase1_callback_bridge_spec'
62
+
59
63
  # Testes for NSE
60
64
  # require_relative 'r_nse.spec'
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'galaaz'
4
+
5
+ describe 'Arrow from Ruby batches' do
6
+ before(:all) do
7
+ ok = R::Support.eval("requireNamespace('arrow', quietly=TRUE) && requireNamespace('dplyr', quietly=TRUE)")
8
+ skip 'R packages arrow/dplyr are not available' unless ok == true
9
+ end
10
+
11
+ it 'builds Arrow table from Ruby-threaded batches and reduces in R' do
12
+ batches = []
13
+ mutex = Mutex.new
14
+ threads = []
15
+
16
+ # Simulate parallel Ruby ingestion.
17
+ [0, 1, 2, 3].each do |tid|
18
+ threads << Thread.new do
19
+ start = tid * 1000
20
+ local = (start...(start + 1000)).map do |i|
21
+ { id: i, grp: "g#{i % 5}", value: (i % 10) + 1 }
22
+ end
23
+ mutex.synchronize { batches << local }
24
+ end
25
+ end
26
+ threads.each(&:join)
27
+
28
+ tbl = R::Arrow.from_ruby_batches(batches)
29
+ expect(tbl.rclass.split(' ')).to include('Table')
30
+
31
+ grouped = R.dplyr___group_by(tbl, :grp)
32
+ summed = R.dplyr___summarise(grouped, total: E.sum(:value))
33
+ out = R.dplyr___collect(summed)
34
+
35
+ groups = out[['grp']]
36
+ totals = out[['total']]
37
+ result = {}
38
+ (1..(groups.length >> 0)).each do |i|
39
+ grp = groups[i]
40
+ tot = totals[i]
41
+ grp = grp.respond_to?(:>>) ? (grp >> 0) : grp
42
+ tot = tot.respond_to?(:>>) ? (tot >> 0) : tot
43
+ result[grp] = tot
44
+ end
45
+
46
+ expected = Hash.new(0)
47
+ batches.flatten.each { |r| expected[r[:grp]] += r[:value] }
48
+ expect(result).to eq(expected)
49
+ end
50
+ end