galaaz 0.5.0 → 2.1.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 (378) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +46 -0
  3. data/LICENSE +0 -0
  4. data/README.md +1416 -667
  5. data/Rakefile +68 -41
  6. data/bin/galaaz-bootstrap +137 -0
  7. data/bin/galaaz-jruby +11 -0
  8. data/bin/galaaz-ruby +16 -0
  9. data/bin/galaaz_jruby_env.inc.sh +6 -0
  10. data/bin/galaaz_ruby_env.inc.sh +36 -0
  11. data/bin/gbookdown +63 -0
  12. data/bin/gknit +83 -13
  13. data/bin/gknit-draft.rb +0 -0
  14. data/bin/gstudio +5 -3
  15. data/bin/gstudio_irb.rb +0 -0
  16. data/bin/gstudio_pry.rb +0 -0
  17. data/bin/install-tinytex +6 -0
  18. data/bin/run_all_rspec +44 -0
  19. data/bin/run_example +17 -0
  20. data/bin/run_old_rspec +20 -0
  21. data/bin/run_rspec +24 -0
  22. data/bin/run_rspec_subset +38 -0
  23. data/bin/run_slow_rspec +20 -0
  24. data/blogs/R-on-Rails-Planning-Document.md +940 -0
  25. data/blogs/README.md +100 -0
  26. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
  27. data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
  28. data/blogs/galaaz_ggplot/galaaz_ggplot.md +115 -155
  29. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
  30. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-gfm/midwest_rb.png +0 -0
  31. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-gfm/scatter_plot_rb.png +0 -0
  32. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
  33. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
  34. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
  35. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
  36. data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
  37. data/blogs/galaaz_ggplot/midwest_external_png +0 -0
  38. data/blogs/gknit/gknit.Rmd +47 -52
  39. data/blogs/gknit/gknit.md +1430 -0
  40. data/blogs/gknit/gknit_files/figure-gfm/bubble-1.png +0 -0
  41. data/blogs/gknit/gknit_files/figure-gfm/diverging_bar.png +0 -0
  42. data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
  43. data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
  44. data/blogs/gknit/lst.rds +0 -0
  45. data/blogs/gknit/model.rb +1 -1
  46. data/blogs/gknit/stats.bib +0 -0
  47. data/blogs/manual/include_model_local_repro.Rmd +14 -0
  48. data/blogs/manual/include_model_local_repro.md +75 -0
  49. data/blogs/manual/lst.rds +0 -0
  50. data/blogs/manual/manual.Rmd +855 -239
  51. data/blogs/manual/manual.log +1786 -0
  52. data/blogs/manual/manual.md +1416 -667
  53. data/blogs/manual/manual.tex +1883 -1161
  54. data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
  55. data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
  56. data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
  57. data/blogs/manual/model.rb +1 -1
  58. data/blogs/nse_dplyr/nse_dplyr.Rmd +84 -111
  59. data/blogs/nse_dplyr/nse_dplyr.log +928 -0
  60. data/blogs/nse_dplyr/nse_dplyr.md +198 -229
  61. data/blogs/oh_my/not_so.rb +0 -0
  62. data/blogs/oh_my/oh_my.Rmd +1234 -25
  63. data/blogs/oh_my/oh_my.log +804 -0
  64. data/blogs/oh_my/oh_my.md +1663 -86
  65. data/blogs/oh_my/oh_my.tex +821 -0
  66. data/blogs/oh_my/old.Rmd +15 -14
  67. data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
  68. data/blogs/ruby_plot/ruby_plot.log +885 -0
  69. data/blogs/ruby_plot/ruby_plot.md +71 -102
  70. data/blogs/ruby_plot/ruby_plot.tex +940 -0
  71. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/dose_len.png +0 -0
  72. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facet_by_delivery.png +0 -0
  73. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facet_by_dose.png +0 -0
  74. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_by_delivery_color.png +0 -0
  75. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_by_delivery_color2.png +0 -0
  76. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_decorations.png +0 -0
  77. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_jitter.png +0 -0
  78. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_points.png +0 -0
  79. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/final_box_plot.png +0 -0
  80. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/final_violin_plot.png +0 -0
  81. data/blogs/ruby_plot/ruby_plot_files/figure-gfm/violin_with_jitter.png +0 -0
  82. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
  83. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
  84. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
  85. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
  86. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
  87. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
  88. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
  89. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
  90. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
  91. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
  92. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
  93. data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
  94. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  95. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  96. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  97. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  98. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  99. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  100. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  101. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  102. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  103. data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  104. data/blogs/test/test.Rmd +14 -0
  105. data/blogs/test/test.md +10 -0
  106. data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
  107. data/examples/50Plots_MasterList/ScatterPlot.rb +2 -1
  108. data/examples/50Plots_MasterList/scatter_plot.rb +1 -0
  109. data/examples/Bibliography/master.bib +0 -0
  110. data/examples/Bibliography/stats.bib +0 -0
  111. data/examples/R/calc.R +0 -0
  112. data/examples/R/java_interop.R +0 -0
  113. data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
  114. data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +54 -0
  115. data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
  116. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +34 -0
  117. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +35 -0
  118. data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
  119. data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
  120. data/examples/islr/all.rb +14 -0
  121. data/examples/islr/ch2.spec.rb +38 -7
  122. data/examples/islr/ch3.spec.rb +12 -2
  123. data/examples/islr/ch3_boston.rb +28 -0
  124. data/examples/islr/ch3_multiple_regression.rb +1 -0
  125. data/examples/islr/ch6.spec.rb +25 -1
  126. data/examples/islr/x_y_rnorm.jpg +0 -0
  127. data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +0 -0
  128. data/examples/latex_templates/Test-acm_article/sigproc.bib +0 -0
  129. data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +0 -0
  130. data/examples/latex_templates/Test-acs_article/acs-my_output.bib +0 -0
  131. data/examples/latex_templates/Test-aea_article/BibFile.bib +0 -0
  132. data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +0 -0
  133. data/examples/latex_templates/Test-aea_article/references.bib +0 -0
  134. data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +0 -0
  135. data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +0 -0
  136. data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +0 -0
  137. data/examples/latex_templates/Test-ieee_article/mybibfile.bib +0 -0
  138. data/examples/latex_templates/Test-rjournal_article/RJournal.sty +0 -0
  139. data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +0 -0
  140. data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +0 -0
  141. data/examples/misc/baseball.csv +0 -0
  142. data/examples/misc/ggplot.rb +5 -3
  143. data/examples/misc/moneyball.rb +1 -0
  144. data/examples/misc/subsetting.rb +1 -0
  145. data/examples/multithread_shards_to_r/shards_to_r.rb +68 -0
  146. data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +0 -0
  147. data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +0 -0
  148. data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +0 -0
  149. data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +0 -0
  150. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +0 -0
  151. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +0 -0
  152. data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +0 -0
  153. data/examples/sthda_ggplot/README.md +0 -0
  154. data/examples/sthda_ggplot/RUN.md +41 -0
  155. data/examples/sthda_ggplot/all.rb +1 -0
  156. data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +1 -0
  157. data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +1 -0
  158. data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +3 -0
  159. data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +1 -0
  160. data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +1 -0
  161. data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +1 -0
  162. data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +1 -0
  163. data/examples/sthda_ggplot/one_variable_continuous/stat.rb +1 -0
  164. data/examples/sthda_ggplot/one_variable_discrete/bar.rb +1 -0
  165. data/examples/sthda_ggplot/qplots/box_violin_dot.rb +1 -0
  166. data/examples/sthda_ggplot/qplots/scatter_plots.rb +1 -0
  167. data/examples/sthda_ggplot/scatter_gg.rb +1 -0
  168. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +1 -0
  169. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +1 -0
  170. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +1 -0
  171. data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +1 -0
  172. data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +1 -0
  173. data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +1 -0
  174. data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +5 -3
  175. data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +1 -0
  176. data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +1 -0
  177. data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +1 -0
  178. data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +1 -0
  179. data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +1 -0
  180. data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +1 -0
  181. data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +1 -0
  182. data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +1 -0
  183. data/ext/new_bridge/Makefile +46 -0
  184. data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
  185. data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
  186. data/lib/R_interface/galaaz_device.R +20 -0
  187. data/lib/R_interface/include_engine.R +109 -0
  188. data/lib/R_interface/new_bridge_adapter.rb +824 -0
  189. data/lib/R_interface/r.rb +177 -25
  190. data/lib/R_interface/r_arrow.rb +113 -0
  191. data/lib/R_interface/r_libs.R +3 -3
  192. data/lib/R_interface/r_methods.rb +13 -126
  193. data/lib/R_interface/r_module_s.rb +0 -0
  194. data/lib/R_interface/rbinary_operators.rb +20 -2
  195. data/lib/R_interface/rclosure.rb +5 -1
  196. data/lib/R_interface/rdata_frame.rb +34 -70
  197. data/lib/R_interface/rdevice.rb +125 -0
  198. data/lib/R_interface/rdevices.R +0 -0
  199. data/lib/R_interface/renvironment.rb +10 -4
  200. data/lib/R_interface/rexpression.rb +5 -1
  201. data/lib/R_interface/rindexed_object.rb +41 -13
  202. data/lib/R_interface/rlanguage.rb +20 -62
  203. data/lib/R_interface/rlist.rb +115 -25
  204. data/lib/R_interface/rlogical_operators.rb +0 -0
  205. data/lib/R_interface/rmatrix.rb +2 -11
  206. data/lib/R_interface/rmd_indexed_object.rb +5 -1
  207. data/lib/R_interface/robject.rb +348 -290
  208. data/lib/R_interface/rpkg.rb +0 -0
  209. data/lib/R_interface/rsupport.rb +609 -328
  210. data/lib/R_interface/rsupport_scope.rb +2 -1
  211. data/lib/R_interface/rsymbol.rb +50 -0
  212. data/lib/R_interface/ruby_callback.rb +2 -3
  213. data/lib/R_interface/ruby_extensions.rb +225 -175
  214. data/lib/R_interface/runary_operators.rb +0 -0
  215. data/lib/R_interface/rvector.rb +162 -31
  216. data/lib/galaaz.rb +0 -0
  217. data/lib/galaaz_jruby.rb +22 -0
  218. data/lib/galaaz_ruby.rb +34 -0
  219. data/lib/gknit/diagnostics.rb +50 -0
  220. data/lib/gknit/draft.rb +23 -17
  221. data/lib/gknit/include_engine.rb +15 -7
  222. data/lib/gknit/knitr_engine.rb +223 -74
  223. data/lib/gknit/rb_engine.rb +3 -3
  224. data/lib/gknit/ruby_engine.rb +0 -0
  225. data/lib/gknit.rb +1 -0
  226. data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
  227. data/lib/new_bridge/envelope.rb +51 -0
  228. data/lib/new_bridge/eval_result.rb +26 -0
  229. data/lib/new_bridge/framing.rb +39 -0
  230. data/lib/new_bridge/instance_pool_client.rb +38 -0
  231. data/lib/new_bridge/r_instance_manager.rb +404 -0
  232. data/lib/new_bridge/session_client.rb +530 -0
  233. data/lib/new_bridge/tcp_framed.rb +44 -0
  234. data/lib/new_bridge.rb +9 -0
  235. data/lib/util/exec_ruby.rb +95 -20
  236. data/lib/util/inline_file.rb +35 -30
  237. data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
  238. data/new_bridge_specs/eval_r_async_spec.rb +113 -0
  239. data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
  240. data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
  241. data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
  242. data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
  243. data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
  244. data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
  245. data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
  246. data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
  247. data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
  248. data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
  249. data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
  250. data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
  251. data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
  252. data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
  253. data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
  254. data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
  255. data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
  256. data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
  257. data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
  258. data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
  259. data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
  260. data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
  261. data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
  262. data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
  263. data/r_requires/ggplot.rb +0 -0
  264. data/r_requires/knitr.rb +0 -0
  265. data/specs/all.rb +15 -11
  266. data/specs/arrow_from_ruby_batches_spec.rb +50 -0
  267. data/specs/arrow_semantics_spec.rb +64 -0
  268. data/specs/bridge_concurrent_spec.rb +46 -0
  269. data/specs/bridge_nested_spec.rb +25 -0
  270. data/specs/dataframe_semantics_spec.rb +122 -0
  271. data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
  272. data/specs/dispatch_probe_cache_spec.rb +38 -0
  273. data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
  274. data/specs/dispatch_probe_fallback_spec.rb +18 -0
  275. data/specs/environment_semantics_spec.rb +89 -0
  276. data/specs/field_access_spec.rb +31 -0
  277. data/specs/figures/bg.jpeg +0 -0
  278. data/specs/figures/bg.png +0 -0
  279. data/specs/figures/bg.svg +168 -57
  280. data/specs/figures/dose_len.png +0 -0
  281. data/specs/figures/no_args.jpeg +0 -0
  282. data/specs/figures/no_args.png +0 -0
  283. data/specs/figures/no_args.svg +168 -57
  284. data/specs/figures/width_height.jpeg +0 -0
  285. data/specs/figures/width_height.png +0 -0
  286. data/specs/figures/width_height_units1.jpeg +0 -0
  287. data/specs/figures/width_height_units1.png +0 -0
  288. data/specs/figures/width_height_units2.jpeg +0 -0
  289. data/specs/figures/width_height_units2.png +0 -0
  290. data/specs/formula_semantics_spec.rb +81 -0
  291. data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
  292. data/specs/galaaz_util_inline_file_spec.rb +54 -0
  293. data/specs/gknit_cli_option_permutation_spec.rb +24 -0
  294. data/specs/gknit_include_engine_spec.rb +72 -0
  295. data/specs/gknit_install_timeout_report_spec.rb +69 -0
  296. data/specs/gknit_internal_error_report_spec.rb +57 -0
  297. data/specs/gknit_vector_map_output_spec.rb +59 -0
  298. data/specs/globalenv_guardrail_spec.rb +52 -0
  299. data/specs/language_expression_semantics_spec.rb +145 -0
  300. data/specs/list_semantics_spec.rb +111 -0
  301. data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
  302. data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
  303. data/specs/new_bridge_callback_timeout_spec.rb +69 -0
  304. data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
  305. data/specs/nil_null_spec.rb +42 -0
  306. data/specs/object_build_phase2_spec.rb +53 -0
  307. data/specs/phase1_callback_bridge_spec.rb +84 -0
  308. data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
  309. data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
  310. data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
  311. data/specs/plot_device_semantics_spec.rb +28 -0
  312. data/specs/plot_snapshot_semantics_spec.rb +58 -0
  313. data/specs/protocol_result_spec.rb +236 -0
  314. data/specs/r_batch_fail_fast_spec.rb +47 -0
  315. data/specs/r_bridge_bootstrap_spec.rb +11 -0
  316. data/specs/r_devices.spec.rb +1 -1
  317. data/specs/r_eval.spec.rb +16 -18
  318. data/specs/r_function.spec.rb +1 -1
  319. data/specs/r_instance_manager_spec.rb +285 -0
  320. data/specs/r_list_apply.spec.rb +15 -15
  321. data/specs/r_matrix.spec.rb +0 -0
  322. data/specs/r_nse.spec.rb +5 -5
  323. data/specs/r_object_send_dispatch_spec.rb +13 -0
  324. data/specs/r_vector_comparator_spec.rb +8 -0
  325. data/specs/r_vector_creation.spec.rb +0 -0
  326. data/specs/r_vector_functions.spec.rb +0 -0
  327. data/specs/r_vector_object.spec.rb +0 -0
  328. data/specs/r_vector_operators.spec.rb +0 -0
  329. data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
  330. data/specs/r_vector_subsetting.spec.rb +0 -0
  331. data/specs/range_helper_spec.rb +21 -0
  332. data/specs/rsupport_scope_spec.rb +28 -0
  333. data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
  334. data/specs/scalar_character_spec.rb +44 -0
  335. data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
  336. data/specs/session_env_bridge_spec.rb +25 -0
  337. data/specs/simplecov_bootstrap_spec.rb +10 -0
  338. data/specs/spec_helper.rb +10 -0
  339. data/specs/tmp.rb +0 -0
  340. data/specs/unboxing_recursion_regression_spec.rb +30 -0
  341. data/specs/unboxing_spec.rb +49 -0
  342. data/specs/verify_callbacks.rb +42 -0
  343. data/sty/galaaz.sty +0 -0
  344. data/version.rb +1 -1
  345. metadata +219 -63
  346. data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -520
  347. data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
  348. data/blogs/galaaz_ggplot/midwest.html +0 -188
  349. data/blogs/gknit/gknit.html +0 -2266
  350. data/blogs/gknit/gknit.pdf +0 -0
  351. data/blogs/manual/manual.html +0 -4638
  352. data/blogs/manual/manual.pdf +0 -0
  353. data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
  354. data/blogs/nse_dplyr/nse_dplyr.html +0 -878
  355. data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
  356. data/blogs/oh_my/oh_my.html +0 -568
  357. data/blogs/ruby_plot/ruby_plot.html +0 -544
  358. data/blogs/ruby_plot/ruby_plot.pdf +0 -0
  359. data/examples/latex_templates/Test-acs_article/Test-acs_article.pdf +0 -0
  360. data/examples/latex_templates/Test-aea_article/Test-aea_article.pdf +0 -0
  361. data/examples/latex_templates/Test-amq_article/Test-amq_article.pdf +0 -0
  362. data/examples/latex_templates/Test-amq_article/pics/Figure2.pdf +0 -0
  363. data/examples/latex_templates/Test-asa_article/Test-asa_article.pdf +0 -0
  364. data/examples/latex_templates/Test-ieee_article/Test-ieee_article.pdf +0 -0
  365. data/examples/latex_templates/Test-rjournal_article/RJwrapper.pdf +0 -0
  366. data/examples/latex_templates/Test-springer_article/Test-springer_article.pdf +0 -0
  367. data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.pdf +0 -0
  368. data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.pdf +0 -0
  369. data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.pdf +0 -0
  370. data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.pdf +0 -0
  371. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.pdf +0 -0
  372. data/specs/r_dataframe.spec.rb +0 -379
  373. data/specs/r_environment.spec.rb +0 -140
  374. data/specs/r_formula.spec.rb +0 -232
  375. data/specs/r_language.spec.rb +0 -112
  376. data/specs/r_list.spec.rb +0 -293
  377. data/specs/r_plots.spec.rb +0 -72
  378. data/specs/ruby_expression.spec.rb +0 -316
