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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/LICENSE +0 -0
- data/README.md +1360 -636
- data/Rakefile +61 -41
- data/bin/galaaz-bootstrap +137 -0
- data/bin/galaaz-jruby +14 -0
- data/bin/galaaz_jruby_env.inc.sh +6 -0
- data/bin/gbookdown +64 -0
- data/bin/gknit +84 -13
- data/bin/gknit-draft.rb +0 -0
- data/bin/gstudio +5 -3
- data/bin/gstudio_irb.rb +0 -0
- data/bin/gstudio_pry.rb +0 -0
- data/bin/install-tinytex +6 -0
- data/bin/run_all_rspec +43 -0
- data/bin/run_example +14 -0
- data/bin/run_old_rspec +19 -0
- data/bin/run_rspec +23 -0
- data/bin/run_rspec_subset +38 -0
- data/bin/run_slow_rspec +19 -0
- data/blogs/R-on-Rails-Planning-Document.md +940 -0
- data/blogs/README.md +100 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
- data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.md +115 -155
- data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
- data/blogs/galaaz_ggplot/midwest_external_png +0 -0
- data/blogs/gknit/gknit.Rmd +47 -52
- data/blogs/gknit/gknit.md +1430 -0
- data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
- data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
- data/blogs/gknit/lst.rds +0 -0
- data/blogs/gknit/model.rb +1 -1
- data/blogs/gknit/stats.bib +0 -0
- data/blogs/manual/include_model_local_repro.Rmd +14 -0
- data/blogs/manual/include_model_local_repro.md +75 -0
- data/blogs/manual/lst.rds +0 -0
- data/blogs/manual/manual.Rmd +852 -239
- data/blogs/manual/manual.log +1786 -0
- data/blogs/manual/manual.md +1360 -636
- data/blogs/manual/manual.tex +1883 -1161
- data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
- data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
- data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
- data/blogs/manual/model.rb +1 -1
- data/blogs/nse_dplyr/nse_dplyr.Rmd +84 -111
- data/blogs/nse_dplyr/nse_dplyr.log +928 -0
- data/blogs/nse_dplyr/nse_dplyr.md +198 -229
- data/blogs/oh_my/not_so.rb +0 -0
- data/blogs/oh_my/oh_my.Rmd +1234 -25
- data/blogs/oh_my/oh_my.log +804 -0
- data/blogs/oh_my/oh_my.md +1663 -86
- data/blogs/oh_my/oh_my.tex +821 -0
- data/blogs/oh_my/old.Rmd +15 -14
- data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
- data/blogs/ruby_plot/ruby_plot.log +885 -0
- data/blogs/ruby_plot/ruby_plot.md +71 -102
- data/blogs/ruby_plot/ruby_plot.tex +940 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
- data/blogs/test/test.Rmd +14 -0
- data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
- data/examples/50Plots_MasterList/ScatterPlot.rb +0 -0
- data/examples/50Plots_MasterList/scatter_plot.rb +0 -0
- data/examples/Bibliography/master.bib +0 -0
- data/examples/Bibliography/stats.bib +0 -0
- data/examples/R/calc.R +0 -0
- data/examples/R/java_interop.R +0 -0
- data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
- data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +53 -0
- data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +33 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
- data/examples/islr/all.rb +13 -0
- data/examples/islr/ch2.spec.rb +37 -7
- data/examples/islr/ch3.spec.rb +11 -2
- data/examples/islr/ch3_boston.rb +27 -0
- data/examples/islr/ch3_multiple_regression.rb +0 -0
- data/examples/islr/ch6.spec.rb +24 -1
- data/examples/islr/x_y_rnorm.jpg +0 -0
- data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +0 -0
- data/examples/latex_templates/Test-acm_article/sigproc.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-my_output.bib +0 -0
- data/examples/latex_templates/Test-aea_article/BibFile.bib +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +0 -0
- data/examples/latex_templates/Test-aea_article/references.bib +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +0 -0
- data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +0 -0
- data/examples/latex_templates/Test-ieee_article/mybibfile.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJournal.sty +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +0 -0
- data/examples/misc/baseball.csv +0 -0
- data/examples/misc/ggplot.rb +3 -2
- data/examples/misc/moneyball.rb +0 -0
- data/examples/misc/subsetting.rb +0 -0
- data/examples/multithread_shards_to_r/shards_to_r.rb +67 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +0 -0
- data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +0 -0
- data/examples/sthda_ggplot/README.md +0 -0
- data/examples/sthda_ggplot/RUN.md +41 -0
- data/examples/sthda_ggplot/all.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +2 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/stat.rb +0 -0
- data/examples/sthda_ggplot/one_variable_discrete/bar.rb +0 -0
- data/examples/sthda_ggplot/qplots/box_violin_dot.rb +0 -0
- data/examples/sthda_ggplot/qplots/scatter_plots.rb +0 -0
- data/examples/sthda_ggplot/scatter_gg.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +4 -3
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +0 -0
- data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +0 -0
- data/ext/new_bridge/Makefile +46 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
- data/lib/R_interface/galaaz_device.R +20 -0
- data/lib/R_interface/include_engine.R +109 -0
- data/lib/R_interface/new_bridge_adapter.rb +824 -0
- data/lib/R_interface/r.rb +177 -25
- data/lib/R_interface/r_arrow.rb +113 -0
- data/lib/R_interface/r_libs.R +3 -3
- data/lib/R_interface/r_methods.rb +13 -126
- data/lib/R_interface/r_module_s.rb +0 -0
- data/lib/R_interface/rbinary_operators.rb +20 -2
- data/lib/R_interface/rclosure.rb +5 -1
- data/lib/R_interface/rdata_frame.rb +34 -70
- data/lib/R_interface/rdevice.rb +125 -0
- data/lib/R_interface/rdevices.R +0 -0
- data/lib/R_interface/renvironment.rb +10 -4
- data/lib/R_interface/rexpression.rb +5 -1
- data/lib/R_interface/rindexed_object.rb +41 -13
- data/lib/R_interface/rlanguage.rb +20 -62
- data/lib/R_interface/rlist.rb +115 -25
- data/lib/R_interface/rlogical_operators.rb +0 -0
- data/lib/R_interface/rmatrix.rb +2 -11
- data/lib/R_interface/rmd_indexed_object.rb +5 -1
- data/lib/R_interface/robject.rb +348 -290
- data/lib/R_interface/rpkg.rb +0 -0
- data/lib/R_interface/rsupport.rb +609 -328
- data/lib/R_interface/rsupport_scope.rb +2 -1
- data/lib/R_interface/rsymbol.rb +50 -0
- data/lib/R_interface/ruby_callback.rb +2 -3
- data/lib/R_interface/ruby_extensions.rb +225 -175
- data/lib/R_interface/runary_operators.rb +0 -0
- data/lib/R_interface/rvector.rb +147 -31
- data/lib/galaaz.rb +0 -0
- data/lib/galaaz_jruby.rb +22 -0
- data/lib/gknit/diagnostics.rb +50 -0
- data/lib/gknit/draft.rb +23 -17
- data/lib/gknit/include_engine.rb +15 -7
- data/lib/gknit/knitr_engine.rb +223 -74
- data/lib/gknit/rb_engine.rb +3 -3
- data/lib/gknit/ruby_engine.rb +0 -0
- data/lib/gknit.rb +1 -0
- data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
- data/lib/new_bridge/envelope.rb +51 -0
- data/lib/new_bridge/eval_result.rb +26 -0
- data/lib/new_bridge/framing.rb +39 -0
- data/lib/new_bridge/instance_pool_client.rb +38 -0
- data/lib/new_bridge/r_instance_manager.rb +404 -0
- data/lib/new_bridge/session_client.rb +530 -0
- data/lib/new_bridge/tcp_framed.rb +44 -0
- data/lib/new_bridge.rb +9 -0
- data/lib/util/exec_ruby.rb +95 -20
- data/lib/util/inline_file.rb +35 -30
- data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
- data/new_bridge_specs/eval_r_async_spec.rb +113 -0
- data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
- data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
- data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
- data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
- data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
- data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
- data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
- data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
- data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
- data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
- data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
- data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
- data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
- data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
- data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
- data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
- data/r_requires/ggplot.rb +0 -0
- data/r_requires/knitr.rb +0 -0
- data/specs/all.rb +15 -11
- data/specs/arrow_from_ruby_batches_spec.rb +50 -0
- data/specs/arrow_semantics_spec.rb +64 -0
- data/specs/bridge_concurrent_spec.rb +46 -0
- data/specs/bridge_nested_spec.rb +25 -0
- data/specs/dataframe_semantics_spec.rb +122 -0
- data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
- data/specs/dispatch_probe_cache_spec.rb +38 -0
- data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
- data/specs/dispatch_probe_fallback_spec.rb +18 -0
- data/specs/environment_semantics_spec.rb +89 -0
- data/specs/field_access_spec.rb +31 -0
- data/specs/figures/bg.jpeg +0 -0
- data/specs/figures/bg.png +0 -0
- data/specs/figures/bg.svg +168 -57
- data/specs/figures/dose_len.png +0 -0
- data/specs/figures/no_args.jpeg +0 -0
- data/specs/figures/no_args.png +0 -0
- data/specs/figures/no_args.svg +168 -57
- data/specs/figures/width_height.jpeg +0 -0
- data/specs/figures/width_height.png +0 -0
- data/specs/figures/width_height_units1.jpeg +0 -0
- data/specs/figures/width_height_units1.png +0 -0
- data/specs/figures/width_height_units2.jpeg +0 -0
- data/specs/figures/width_height_units2.png +0 -0
- data/specs/formula_semantics_spec.rb +81 -0
- data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
- data/specs/galaaz_util_inline_file_spec.rb +54 -0
- data/specs/gknit_cli_option_permutation_spec.rb +24 -0
- data/specs/gknit_include_engine_spec.rb +72 -0
- data/specs/gknit_install_timeout_report_spec.rb +69 -0
- data/specs/gknit_internal_error_report_spec.rb +57 -0
- data/specs/gknit_vector_map_output_spec.rb +59 -0
- data/specs/globalenv_guardrail_spec.rb +52 -0
- data/specs/language_expression_semantics_spec.rb +145 -0
- data/specs/list_semantics_spec.rb +111 -0
- data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
- data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
- data/specs/new_bridge_callback_timeout_spec.rb +69 -0
- data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
- data/specs/nil_null_spec.rb +42 -0
- data/specs/object_build_phase2_spec.rb +53 -0
- data/specs/phase1_callback_bridge_spec.rb +84 -0
- data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
- data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
- data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
- data/specs/plot_device_semantics_spec.rb +28 -0
- data/specs/plot_snapshot_semantics_spec.rb +58 -0
- data/specs/protocol_result_spec.rb +236 -0
- data/specs/r_batch_fail_fast_spec.rb +47 -0
- data/specs/r_bridge_bootstrap_spec.rb +11 -0
- data/specs/r_devices.spec.rb +1 -1
- data/specs/r_eval.spec.rb +16 -18
- data/specs/r_function.spec.rb +1 -1
- data/specs/r_instance_manager_spec.rb +285 -0
- data/specs/r_list_apply.spec.rb +15 -15
- data/specs/r_matrix.spec.rb +0 -0
- data/specs/r_nse.spec.rb +5 -5
- data/specs/r_object_send_dispatch_spec.rb +13 -0
- data/specs/r_vector_comparator_spec.rb +8 -0
- data/specs/r_vector_creation.spec.rb +0 -0
- data/specs/r_vector_functions.spec.rb +0 -0
- data/specs/r_vector_object.spec.rb +0 -0
- data/specs/r_vector_operators.spec.rb +0 -0
- data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
- data/specs/r_vector_subsetting.spec.rb +0 -0
- data/specs/range_helper_spec.rb +21 -0
- data/specs/rsupport_scope_spec.rb +28 -0
- data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
- data/specs/scalar_character_spec.rb +44 -0
- data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
- data/specs/session_env_bridge_spec.rb +25 -0
- data/specs/simplecov_bootstrap_spec.rb +10 -0
- data/specs/spec_helper.rb +10 -0
- data/specs/tmp.rb +0 -0
- data/specs/unboxing_recursion_regression_spec.rb +30 -0
- data/specs/unboxing_spec.rb +49 -0
- data/specs/verify_callbacks.rb +42 -0
- data/sty/galaaz.sty +0 -0
- data/version.rb +1 -1
- metadata +194 -64
- data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -520
- data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
- data/blogs/galaaz_ggplot/midwest.html +0 -188
- data/blogs/gknit/gknit.html +0 -2266
- data/blogs/gknit/gknit.pdf +0 -0
- data/blogs/manual/manual.html +0 -4638
- data/blogs/manual/manual.pdf +0 -0
- data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
- data/blogs/nse_dplyr/nse_dplyr.html +0 -878
- data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
- data/blogs/oh_my/oh_my.html +0 -568
- data/blogs/ruby_plot/ruby_plot.html +0 -544
- data/blogs/ruby_plot/ruby_plot.pdf +0 -0
- data/examples/latex_templates/Test-acs_article/Test-acs_article.pdf +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/pics/Figure2.pdf +0 -0
- data/examples/latex_templates/Test-asa_article/Test-asa_article.pdf +0 -0
- data/examples/latex_templates/Test-ieee_article/Test-ieee_article.pdf +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJwrapper.pdf +0 -0
- data/examples/latex_templates/Test-springer_article/Test-springer_article.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.pdf +0 -0
- data/specs/r_dataframe.spec.rb +0 -379
- data/specs/r_environment.spec.rb +0 -140
- data/specs/r_formula.spec.rb +0 -232
- data/specs/r_language.spec.rb +0 -112
- data/specs/r_list.spec.rb +0 -293
- data/specs/r_plots.spec.rb +0 -72
- data/specs/ruby_expression.spec.rb +0 -316
data/lib/util/exec_ruby.rb
CHANGED
|
@@ -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
|
-
#
|
|
83
|
-
|
|
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
|
|
87
|
-
# the list
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
# RChunk.instance_eval(code) if (options[["eval"]]
|
|
102
|
-
eval(code, RCbinding, __FILE__, __LINE__ + 1) if (options
|
|
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
|
-
#
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
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
|
-
|
|
124
|
-
out_list = R.c(out_list,
|
|
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.
|
|
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,7 +206,9 @@ module GalaazUtil
|
|
|
133
206
|
$stdout = STDOUT
|
|
134
207
|
end
|
|
135
208
|
|
|
136
|
-
|
|
209
|
+
# include=FALSE must still execute code (knitr semantics). Output suppression is handled
|
|
210
|
+
# at engine emission stage, not here.
|
|
211
|
+
out_list
|
|
137
212
|
|
|
138
213
|
end
|
|
139
214
|
|
data/lib/util/inline_file.rb
CHANGED
|
@@ -24,22 +24,20 @@
|
|
|
24
24
|
module GalaazUtil
|
|
25
25
|
|
|
26
26
|
#========================================================================================
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# @param relative [String]
|
|
32
|
-
#
|
|
33
|
-
# @
|
|
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
|
-
|
|
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
|
-
|
|
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}/#{
|
|
52
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.3 callback argument compatibility on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_3_callback_args_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.3 integration callback args (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
R.bridge.eval_r('call_with_arg <- function(f, x) { f(x) }')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'passes a numeric scalar argument from R into Ruby callback' do
|
|
17
|
+
result = R.call_with_arg(proc { |x| x.to_i + 1 }, 41)
|
|
18
|
+
expect(result).to be_a(R::Object)
|
|
19
|
+
expect(result.to_ruby).to eq(42.0)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'passes a character scalar argument from R into Ruby callback' do
|
|
23
|
+
result = R.call_with_arg(proc { |x| x.to_ruby.to_s.upcase == 'ABC' ? 1 : 0 }, 'abc')
|
|
24
|
+
expect(result).to be_a(R::Object)
|
|
25
|
+
expect(result.to_ruby).to eq(1.0)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|