galaaz 0.4.10 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/LICENSE +0 -0
- data/README.md +3123 -882
- data/Rakefile +62 -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 +223 -6
- data/bin/gknit-draft +105 -0
- data/bin/gknit-draft.rb +28 -0
- data/bin/gknit_Rscript +127 -0
- data/bin/grun +27 -1
- data/bin/gstudio +49 -4
- data/bin/{gstudio.rb → gstudio_irb.rb} +0 -0
- data/bin/gstudio_pry.rb +7 -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 +364 -0
- 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 +52 -55
- data/blogs/gknit/gknit.md +94 -94
- 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 +1582 -196
- data/blogs/manual/manual.log +1786 -0
- data/blogs/manual/manual.md +3107 -890
- data/blogs/manual/manual.tex +3018 -1086
- 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 +41 -0
- data/blogs/nse_dplyr/nse_dplyr.Rmd +277 -151
- data/blogs/nse_dplyr/nse_dplyr.log +928 -0
- data/blogs/nse_dplyr/nse_dplyr.md +457 -293
- 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 +1808 -228
- 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 -103
- 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 +50 -0
- data/examples/Bibliography/stats.bib +72 -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/Makefile +16 -0
- data/examples/latex_templates/Test-acm_article/Test-acm_article.Rmd +65 -0
- data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +1670 -0
- data/examples/latex_templates/Test-acm_article/sensys-abstract.cls +703 -0
- data/examples/latex_templates/Test-acm_article/sigproc.bib +59 -0
- data/examples/latex_templates/Test-acs_article/Test-acs_article.Rmd +260 -0
- data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +11 -0
- data/examples/latex_templates/Test-acs_article/acs-my_output.bib +11 -0
- data/examples/latex_templates/Test-acs_article/acstest.bib +17 -0
- data/examples/latex_templates/Test-aea_article/AEA.cls +1414 -0
- data/{blogs/gknit/marshal.dump → examples/latex_templates/Test-aea_article/BibFile.bib} +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +108 -0
- data/examples/latex_templates/Test-aea_article/aea.bst +1269 -0
- data/examples/latex_templates/Test-aea_article/multicol.sty +853 -0
- data/examples/latex_templates/Test-aea_article/references.bib +0 -0
- data/examples/latex_templates/Test-aea_article/setspace.sty +546 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +256 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +3397 -0
- data/examples/latex_templates/Test-ams_article/Test-ams_article.Rmd +215 -0
- data/examples/latex_templates/Test-ams_article/amstest.bib +436 -0
- data/examples/latex_templates/Test-asa_article/Test-asa_article.Rmd +153 -0
- data/examples/latex_templates/Test-asa_article/agsm.bst +1353 -0
- data/examples/latex_templates/Test-asa_article/bibliography.bib +233 -0
- data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +2409 -0
- data/examples/latex_templates/Test-ieee_article/IEEEtran.cls +6346 -0
- data/examples/latex_templates/Test-ieee_article/Test-ieee_article.Rmd +175 -0
- data/examples/latex_templates/Test-ieee_article/mybibfile.bib +20 -0
- data/examples/latex_templates/Test-rjournal_article/RJournal.sty +335 -0
- data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +18 -0
- data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +52 -0
- data/examples/latex_templates/Test-springer_article/Test-springer_article.Rmd +65 -0
- data/examples/latex_templates/Test-springer_article/bibliography.bib +26 -0
- data/examples/latex_templates/Test-springer_article/spbasic.bst +1658 -0
- data/examples/latex_templates/Test-springer_article/spmpsci.bst +1512 -0
- data/examples/latex_templates/Test-springer_article/spphys.bst +1443 -0
- data/examples/latex_templates/Test-springer_article/svglov3.clo +113 -0
- data/examples/latex_templates/Test-springer_article/svjour3.cls +1431 -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 +73 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +382 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +164 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +92 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +482 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +280 -0
- data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +386 -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 +4 -4
- data/lib/R_interface/r_methods.rb +13 -116
- 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 +1 -0
- data/lib/R_interface/rsupport.rb +610 -331
- 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 +111 -0
- data/lib/gknit/include_engine.rb +15 -7
- data/lib/gknit/knitr_engine.rb +223 -107
- data/lib/gknit/rb_engine.rb +3 -3
- data/lib/gknit/ruby_engine.rb +0 -0
- data/lib/gknit.rb +3 -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 -46
- 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 +41 -20
- 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 +239 -71
- data/blogs/galaaz_ggplot/galaaz_ggplot.aux +0 -41
- data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -705
- data/blogs/galaaz_ggplot/galaaz_ggplot.out +0 -10
- data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-latex/midwest_rb.pdf +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-latex/scatter_plot_rb.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/gknit/gknit.tex +0 -1358
- data/blogs/manual/graph.rb +0 -29
- data/blogs/manual/manual.html +0 -2995
- 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 -960
- data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
- data/blogs/nse_dplyr/nse_dplyr.tex +0 -1373
- data/blogs/oh_my/oh_my.html +0 -680
- data/blogs/ruby_plot/ruby_plot.Rmd_external_figs +0 -662
- data/blogs/ruby_plot/ruby_plot.html +0 -729
- data/blogs/ruby_plot/ruby_plot.pdf +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.svg +0 -57
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.svg +0 -106
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.svg +0 -110
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.svg +0 -174
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.svg +0 -236
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.svg +0 -296
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.svg +0 -236
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.svg +0 -218
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.svg +0 -128
- data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.svg +0 -150
- data/examples/paper/paper.rb +0 -36
- 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 -315
data/lib/R_interface/robject.rb
CHANGED
|
@@ -1,351 +1,409 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
##########################################################################################
|
|
4
|
-
# @author Rodrigo Botafogo
|
|
1
|
+
# robject.rb
|
|
5
2
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# licensing agreement, is hereby granted, provided that the above copyright notice, this
|
|
9
|
-
# paragraph and the following two paragraphs appear in all copies, modifications, and
|
|
10
|
-
# distributions.
|
|
3
|
+
# R::Object is the Ruby proxy for an R value. It inherits from BasicObject so that most
|
|
4
|
+
# method calls (e.g. .dim, .names, .length) are forwarded to R via method_missing.
|
|
11
5
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
6
|
+
# Each instance holds @r_interop (the R-side handle, e.g. "g2_v42") and optionally
|
|
7
|
+
# @expression (source expression for Language objects). Object.build(...) turns a handle
|
|
8
|
+
# into the appropriate subclass: DataFrame, Matrix, Vector, List, Closure, RSymbol,
|
|
9
|
+
# RExpression, or a plain Object for other R types. Handles "rb_obj_*" are unwrapped
|
|
10
|
+
# to the stored Ruby object; R NULL becomes Ruby nil.
|
|
16
11
|
#
|
|
17
|
-
# RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
18
|
-
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
|
19
|
-
# SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
|
20
|
-
# RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
|
21
|
-
# OR MODIFICATIONS.
|
|
22
|
-
##########################################################################################
|
|
23
|
-
|
|
24
12
|
require_relative 'r_methods'
|
|
25
13
|
|
|
26
14
|
module R
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
class Object < BasicObject
|
|
16
|
+
include IndexedObject
|
|
17
|
+
include BinaryOperators
|
|
18
|
+
include ExecBinOp
|
|
19
|
+
include UnaryOperators
|
|
20
|
+
include ExecUniOp
|
|
21
|
+
|
|
22
|
+
# Methods we explicitly define (Phase A / BasicObject). respond_to?(sym) is true for these and for any symbol we forward to R.
|
|
23
|
+
EXPLICIT_RUBY_SURFACE = [
|
|
24
|
+
:r_interop, :expression, :expression=,
|
|
25
|
+
:[], :[]=, :>>, :unboxed_get, :to_ruby, :to_i, :to_ary, :length, :size,
|
|
26
|
+
:class, :to_s, :rclass, :typeof, :inspect, :object_id, :__id__,
|
|
27
|
+
:==, :equal?, :call, :nil?, :pretty_print, :send,
|
|
28
|
+
:instance_variable_set, :instance_variable_get,
|
|
29
|
+
:is_a?, :kind_of?, :instance_of?, :respond_to?,
|
|
30
|
+
:method_missing
|
|
31
|
+
].freeze
|
|
31
32
|
|
|
32
|
-
class Object
|
|
33
|
-
|
|
34
33
|
attr_reader :r_interop
|
|
35
|
-
attr_accessor :
|
|
36
|
-
|
|
37
|
-
#--------------------------------------------------------------------------------------
|
|
38
|
-
#
|
|
39
|
-
#--------------------------------------------------------------------------------------
|
|
34
|
+
attr_accessor :expression
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
# Delegate to Kernel#instance_variable_set so that instance vars work despite BasicObject.
|
|
37
|
+
def instance_variable_set(name, value)
|
|
38
|
+
::Object.instance_method(:instance_variable_set).bind(self).call(name, value)
|
|
43
39
|
end
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# [FALSE]
|
|
49
|
-
#--------------------------------------------------------------------------------------
|
|
50
|
-
|
|
51
|
-
def ==(other_object)
|
|
52
|
-
res =
|
|
53
|
-
R::Support.exec_function_name('identical', @r_interop,
|
|
54
|
-
R::Support.parse_arg(other_object))
|
|
55
|
-
return nil if (res.length >> 0) == 0
|
|
56
|
-
res >> 0
|
|
41
|
+
# Delegate to Kernel#instance_variable_get so that instance vars work despite BasicObject.
|
|
42
|
+
def instance_variable_get(name)
|
|
43
|
+
::Object.instance_method(:instance_variable_get).bind(self).call(name)
|
|
57
44
|
end
|
|
58
45
|
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def eql(other_object)
|
|
64
|
-
# exec_bin_oper("`==`", other_object)
|
|
65
|
-
R::Support.exec_function_name("`==`", @r_interop,
|
|
66
|
-
R::Support.parse_arg(other_object))
|
|
46
|
+
# BasicObject lacks Kernel#send; provide Ruby dispatch explicitly so calls like
|
|
47
|
+
# obj.send(:mpg) do not get forwarded to R as send(obj, mpg).
|
|
48
|
+
def send(method_name, *args, &block)
|
|
49
|
+
::Object.instance_method(:send).bind(self).call(method_name, *args, &block)
|
|
67
50
|
end
|
|
68
|
-
|
|
69
|
-
#--------------------------------------------------------------------------------------
|
|
70
|
-
# @param r_interop [Interop] pointer to an R object
|
|
71
|
-
# @return the R object wrapped in a Ruby class
|
|
72
|
-
#--------------------------------------------------------------------------------------
|
|
73
|
-
|
|
74
|
-
def self.build(r_interop)
|
|
75
|
-
|
|
76
|
-
# if the value is actually not an r_interop, then just return it: native Ruby
|
|
77
|
-
# object
|
|
78
|
-
if (!Truffle::Interop.foreign?(r_interop))
|
|
79
|
-
# puts "I'm native"
|
|
80
|
-
return r_interop
|
|
81
|
-
# a matrix is also a vector... test should come before
|
|
82
|
-
elsif (R::Support.eval("is.matrix").call(r_interop) == true)
|
|
83
|
-
# puts "1"
|
|
84
|
-
R::Matrix.new(r_interop)
|
|
85
|
-
elsif (R::Support.eval("is.atomic").call(r_interop) == true)
|
|
86
|
-
# puts "2"
|
|
87
|
-
Vector.new(r_interop)
|
|
88
|
-
elsif (R::Support.eval("is.function").call(r_interop) == true)
|
|
89
|
-
# puts "3"
|
|
90
|
-
Closure.new(r_interop)
|
|
91
|
-
elsif (R::Support.eval("is.data.frame").call(r_interop) == true)
|
|
92
|
-
# puts "4"
|
|
93
|
-
DataFrame.new(r_interop)
|
|
94
|
-
elsif (R::Support.eval("is.list").call(r_interop) == true)
|
|
95
|
-
# puts "5"
|
|
96
|
-
List.new(r_interop)
|
|
97
|
-
elsif (R::Support.eval("typeof").call(r_interop) == "language")
|
|
98
|
-
# @TODO: tests are passing both when we use Language.new
|
|
99
|
-
# and RExpression.new. Check what should be and write
|
|
100
|
-
# discriminating tests.
|
|
101
|
-
# print "robject buid: language\n"
|
|
102
|
-
# R::Support.print_foreign(r_interop)
|
|
103
|
-
# puts "6"
|
|
104
|
-
Language.new(r_interop)
|
|
105
|
-
# RExpression.new(r_interop)
|
|
106
|
-
elsif (R::Support.eval("typeof").call(r_interop) == "expression")
|
|
107
|
-
# puts "7"
|
|
108
|
-
RExpression.new(r_interop)
|
|
109
|
-
elsif (R::Support.eval("typeof").call(r_interop) == "name")
|
|
110
|
-
# puts "8"
|
|
111
|
-
p "i'm of type name"
|
|
112
|
-
Name.new(r_interop)
|
|
113
|
-
elsif (R::Support.eval("typeof").call(r_interop) == "symbol")
|
|
114
|
-
# puts "9"
|
|
115
|
-
RSymbol.new(r_interop)
|
|
116
|
-
elsif (R::Support.eval("typeof").call(r_interop) == "environment")
|
|
117
|
-
# puts "10"
|
|
118
|
-
Environment.new(r_interop)
|
|
119
|
-
else # Generic type
|
|
120
|
-
# puts "11"
|
|
121
|
-
p "Generic type: #{R::Support.eval("typeof").call(r_interop).to_s}"
|
|
122
|
-
r_interop
|
|
123
|
-
end
|
|
124
51
|
|
|
52
|
+
# R objects are never nil; R NULL is converted to Ruby nil in Object.build.
|
|
53
|
+
def nil?
|
|
54
|
+
false
|
|
125
55
|
end
|
|
126
56
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def method_missing(symbol, *args, &block)
|
|
132
|
-
name = R::Support.convert_symbol2r(symbol)
|
|
133
|
-
|
|
134
|
-
# Need to raise a NoMethodError when method_missing is called by an implicit
|
|
135
|
-
# call to "to_ary". The explanation for that is:
|
|
136
|
-
# Okay, I've found the source of the behaviour. IOOperations.puts will attempt to
|
|
137
|
-
# coerce an argument to an array and print its contents, and R::Vector responds to
|
|
138
|
-
# to_ary but returns the empty array which results in no output.
|
|
139
|
-
#
|
|
140
|
-
# Previously IOOperations.puts only checked the type of the argument, and did not
|
|
141
|
-
# attempt coercion, but that meant we didn't match MRI's behaviour and had some test
|
|
142
|
-
# failures in other gems. I'd suggest either removing the to_ary methods on
|
|
143
|
-
# R::Object and R::Vector or implementing them more fully. I see from the comments on
|
|
144
|
-
# those methods that you needed them for RSpec, it might worth seeing if those problems
|
|
145
|
-
# still occur and we can look a better way to resolve those.
|
|
146
|
-
raise NoMethodError if name == "to_ary"
|
|
147
|
-
|
|
148
|
-
case
|
|
149
|
-
when block_given?
|
|
150
|
-
R::Support.new_scope(symbol, self, *args, &block)
|
|
151
|
-
when name =~ /(.*)=$/
|
|
152
|
-
method_missing_assign($1, args[0])
|
|
153
|
-
when name == "eval"
|
|
154
|
-
# R function 'eval' needs to be called in a special way, since it expects
|
|
155
|
-
# the second argument to be an environment. If the arguments are packed
|
|
156
|
-
# into a list, then there is no second argument and the function fails to
|
|
157
|
-
# use the second argument as environment
|
|
158
|
-
R::Support.r_evaluate(@r_interop, *args)
|
|
159
|
-
when args.length == 0
|
|
160
|
-
# no arguments: 2 options: either a named item of the object or apply the function
|
|
161
|
-
# to the object
|
|
162
|
-
# if name is a named item of the object, then return the named item
|
|
163
|
-
named = R::Support.eval("`%in%`").
|
|
164
|
-
call(name, R::Support.eval("names").call(@r_interop))
|
|
165
|
-
(false === named || !(true === named || named[0])) ?
|
|
166
|
-
R::Support.exec_function_name(name, @r_interop) :
|
|
167
|
-
R::Support.exec_function_name("`[[`", @r_interop, name)
|
|
168
|
-
else
|
|
169
|
-
args.unshift(@r_interop)
|
|
170
|
-
R::Support.exec_function_name(name, *args)
|
|
171
|
-
end
|
|
172
|
-
|
|
57
|
+
# Used by pp/inspect-style pretty printing.
|
|
58
|
+
def pretty_print(pp)
|
|
59
|
+
pp.text(inspect)
|
|
173
60
|
end
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
# @param args [Array] The first element of the array is an R infix function, the other
|
|
179
|
-
# arguments are the list of arguments for the function.
|
|
180
|
-
#----------------------------------------------------------------------------------------
|
|
181
|
-
|
|
182
|
-
def _(*args)
|
|
183
|
-
name = "`%#{args.shift.to_s}%`"
|
|
184
|
-
args.unshift(@r_interop)
|
|
185
|
-
R::Support.exec_function_name(name, *args)
|
|
61
|
+
|
|
62
|
+
def initialize(r_interop, expression = nil)
|
|
63
|
+
@r_interop = r_interop
|
|
64
|
+
@expression = expression
|
|
186
65
|
end
|
|
187
66
|
|
|
188
|
-
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
# @param [Interop] Interop pointer to R function
|
|
193
|
-
# @param [Array] Array of arguments
|
|
194
|
-
#--------------------------------------------------------------------------------------
|
|
195
|
-
|
|
196
|
-
def setR(method, *args)
|
|
197
|
-
@r_interop = R::Support.exec_function_i(method, @r_interop, *args)
|
|
198
|
-
self
|
|
67
|
+
# Number of R `class()` probes issued from Object.build (missing r_class and no usable wrapper_tag).
|
|
68
|
+
# Reset with reset_build_counters! before measuring. See docs/performance_plan.md Phase 2.
|
|
69
|
+
def self.build_class_probe_count
|
|
70
|
+
@build_class_probe_count ||= 0
|
|
199
71
|
end
|
|
200
72
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
73
|
+
def self.reset_build_counters!
|
|
74
|
+
@build_class_probe_count = 0
|
|
75
|
+
end
|
|
204
76
|
|
|
205
|
-
def
|
|
206
|
-
|
|
207
|
-
setR(method, *args)
|
|
208
|
-
self
|
|
77
|
+
def self.increment_build_class_probe_count!
|
|
78
|
+
@build_class_probe_count = build_class_probe_count + 1
|
|
209
79
|
end
|
|
210
80
|
|
|
211
|
-
|
|
212
|
-
#
|
|
213
|
-
#
|
|
214
|
-
|
|
81
|
+
# Factory: build the right Ruby wrapper for an R value. Returns a subclass (DataFrame, Vector, etc.),
|
|
82
|
+
# or the unwrapped Ruby value for rb_obj_* handles and for R NULL. Pass r_class to avoid an R class() call.
|
|
83
|
+
# Pass wrapper_tag from the new-bridge envelope to classify without string-matching r_class and to allow
|
|
84
|
+
# probe-free builds when r_class is absent but tag is present (non-+other+).
|
|
85
|
+
def self.build(r_interop, expression = nil, r_class: nil, wrapper_tag: nil)
|
|
86
|
+
# Ruby object handles stored in R: unwrap to the original Ruby object.
|
|
87
|
+
if r_interop.is_a?(::String) && r_interop.start_with?("rb_obj_")
|
|
88
|
+
return ::R::Support.get_ruby_object(r_interop)
|
|
89
|
+
end
|
|
215
90
|
|
|
216
|
-
|
|
217
|
-
|
|
91
|
+
# If we got a basic Ruby type, it's already unboxed
|
|
92
|
+
return r_interop if r_interop.is_a?(::Numeric) || r_interop.is_a?(::TrueClass) ||
|
|
93
|
+
r_interop.is_a?(::FalseClass) || r_interop.nil? || r_interop.is_a?(::Symbol)
|
|
94
|
+
|
|
95
|
+
if r_interop.is_a?(::String) && r_interop.start_with?("g2_v")
|
|
96
|
+
return new(r_interop, expression) unless ::R.bridge.ready?
|
|
97
|
+
|
|
98
|
+
begin
|
|
99
|
+
rc_in = r_class
|
|
100
|
+
rc = r_class.to_s.strip
|
|
101
|
+
rc = nil if rc.nil? || rc.empty?
|
|
102
|
+
tag = wrapper_tag.to_s.strip
|
|
103
|
+
tag = nil if tag.nil? || tag.empty?
|
|
104
|
+
|
|
105
|
+
# Probe only when we have no class string and no definitive wrapper tag.
|
|
106
|
+
if rc.nil? && (!tag || tag == "other")
|
|
107
|
+
rc = class_probe_fetch_r_class(r_interop)
|
|
108
|
+
elsif rc.nil? && tag && tag != "other"
|
|
109
|
+
# Envelope-style path: tag is enough; avoid class() round-trip.
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
return nil if rc && rc.strip == "NULL"
|
|
113
|
+
|
|
114
|
+
if ::ENV['GALAAZ_DEBUG']
|
|
115
|
+
::Kernel.puts "DEBUG: Object.build r_interop=#{r_interop.inspect} r_class_arg=#{rc_in.inspect} r_class=#{rc.inspect} wrapper_tag=#{tag.inspect}"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
if tag && tag != "other"
|
|
119
|
+
obj = build_from_wrapper_tag(r_interop, expression, tag, r_class_hint: rc)
|
|
120
|
+
if obj
|
|
121
|
+
::Kernel.puts "DEBUG: Object.build returning #{obj.class}" if ::ENV['GALAAZ_DEBUG']
|
|
122
|
+
return obj
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
if rc.nil?
|
|
127
|
+
rc = class_probe_fetch_r_class(r_interop)
|
|
128
|
+
return nil if rc.strip == "NULL"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
obj = build_from_r_class_string(r_interop, expression, rc)
|
|
132
|
+
::Kernel.puts "DEBUG: Object.build returning #{obj.class}" if ::ENV['GALAAZ_DEBUG']
|
|
133
|
+
obj
|
|
134
|
+
rescue => e
|
|
135
|
+
::Kernel.puts "DEBUG: Object.build rescue: #{e.message}" if ::ENV['GALAAZ_DEBUG']
|
|
136
|
+
new(r_interop, expression)
|
|
137
|
+
end
|
|
138
|
+
else
|
|
139
|
+
# Fallback for already unboxed or unexpected strings
|
|
140
|
+
r_interop
|
|
141
|
+
end
|
|
218
142
|
end
|
|
219
143
|
|
|
220
|
-
def
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
self
|
|
144
|
+
def self.class_probe_fetch_r_class(r_interop)
|
|
145
|
+
increment_build_class_probe_count!
|
|
146
|
+
::R.bridge.eval_r("paste(class(#{r_interop}), collapse=' ')").gsub(/^\[1\] /, "").gsub(/"/, "").strip
|
|
224
147
|
end
|
|
225
|
-
|
|
226
|
-
#--------------------------------------------------------------------------------------
|
|
227
|
-
#
|
|
228
|
-
#--------------------------------------------------------------------------------------
|
|
229
148
|
|
|
230
|
-
def
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
R::Support.exec_function_name("class", @r_interop)
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
#--------------------------------------------------------------------------------------
|
|
239
|
-
#
|
|
240
|
-
#--------------------------------------------------------------------------------------
|
|
149
|
+
def self.build_from_wrapper_tag(r_interop, expression, tag, r_class_hint: nil)
|
|
150
|
+
# typeof(formula) is language in R, but class is "formula"; keep plain R::Object (legacy semantics).
|
|
151
|
+
if tag == "language" && r_class_hint && r_class_hint.include?("formula")
|
|
152
|
+
return nil
|
|
153
|
+
end
|
|
241
154
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
155
|
+
case tag
|
|
156
|
+
when "data_frame"
|
|
157
|
+
::R::DataFrame.new(r_interop, expression)
|
|
158
|
+
when "matrix"
|
|
159
|
+
::R::Matrix.new(r_interop, expression)
|
|
160
|
+
when "vector"
|
|
161
|
+
v = ::R::Vector.new(r_interop)
|
|
162
|
+
v.expression = expression if expression
|
|
163
|
+
v
|
|
164
|
+
when "list"
|
|
165
|
+
::R::List.new(r_interop, expression)
|
|
166
|
+
when "environment"
|
|
167
|
+
::R::Environment.new(r_interop, expression)
|
|
168
|
+
when "closure"
|
|
169
|
+
::R::Closure.new(r_interop, expression)
|
|
170
|
+
when "language"
|
|
171
|
+
::R::Language.new(r_interop, expression)
|
|
172
|
+
when "symbol"
|
|
173
|
+
::R::RSymbol.new(r_interop, expression)
|
|
174
|
+
else
|
|
175
|
+
nil
|
|
176
|
+
end
|
|
248
177
|
end
|
|
249
|
-
|
|
250
|
-
#--------------------------------------------------------------------------------------
|
|
251
|
-
#
|
|
252
|
-
#--------------------------------------------------------------------------------------
|
|
253
178
|
|
|
254
|
-
def
|
|
255
|
-
|
|
179
|
+
def self.build_from_r_class_string(r_interop, expression, r_class)
|
|
180
|
+
case
|
|
181
|
+
when r_class.include?("data.frame") || r_class.include?("tbl_df")
|
|
182
|
+
::R::DataFrame.new(r_interop, expression)
|
|
183
|
+
when r_class.include?("matrix") || r_class.include?("array")
|
|
184
|
+
::R::Matrix.new(r_interop, expression)
|
|
185
|
+
when r_class.include?("numeric") || r_class.include?("integer") ||
|
|
186
|
+
r_class.include?("logical") || r_class.include?("character")
|
|
187
|
+
v = ::R::Vector.new(r_interop)
|
|
188
|
+
v.expression = expression if expression
|
|
189
|
+
v
|
|
190
|
+
when r_class.include?("list")
|
|
191
|
+
::R::List.new(r_interop, expression)
|
|
192
|
+
when r_class.include?("environment")
|
|
193
|
+
::R::Environment.new(r_interop, expression)
|
|
194
|
+
when r_class.include?("function")
|
|
195
|
+
::R::Closure.new(r_interop, expression)
|
|
196
|
+
when r_class.include?("language") || r_class == "call"
|
|
197
|
+
::R::Language.new(r_interop, expression)
|
|
198
|
+
when r_class == "name" || r_class == "symbol"
|
|
199
|
+
::R::RSymbol.new(r_interop, expression)
|
|
200
|
+
when r_class == "expression"
|
|
201
|
+
::R::RExpression.new(r_interop, expression)
|
|
202
|
+
else
|
|
203
|
+
::Kernel.puts "DEBUG: Object.build fell through to else (r_class=#{r_class.inspect})" if ::ENV['GALAAZ_DEBUG']
|
|
204
|
+
new(r_interop, expression)
|
|
205
|
+
end
|
|
256
206
|
end
|
|
257
207
|
|
|
258
|
-
|
|
259
|
-
|
|
208
|
+
# Printed representation of the R object (as R would print it).
|
|
209
|
+
def to_s
|
|
210
|
+
return super unless ::R.bridge.ready?
|
|
211
|
+
::R.bridge.print_r(@r_interop)
|
|
260
212
|
end
|
|
261
|
-
|
|
262
|
-
#--------------------------------------------------------------------------------------
|
|
263
|
-
#
|
|
264
|
-
#--------------------------------------------------------------------------------------
|
|
265
213
|
|
|
266
|
-
|
|
267
|
-
|
|
214
|
+
# Phase B: BasicObject has no class; we must define it.
|
|
215
|
+
def class
|
|
216
|
+
::R::Object
|
|
268
217
|
end
|
|
269
218
|
|
|
270
|
-
|
|
271
|
-
|
|
219
|
+
# true for EXPLICIT_RUBY_SURFACE and for any other symbol (forwarded to R via method_missing).
|
|
220
|
+
def respond_to?(sym, include_private = false)
|
|
221
|
+
sym = sym.to_sym
|
|
222
|
+
return true if EXPLICIT_RUBY_SURFACE.include?(sym)
|
|
223
|
+
true
|
|
272
224
|
end
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
# since we need to call a method and the method changes the object, then we need to
|
|
279
|
-
# change our internal pointer also @r_interop. Ideally, just setting the row.names
|
|
280
|
-
# should work.
|
|
281
|
-
def row__names=(names_vector)
|
|
282
|
-
setR_name("`row.names<-`", names_vector)
|
|
225
|
+
|
|
226
|
+
# Type check against Ruby modules/classes (e.g. obj.is_a?(R::DataFrame)).
|
|
227
|
+
def is_a?(mod)
|
|
228
|
+
return false unless mod.is_a?(::Module)
|
|
229
|
+
!!(self.class <= mod)
|
|
283
230
|
end
|
|
231
|
+
alias_method :kind_of?, :is_a?
|
|
284
232
|
|
|
285
|
-
|
|
286
|
-
|
|
233
|
+
# Exact class check (e.g. obj.instance_of?(R::Object)).
|
|
234
|
+
def instance_of?(mod)
|
|
235
|
+
return false unless mod.is_a?(::Module)
|
|
236
|
+
self.class == mod
|
|
287
237
|
end
|
|
288
|
-
|
|
289
|
-
#--------------------------------------------------------------------------------------
|
|
290
|
-
#
|
|
291
|
-
#--------------------------------------------------------------------------------------
|
|
292
238
|
|
|
293
|
-
|
|
294
|
-
|
|
239
|
+
# Debug string: class, object id, and @r_interop handle.
|
|
240
|
+
def inspect
|
|
241
|
+
"#<#{self.class}:#{__id__.to_s(16)} @r_interop=#{@r_interop.inspect}>"
|
|
295
242
|
end
|
|
296
243
|
|
|
297
|
-
|
|
298
|
-
|
|
244
|
+
alias_method :object_id, :__id__
|
|
245
|
+
|
|
246
|
+
# R's class() of this object; unwrapped to a single string when length 1.
|
|
247
|
+
def rclass
|
|
248
|
+
res = ::R::Support.exec_function("class", self)
|
|
249
|
+
val = res.respond_to?(:>>) ? (res >> nil) : res
|
|
250
|
+
val.is_a?(::Array) ? val[0] : val
|
|
299
251
|
end
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
value = (R::Support.interop(value) ? value.r_interop : value)
|
|
307
|
-
# setR(@@set_attr, which, value)
|
|
308
|
-
setR_name("`attr<-`", which, value)
|
|
252
|
+
|
|
253
|
+
# R's typeof() of this object; unwrapped to a single string when length 1.
|
|
254
|
+
def typeof
|
|
255
|
+
res = ::R::Support.exec_function("typeof", self)
|
|
256
|
+
val = res.respond_to?(:>>) ? (res >> nil) : res
|
|
257
|
+
val.is_a?(::Array) ? val[0] : val
|
|
309
258
|
end
|
|
310
|
-
|
|
311
|
-
#--------------------------------------------------------------------------------------
|
|
312
|
-
#
|
|
313
|
-
#--------------------------------------------------------------------------------------
|
|
314
259
|
|
|
315
|
-
|
|
316
|
-
|
|
260
|
+
# Unbox this R object to a Ruby value. Recurses until only Ruby values (no R::Object).
|
|
261
|
+
# Plain R::Object: re-evaluates handle; if list (typeof=="list") iterates [[i]] and recurses;
|
|
262
|
+
# if atomic uses [[index+1]] and result protocol (never uses $ on atomic). Raises UnboxDepthError when depth exceeded.
|
|
263
|
+
def unboxed_get(index = nil, depth = 0)
|
|
264
|
+
if depth >= ::R::Support::MAX_UNBOX_DEPTH
|
|
265
|
+
::Kernel.raise(::R::UnboxDepthError, "unbox: list too deep (max depth #{::R::Support::MAX_UNBOX_DEPTH} exceeded)")
|
|
266
|
+
end
|
|
267
|
+
val = ::R::Support.eval(@r_interop)
|
|
268
|
+
return val unless val.is_a?(::R::Object)
|
|
269
|
+
return val.unboxed_get(index, depth + 1) if val.class.instance_method(:unboxed_get).owner != ::R::Object
|
|
270
|
+
|
|
271
|
+
handle = @r_interop.to_s
|
|
272
|
+
safe_handle = handle =~ /\Ag2_v\d+\z/
|
|
273
|
+
|
|
274
|
+
# Whole object (index.nil?): plain Object may be a list in R — use typeof/length, never $
|
|
275
|
+
if index.nil?
|
|
276
|
+
type_str = self.typeof.to_s.strip
|
|
277
|
+
len_obj = self.length
|
|
278
|
+
n = len_obj.respond_to?(:unboxed_get) ? len_obj.unboxed_get(0) : len_obj
|
|
279
|
+
n = n.to_i if n.respond_to?(:to_i)
|
|
280
|
+
if type_str == "list" && n.is_a?(::Integer) && n >= 1
|
|
281
|
+
list_handle = handle
|
|
282
|
+
unless safe_handle
|
|
283
|
+
list_handle = ::R::Support.generate_var_name
|
|
284
|
+
::R.bridge.eval_r("#{list_handle} <- #{::R::Support.parse_arg(self)}")
|
|
285
|
+
end
|
|
286
|
+
arr = []
|
|
287
|
+
(1..n).each do |i|
|
|
288
|
+
elt = ::R::Support.eval("#{list_handle}[[#{i}]]")
|
|
289
|
+
if elt.nil?
|
|
290
|
+
arr << nil
|
|
291
|
+
elsif !elt.is_a?(::R::Object)
|
|
292
|
+
arr << elt
|
|
293
|
+
else
|
|
294
|
+
arr << (elt.is__null.unboxed_get(0) ? nil : elt.unboxed_get(nil, depth + 1))
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
return arr
|
|
298
|
+
end
|
|
299
|
+
# Atomic (or length 0): treat as single element for consistency
|
|
300
|
+
index = 0
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
idx = index + 1
|
|
304
|
+
r_code = safe_handle ? "#{handle}[[#{idx}]]" : nil
|
|
305
|
+
unless r_code
|
|
306
|
+
var = ::R::Support.generate_var_name
|
|
307
|
+
::R.bridge.eval_r("#{var} <- #{::R::Support.parse_arg(self)}")
|
|
308
|
+
r_code = "#{var}[[#{idx}]]"
|
|
309
|
+
end
|
|
310
|
+
val2 = ::R::Support.eval(r_code)
|
|
311
|
+
return val2 unless val2.is_a?(::R::Object)
|
|
312
|
+
return val2.unboxed_get(nil, depth + 1) if val2.class.instance_method(:unboxed_get).owner != ::R::Object
|
|
313
|
+
|
|
314
|
+
# Plain R::Object single element: use result protocol until scalar or Vector/List
|
|
315
|
+
r_code = "#{val2.r_interop}[[1]]"
|
|
316
|
+
max_plain = ::R::Support::MAX_UNBOX_DEPTH - depth
|
|
317
|
+
loop do
|
|
318
|
+
var = ::R::Support.generate_var_name
|
|
319
|
+
assignment = "#{var} <- #{r_code}"
|
|
320
|
+
envelope = ::R.bridge.eval_r_with_result(assignment)
|
|
321
|
+
raise "Result protocol: no envelope (buffer missing or invalid)" unless envelope
|
|
322
|
+
case envelope[:type]
|
|
323
|
+
when :scalar_double, :scalar_integer, :scalar_logical, :scalar_symbol
|
|
324
|
+
return envelope[:value]
|
|
325
|
+
when :scalar_character
|
|
326
|
+
v = envelope[:value]
|
|
327
|
+
return (v.is_a?(::String) && v =~ /^rb_obj_\d+$/) ? ::R::Support.get_ruby_object(v) : v
|
|
328
|
+
when :handle
|
|
329
|
+
obj = ::R::Object.build(envelope[:handle], nil, r_class: envelope[:r_class], wrapper_tag: envelope[:wrapper_tag])
|
|
330
|
+
unless obj.instance_of?(::R::Object)
|
|
331
|
+
return obj.unboxed_get(nil, depth + 1)
|
|
332
|
+
end
|
|
333
|
+
r_code = "#{envelope[:handle]}[[1]]"
|
|
334
|
+
max_plain -= 1
|
|
335
|
+
if max_plain <= 0
|
|
336
|
+
::Kernel.raise(::R::UnboxDepthError, "unbox: list too deep (max depth #{::R::Support::MAX_UNBOX_DEPTH} exceeded)")
|
|
337
|
+
end
|
|
338
|
+
else
|
|
339
|
+
raise "Result protocol: unknown envelope type #{envelope[:type].inspect}"
|
|
340
|
+
end
|
|
341
|
+
end
|
|
317
342
|
end
|
|
318
343
|
|
|
319
|
-
|
|
320
|
-
#
|
|
321
|
-
|
|
344
|
+
# Unbox via >>: same as unboxed_get so (self >> nil) and (self >> 0) work.
|
|
345
|
+
# << is kept as a compatibility alias for older Galaaz docs/examples.
|
|
346
|
+
alias_method :>>, :unboxed_get
|
|
347
|
+
alias_method :<<, :unboxed_get
|
|
348
|
+
|
|
349
|
+
# Unboxing semantics (>> nil / to_ruby / unboxed_get(nil)): recurse until result contains only Ruby
|
|
350
|
+
# values (Integer, Float, String, true/false, Array, nil). List → Array (single list → [x]).
|
|
351
|
+
# Atomic length 1 → scalar; length > 1 → Array. Can be expensive for large/deep structures.
|
|
352
|
+
# Raises R::UnboxDepthError when recursion exceeds MAX_UNBOX_DEPTH.
|
|
322
353
|
|
|
323
|
-
|
|
324
|
-
|
|
354
|
+
# Simple way to get a Ruby value: (self >> nil). For length-1 vectors returns the scalar; for longer returns array.
|
|
355
|
+
def to_ruby
|
|
356
|
+
self >> nil
|
|
325
357
|
end
|
|
326
|
-
|
|
327
|
-
#--------------------------------------------------------------------------------------
|
|
328
|
-
#
|
|
329
|
-
#--------------------------------------------------------------------------------------
|
|
330
358
|
|
|
331
|
-
|
|
359
|
+
# Unbox length-1 numeric (or string digits) to Integer without forwarding to R (R has no to_i).
|
|
360
|
+
# Callback procs often use x.to_i when R passes scalars as R::Object.
|
|
361
|
+
def to_i
|
|
362
|
+
v = to_ruby
|
|
363
|
+
v = v.first if v.is_a?(::Array) && v.size == 1
|
|
364
|
+
case v
|
|
365
|
+
when ::Integer then v
|
|
366
|
+
when ::Float then v.to_i
|
|
367
|
+
when ::String then Integer(v)
|
|
368
|
+
else
|
|
369
|
+
Integer(v)
|
|
370
|
+
end
|
|
371
|
+
end
|
|
332
372
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
373
|
+
# Return nil so RSpec/eq and array conversion don't forward to_ary to R (plain Object is not array-like).
|
|
374
|
+
def to_ary
|
|
375
|
+
nil
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# Equality: R::Object vs R::Object uses all.equal; vs Ruby scalar uses unboxed value(s).
|
|
379
|
+
def ==(other)
|
|
380
|
+
return true if self.equal?(other)
|
|
381
|
+
if other.is_a?(::R::Object)
|
|
382
|
+
res = ::R.bridge.eval_r("isTRUE(all.equal(#{@r_interop}, #{other.r_interop}))")
|
|
383
|
+
return res == "[1] TRUE"
|
|
384
|
+
elsif other.is_a?(::Numeric) || other.is_a?(::String) || other.is_a?(::TrueClass) ||
|
|
385
|
+
other.is_a?(::FalseClass) || other.nil? || other.is_a?(::Symbol)
|
|
386
|
+
# DataFrame/Matrix etc. are not equal to a scalar even if they contain that value (e.g. row['mpg'] != 21.0).
|
|
387
|
+
return false if self.class == ::R::DataFrame || self.class == ::R::Matrix
|
|
388
|
+
val = (self >> nil)
|
|
389
|
+
if val.is_a?(::Array)
|
|
390
|
+
return val[0] == other if val.size == 1
|
|
391
|
+
return val.include?(other) if other.is_a?(::String)
|
|
339
392
|
end
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
puts e
|
|
393
|
+
return val == other
|
|
394
|
+
else
|
|
395
|
+
super
|
|
344
396
|
end
|
|
345
|
-
|
|
346
397
|
end
|
|
347
398
|
|
|
348
|
-
|
|
399
|
+
# Call this object as an R function with the given args (e.g. obj.call(1, 2)).
|
|
400
|
+
def call(*args)
|
|
401
|
+
::R::Support.exec_function(self, *args)
|
|
402
|
+
end
|
|
349
403
|
|
|
350
|
-
|
|
404
|
+
# Forward unknown methods to R: process_missing(symbol, self, *args) builds and runs the R call.
|
|
405
|
+
def method_missing(symbol, *args)
|
|
406
|
+
::R::Support.process_missing(symbol, self, *args)
|
|
407
|
+
end
|
|
408
|
+
end
|
|
351
409
|
end
|