@@ -0,0 +1,285 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+ require 'galaaz'
5
+ require_relative '../lib/new_bridge/r_instance_manager'
6
+
7
+ module NewBridge
8
+ class StubSessionClient
9
+ attr_reader :source_path, :host, :bridge_host, :r_cmd, :runtime_source_path, :start_calls
10
+ attr_accessor :eval_proc, :stopped
11
+
12
+ @@instances = []
13
+ @@start_errors = []
14
+
15
+ def self.instances
16
+ @@instances
17
+ end
18
+
19
+ def self.reset!
20
+ @@instances = []
21
+ @@start_errors = []
22
+ end
23
+
24
+ def self.enqueue_start_error(error)
25
+ @@start_errors << error
26
+ end
27
+
28
+ def initialize(source_path:, host:, r_cmd:, runtime_source_path: nil, bridge_host: nil)
29
+ @source_path = source_path
30
+ @host = host
31
+ @bridge_host = bridge_host
32
+ @r_cmd = r_cmd
33
+ @runtime_source_path = runtime_source_path
34
+ @start_calls = []
35
+ @stopped = false
36
+ @eval_proc = ->(_code, _kwargs) { 'ok' }
37
+ @@instances << self
38
+ end
39
+
40
+ def start(accept_timeout: nil)
41
+ @start_calls << accept_timeout
42
+ raise @@start_errors.shift unless @@start_errors.empty?
43
+ true
44
+ end
45
+
46
+ def stop
47
+ @stopped = true
48
+ end
49
+
50
+ def eval_r(code = nil, **kwargs)
51
+ @eval_proc.call(code, kwargs)
52
+ end
53
+ end
54
+ end
55
+
56
+ describe NewBridge::RInstanceManager do
57
+ let(:out) { StringIO.new }
58
+ let(:mgr) do
59
+ described_class.new(
60
+ source_path: File.expand_path('../ext/new_bridge/gatekeeper.cpp', __dir__),
61
+ session_client_class: NewBridge::StubSessionClient,
62
+ out: out,
63
+ docker_access_checker: -> { [true, nil] }
64
+ )
65
+ end
66
+
67
+ before do
68
+ NewBridge::StubSessionClient.reset!
69
+ end
70
+
71
+ it 'spawns local instances and tracks metadata/default' do
72
+ mgr.spawn_local(instance_id: 'a', r_cmd: 'R', version: 'v1')
73
+ mgr.spawn_local(instance_id: 'b', r_cmd: '/usr/bin/R', version: 'v2')
74
+
75
+ expect(mgr.default_instance_id).to eq('a')
76
+ ids = mgr.instance_ids
77
+ expect(ids).to include('a', 'b')
78
+
79
+ info = mgr.instances
80
+ expect(info.size).to eq(2)
81
+ expect(info.find { |h| h[:id] == 'a' }[:default]).to eq(true)
82
+ expect(info.find { |h| h[:id] == 'b' }[:runtime]).to eq('local')
83
+ end
84
+
85
+ it 'raises on duplicate local instance id' do
86
+ mgr.spawn_local(instance_id: 'a', version: 'v1')
87
+ expect { mgr.spawn_local(instance_id: 'a', version: 'v1') }.to raise_error(ArgumentError, /already exists/)
88
+ end
89
+
90
+ it 'supports spawn runtime dispatch and container metadata' do
91
+ mgr.spawn(instance_id: 'c1', runtime: 'container', version: 'v-current', image: 'r-image', bridge_hosts: ['host.docker.internal'])
92
+
93
+ item = mgr.instances.find { |h| h[:id] == 'c1' }
94
+ expect(item[:runtime]).to eq('container')
95
+ expect(item[:provider]).to eq('docker')
96
+ expect(item[:image]).to eq('r-image')
97
+ expect(item[:container_name]).to include('galaaz-c1')
98
+ end
99
+
100
+ it 'supports local runtime via unified spawn API' do
101
+ mgr.spawn(instance_id: 'l1', runtime: 'local', version: 'v-local', r_cmd: 'R')
102
+ expect(mgr.instance_ids).to include('l1')
103
+ end
104
+
105
+ it 'rejects invalid runtime values and missing container image' do
106
+ expect do
107
+ mgr.spawn(instance_id: 'x', runtime: 'unknown', version: 'v')
108
+ end.to raise_error(ArgumentError, /unsupported runtime/)
109
+
110
+ expect do
111
+ mgr.spawn(instance_id: 'x', runtime: 'container', version: 'v', image: '')
112
+ end.to raise_error(ArgumentError, /image is required/)
113
+ end
114
+
115
+ it 'retries once on infrastructure timeout by restarting instance' do
116
+ mgr.spawn_local(instance_id: 'a', version: 'v1')
117
+ first = NewBridge::StubSessionClient.instances.first
118
+ first.eval_proc = ->(_code, _kwargs) { raise Timeout::Error, 'timeout' }
119
+
120
+ result = mgr.eval_r('1+1', session_id: 's1', instance_id: 'a')
121
+ expect(result).to eq('ok')
122
+ expect(NewBridge::StubSessionClient.instances.size).to eq(2)
123
+ expect(first.stopped).to eq(true)
124
+ end
125
+
126
+ it 'routes by version and evaluates once per version' do
127
+ mgr.spawn_local(instance_id: 'a', version: 'v1')
128
+ mgr.spawn_local(instance_id: 'b', version: 'v1')
129
+ mgr.spawn_local(instance_id: 'c', version: 'v2')
130
+
131
+ expect(mgr.eval_with_version('2+2', version: 'v2')).to eq('ok')
132
+ expect { mgr.eval_with_version('2+2', version: 'missing') }.to raise_error(KeyError)
133
+
134
+ out = mgr.eval_all_versions('2+2')
135
+ expect(out.keys.sort).to eq(%w[v1 v2])
136
+ end
137
+
138
+ it 'supports default switching and stop variants' do
139
+ mgr.spawn_local(instance_id: 'a', version: 'v1')
140
+ mgr.spawn_local(instance_id: 'b', version: 'v2')
141
+ mgr.set_default_instance('b')
142
+ expect(mgr.default_instance_id).to eq('b')
143
+ expect { mgr.set_default_instance('missing') }.to raise_error(KeyError)
144
+
145
+ mgr.stop_all(keep_default: true)
146
+ expect(mgr.instance_ids).to eq(['b'])
147
+
148
+ mgr.stop('b')
149
+ expect(mgr.instance_ids).to eq([])
150
+ expect(mgr.default_instance_id).to eq(nil)
151
+ end
152
+
153
+ it 'supports force killing container instances' do
154
+ mgr.spawn(instance_id: 'c1', runtime: 'container', version: 'v-current', image: 'r-image', bridge_hosts: ['host.docker.internal'])
155
+ expect { mgr.kill_container('c1') }.not_to raise_error
156
+
157
+ mgr.spawn_local(instance_id: 'a', version: 'v1')
158
+ expect { mgr.kill_container('a') }.to raise_error(ArgumentError, /not container runtime/)
159
+ end
160
+
161
+ it 'fails container spawn when docker checker reports inaccessible daemon' do
162
+ bad_mgr = described_class.new(
163
+ source_path: File.expand_path('../ext/new_bridge/gatekeeper.cpp', __dir__),
164
+ session_client_class: NewBridge::StubSessionClient,
165
+ out: out,
166
+ docker_access_checker: -> { [false, 'permission denied'] }
167
+ )
168
+
169
+ expect do
170
+ bad_mgr.spawn(instance_id: 'c2', runtime: 'container', version: 'v', image: 'img')
171
+ end.to raise_error(NewBridge::RInstanceManager::Error, /docker daemon is not accessible: permission denied/)
172
+ end
173
+
174
+ it 'tries multiple bridge hosts and logs failures before succeeding' do
175
+ NewBridge::StubSessionClient.enqueue_start_error(StandardError.new('accept failed'))
176
+ mgr.spawn(
177
+ instance_id: 'c-fallback',
178
+ runtime: 'container',
179
+ version: 'v',
180
+ image: 'img',
181
+ bridge_hosts: %w[bad.host good.host]
182
+ )
183
+
184
+ text = out.string
185
+ expect(text).to include('trying bridge host bad.host')
186
+ expect(text).to include('trying bridge host good.host')
187
+ expect(text).to include('bridge host bad.host failed')
188
+ end
189
+
190
+ it 'raises when all bridge host candidates fail' do
191
+ NewBridge::StubSessionClient.enqueue_start_error(StandardError.new('fail 1'))
192
+ NewBridge::StubSessionClient.enqueue_start_error(StandardError.new('fail 2'))
193
+
194
+ expect do
195
+ mgr.spawn(
196
+ instance_id: 'c-fail',
197
+ runtime: 'container',
198
+ version: 'v',
199
+ image: 'img',
200
+ bridge_hosts: %w[h1 h2]
201
+ )
202
+ end.to raise_error(NewBridge::RInstanceManager::Error, /container runtime start failed/)
203
+ end
204
+
205
+ it 'classifies retryable infrastructure errors conservatively' do
206
+ expect(mgr.send(:infrastructure_retryable_error?, Timeout::Error.new('t'))).to eq(true)
207
+ expect(mgr.send(:infrastructure_retryable_error?, IOError.new('io'))).to eq(true)
208
+ expect(mgr.send(:infrastructure_retryable_error?, NewBridge::SessionClient::TimeoutError.new('timeout'))).to eq(true)
209
+ expect(mgr.send(:infrastructure_retryable_error?, NewBridge::SessionClient::RProcessError.new('connection closed by peer'))).to eq(true)
210
+ expect(mgr.send(:infrastructure_retryable_error?, NewBridge::SessionClient::RProcessError.new('evaluation error: bad call'))).to eq(false)
211
+ expect(mgr.send(:infrastructure_retryable_error?, StandardError.new('other'))).to eq(false)
212
+ end
213
+
214
+ it 'builds bridge host candidates honoring preferred host cache' do
215
+ mgr.instance_variable_set(:@preferred_bridge_host, 'cached.host')
216
+ allow(mgr).to receive(:running_in_wsl?).and_return(false)
217
+ allow(mgr).to receive(:local_wsl_ip).and_return('172.22.0.5')
218
+
219
+ with_cache = mgr.send(:bridge_host_candidates, relearn: false)
220
+ relearn = mgr.send(:bridge_host_candidates, relearn: true)
221
+
222
+ expect(with_cache.first).to eq('cached.host')
223
+ expect(with_cache).to include('host.docker.internal', '172.22.0.5')
224
+ expect(relearn).to eq(%w[host.docker.internal 172.22.0.5])
225
+ end
226
+
227
+ it 'prefers WSL IP before host.docker.internal when running in WSL' do
228
+ allow(mgr).to receive(:running_in_wsl?).and_return(true)
229
+ allow(mgr).to receive(:local_wsl_ip).and_return('172.22.0.5')
230
+
231
+ expect(mgr.send(:bridge_host_candidates, relearn: true)).to eq(%w[172.22.0.5 host.docker.internal])
232
+
233
+ mgr.instance_variable_set(:@preferred_bridge_host, 'cached.host')
234
+ with_cache = mgr.send(:bridge_host_candidates, relearn: false)
235
+ expect(with_cache.first).to eq('cached.host')
236
+ expect(with_cache).to eq(%w[cached.host 172.22.0.5 host.docker.internal])
237
+ end
238
+
239
+ it 'handles docker log and cleanup helper branches' do
240
+ allow(Open3).to receive(:capture3).with('docker', 'logs', '--tail', '80', 'cname').and_return(['ok logs', '', instance_double(Process::Status, success?: true)])
241
+ expect(mgr.send(:docker_logs, 'cname')).to eq('ok logs')
242
+
243
+ allow(Open3).to receive(:capture3).with('docker', 'logs', '--tail', '80', 'cname2').and_return(['', 'no logs', instance_double(Process::Status, success?: false)])
244
+ expect(mgr.send(:docker_logs, 'cname2')).to eq('no logs')
245
+
246
+ allow(Open3).to receive(:capture3).with('docker', 'rm', '-f', 'dead-c').and_return(['', '', instance_double(Process::Status, success?: true)])
247
+ expect { mgr.send(:cleanup_container, { runtime: 'container', container_name: 'dead-c' }, force: true) }.not_to raise_error
248
+ expect { mgr.send(:cleanup_container, { runtime: 'container', container_name: '' }, force: true) }.not_to raise_error
249
+ expect { mgr.send(:cleanup_container, { runtime: 'local' }, force: true) }.not_to raise_error
250
+ end
251
+
252
+ it 'reads local wsl ip and handles shell failures' do
253
+ allow(Open3).to receive(:capture3).with('bash', '-lc', "hostname -I | awk '{print $1}'").and_return(["172.22.0.7\n", '', instance_double(Process::Status, success?: true)])
254
+ expect(mgr.send(:local_wsl_ip)).to eq('172.22.0.7')
255
+
256
+ allow(Open3).to receive(:capture3).with('bash', '-lc', "hostname -I | awk '{print $1}'").and_return(['', 'err', instance_double(Process::Status, success?: false)])
257
+ expect(mgr.send(:local_wsl_ip)).to eq(nil)
258
+ end
259
+
260
+ it 'checks docker daemon access when checker is not provided' do
261
+ mgr2 = described_class.new(
262
+ source_path: File.expand_path('../ext/new_bridge/gatekeeper.cpp', __dir__),
263
+ session_client_class: NewBridge::StubSessionClient,
264
+ out: out
265
+ )
266
+
267
+ allow(Open3).to receive(:capture3).with('docker', 'info').and_return(['ok', '', instance_double(Process::Status, success?: true)])
268
+ expect { mgr2.send(:ensure_docker_daemon_access!) }.not_to raise_error
269
+
270
+ allow(Open3).to receive(:capture3).with('docker', 'info').and_return(['', 'permission denied', instance_double(Process::Status, success?: false)])
271
+ expect { mgr2.send(:ensure_docker_daemon_access!) }.to raise_error(NewBridge::RInstanceManager::Error, /docker daemon is not accessible: permission denied/)
272
+ end
273
+
274
+ it 'handles helper rescues for docker logs, cleanup, and local ip' do
275
+ allow(Open3).to receive(:capture3).with('docker', 'logs', '--tail', '80', 'boom').and_raise(StandardError, 'x')
276
+ expect(mgr.send(:docker_logs, 'boom')).to eq('')
277
+
278
+ allow(Open3).to receive(:capture3).with('docker', 'rm', '-f', 'boom').and_raise(StandardError, 'x')
279
+ expect { mgr.send(:cleanup_container, { runtime: 'container', container_name: 'boom' }, force: true) }.not_to raise_error
280
+
281
+ allow(Open3).to receive(:capture3).with('bash', '-lc', "hostname -I | awk '{print $1}'").and_raise(StandardError, 'x')
282
+ expect(mgr.send(:local_wsl_ip)).to eq(nil)
283
+ end
284
+ end
285
+
@@ -32,7 +32,7 @@ describe R::List do
32
32
  @x = R.list(a: (1..10), beta: R.exp(-3..3), logic: R.c(true, false, false, true))
33
33
  R.library("stats")
34
34
  # Make @q the function R quantile
35
- @q = ~:quantile
35
+ @q = ~R[:quantile]
36
36
  end
37
37
 
38
38
  it "should work with lapply and mean" do
@@ -49,7 +49,7 @@ describe R::List do
49
49
  # and method all__equal is not defined on floats.
50
50
  expect(R.all__equal(mean.beta,
51
51
  4.5351252347,
52
- tolerance: (~:".Machine").double__eps ** 0.5)).to eq true
52
+ tolerance: (~R[:".Machine"]).double__eps ** 0.5)).to eq true
53
53
 
54
54
  expect(mean.logic).to eq 0.5
55
55
  end
@@ -62,21 +62,21 @@ describe R::List do
62
62
  expect(quant.a[1]).to eq R.c('0%': 1.0)
63
63
  expect(quant.a[[1]]).to eq 1.0
64
64
 
65
- expect(quant.a[['50,00000%']]).to eq 5.50
66
- expect(quant.a['50,00000%']).to eq R.c('50,00000%': 5.50)
67
- expect(R.all__equal(quant.beta['100,0000%'],
68
- R.c('100,0000%': 20.08553692),
69
- tolerance: (~:".Machine").double__eps ** 0.5)).to eq true
65
+ expect(quant.a[['50%']]).to eq 5.50
66
+ expect(quant.a['50%']).to eq R.c('50%': 5.50)
67
+ expect(R.all__equal(quant.beta['100%'],
68
+ R.c('100%': 20.08553692),
69
+ tolerance: (~R[:".Machine"]).double__eps ** 0.5)).to eq true
70
70
  expect(quant.logic[[2]]).to eq 0.0
71
71
  end
72
72
 
73
73
  it "should allow using method lapply with quantile" do
74
74
  x = R.lapply(@x, @q, R.c(0.25, 0.50, 0.75))
75
75
  expect(x.a[[1]]).to eq 3.25
76
- expect(x.a[['50,00000%']]).to eq 5.50
77
- expect(R.all__equal(x.beta['75,00000%'],
78
- R.c('75,00000%': 5.0536690),
79
- tolerance: (~:".Machine").double__eps ** 0.5)).to eq true
76
+ expect(x.a[['50%']]).to eq 5.50
77
+ expect(R.all__equal(x.beta['75%'],
78
+ R.c('75%': 5.0536690),
79
+ tolerance: (~R[:".Machine"]).double__eps ** 0.5)).to eq true
80
80
  expect(x.logic[[2]]).to eq 0.5
81
81
  end
82
82
 
@@ -84,9 +84,9 @@ describe R::List do
84
84
  # sapply will return a matrix
85
85
  quant = R.sapply(@x, @q)
86
86
  expect(quant.rclass).to eq 'matrix'
87
- expect(quant[:all, 'a']).to eq R.c('0%': 1, '25,00000%': 3.25,
88
- '50,00000%': 5.50, '75,00000%': 7.75,
89
- '100,0000%': 10)
87
+ expect(quant[:all, 'a']).to eq R.c('0%': 1, '25%': 3.25,
88
+ '50%': 5.50, '75%': 7.75,
89
+ '100%': 10)
90
90
 
91
91
  expect(quant[3, 'beta']).to eq 1.0
92
92
  end
@@ -97,7 +97,7 @@ describe R::List do
97
97
  i39 = R.sapply((3..9), "seq")
98
98
  expect(i39[[1]]).to eq R.c(1, 2, 3)
99
99
  expect(i39[[7]]).to eq R.c(1, 2, 3, 4, 5, 6, 7, 8, 9)
100
- sap = R.sapply(i39, ~:fivenum)
100
+ sap = R.sapply(i39, ~R[:fivenum])
101
101
  expect(sap[1, 1]).to eq 1.0
102
102
  expect(sap[5, 7]).to eq 9.0
103
103
  end
File without changes
data/specs/r_nse.spec.rb CHANGED
@@ -40,17 +40,17 @@ describe R do
40
40
  df[r, :all]
41
41
  end
42
42
 
43
- puts subset(@sample_df, :a >= 4)
43
+ puts subset(@sample_df, R[:a] >= 4)
44
44
 
45
45
  y = 4
46
46
  x = 4
47
47
  condition = 4
48
48
  condition_call = 4
49
49
 
50
- puts subset(@sample_df, :a == 4)
51
- puts subset(@sample_df, :a == y)
52
- puts subset(@sample_df, :a == condition)
53
- puts subset(@sample_df, :a == condition_call)
50
+ puts subset(@sample_df, R[:a] == 4)
51
+ puts subset(@sample_df, R[:a] == y)
52
+ puts subset(@sample_df, R[:a] == condition)
53
+ puts subset(@sample_df, R[:a] == condition_call)
54
54
  end
55
55
 
56
56
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'galaaz'
4
+
5
+ describe 'R::Object send dispatch' do
6
+ it 'uses Ruby send instead of R send(...) function call' do
7
+ df = R.data__frame(mpg: R.c(21, 22), cyl: R.c(6, 4))
8
+ mpg = df.send(:mpg)
9
+
10
+ expect(mpg).to be_a(R::Object)
11
+ expect(mpg.unboxed_get(0)).to eq(21)
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'galaaz'
2
+
3
+ describe R::Vector do
4
+ it 'raises NotImplementedError for <=>' do
5
+ vec = R.c(1, 2, 3)
6
+ expect { vec <=> vec }.to raise_error(NotImplementedError, /not implemented/)
7
+ end
8
+ end
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'galaaz'
4
+
5
+ describe 'R::Vector structured scalar reads (result protocol)' do
6
+ it 'unboxes indexed integer element without relying on printed length/typeof' do
7
+ v = R.c(10, 20, 30)
8
+ expect(v.unboxed_get(1)).to eq(20)
9
+ end
10
+
11
+ it 'unboxes indexed double element' do
12
+ v = R.c(1.5, 2.5)
13
+ expect(v.unboxed_get(0)).to eq(1.5)
14
+ end
15
+
16
+ it 'unboxes logical TRUE, FALSE, and NA via scalar_logical envelope' do
17
+ v = R.c(true, false, R::NA)
18
+ expect(v.unboxed_get(0)).to eq(true)
19
+ expect(v.unboxed_get(1)).to eq(false)
20
+ expect(v.unboxed_get(2)).to be_nil
21
+ end
22
+
23
+ it 'unboxes indexed character element' do
24
+ v = R.c('a', 'b')
25
+ expect(v.unboxed_get(1)).to eq('b')
26
+ end
27
+
28
+ it 'stitch uses protocol-based length' do
29
+ v = R.c(1.0, 2.0, 3.0)
30
+ out = v.stitch(halo: 0) { |chunk| chunk.map { |x| x * 2 } }
31
+ expect(out).to be_a(R::Vector)
32
+ expect(out.length.unboxed_get(0)).to eq(3)
33
+ expect((out >> nil)).to eq([2.0, 4.0, 6.0])
34
+ end
35
+ end
File without changes
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'galaaz'
4
+
5
+ describe 'range_helper / up_to DSL' do
6
+ it 'supports select with symbol range syntax' do
7
+ ok = R::Support.eval("requireNamespace('dplyr', quietly=TRUE)")
8
+ skip 'dplyr is not available' unless ok == true
9
+
10
+ df = R.data__frame(
11
+ year: R.c(2020, 2021),
12
+ month: R.c(1, 2),
13
+ day: R.c(10, 11),
14
+ tailnum: R.c('N1', 'N2')
15
+ )
16
+
17
+ out = R.dplyr___select(df, R[:year].up_to(R[:day]))
18
+ cols = R.names(out) >> nil
19
+ expect(cols).to eq(%w[year month day])
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'galaaz'
4
+
5
+ describe R::Support do
6
+ describe '.new_scope' do
7
+ it 'evaluates expression-style calls inside dataframe scope' do
8
+ df = R.data__frame(a: (1..4), b: R.c(10, 20, 30, 40))
9
+
10
+ out = R::Support.new_scope(:with, df) do
11
+ (a > 2).eval(df)
12
+ end
13
+
14
+ expect(out).to eq R.c(false, false, true, true)
15
+ end
16
+
17
+ it 'allows direct column access via generated methods' do
18
+ df = R.data__frame(a: (1..3), b: R.c(5, 6, 7))
19
+
20
+ val = R::Support.new_scope(:with, df) do
21
+ (a + b).eval(df)
22
+ end
23
+
24
+ expect(val).to eq R.c(6, 8, 10)
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,24 @@
1
+ require 'galaaz'
2
+
3
+ describe R::Support do
4
+ it 'generates unique g2_v handles under concurrency' do
5
+ n_threads = 8
6
+ per_thread = 200
7
+ names = []
8
+ lock = Mutex.new
9
+
10
+ threads = n_threads.times.map do
11
+ Thread.new do
12
+ local = []
13
+ per_thread.times { local << R::Support.generate_var_name }
14
+ lock.synchronize { names.concat(local) }
15
+ end
16
+ end
17
+
18
+ threads.each(&:join)
19
+
20
+ expect(names.length).to eq(n_threads * per_thread)
21
+ expect(names.uniq.length).to eq(names.length)
22
+ expect(names).to all(match(/\Ag2_v\d+\z/))
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Scalar character result protocol: when R sends a length-1 character (type 3),
3
+ # the bridge unescapes so Ruby receives real newlines and double quotes
4
+ # (e.g. \n -> newline, \" -> ", \\ -> \). This avoids SyntaxError when chunk
5
+ # code is round-tripped (e.g. gknit exec_ruby).
6
+ # Run with: bin/run_rspec specs/scalar_character_spec.rb
7
+
8
+ require 'galaaz'
9
+
10
+ describe "Scalar character (result protocol unescaping)" do
11
+
12
+ context "R -> Ruby: literal \\n and \" in string" do
13
+ # R string "a\\nb" has chars: a, backslash, n, b. Bridge unescapes \n -> newline.
14
+ it "unescapes \\n to real newline when unboxing length-1 character" do
15
+ v = R::Support.eval('"a\\\\nb"')
16
+ expect(v).to be_a(R::Object)
17
+ s = v >> 0
18
+ expect(s).to eq "a\nb"
19
+ end
20
+
21
+ # R string "a\\\"b" has chars: a, backslash, double-quote, b. Bridge unescapes \" -> ".
22
+ it "unescapes \\\" to real double-quote when unboxing length-1 character" do
23
+ v = R::Support.eval('"a\\\\\\"b"')
24
+ expect(v).to be_a(R::Object)
25
+ s = v >> 0
26
+ expect(s).to eq 'a"b'
27
+ end
28
+
29
+ it "unescapes both \\n and \\\" in one string" do
30
+ # R string with a, \n, b, \", c -> Ruby "a\nb\"c"
31
+ v = R::Support.eval('"a\\\\nb\\\\\\"c"')
32
+ expect(v).to be_a(R::Object)
33
+ s = v >> 0
34
+ expect(s).to eq "a\nb\"c"
35
+ end
36
+ end
37
+
38
+ context "plain strings unchanged" do
39
+ it "leaves strings without backslash escapes unchanged" do
40
+ v = R::Support.eval('"hello"')
41
+ expect((v >> 0)).to eq "hello"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'galaaz'
4
+
5
+ module ScopedSymbolDslWithUsing
6
+ using Galaaz::SymbolDSL
7
+
8
+ def self.build_expr
9
+ :a + :b + 5
10
+ end
11
+
12
+ def self.fetch_symbol
13
+ ~:letters
14
+ end
15
+ end
16
+
17
+ module ScopedSymbolDslWithoutUsing
18
+ def self.build_expr
19
+ :a + :b + 5
20
+ end
21
+ end
22
+
23
+ describe 'Scoped Symbol DSL refinement' do
24
+ it 'enables symbol expression DSL inside lexical using scope' do
25
+ expr = ScopedSymbolDslWithUsing.build_expr
26
+ expect(expr).to be_a(R::Language)
27
+ expect(expr.to_s).to eq('a + b + 5L')
28
+ end
29
+
30
+ it 'enables unary symbol fetch inside lexical using scope' do
31
+ vec = ScopedSymbolDslWithUsing.fetch_symbol
32
+ expect(vec).to be_a(R::Vector)
33
+ expect(vec[1]).to eq('a')
34
+ end
35
+
36
+ it 'does not enable symbol expression DSL outside using scope' do
37
+ expect { ScopedSymbolDslWithoutUsing.build_expr }.to raise_error(NoMethodError)
38
+ end
39
+ end
40
+
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'galaaz'
4
+
5
+ describe 'Session env bridge helpers' do
6
+ it 'ensures, assigns, gets, and removes values in a session-scoped env' do
7
+ bridge = R.bridge
8
+ skip 'session env API available only on NewBridge adapter' unless bridge.respond_to?(:ensure_session_env)
9
+
10
+ sid = "spec_sid_#{Time.now.to_i}_#{rand(1000)}"
11
+ key = 'tmp_value'
12
+
13
+ expect(bridge.ensure_session_env(sid)).to eq(nil)
14
+
15
+ bridge.assign_session(sid, key, '42L')
16
+ got = bridge.get_session(sid, key)
17
+ expect(got['kind'].to_s).to eq('integer')
18
+ expect(got['value']).to eq(42)
19
+
20
+ bridge.rm_session(sid, key)
21
+ expect do
22
+ bridge.get_session(sid, key)
23
+ end.to raise_error(NewBridge::SessionClient::RProcessError)
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ describe 'SimpleCov bootstrap' do
2
+ it 'loads SimpleCov when available' do
3
+ if Gem.loaded_specs.key?('simplecov')
4
+ expect(defined?(SimpleCov)).to eq('constant')
5
+ expect(SimpleCov.running).to eq(true)
6
+ else
7
+ skip('simplecov gem is not available in this environment')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start do
5
+ add_filter '/specs/'
6
+ add_filter '/new_bridge_specs/'
7
+ end
8
+ rescue LoadError
9
+ # Keep spec bootstrap working even if simplecov is unavailable locally.
10
+ end
data/specs/tmp.rb CHANGED
File without changes