enclave 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +182 -0
- data/Rakefile +30 -0
- data/ext/enclave/enclave.c +390 -0
- data/ext/enclave/extconf.rb +33 -0
- data/ext/enclave/mruby/Makefile +63 -0
- data/ext/enclave/mruby/Rakefile +102 -0
- data/ext/enclave/mruby/benchmark/bm_ao_render.rb +309 -0
- data/ext/enclave/mruby/benchmark/bm_app_lc_fizzbuzz.rb +51 -0
- data/ext/enclave/mruby/benchmark/bm_fib.rb +6 -0
- data/ext/enclave/mruby/benchmark/bm_mandel_term.rb +34 -0
- data/ext/enclave/mruby/benchmark/bm_so_lists.rb +49 -0
- data/ext/enclave/mruby/benchmark/bm_so_mandelbrot.rb +65 -0
- data/ext/enclave/mruby/benchmark/vm_dispatch_bench.c +197 -0
- data/ext/enclave/mruby/benchmark/vm_optimization_bench.rb +513 -0
- data/ext/enclave/mruby/build/host/include/mrbconf.h +230 -0
- data/ext/enclave/mruby/build/host/include/mruby/array.h +303 -0
- data/ext/enclave/mruby/build/host/include/mruby/boxing_nan.h +169 -0
- data/ext/enclave/mruby/build/host/include/mruby/boxing_no.h +59 -0
- data/ext/enclave/mruby/build/host/include/mruby/boxing_word.h +248 -0
- data/ext/enclave/mruby/build/host/include/mruby/class.h +157 -0
- data/ext/enclave/mruby/build/host/include/mruby/common.h +127 -0
- data/ext/enclave/mruby/build/host/include/mruby/compile.h +187 -0
- data/ext/enclave/mruby/build/host/include/mruby/data.h +76 -0
- data/ext/enclave/mruby/build/host/include/mruby/debug.h +75 -0
- data/ext/enclave/mruby/build/host/include/mruby/dump.h +159 -0
- data/ext/enclave/mruby/build/host/include/mruby/endian.h +44 -0
- data/ext/enclave/mruby/build/host/include/mruby/error.h +168 -0
- data/ext/enclave/mruby/build/host/include/mruby/gc.h +77 -0
- data/ext/enclave/mruby/build/host/include/mruby/hash.h +234 -0
- data/ext/enclave/mruby/build/host/include/mruby/internal.h +278 -0
- data/ext/enclave/mruby/build/host/include/mruby/irep.h +142 -0
- data/ext/enclave/mruby/build/host/include/mruby/istruct.h +50 -0
- data/ext/enclave/mruby/build/host/include/mruby/khash.h +455 -0
- data/ext/enclave/mruby/build/host/include/mruby/mempool.h +19 -0
- data/ext/enclave/mruby/build/host/include/mruby/numeric.h +174 -0
- data/ext/enclave/mruby/build/host/include/mruby/object.h +44 -0
- data/ext/enclave/mruby/build/host/include/mruby/opcode.h +73 -0
- data/ext/enclave/mruby/build/host/include/mruby/ops.h +133 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym/id.h +895 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym/scanning.h +82 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym/table.h +1787 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym.h +65 -0
- data/ext/enclave/mruby/build/host/include/mruby/proc.h +184 -0
- data/ext/enclave/mruby/build/host/include/mruby/range.h +77 -0
- data/ext/enclave/mruby/build/host/include/mruby/re.h +16 -0
- data/ext/enclave/mruby/build/host/include/mruby/string.h +428 -0
- data/ext/enclave/mruby/build/host/include/mruby/throw.h +81 -0
- data/ext/enclave/mruby/build/host/include/mruby/value.h +471 -0
- data/ext/enclave/mruby/build/host/include/mruby/variable.h +108 -0
- data/ext/enclave/mruby/build/host/include/mruby/version.h +143 -0
- data/ext/enclave/mruby/build/host/include/mruby.h +1632 -0
- data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/id.h +281 -0
- data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/table.h +559 -0
- data/ext/enclave/mruby/build/host/mrbgems/gem_init.c +164 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-array-ext/gem_init.c +650 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-binding/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-catch/gem_init.c +86 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-class-ext/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-compar-ext/gem_init.c +99 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-complex/gem_init.c +362 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-data/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-chain/gem_init.c +229 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-ext/gem_init.c +1420 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-lazy/gem_init.c +602 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enumerator/gem_init.c +822 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-eval/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-fiber/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-hash-ext/gem_init.c +591 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-kernel-ext/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-math/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-metaprog/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-method/gem_init.c +153 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-numeric-ext/gem_init.c +211 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-object-ext/gem_init.c +94 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-objectspace/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-pack/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-binding/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-ext/gem_init.c +237 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-random/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-range-ext/gem_init.c +205 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-rational/gem_init.c +147 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-set/gem_init.c +487 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-sprintf/gem_init.c +83 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-string-ext/gem_init.c +220 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-struct/gem_init.c +175 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-symbol-ext/gem_init.c +153 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-time/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-toplevel-ext/gem_init.c +78 -0
- data/ext/enclave/mruby/build/host/mrblib/mrblib.c +1758 -0
- data/ext/enclave/mruby/build_config/ArduinoDue.rb +72 -0
- data/ext/enclave/mruby/build_config/IntelEdison.rb +69 -0
- data/ext/enclave/mruby/build_config/IntelGalileo.rb +88 -0
- data/ext/enclave/mruby/build_config/RX630.rb +63 -0
- data/ext/enclave/mruby/build_config/android_arm64_v8a.rb +11 -0
- data/ext/enclave/mruby/build_config/android_armeabi_v7a_neon_hard.rb +13 -0
- data/ext/enclave/mruby/build_config/bench.rb +11 -0
- data/ext/enclave/mruby/build_config/boxing.rb +19 -0
- data/ext/enclave/mruby/build_config/chipKITMax32.rb +68 -0
- data/ext/enclave/mruby/build_config/ci/gcc-clang.rb +40 -0
- data/ext/enclave/mruby/build_config/ci/msvc.rb +20 -0
- data/ext/enclave/mruby/build_config/clang-asan.rb +11 -0
- data/ext/enclave/mruby/build_config/cosmopolitan.rb +86 -0
- data/ext/enclave/mruby/build_config/cross-32bit.rb +14 -0
- data/ext/enclave/mruby/build_config/cross-mingw-winetest.rb +90 -0
- data/ext/enclave/mruby/build_config/cross-mingw.rb +14 -0
- data/ext/enclave/mruby/build_config/default.rb +83 -0
- data/ext/enclave/mruby/build_config/dreamcast_shelf.rb +81 -0
- data/ext/enclave/mruby/build_config/emscripten-cxx.rb +12 -0
- data/ext/enclave/mruby/build_config/emscripten.rb +10 -0
- data/ext/enclave/mruby/build_config/gameboyadvance.rb +72 -0
- data/ext/enclave/mruby/build_config/helpers/wine_runner.rb +71 -0
- data/ext/enclave/mruby/build_config/host-cxx.rb +12 -0
- data/ext/enclave/mruby/build_config/host-debug.rb +20 -0
- data/ext/enclave/mruby/build_config/host-f32.rb +14 -0
- data/ext/enclave/mruby/build_config/host-gprof.rb +14 -0
- data/ext/enclave/mruby/build_config/host-m32.rb +15 -0
- data/ext/enclave/mruby/build_config/host-nofloat.rb +22 -0
- data/ext/enclave/mruby/build_config/host-shared.rb +36 -0
- data/ext/enclave/mruby/build_config/i586-pc-msdosdjgpp.rb +76 -0
- data/ext/enclave/mruby/build_config/luckfox_pico.rb +106 -0
- data/ext/enclave/mruby/build_config/milkv_duo.rb +106 -0
- data/ext/enclave/mruby/build_config/minimal.rb +4 -0
- data/ext/enclave/mruby/build_config/mrbc.rb +10 -0
- data/ext/enclave/mruby/build_config/nintendo_switch.rb +73 -0
- data/ext/enclave/mruby/build_config/nintendo_wii.rb +95 -0
- data/ext/enclave/mruby/build_config/no-float.rb +17 -0
- data/ext/enclave/mruby/build_config/playstationportable.rb +78 -0
- data/ext/enclave/mruby/build_config/serenity.rb +26 -0
- data/ext/enclave/mruby/build_config.rb +9 -0
- data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb +5 -0
- data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c +23 -0
- data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb +7 -0
- data/ext/enclave/mruby/examples/mrbgems/c_extension_example/src/example.c +23 -0
- data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.c +7 -0
- data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.rb +3 -0
- data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/src/example.c +77 -0
- data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/test/example.c +7 -0
- data/ext/enclave/mruby/examples/mrbgems/mruby-YOUR-bigint/core/bigint.c +70 -0
- data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb +5 -0
- data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/test/example.rb +3 -0
- data/ext/enclave/mruby/include/mrbconf.h +230 -0
- data/ext/enclave/mruby/include/mruby/array.h +303 -0
- data/ext/enclave/mruby/include/mruby/boxing_nan.h +169 -0
- data/ext/enclave/mruby/include/mruby/boxing_no.h +59 -0
- data/ext/enclave/mruby/include/mruby/boxing_word.h +248 -0
- data/ext/enclave/mruby/include/mruby/class.h +157 -0
- data/ext/enclave/mruby/include/mruby/common.h +127 -0
- data/ext/enclave/mruby/include/mruby/compile.h +187 -0
- data/ext/enclave/mruby/include/mruby/data.h +76 -0
- data/ext/enclave/mruby/include/mruby/debug.h +75 -0
- data/ext/enclave/mruby/include/mruby/dump.h +159 -0
- data/ext/enclave/mruby/include/mruby/endian.h +44 -0
- data/ext/enclave/mruby/include/mruby/error.h +168 -0
- data/ext/enclave/mruby/include/mruby/gc.h +77 -0
- data/ext/enclave/mruby/include/mruby/hash.h +234 -0
- data/ext/enclave/mruby/include/mruby/internal.h +278 -0
- data/ext/enclave/mruby/include/mruby/irep.h +142 -0
- data/ext/enclave/mruby/include/mruby/istruct.h +50 -0
- data/ext/enclave/mruby/include/mruby/khash.h +455 -0
- data/ext/enclave/mruby/include/mruby/mempool.h +19 -0
- data/ext/enclave/mruby/include/mruby/numeric.h +174 -0
- data/ext/enclave/mruby/include/mruby/object.h +44 -0
- data/ext/enclave/mruby/include/mruby/opcode.h +73 -0
- data/ext/enclave/mruby/include/mruby/ops.h +133 -0
- data/ext/enclave/mruby/include/mruby/presym/scanning.h +82 -0
- data/ext/enclave/mruby/include/mruby/presym.h +65 -0
- data/ext/enclave/mruby/include/mruby/proc.h +184 -0
- data/ext/enclave/mruby/include/mruby/range.h +77 -0
- data/ext/enclave/mruby/include/mruby/re.h +16 -0
- data/ext/enclave/mruby/include/mruby/string.h +428 -0
- data/ext/enclave/mruby/include/mruby/throw.h +81 -0
- data/ext/enclave/mruby/include/mruby/value.h +471 -0
- data/ext/enclave/mruby/include/mruby/variable.h +108 -0
- data/ext/enclave/mruby/include/mruby/version.h +143 -0
- data/ext/enclave/mruby/include/mruby.h +1632 -0
- data/ext/enclave/mruby/lib/mruby/amalgam.rb +568 -0
- data/ext/enclave/mruby/lib/mruby/build/command.rb +383 -0
- data/ext/enclave/mruby/lib/mruby/build/load_gems.rb +383 -0
- data/ext/enclave/mruby/lib/mruby/build.rb +616 -0
- data/ext/enclave/mruby/lib/mruby/core_ext.rb +61 -0
- data/ext/enclave/mruby/lib/mruby/doc.rb +51 -0
- data/ext/enclave/mruby/lib/mruby/gem.rb +585 -0
- data/ext/enclave/mruby/lib/mruby/lockfile.rb +81 -0
- data/ext/enclave/mruby/lib/mruby/presym.rb +167 -0
- data/ext/enclave/mruby/lib/mruby/source.rb +32 -0
- data/ext/enclave/mruby/mrbgems/default-no-fpu.gembox +3 -0
- data/ext/enclave/mruby/mrbgems/default-no-stdio.gembox +4 -0
- data/ext/enclave/mruby/mrbgems/default.gembox +25 -0
- data/ext/enclave/mruby/mrbgems/full-core.gembox +6 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-dir/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-dir/src/dir_hal.c +193 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-io/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-io/src/io_hal.c +602 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-socket/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-socket/src/socket_hal.c +158 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-task/README.md +102 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-task/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-task/src/task_hal.c +252 -0
- data/ext/enclave/mruby/mrbgems/hal-win-dir/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/hal-win-dir/src/dir_hal.c +249 -0
- data/ext/enclave/mruby/mrbgems/hal-win-io/mrbgem.rake +11 -0
- data/ext/enclave/mruby/mrbgems/hal-win-io/src/io_hal.c +646 -0
- data/ext/enclave/mruby/mrbgems/hal-win-socket/mrbgem.rake +12 -0
- data/ext/enclave/mruby/mrbgems/hal-win-socket/src/socket_hal.c +177 -0
- data/ext/enclave/mruby/mrbgems/hal-win-task/README.md +109 -0
- data/ext/enclave/mruby/mrbgems/hal-win-task/mrbgem.rake +11 -0
- data/ext/enclave/mruby/mrbgems/hal-win-task/src/task_hal.c +187 -0
- data/ext/enclave/mruby/mrbgems/math.gembox +12 -0
- data/ext/enclave/mruby/mrbgems/metaprog.gembox +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/README.md +87 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrblib/array.rb +784 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/src/array.c +1583 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/test/array.rb +849 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/README.md +257 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrblib/benchmark.rb +131 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/test/benchmark.rb +244 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/README-fgmp.md +154 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/README.md +44 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.c +6335 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.h +117 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/test/bigint.rb +157 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/README.md +46 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/mrbgem.rake +49 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config +46 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config.bat +92 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/README.md +63 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb +283 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb +703 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c +523 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h +26 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c +238 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c +88 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h +13 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.c +34 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.h +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c +436 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c +509 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c +71 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c +64 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +768 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h +159 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h +19 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/README.md +94 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb +58 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +808 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.c +1035 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.h +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c +797 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h +132 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c +1118 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h +153 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.c +516 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.h +95 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.c +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.h +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.c +491 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.h +137 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/README.md +58 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/bintest/mrbc.rb +30 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake +15 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +362 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/stub.c +104 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/README.md +47 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb +178 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +380 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/README.md +38 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/bintest/mruby_strip.rb +73 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c +139 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/README.md +256 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/src/binding.c +518 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.c +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.rb +64 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/README.md +94 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/mrblib/catch.rb +29 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/src/catch.c +149 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/test/catch.rb +86 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/README.md +81 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/src/class.c +377 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/class.rb +46 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/module.rb +109 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/README.md +45 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/src/cmath.c +426 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/test/cmath.rb +41 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/README.md +65 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrblib/compar.rb +75 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/test/compar.rb +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/README.md +28 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/codegen.c +7316 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/keywords +52 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/lex.def +207 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/node.h +784 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/parse.y +8977 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/y.tab.c +16136 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/mrbgem.rake +42 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/README.md +55 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/mrblib/complex.rb +259 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/src/complex.c +597 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/test/complex.rb +174 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/README.md +126 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/src/data.c +550 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/test/data.rb +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/README.md +53 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/include/dir_hal.h +79 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/mrbgem.rake +35 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/mrblib/dir.rb +124 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/src/dir.c +493 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/test/dir.rb +138 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/test/dirtest.c +125 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/README.md +96 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/src/encoding.c +128 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/test/numeric.rb +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/test/string.rb +30 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/README.md +80 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrbgem.rake +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrblib/chain.rb +149 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/test/enum_chain.rb +108 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/README.md +487 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb +938 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/test/enum.rb +223 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/README.md +91 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb +363 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb +59 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/README.md +89 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrbgem.rake +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb +861 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/test/enumerator.rb +664 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/README.md +83 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/mrblib/errno.rb +50 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/errno.c +335 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/gen.rb +18 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors.def +156 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors_def.cstub +780 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/test/errno.rb +57 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/README.md +103 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/src/exception.c +143 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.c +60 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.rb +55 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/README.md +26 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/src/eval.c +437 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/test/binding.rb +81 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/test/eval.rb +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-exit/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-exit/src/mruby_exit.c +83 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/src/fiber.c +575 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber.rb +210 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber2.rb +155 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fibertest.c +87 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/README.md +392 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrbgem.rake +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb +408 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/src/hash_ext.c +392 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/test/hash.rb +317 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/README.md +198 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/include/io_hal.h +451 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/include/mruby/io.h +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrbgem.rake +34 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file.rb +109 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file_constants.rb +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/io.rb +303 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/kernel.rb +175 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/file.c +1192 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/file_test.c +403 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/io.c +2260 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/mruby_io_gem.c +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/file.rb +415 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/file_test.rb +112 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/io.rb +668 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/mruby_io_test.c +293 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/README.md +165 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/src/kernel.c +316 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb +134 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/README.md +77 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/src/math.c +753 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/test/math.rb +201 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/README.md +123 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/src/metaprog.c +739 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/test/metaprog.rb +465 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/README.md +66 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/mrblib/method.rb +73 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/src/method.c +890 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/test/method.rb +514 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/README.md +78 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb +125 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c +527 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb +137 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/README.md +144 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrblib/object.rb +33 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/src/object.c +128 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/nil.rb +16 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object.rb +67 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object_ext.c +17 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/README.md +59 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c +188 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/test/objectspace.rb +60 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/README.md +75 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/src/memsize.c +271 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/test/memsize.rb +63 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/README.md +140 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/src/pack.c +2129 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/test/pack.rb +202 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/README.md +140 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/src/proc_binding.c +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.c +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.rb +22 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/README.md +107 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb +130 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/src/proc.c +267 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.c +62 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.rb +130 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/README.md +272 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/src/random.c +608 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/test/random.rb +151 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/README.md +93 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrblib/range.rb +155 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/src/range.c +236 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/test/range.rb +211 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/README.md +61 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/mrblib/rational.rb +66 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/src/rational.c +1269 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/test/rational.rb +316 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/LICENSE +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/README.md +260 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/mrbgem.rake +9 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/mrblib/set.rb +325 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/mruby-set.gem +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/src/set.c +1535 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/test/set.rb +764 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/README.md +29 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/example/sleep.rb +2 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/src/sleep.c +187 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/test/sleep_test.rb +29 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/README.md +56 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/include/socket_hal.h +83 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/mrbgem.rake +37 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/mrblib/socket.rb +1131 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.cstub +480 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.def +172 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/gen.rb +17 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/socket.c +1374 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/addrinfo.rb +91 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/basicsocket.rb +17 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/ipsocket.rb +44 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/socket.rb +38 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/sockettest.c +84 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/tcpsocket.rb +4 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/udpsocket.rb +16 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/unix.rb +130 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/README.md +235 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrblib/string.rb +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/src/sprintf.c +1195 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/test/sprintf.rb +92 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/README.md +140 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/src/strftime.c +119 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/test/strftime.rb +152 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/README.md +886 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrblib/string.rb +166 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/src/string.c +2290 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/numeric.rb +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/range.rb +26 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/string.rb +765 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/README.md +105 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/mrblib/struct.rb +69 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/src/struct.c +812 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/test/struct.rb +303 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/README.md +50 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb +72 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/src/symbol.c +79 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb +55 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/README.md +770 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/inspection.rb +65 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/priority.rb +41 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/producer_consumer.rb +58 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/simple.rb +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/statistics.rb +59 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/suspend_resume.rb +47 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/task_pass.rb +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/include/task.h +143 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/include/task_hal.h +162 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/mrbgem.rake +36 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/src/task.c +1573 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/test/task.rb +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/README.md +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/driver.c +315 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/mrbgem.rake +173 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/vformat.c +151 -0
- data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.c +92 -0
- data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.rb +118 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/README.md +102 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/include/mruby/time.h +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/src/time.c +1739 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/test/time.rb +313 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/README.md +32 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb +23 -0
- data/ext/enclave/mruby/mrbgems/stdlib-ext.gembox +21 -0
- data/ext/enclave/mruby/mrbgems/stdlib-io.gembox +15 -0
- data/ext/enclave/mruby/mrbgems/stdlib.gembox +63 -0
- data/ext/enclave/mruby/mrblib/10error.rb +23 -0
- data/ext/enclave/mruby/mrblib/array.rb +102 -0
- data/ext/enclave/mruby/mrblib/compar.rb +102 -0
- data/ext/enclave/mruby/mrblib/enum.rb +358 -0
- data/ext/enclave/mruby/mrblib/hash.rb +276 -0
- data/ext/enclave/mruby/mrblib/kernel.rb +45 -0
- data/ext/enclave/mruby/mrblib/numeric.rb +160 -0
- data/ext/enclave/mruby/mrblib/range.rb +98 -0
- data/ext/enclave/mruby/mrblib/string.rb +173 -0
- data/ext/enclave/mruby/mrblib/symbol.rb +8 -0
- data/ext/enclave/mruby/oss-fuzz/mruby_fuzzer.c +18 -0
- data/ext/enclave/mruby/oss-fuzz/proto_to_ruby.h +55 -0
- data/ext/enclave/mruby/src/allocf.c +37 -0
- data/ext/enclave/mruby/src/array.c +2302 -0
- data/ext/enclave/mruby/src/backtrace.c +294 -0
- data/ext/enclave/mruby/src/cdump.c +498 -0
- data/ext/enclave/mruby/src/class.c +4394 -0
- data/ext/enclave/mruby/src/codedump.c +693 -0
- data/ext/enclave/mruby/src/debug.c +290 -0
- data/ext/enclave/mruby/src/dump.c +998 -0
- data/ext/enclave/mruby/src/enum.c +30 -0
- data/ext/enclave/mruby/src/error.c +937 -0
- data/ext/enclave/mruby/src/etc.c +421 -0
- data/ext/enclave/mruby/src/fmt_fp.c +372 -0
- data/ext/enclave/mruby/src/gc.c +1610 -0
- data/ext/enclave/mruby/src/hash.c +2355 -0
- data/ext/enclave/mruby/src/init.c +50 -0
- data/ext/enclave/mruby/src/kernel.c +718 -0
- data/ext/enclave/mruby/src/load.c +760 -0
- data/ext/enclave/mruby/src/mempool.c +225 -0
- data/ext/enclave/mruby/src/numeric.c +2420 -0
- data/ext/enclave/mruby/src/numops.c +112 -0
- data/ext/enclave/mruby/src/object.c +883 -0
- data/ext/enclave/mruby/src/print.c +136 -0
- data/ext/enclave/mruby/src/proc.c +572 -0
- data/ext/enclave/mruby/src/range.c +597 -0
- data/ext/enclave/mruby/src/readfloat.c +228 -0
- data/ext/enclave/mruby/src/readint.c +27 -0
- data/ext/enclave/mruby/src/readnum.c +43 -0
- data/ext/enclave/mruby/src/state.c +247 -0
- data/ext/enclave/mruby/src/string.c +3577 -0
- data/ext/enclave/mruby/src/symbol.c +1023 -0
- data/ext/enclave/mruby/src/value_array.h +28 -0
- data/ext/enclave/mruby/src/variable.c +1475 -0
- data/ext/enclave/mruby/src/version.c +17 -0
- data/ext/enclave/mruby/src/vm.c +3696 -0
- data/ext/enclave/mruby/tasks/amalgam.rake +34 -0
- data/ext/enclave/mruby/tasks/benchmark.rake +93 -0
- data/ext/enclave/mruby/tasks/bin.rake +23 -0
- data/ext/enclave/mruby/tasks/core.rake +12 -0
- data/ext/enclave/mruby/tasks/doc.rake +118 -0
- data/ext/enclave/mruby/tasks/install.rake +40 -0
- data/ext/enclave/mruby/tasks/libmruby.rake +90 -0
- data/ext/enclave/mruby/tasks/mrbgems.rake +152 -0
- data/ext/enclave/mruby/tasks/mrblib.rake +29 -0
- data/ext/enclave/mruby/tasks/presym.rake +57 -0
- data/ext/enclave/mruby/tasks/test.rake +84 -0
- data/ext/enclave/mruby/tasks/toolchains/android.rake +228 -0
- data/ext/enclave/mruby/tasks/toolchains/clang.rake +8 -0
- data/ext/enclave/mruby/tasks/toolchains/emscripten.rake +57 -0
- data/ext/enclave/mruby/tasks/toolchains/gcc.rake +74 -0
- data/ext/enclave/mruby/tasks/toolchains/openwrt.rake +32 -0
- data/ext/enclave/mruby/tasks/toolchains/visualcpp.rake +48 -0
- data/ext/enclave/mruby/test/assert.rb +404 -0
- data/ext/enclave/mruby/test/bintest.rb +55 -0
- data/ext/enclave/mruby/test/t/argumenterror.rb +37 -0
- data/ext/enclave/mruby/test/t/array.rb +478 -0
- data/ext/enclave/mruby/test/t/basicobject.rb +10 -0
- data/ext/enclave/mruby/test/t/bs_block.rb +621 -0
- data/ext/enclave/mruby/test/t/bs_literal.rb +38 -0
- data/ext/enclave/mruby/test/t/class.rb +505 -0
- data/ext/enclave/mruby/test/t/codegen.rb +196 -0
- data/ext/enclave/mruby/test/t/comparable.rb +79 -0
- data/ext/enclave/mruby/test/t/ensure.rb +36 -0
- data/ext/enclave/mruby/test/t/enumerable.rb +134 -0
- data/ext/enclave/mruby/test/t/exception.rb +425 -0
- data/ext/enclave/mruby/test/t/false.rb +31 -0
- data/ext/enclave/mruby/test/t/float.rb +296 -0
- data/ext/enclave/mruby/test/t/gc.rb +45 -0
- data/ext/enclave/mruby/test/t/hash.rb +976 -0
- data/ext/enclave/mruby/test/t/indexerror.rb +6 -0
- data/ext/enclave/mruby/test/t/integer.rb +247 -0
- data/ext/enclave/mruby/test/t/iterations.rb +61 -0
- data/ext/enclave/mruby/test/t/kernel.rb +462 -0
- data/ext/enclave/mruby/test/t/lang.rb +74 -0
- data/ext/enclave/mruby/test/t/literals.rb +386 -0
- data/ext/enclave/mruby/test/t/localjumperror.rb +13 -0
- data/ext/enclave/mruby/test/t/methods.rb +138 -0
- data/ext/enclave/mruby/test/t/module.rb +931 -0
- data/ext/enclave/mruby/test/t/nameerror.rb +28 -0
- data/ext/enclave/mruby/test/t/nil.rb +39 -0
- data/ext/enclave/mruby/test/t/nomethoderror.rb +22 -0
- data/ext/enclave/mruby/test/t/numeric.rb +114 -0
- data/ext/enclave/mruby/test/t/object.rb +10 -0
- data/ext/enclave/mruby/test/t/proc.rb +198 -0
- data/ext/enclave/mruby/test/t/range.rb +194 -0
- data/ext/enclave/mruby/test/t/rangeerror.rb +6 -0
- data/ext/enclave/mruby/test/t/regexperror.rb +4 -0
- data/ext/enclave/mruby/test/t/runtimeerror.rb +6 -0
- data/ext/enclave/mruby/test/t/standarderror.rb +6 -0
- data/ext/enclave/mruby/test/t/string.rb +981 -0
- data/ext/enclave/mruby/test/t/superclass.rb +46 -0
- data/ext/enclave/mruby/test/t/symbol.rb +30 -0
- data/ext/enclave/mruby/test/t/syntax.rb +1296 -0
- data/ext/enclave/mruby/test/t/true.rb +31 -0
- data/ext/enclave/mruby/test/t/typeerror.rb +6 -0
- data/ext/enclave/mruby/test/t/unicode.rb +39 -0
- data/ext/enclave/mruby/test/t/vformat.rb +57 -0
- data/ext/enclave/mruby/tools/lrama/LEGAL.md +12 -0
- data/ext/enclave/mruby/tools/lrama/MIT +21 -0
- data/ext/enclave/mruby/tools/lrama/NEWS.md +696 -0
- data/ext/enclave/mruby/tools/lrama/exe/lrama +7 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/bitmap.rb +34 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/command.rb +68 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/context.rb +499 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/derivation.rb +66 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/example.rb +129 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/path.rb +29 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/production_path.rb +19 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/start_path.rb +23 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/state_item.rb +8 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/transition_path.rb +19 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/triple.rb +23 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples.rb +298 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/diagnostics.rb +36 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/digraph.rb +83 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/auxiliary.rb +9 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/binding.rb +67 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/destructor_code.rb +42 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/initial_action_code.rb +36 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/no_reference_code.rb +30 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/printer_code.rb +42 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/rule_action.rb +92 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code.rb +53 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/counter.rb +17 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/destructor.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/error_token.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb +62 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb +40 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb +24 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule.rb +5 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/percent_code.rb +14 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/precedence.rb +13 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/printer.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/reference.rb +16 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule.rb +75 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule_builder.rb +255 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/stdlib.y +122 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbol.rb +105 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols/resolver.rb +301 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols.rb +3 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/type.rb +20 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/union.rb +12 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar.rb +407 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar_validator.rb +37 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/grammar_file.rb +40 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/location.rb +115 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/char.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/ident.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/instantiate_rule.rb +30 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/tag.rb +16 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/user_code.rb +83 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token.rb +70 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer.rb +191 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/logger.rb +21 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/option_parser.rb +169 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/options.rb +28 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/output.rb +459 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/parser.rb +2144 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/report/duration.rb +27 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/report/profile.rb +16 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/report.rb +4 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce.rb +37 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce_reduce_conflict.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/resolved_conflict.rb +31 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift.rb +15 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift_reduce_conflict.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state.rb +433 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/states/item.rb +91 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/states.rb +595 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/states_reporter.rb +362 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/trace_reporter.rb +45 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/version.rb +5 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama.rb +22 -0
- data/ext/enclave/mruby/tools/lrama/template/bison/_yacc.h +71 -0
- data/ext/enclave/mruby/tools/lrama/template/bison/yacc.c +2068 -0
- data/ext/enclave/mruby/tools/lrama/template/bison/yacc.h +40 -0
- data/ext/enclave/sandbox_build_config.rb +15 -0
- data/ext/enclave/sandbox_core.c +722 -0
- data/ext/enclave/sandbox_core.h +87 -0
- data/lib/enclave/result.rb +29 -0
- data/lib/enclave/tool.rb +38 -0
- data/lib/enclave/version.rb +3 -0
- data/lib/enclave.rb +73 -0
- metadata +819 -0
|
@@ -0,0 +1,3696 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** vm.c - virtual machine for mruby
|
|
3
|
+
**
|
|
4
|
+
** See Copyright Notice in mruby.h
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <mruby.h>
|
|
8
|
+
#include <mruby/array.h>
|
|
9
|
+
#include <mruby/class.h>
|
|
10
|
+
#include <mruby/hash.h>
|
|
11
|
+
#include <mruby/irep.h>
|
|
12
|
+
#include <mruby/numeric.h>
|
|
13
|
+
#include <mruby/proc.h>
|
|
14
|
+
#include <mruby/range.h>
|
|
15
|
+
#include <mruby/string.h>
|
|
16
|
+
#include <mruby/variable.h>
|
|
17
|
+
#include <mruby/error.h>
|
|
18
|
+
#include <mruby/opcode.h>
|
|
19
|
+
#include "value_array.h"
|
|
20
|
+
#include <mruby/throw.h>
|
|
21
|
+
#include <mruby/dump.h>
|
|
22
|
+
#include <mruby/internal.h>
|
|
23
|
+
#include <mruby/presym.h>
|
|
24
|
+
|
|
25
|
+
#ifdef MRB_NO_STDIO
|
|
26
|
+
#if defined(__cplusplus)
|
|
27
|
+
extern "C" {
|
|
28
|
+
#endif
|
|
29
|
+
void abort(void);
|
|
30
|
+
#if defined(__cplusplus)
|
|
31
|
+
} /* extern "C" */
|
|
32
|
+
#endif
|
|
33
|
+
#endif
|
|
34
|
+
|
|
35
|
+
#define STACK_INIT_SIZE 128
|
|
36
|
+
#define CALLINFO_INIT_SIZE 32
|
|
37
|
+
|
|
38
|
+
/* Define amount of linear stack growth. */
|
|
39
|
+
#ifndef MRB_STACK_GROWTH
|
|
40
|
+
#define MRB_STACK_GROWTH 128
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
/* Maximum recursive depth. Should be set lower on memory constrained systems. */
|
|
44
|
+
#ifdef __clang__
|
|
45
|
+
#if __has_feature(address_sanitizer) && !defined(__SANITIZE_ADDRESS__)
|
|
46
|
+
#define __SANITIZE_ADDRESS__
|
|
47
|
+
#endif
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
#ifndef MRB_CALL_LEVEL_MAX
|
|
51
|
+
#if defined(__SANITIZE_ADDRESS__)
|
|
52
|
+
#define MRB_CALL_LEVEL_MAX 128
|
|
53
|
+
#else
|
|
54
|
+
#define MRB_CALL_LEVEL_MAX 512
|
|
55
|
+
#endif
|
|
56
|
+
#endif
|
|
57
|
+
|
|
58
|
+
/* Maximum stack depth. Should be set lower on memory constrained systems.
|
|
59
|
+
The value below allows about 60000 recursive calls in the simplest case. */
|
|
60
|
+
#ifndef MRB_STACK_MAX
|
|
61
|
+
#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH)
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
#ifdef VM_DEBUG
|
|
65
|
+
# define DEBUG(x) (x)
|
|
66
|
+
#else
|
|
67
|
+
# define DEBUG(x)
|
|
68
|
+
#endif
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
#ifndef MRB_GC_FIXED_ARENA
|
|
72
|
+
static void
|
|
73
|
+
mrb_gc_arena_shrink(mrb_state *mrb, int idx)
|
|
74
|
+
{
|
|
75
|
+
mrb_gc *gc = &mrb->gc;
|
|
76
|
+
int capa = gc->arena_capa;
|
|
77
|
+
|
|
78
|
+
gc->arena_idx = idx;
|
|
79
|
+
if (idx < capa / 4) {
|
|
80
|
+
capa >>= 2;
|
|
81
|
+
if (capa < MRB_GC_ARENA_SIZE) {
|
|
82
|
+
capa = MRB_GC_ARENA_SIZE;
|
|
83
|
+
}
|
|
84
|
+
if (capa != gc->arena_capa) {
|
|
85
|
+
gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa);
|
|
86
|
+
gc->arena_capa = capa;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
#else
|
|
91
|
+
#define mrb_gc_arena_shrink(mrb, idx) mrb_gc_arena_restore(mrb, idx)
|
|
92
|
+
#endif
|
|
93
|
+
|
|
94
|
+
#define CALL_MAXARGS 15
|
|
95
|
+
#define CALL_VARARGS (CALL_MAXARGS<<4 | CALL_MAXARGS)
|
|
96
|
+
|
|
97
|
+
static inline void
|
|
98
|
+
stack_clear(mrb_value *from, size_t count)
|
|
99
|
+
{
|
|
100
|
+
while (count-- > 0) {
|
|
101
|
+
SET_NIL_VALUE(*from);
|
|
102
|
+
from++;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static inline void
|
|
107
|
+
stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
|
|
108
|
+
{
|
|
109
|
+
if (!src) return;
|
|
110
|
+
memcpy(dst, src, sizeof(mrb_value)*size);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static void
|
|
114
|
+
stack_init(mrb_state *mrb)
|
|
115
|
+
{
|
|
116
|
+
struct mrb_context *c = mrb->c;
|
|
117
|
+
|
|
118
|
+
/* mrb_assert(mrb->stack == NULL); */
|
|
119
|
+
c->stbase = (mrb_value*)mrb_malloc(mrb, STACK_INIT_SIZE * sizeof(mrb_value));
|
|
120
|
+
c->stend = c->stbase + STACK_INIT_SIZE;
|
|
121
|
+
stack_clear(c->stbase, STACK_INIT_SIZE);
|
|
122
|
+
|
|
123
|
+
/* mrb_assert(ci == NULL); */
|
|
124
|
+
static const mrb_callinfo ci_zero = { 0 };
|
|
125
|
+
c->cibase = (mrb_callinfo*)mrb_malloc(mrb, CALLINFO_INIT_SIZE * sizeof(mrb_callinfo));
|
|
126
|
+
c->ciend = c->cibase + CALLINFO_INIT_SIZE;
|
|
127
|
+
c->cibase[0] = ci_zero;
|
|
128
|
+
c->ci = c->cibase;
|
|
129
|
+
c->ci->u.target_class = mrb->object_class;
|
|
130
|
+
c->ci->stack = c->stbase;
|
|
131
|
+
c->ci->vis = 1; /* private (2-bit packed) */
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static inline void
|
|
135
|
+
envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
|
|
136
|
+
{
|
|
137
|
+
mrb_callinfo *ci = mrb->c->cibase;
|
|
138
|
+
ptrdiff_t delta = newbase - oldbase;
|
|
139
|
+
|
|
140
|
+
if (delta == 0) return;
|
|
141
|
+
while (ci <= mrb->c->ci) {
|
|
142
|
+
struct REnv *e = mrb_vm_ci_env(ci);
|
|
143
|
+
|
|
144
|
+
if (e) {
|
|
145
|
+
mrb_assert(e->cxt == mrb->c && MRB_ENV_ONSTACK_P(e));
|
|
146
|
+
mrb_assert(e->stack == ci->stack);
|
|
147
|
+
|
|
148
|
+
e->stack += delta;
|
|
149
|
+
}
|
|
150
|
+
ci->stack += delta;
|
|
151
|
+
ci++;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** def rec; $deep =+ 1; if $deep > 1000; return 0; end; rec; end **/
|
|
156
|
+
|
|
157
|
+
static void
|
|
158
|
+
stack_extend_alloc(mrb_state *mrb, mrb_int room)
|
|
159
|
+
{
|
|
160
|
+
mrb_value *oldbase = mrb->c->stbase;
|
|
161
|
+
size_t oldsize = mrb->c->stend - mrb->c->stbase;
|
|
162
|
+
size_t size = oldsize;
|
|
163
|
+
size_t off = mrb->c->ci->stack ? mrb->c->stend - mrb->c->ci->stack : 0;
|
|
164
|
+
|
|
165
|
+
if (off > size) size = off;
|
|
166
|
+
#ifdef MRB_STACK_EXTEND_DOUBLING
|
|
167
|
+
if ((size_t)room <= size)
|
|
168
|
+
size *= 2;
|
|
169
|
+
else
|
|
170
|
+
size += room;
|
|
171
|
+
#else
|
|
172
|
+
/* Use 1.5x stack growth.
|
|
173
|
+
It is slightly slower than doubling the stack space,
|
|
174
|
+
but it saves memory on small devices. */
|
|
175
|
+
{
|
|
176
|
+
size_t newsize = size + (size >> 1); /* 1.5x growth */
|
|
177
|
+
if (newsize < size + MRB_STACK_GROWTH)
|
|
178
|
+
newsize = size + MRB_STACK_GROWTH;
|
|
179
|
+
if (newsize < size + (size_t)room)
|
|
180
|
+
newsize = size + room;
|
|
181
|
+
size = newsize;
|
|
182
|
+
}
|
|
183
|
+
#endif
|
|
184
|
+
|
|
185
|
+
mrb_value *newstack = (mrb_value*)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
|
|
186
|
+
stack_clear(&(newstack[oldsize]), size - oldsize);
|
|
187
|
+
envadjust(mrb, oldbase, newstack);
|
|
188
|
+
mrb->c->stbase = newstack;
|
|
189
|
+
mrb->c->stend = mrb->c->stbase + size;
|
|
190
|
+
|
|
191
|
+
/* Raise an exception if the new stack size will be too large,
|
|
192
|
+
to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
|
|
193
|
+
if (size > MRB_STACK_MAX) {
|
|
194
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
static inline void
|
|
199
|
+
stack_extend(mrb_state *mrb, mrb_int room)
|
|
200
|
+
{
|
|
201
|
+
if (mrb_unlikely(!mrb->c->ci->stack || mrb->c->ci->stack + room >= mrb->c->stend)) {
|
|
202
|
+
stack_extend_alloc(mrb, room);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @brief Extends the VM stack.
|
|
208
|
+
*
|
|
209
|
+
* This function extends the virtual machine stack to accommodate more values.
|
|
210
|
+
* If the current stack size is insufficient, it reallocates the stack
|
|
211
|
+
* with a larger size.
|
|
212
|
+
*
|
|
213
|
+
* @param mrb The mruby state.
|
|
214
|
+
* @param room The additional number of mrb_value slots required.
|
|
215
|
+
*/
|
|
216
|
+
MRB_API void
|
|
217
|
+
mrb_stack_extend(mrb_state *mrb, mrb_int room)
|
|
218
|
+
{
|
|
219
|
+
stack_extend(mrb, room);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static void
|
|
223
|
+
stack_extend_adjust(mrb_state *mrb, mrb_int room, const mrb_value **argp)
|
|
224
|
+
{
|
|
225
|
+
const struct mrb_context *c = mrb->c;
|
|
226
|
+
ptrdiff_t voff = *argp - c->stbase;
|
|
227
|
+
|
|
228
|
+
if (voff < 0 || voff >= c->stend - c->stbase) {
|
|
229
|
+
stack_extend(mrb, room);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
stack_extend(mrb, room);
|
|
233
|
+
*argp = c->stbase + voff;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
static inline struct REnv*
|
|
238
|
+
uvenv(mrb_state *mrb, mrb_int up)
|
|
239
|
+
{
|
|
240
|
+
const struct RProc *proc = mrb->c->ci->proc;
|
|
241
|
+
|
|
242
|
+
while (up--) {
|
|
243
|
+
proc = proc->upper;
|
|
244
|
+
if (!proc) return NULL;
|
|
245
|
+
}
|
|
246
|
+
struct REnv *e = MRB_PROC_ENV(proc);
|
|
247
|
+
if (e) return e; /* proc has enclosed env */
|
|
248
|
+
return NULL;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
static inline const struct RProc*
|
|
252
|
+
top_proc(mrb_state *mrb, const struct RProc *proc, const struct REnv **envp)
|
|
253
|
+
{
|
|
254
|
+
while (proc->upper) {
|
|
255
|
+
if (MRB_PROC_SCOPE_P(proc) || MRB_PROC_STRICT_P(proc))
|
|
256
|
+
return proc;
|
|
257
|
+
*envp = proc->e.env;
|
|
258
|
+
proc = proc->upper;
|
|
259
|
+
}
|
|
260
|
+
return proc;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
#define CI_PROC_SET(ci, p) do {\
|
|
264
|
+
ci->proc = p;\
|
|
265
|
+
mrb_assert(!p || !MRB_PROC_ALIAS_P(p));\
|
|
266
|
+
ci->pc = (p && !MRB_PROC_CFUNC_P(p) && p->body.irep) ? p->body.irep->iseq : NULL;\
|
|
267
|
+
} while (0)
|
|
268
|
+
|
|
269
|
+
void
|
|
270
|
+
mrb_vm_ci_proc_set(mrb_callinfo *ci, const struct RProc *p)
|
|
271
|
+
{
|
|
272
|
+
CI_PROC_SET(ci, p);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
#define MRB_PROC_RESOLVE_ALIAS(ci, p) do {\
|
|
276
|
+
if (MRB_PROC_ALIAS_P(p)) {\
|
|
277
|
+
(ci)->mid = (p)->body.mid;\
|
|
278
|
+
(p) = (p)->upper;\
|
|
279
|
+
}\
|
|
280
|
+
} while (0)
|
|
281
|
+
|
|
282
|
+
#define CI_TARGET_CLASS(ci) (((ci)->u.env && (ci)->u.env->tt == MRB_TT_ENV)? (ci)->u.env->c : (ci)->u.target_class)
|
|
283
|
+
|
|
284
|
+
struct RClass*
|
|
285
|
+
mrb_vm_ci_target_class(const mrb_callinfo *ci)
|
|
286
|
+
{
|
|
287
|
+
return CI_TARGET_CLASS(ci);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
void
|
|
291
|
+
mrb_vm_ci_target_class_set(mrb_callinfo *ci, struct RClass *tc)
|
|
292
|
+
{
|
|
293
|
+
struct REnv *e = ci->u.env;
|
|
294
|
+
if (e && e->tt == MRB_TT_ENV) {
|
|
295
|
+
e->c = tc;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
ci->u.target_class = tc;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
#define CI_ENV(ci) (((ci)->u.env && (ci)->u.env->tt == MRB_TT_ENV)? (ci)->u.env : NULL)
|
|
303
|
+
|
|
304
|
+
struct REnv*
|
|
305
|
+
mrb_vm_ci_env(const mrb_callinfo *ci)
|
|
306
|
+
{
|
|
307
|
+
return CI_ENV(ci);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
static inline void
|
|
311
|
+
ci_env_set(mrb_callinfo *ci, struct REnv *e)
|
|
312
|
+
{
|
|
313
|
+
if (ci->u.env) {
|
|
314
|
+
if (ci->u.env->tt == MRB_TT_ENV) {
|
|
315
|
+
if (e) {
|
|
316
|
+
e->c = ci->u.env->c;
|
|
317
|
+
ci->u.env = e;
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
ci->u.target_class = ci->u.env->c;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
else if (e) {
|
|
324
|
+
e->c = ci->u.target_class;
|
|
325
|
+
ci->u.env = e;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
ci->u.env = e;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
void
|
|
334
|
+
mrb_vm_ci_env_set(mrb_callinfo *ci, struct REnv *e)
|
|
335
|
+
{
|
|
336
|
+
ci_env_set(ci, e);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
MRB_API void
|
|
340
|
+
mrb_vm_ci_env_clear(mrb_state *mrb, mrb_callinfo *ci)
|
|
341
|
+
{
|
|
342
|
+
struct REnv *e = ci->u.env;
|
|
343
|
+
if (e && e->tt == MRB_TT_ENV) {
|
|
344
|
+
ci->u.target_class = e->c;
|
|
345
|
+
mrb_env_unshare(mrb, e, FALSE);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
#define CINFO_NONE 0 // called method from mruby VM (without C functions)
|
|
350
|
+
#define CINFO_SKIP 1 // ignited mruby VM from C
|
|
351
|
+
#define CINFO_DIRECT 2 // called method from C
|
|
352
|
+
#define CINFO_RESUMED 3 // resumed by `Fiber.yield` (probably the main call is `mrb_fiber_resume()`)
|
|
353
|
+
|
|
354
|
+
#define BLK_PTR(b) ((mrb_proc_p(b)) ? mrb_proc_ptr(b) : NULL)
|
|
355
|
+
|
|
356
|
+
static inline mrb_callinfo*
|
|
357
|
+
cipush(mrb_state *mrb, mrb_int push_stacks, uint8_t cci, struct RClass *target_class,
|
|
358
|
+
const struct RProc *proc, struct RProc *blk, mrb_sym mid, uint16_t argc)
|
|
359
|
+
{
|
|
360
|
+
struct mrb_context *c = mrb->c;
|
|
361
|
+
mrb_callinfo *ci = c->ci + 1;
|
|
362
|
+
|
|
363
|
+
if (ci < c->ciend) {
|
|
364
|
+
c->ci = ci;
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
ptrdiff_t size = ci - c->cibase;
|
|
368
|
+
|
|
369
|
+
if (size >= MRB_CALL_LEVEL_MAX) {
|
|
370
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
|
|
371
|
+
}
|
|
372
|
+
c->cibase = (mrb_callinfo*)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2);
|
|
373
|
+
c->ci = ci = c->cibase + size;
|
|
374
|
+
c->ciend = c->cibase + size * 2;
|
|
375
|
+
}
|
|
376
|
+
ci->mid = mid;
|
|
377
|
+
CI_PROC_SET(ci, proc);
|
|
378
|
+
ci->blk = blk;
|
|
379
|
+
ci->stack = ci[-1].stack + push_stacks;
|
|
380
|
+
ci->n = argc & 0xf;
|
|
381
|
+
ci->nk = (argc>>4) & 0xf;
|
|
382
|
+
ci->cci = cci;
|
|
383
|
+
ci->vis = MRB_METHOD_PUBLIC_FL;
|
|
384
|
+
ci->u.target_class = target_class;
|
|
385
|
+
|
|
386
|
+
return ci;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
static void
|
|
390
|
+
fiber_terminate(mrb_state *mrb, struct mrb_context *c, mrb_callinfo *ci)
|
|
391
|
+
{
|
|
392
|
+
mrb_assert(c != mrb->root_c);
|
|
393
|
+
|
|
394
|
+
struct REnv *env = CI_ENV(ci);
|
|
395
|
+
mrb_assert(env == NULL || MRB_ENV_LEN(env) <= c->stend - ci->stack);
|
|
396
|
+
|
|
397
|
+
c->status = MRB_FIBER_TERMINATED;
|
|
398
|
+
mrb_free(mrb, c->cibase);
|
|
399
|
+
c->cibase = c->ciend = c->ci = NULL;
|
|
400
|
+
mrb_value *stack = c->stbase;
|
|
401
|
+
c->stbase = c->stend = NULL;
|
|
402
|
+
|
|
403
|
+
if (!env) {
|
|
404
|
+
mrb_free(mrb, stack);
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
size_t len = (size_t)MRB_ENV_LEN(env);
|
|
408
|
+
if (len == 0) {
|
|
409
|
+
env->stack = NULL;
|
|
410
|
+
MRB_ENV_CLOSE(env);
|
|
411
|
+
mrb_free(mrb, stack);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
mrb_assert(stack == env->stack);
|
|
415
|
+
mrb_write_barrier(mrb, (struct RBasic*)env);
|
|
416
|
+
|
|
417
|
+
// don't call MRB_ENV_CLOSE() before mrb_realloc().
|
|
418
|
+
// the reason is that env->stack may be freed by mrb_realloc() if MRB_DEBUG + MRB_GC_STRESS are enabled.
|
|
419
|
+
// realloc() on a freed heap will cause double-free.
|
|
420
|
+
|
|
421
|
+
stack = (mrb_value*)mrb_realloc(mrb, stack, len * sizeof(mrb_value));
|
|
422
|
+
if (mrb_object_dead_p(mrb, (struct RBasic*)env)) {
|
|
423
|
+
mrb_free(mrb, stack);
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
env->stack = stack;
|
|
427
|
+
MRB_ENV_CLOSE(env);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/* fiber termination should automatic yield or transfer to root */
|
|
433
|
+
mrb->c = c->prev;
|
|
434
|
+
if (!mrb->c) mrb->c = mrb->root_c;
|
|
435
|
+
else c->prev = NULL;
|
|
436
|
+
mrb->c->status = MRB_FIBER_RUNNING;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
mrb_bool
|
|
440
|
+
mrb_env_unshare(mrb_state *mrb, struct REnv *e, mrb_bool noraise)
|
|
441
|
+
{
|
|
442
|
+
mrb_assert(e != NULL);
|
|
443
|
+
mrb_assert(MRB_ENV_ONSTACK_P(e));
|
|
444
|
+
|
|
445
|
+
size_t len = (size_t)MRB_ENV_LEN(e);
|
|
446
|
+
if (len == 0) {
|
|
447
|
+
e->stack = NULL;
|
|
448
|
+
MRB_ENV_CLOSE(e);
|
|
449
|
+
return TRUE;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
size_t live = mrb->gc.live;
|
|
453
|
+
mrb_value *p = (mrb_value*)mrb_malloc_simple(mrb, sizeof(mrb_value)*len);
|
|
454
|
+
if (live != mrb->gc.live && mrb_object_dead_p(mrb, (struct RBasic*)e)) {
|
|
455
|
+
// The e object is now subject to GC inside mrb_malloc_simple().
|
|
456
|
+
// Moreover, if NULL is returned due to mrb_malloc_simple() failure, simply ignore it.
|
|
457
|
+
mrb_free(mrb, p);
|
|
458
|
+
return TRUE;
|
|
459
|
+
}
|
|
460
|
+
else if (p) {
|
|
461
|
+
stack_copy(p, e->stack, len);
|
|
462
|
+
e->stack = p;
|
|
463
|
+
MRB_ENV_CLOSE(e);
|
|
464
|
+
mrb_write_barrier(mrb, (struct RBasic*)e);
|
|
465
|
+
return TRUE;
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
e->stack = NULL;
|
|
469
|
+
MRB_ENV_CLOSE(e);
|
|
470
|
+
MRB_ENV_SET_LEN(e, 0);
|
|
471
|
+
MRB_ENV_SET_BIDX(e, 0);
|
|
472
|
+
if (!noraise) {
|
|
473
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
|
|
474
|
+
}
|
|
475
|
+
return FALSE;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
static inline mrb_callinfo*
|
|
480
|
+
cipop(mrb_state *mrb)
|
|
481
|
+
{
|
|
482
|
+
struct mrb_context *c = mrb->c;
|
|
483
|
+
mrb_callinfo *ci = c->ci;
|
|
484
|
+
struct REnv *env = CI_ENV(ci);
|
|
485
|
+
|
|
486
|
+
ci_env_set(ci, NULL); // make possible to free env by GC if not needed
|
|
487
|
+
struct RProc *b = ci->blk;
|
|
488
|
+
if (b && !MRB_PROC_STRICT_P(b) && MRB_PROC_ENV(b) == CI_ENV(&ci[-1])) {
|
|
489
|
+
b->flags |= MRB_PROC_ORPHAN;
|
|
490
|
+
}
|
|
491
|
+
if (env && !mrb_env_unshare(mrb, env, TRUE)) {
|
|
492
|
+
c->ci--; // exceptions are handled at the method caller; see #3087
|
|
493
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
|
|
494
|
+
}
|
|
495
|
+
c->ci--;
|
|
496
|
+
return c->ci;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* @brief Protects a C function call from mruby exceptions.
|
|
501
|
+
*
|
|
502
|
+
* This function executes a C function (`body`) within a protected environment.
|
|
503
|
+
* If an mruby exception occurs during the execution of `body`, this function
|
|
504
|
+
* catches the exception, sets the `error` flag, and returns the exception object.
|
|
505
|
+
* Otherwise, it returns the result of the `body` function and `error` remains FALSE.
|
|
506
|
+
*
|
|
507
|
+
* This is crucial for calling mruby-related C functions from within C code
|
|
508
|
+
* that needs to handle potential mruby exceptions gracefully.
|
|
509
|
+
*
|
|
510
|
+
* @param mrb The mruby state.
|
|
511
|
+
* @param body A pointer to the C function to be executed.
|
|
512
|
+
* The function should have the signature: `mrb_value func(mrb_state *mrb, void *userdata)`
|
|
513
|
+
* @param userdata A pointer to arbitrary data that will be passed to the `body` function.
|
|
514
|
+
* @param error A pointer to an mrb_bool that will be set to TRUE if an exception
|
|
515
|
+
* occurred, and FALSE otherwise. Can be NULL if not needed.
|
|
516
|
+
* @return The value returned by the `body` function if no exception occurred,
|
|
517
|
+
* or the exception object if an exception occurred.
|
|
518
|
+
*/
|
|
519
|
+
MRB_API mrb_value
|
|
520
|
+
mrb_protect_error(mrb_state *mrb, mrb_protect_error_func *body, void *userdata, mrb_bool *error)
|
|
521
|
+
{
|
|
522
|
+
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
|
523
|
+
struct mrb_jmpbuf c_jmp;
|
|
524
|
+
mrb_value result;
|
|
525
|
+
int ai = mrb_gc_arena_save(mrb);
|
|
526
|
+
const struct mrb_context *c = mrb->c;
|
|
527
|
+
ptrdiff_t ci_index = c->ci - c->cibase;
|
|
528
|
+
|
|
529
|
+
if (error) { *error = FALSE; }
|
|
530
|
+
|
|
531
|
+
MRB_TRY(&c_jmp) {
|
|
532
|
+
mrb->jmp = &c_jmp;
|
|
533
|
+
result = body(mrb, userdata);
|
|
534
|
+
mrb->jmp = prev_jmp;
|
|
535
|
+
}
|
|
536
|
+
MRB_CATCH(&c_jmp) {
|
|
537
|
+
mrb->jmp = prev_jmp;
|
|
538
|
+
result = mrb_obj_value(mrb->exc);
|
|
539
|
+
mrb->exc = NULL;
|
|
540
|
+
if (error) { *error = TRUE; }
|
|
541
|
+
if (mrb->c == c) {
|
|
542
|
+
while (c->ci - c->cibase > ci_index) {
|
|
543
|
+
cipop(mrb);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
// It was probably switched by mrb_fiber_resume().
|
|
548
|
+
// Simply destroy all successive CINFO_DIRECTs once the fiber has been switched.
|
|
549
|
+
c = mrb->c;
|
|
550
|
+
while (c->ci > c->cibase && c->ci->cci == CINFO_DIRECT) {
|
|
551
|
+
cipop(mrb);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
MRB_END_EXC(&c_jmp);
|
|
556
|
+
|
|
557
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
558
|
+
mrb_gc_protect(mrb, result);
|
|
559
|
+
return result;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
void mrb_exc_set(mrb_state *mrb, mrb_value exc);
|
|
563
|
+
static mrb_value mrb_run(mrb_state *mrb, const struct RProc* proc, mrb_value self);
|
|
564
|
+
|
|
565
|
+
#ifndef MRB_FUNCALL_ARGC_MAX
|
|
566
|
+
#define MRB_FUNCALL_ARGC_MAX 16
|
|
567
|
+
#endif
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* @brief Calls a method on an object.
|
|
571
|
+
*
|
|
572
|
+
* This function invokes a method identified by its name on the `self` object,
|
|
573
|
+
* passing the given arguments.
|
|
574
|
+
*
|
|
575
|
+
* @param mrb The mruby state.
|
|
576
|
+
* @param self The receiver object of the method call.
|
|
577
|
+
* @param name The name of the method to call (C string).
|
|
578
|
+
* @param argc The number of arguments to pass to the method.
|
|
579
|
+
* @param ... The variable arguments to pass to the method.
|
|
580
|
+
* Each argument must be of type `mrb_value`.
|
|
581
|
+
* @return The result of the method call.
|
|
582
|
+
* @raise E_ARGUMENT_ERROR if `argc` is greater than `MRB_FUNCALL_ARGC_MAX`.
|
|
583
|
+
*/
|
|
584
|
+
MRB_API mrb_value
|
|
585
|
+
mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
|
|
586
|
+
{
|
|
587
|
+
mrb_value argv[MRB_FUNCALL_ARGC_MAX];
|
|
588
|
+
mrb_sym mid = mrb_intern_cstr(mrb, name);
|
|
589
|
+
|
|
590
|
+
if (argc > MRB_FUNCALL_ARGC_MAX) {
|
|
591
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")");
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
va_list ap;
|
|
595
|
+
va_start(ap, argc);
|
|
596
|
+
for (mrb_int i = 0; i < argc; i++) {
|
|
597
|
+
argv[i] = va_arg(ap, mrb_value);
|
|
598
|
+
}
|
|
599
|
+
va_end(ap);
|
|
600
|
+
return mrb_funcall_argv(mrb, self, mid, argc, argv);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* @brief Calls a method on an object using a method ID.
|
|
605
|
+
*
|
|
606
|
+
* This function invokes a method identified by its symbol ID (`mid`) on
|
|
607
|
+
* the `self` object, passing the given arguments. Using a method ID
|
|
608
|
+
* can be more efficient than using a string name if the method is called
|
|
609
|
+
* frequently, as it avoids repeated string-to-symbol lookups.
|
|
610
|
+
*
|
|
611
|
+
* @param mrb The mruby state.
|
|
612
|
+
* @param self The receiver object of the method call.
|
|
613
|
+
* @param mid The symbol ID of the method to call.
|
|
614
|
+
* @param argc The number of arguments to pass to the method.
|
|
615
|
+
* @param ... The variable arguments to pass to the method.
|
|
616
|
+
* Each argument must be of type `mrb_value`.
|
|
617
|
+
* @return The result of the method call.
|
|
618
|
+
* @raise E_ARGUMENT_ERROR if `argc` is greater than `MRB_FUNCALL_ARGC_MAX`.
|
|
619
|
+
*/
|
|
620
|
+
MRB_API mrb_value
|
|
621
|
+
mrb_funcall_id(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, ...)
|
|
622
|
+
{
|
|
623
|
+
mrb_value argv[MRB_FUNCALL_ARGC_MAX];
|
|
624
|
+
|
|
625
|
+
if (argc > MRB_FUNCALL_ARGC_MAX) {
|
|
626
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")");
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
va_list ap;
|
|
630
|
+
va_start(ap, argc);
|
|
631
|
+
for (mrb_int i = 0; i < argc; i++) {
|
|
632
|
+
argv[i] = va_arg(ap, mrb_value);
|
|
633
|
+
}
|
|
634
|
+
va_end(ap);
|
|
635
|
+
return mrb_funcall_argv(mrb, self, mid, argc, argv);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
static mrb_int
|
|
639
|
+
mrb_ci_kidx(const mrb_callinfo *ci)
|
|
640
|
+
{
|
|
641
|
+
if (ci->nk == 0) return -1;
|
|
642
|
+
return (ci->n == CALL_MAXARGS) ? 2 : ci->n + 1;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
static inline mrb_int
|
|
646
|
+
mrb_bidx(uint8_t n, uint8_t k)
|
|
647
|
+
{
|
|
648
|
+
if (n == 15) n = 1;
|
|
649
|
+
if (k == 15) n += 1;
|
|
650
|
+
else n += k*2;
|
|
651
|
+
return n + 1; /* self + args + kargs */
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
static inline mrb_int
|
|
655
|
+
ci_bidx(mrb_callinfo *ci)
|
|
656
|
+
{
|
|
657
|
+
return mrb_bidx(ci->n, ci->nk);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
mrb_int
|
|
661
|
+
mrb_ci_bidx(mrb_callinfo *ci)
|
|
662
|
+
{
|
|
663
|
+
return ci_bidx(ci);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
mrb_int
|
|
667
|
+
mrb_ci_nregs(mrb_callinfo *ci)
|
|
668
|
+
{
|
|
669
|
+
if (!ci) return 4;
|
|
670
|
+
mrb_int nregs = ci_bidx(ci) + 1; /* self + args + kargs + blk */
|
|
671
|
+
const struct RProc *p = ci->proc;
|
|
672
|
+
if (p && !MRB_PROC_CFUNC_P(p) && p->body.irep && p->body.irep->nregs > nregs) {
|
|
673
|
+
return p->body.irep->nregs;
|
|
674
|
+
}
|
|
675
|
+
return nregs;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod);
|
|
679
|
+
|
|
680
|
+
static mrb_method_t
|
|
681
|
+
prepare_missing(mrb_state *mrb, mrb_callinfo *ci, mrb_value recv, mrb_sym mid, mrb_value blk, mrb_bool super)
|
|
682
|
+
{
|
|
683
|
+
mrb_sym missing = MRB_SYM(method_missing);
|
|
684
|
+
mrb_value *argv = &ci->stack[1];
|
|
685
|
+
mrb_value args;
|
|
686
|
+
mrb_method_t m;
|
|
687
|
+
|
|
688
|
+
/* pack positional arguments */
|
|
689
|
+
if (ci->n == 15) args = argv[0];
|
|
690
|
+
else args = mrb_ary_new_from_values(mrb, ci->n, argv);
|
|
691
|
+
|
|
692
|
+
if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) {
|
|
693
|
+
method_missing:
|
|
694
|
+
if (super) mrb_no_method_error(mrb, mid, args, "no superclass method '%n' for %T", mid, recv);
|
|
695
|
+
else mrb_method_missing(mrb, mid, recv, args);
|
|
696
|
+
/* not reached */
|
|
697
|
+
}
|
|
698
|
+
if (mid != missing) {
|
|
699
|
+
ci->u.target_class = mrb_class(mrb, recv);
|
|
700
|
+
}
|
|
701
|
+
m = mrb_vm_find_method(mrb, ci->u.target_class, &ci->u.target_class, missing);
|
|
702
|
+
if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */
|
|
703
|
+
stack_extend(mrb, 4);
|
|
704
|
+
|
|
705
|
+
argv = &ci->stack[1]; /* maybe reallocated */
|
|
706
|
+
if (ci->nk == 0) {
|
|
707
|
+
argv[1] = blk;
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
mrb_assert(ci->nk == 15);
|
|
711
|
+
argv[1] = argv[ci->n];
|
|
712
|
+
argv[2] = blk;
|
|
713
|
+
}
|
|
714
|
+
argv[0] = args; /* must be replaced after saving argv[0] as it may be a keyword argument */
|
|
715
|
+
ci->n = CALL_MAXARGS;
|
|
716
|
+
/* ci->nk is already set to zero or CALL_MAXARGS */
|
|
717
|
+
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
|
|
718
|
+
ci->mid = missing;
|
|
719
|
+
return m;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
static void
|
|
723
|
+
funcall_args_capture(mrb_state *mrb, int stoff, mrb_int argc, const mrb_value *argv, mrb_value block, mrb_callinfo *ci)
|
|
724
|
+
{
|
|
725
|
+
if (argc < 0 || argc > INT32_MAX) {
|
|
726
|
+
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative or too big argc for funcall (%i)", argc);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
ci->nk = 0; /* funcall does not support keyword arguments */
|
|
730
|
+
if (argc < CALL_MAXARGS) {
|
|
731
|
+
mrb_int extends = stoff + argc + 2 /* self + block */;
|
|
732
|
+
stack_extend_adjust(mrb, extends, &argv);
|
|
733
|
+
|
|
734
|
+
mrb_value *args = mrb->c->ci->stack + stoff + 1 /* self */;
|
|
735
|
+
stack_copy(args, argv, argc);
|
|
736
|
+
args[argc] = block;
|
|
737
|
+
ci->n = (uint8_t)argc;
|
|
738
|
+
}
|
|
739
|
+
else {
|
|
740
|
+
int extends = stoff + 3 /* self + splat + block */;
|
|
741
|
+
stack_extend_adjust(mrb, extends, &argv);
|
|
742
|
+
|
|
743
|
+
mrb_value *args = mrb->c->ci->stack + stoff + 1 /* self */;
|
|
744
|
+
args[0] = mrb_ary_new_from_values(mrb, argc, argv);
|
|
745
|
+
args[1] = block;
|
|
746
|
+
ci->n = CALL_MAXARGS;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
static inline mrb_value
|
|
751
|
+
ensure_block(mrb_state *mrb, mrb_value blk)
|
|
752
|
+
{
|
|
753
|
+
if (!mrb_nil_p(blk) && !mrb_proc_p(blk)) {
|
|
754
|
+
blk = mrb_type_convert(mrb, blk, MRB_TT_PROC, MRB_SYM(to_proc));
|
|
755
|
+
/* The stack might have been reallocated during mrb_type_convert(), see #3622 */
|
|
756
|
+
}
|
|
757
|
+
return blk;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* @brief Calls a method on an object with a block.
|
|
762
|
+
*
|
|
763
|
+
* This function invokes a method identified by its symbol ID (`mid`) on
|
|
764
|
+
* the `self` object, passing the given arguments (`argv`) and a block (`blk`).
|
|
765
|
+
*
|
|
766
|
+
* @param mrb The mruby state.
|
|
767
|
+
* @param self The receiver object of the method call.
|
|
768
|
+
* @param mid The symbol ID of the method to call.
|
|
769
|
+
* @param argc The number of arguments in `argv`.
|
|
770
|
+
* @param argv A pointer to an array of `mrb_value` arguments.
|
|
771
|
+
* @param blk The block to pass to the method. If no block is to be passed,
|
|
772
|
+
* use `mrb_nil_value()`. If `blk` is not nil and not a proc,
|
|
773
|
+
* it will be converted to a proc using `to_proc`.
|
|
774
|
+
* @return The result of the method call.
|
|
775
|
+
* @raise E_ARGUMENT_ERROR if `argc` is negative or too large.
|
|
776
|
+
* @raise E_STACK_ERROR if the call level exceeds `MRB_CALL_LEVEL_MAX`.
|
|
777
|
+
*/
|
|
778
|
+
MRB_API mrb_value
|
|
779
|
+
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
|
|
780
|
+
{
|
|
781
|
+
mrb_value val;
|
|
782
|
+
int ai = mrb_gc_arena_save(mrb);
|
|
783
|
+
|
|
784
|
+
if (!mrb->jmp) {
|
|
785
|
+
struct mrb_jmpbuf c_jmp;
|
|
786
|
+
ptrdiff_t nth_ci = mrb->c->ci - mrb->c->cibase;
|
|
787
|
+
|
|
788
|
+
MRB_TRY(&c_jmp) {
|
|
789
|
+
mrb->jmp = &c_jmp;
|
|
790
|
+
/* recursive call */
|
|
791
|
+
val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
|
|
792
|
+
mrb->jmp = NULL;
|
|
793
|
+
}
|
|
794
|
+
MRB_CATCH(&c_jmp) { /* error */
|
|
795
|
+
while (nth_ci < (mrb->c->ci - mrb->c->cibase)) {
|
|
796
|
+
cipop(mrb);
|
|
797
|
+
}
|
|
798
|
+
mrb->jmp = 0;
|
|
799
|
+
val = mrb_obj_value(mrb->exc);
|
|
800
|
+
}
|
|
801
|
+
MRB_END_EXC(&c_jmp);
|
|
802
|
+
mrb->jmp = NULL;
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
mrb_method_t m;
|
|
806
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
807
|
+
mrb_int n = mrb_ci_nregs(ci);
|
|
808
|
+
|
|
809
|
+
if (!mrb->c->stbase) {
|
|
810
|
+
stack_init(mrb);
|
|
811
|
+
}
|
|
812
|
+
if (ci - mrb->c->cibase > MRB_CALL_LEVEL_MAX) {
|
|
813
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
|
|
814
|
+
}
|
|
815
|
+
blk = ensure_block(mrb, blk);
|
|
816
|
+
ci = cipush(mrb, n, CINFO_DIRECT, NULL, NULL, BLK_PTR(blk), 0, 0);
|
|
817
|
+
funcall_args_capture(mrb, 0, argc, argv, blk, ci);
|
|
818
|
+
ci->u.target_class = mrb_class(mrb, self);
|
|
819
|
+
m = mrb_vm_find_method(mrb, ci->u.target_class, &ci->u.target_class, mid);
|
|
820
|
+
if (MRB_METHOD_UNDEF_P(m)) {
|
|
821
|
+
m = prepare_missing(mrb, ci, self, mid, mrb_nil_value(), FALSE);
|
|
822
|
+
}
|
|
823
|
+
else {
|
|
824
|
+
ci->mid = mid;
|
|
825
|
+
}
|
|
826
|
+
ci->proc = MRB_METHOD_PROC_P(m) ? MRB_METHOD_PROC(m) : NULL;
|
|
827
|
+
|
|
828
|
+
if (MRB_METHOD_CFUNC_P(m)) {
|
|
829
|
+
mrb->exc = NULL;
|
|
830
|
+
ci->stack[0] = self;
|
|
831
|
+
val = MRB_METHOD_CFUNC(m)(mrb, self);
|
|
832
|
+
cipop(mrb);
|
|
833
|
+
if (mrb->exc != NULL) {
|
|
834
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
838
|
+
/* handle alias */
|
|
839
|
+
MRB_PROC_RESOLVE_ALIAS(ci, ci->proc);
|
|
840
|
+
ci->cci = CINFO_SKIP;
|
|
841
|
+
val = mrb_run(mrb, ci->proc, self);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
845
|
+
mrb_gc_protect(mrb, val);
|
|
846
|
+
return val;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @brief Calls a method on an object with an array of arguments.
|
|
851
|
+
*
|
|
852
|
+
* This function is similar to `mrb_funcall_with_block` but takes arguments
|
|
853
|
+
* as a C array (`argv`) and does not take an explicit block argument.
|
|
854
|
+
* If a block is needed, `mrb_funcall_with_block` should be used.
|
|
855
|
+
* This function is essentially a convenience wrapper around
|
|
856
|
+
* `mrb_funcall_with_block` with `mrb_nil_value()` for the block.
|
|
857
|
+
*
|
|
858
|
+
* @param mrb The mruby state.
|
|
859
|
+
* @param self The receiver object of the method call.
|
|
860
|
+
* @param mid The symbol ID of the method to call.
|
|
861
|
+
* @param argc The number of arguments in `argv`.
|
|
862
|
+
* @param argv A pointer to an array of `mrb_value` arguments.
|
|
863
|
+
* @return The result of the method call.
|
|
864
|
+
* @see mrb_funcall_with_block
|
|
865
|
+
*/
|
|
866
|
+
MRB_API mrb_value
|
|
867
|
+
mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv)
|
|
868
|
+
{
|
|
869
|
+
return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value());
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
static void
|
|
873
|
+
check_argument_count(mrb_state *mrb, const mrb_callinfo *ci, mrb_aspec aspec)
|
|
874
|
+
{
|
|
875
|
+
mrb_int argc = ci->n;
|
|
876
|
+
if (mrb_unlikely(argc == CALL_MAXARGS)) {
|
|
877
|
+
argc = RARRAY_LEN(ci->stack[1]);
|
|
878
|
+
}
|
|
879
|
+
/* keyword hash counts as positional if method doesn't accept keywords */
|
|
880
|
+
if (ci->nk > 0 && MRB_ASPEC_KEY(aspec) == 0 && !MRB_ASPEC_KDICT(aspec)) {
|
|
881
|
+
mrb_value kdict = ci->stack[mrb_ci_kidx(ci)];
|
|
882
|
+
if (mrb_hash_p(kdict) && !mrb_hash_empty_p(mrb, kdict)) {
|
|
883
|
+
argc++;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
int min = MRB_ASPEC_REQ(aspec) + MRB_ASPEC_POST(aspec);
|
|
887
|
+
int max = MRB_ASPEC_REST(aspec) ? -1 : min + MRB_ASPEC_OPT(aspec);
|
|
888
|
+
if (mrb_unlikely(argc < min || (max >= 0 && argc > max))) {
|
|
889
|
+
mrb_argnum_error(mrb, argc, min, max);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
static mrb_value
|
|
894
|
+
exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p)
|
|
895
|
+
{
|
|
896
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
897
|
+
|
|
898
|
+
ci->stack[0] = self;
|
|
899
|
+
/* handle alias */
|
|
900
|
+
MRB_PROC_RESOLVE_ALIAS(ci, p);
|
|
901
|
+
CI_PROC_SET(ci, p);
|
|
902
|
+
if (MRB_PROC_CFUNC_P(p)) {
|
|
903
|
+
if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
|
904
|
+
check_argument_count(mrb, ci, 0);
|
|
905
|
+
}
|
|
906
|
+
return MRB_PROC_CFUNC(p)(mrb, self);
|
|
907
|
+
}
|
|
908
|
+
mrb_int nregs = p->body.irep->nregs;
|
|
909
|
+
mrb_int keep = ci_bidx(ci)+1;
|
|
910
|
+
if (nregs < keep) {
|
|
911
|
+
stack_extend(mrb, keep);
|
|
912
|
+
}
|
|
913
|
+
else {
|
|
914
|
+
stack_extend(mrb, nregs);
|
|
915
|
+
stack_clear(ci->stack+keep, nregs-keep);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
cipush(mrb, 0, 0, NULL, NULL, NULL, 0, 0);
|
|
919
|
+
|
|
920
|
+
return self;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
mrb_value
|
|
924
|
+
mrb_exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p)
|
|
925
|
+
{
|
|
926
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
927
|
+
if (ci->cci == CINFO_NONE) {
|
|
928
|
+
return exec_irep(mrb, self, p);
|
|
929
|
+
}
|
|
930
|
+
else {
|
|
931
|
+
mrb_value ret;
|
|
932
|
+
if (MRB_PROC_CFUNC_P(p)) {
|
|
933
|
+
if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
|
934
|
+
check_argument_count(mrb, ci, 0);
|
|
935
|
+
}
|
|
936
|
+
ci = cipush(mrb, 0, CINFO_DIRECT, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4));
|
|
937
|
+
mrb->exc = NULL;
|
|
938
|
+
ret = MRB_PROC_CFUNC(p)(mrb, self);
|
|
939
|
+
cipop(mrb);
|
|
940
|
+
}
|
|
941
|
+
else {
|
|
942
|
+
mrb_int keep = ci_bidx(ci) + 1; /* receiver + block */
|
|
943
|
+
ci = cipush(mrb, 0, CINFO_SKIP, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4));
|
|
944
|
+
ret = mrb_vm_run(mrb, p, self, keep);
|
|
945
|
+
}
|
|
946
|
+
if (mrb->exc && mrb->jmp) {
|
|
947
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
|
|
948
|
+
}
|
|
949
|
+
return ret;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
mrb_value
|
|
954
|
+
mrb_object_exec(mrb_state *mrb, mrb_value self, struct RClass *target_class)
|
|
955
|
+
{
|
|
956
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
957
|
+
mrb_int bidx = ci_bidx(ci);
|
|
958
|
+
mrb_value blk = ci->stack[bidx];
|
|
959
|
+
if (mrb_nil_p(blk)) {
|
|
960
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
mrb_assert(mrb_proc_p(blk));
|
|
964
|
+
mrb_gc_protect(mrb, blk);
|
|
965
|
+
ci->stack[bidx] = mrb_nil_value();
|
|
966
|
+
mrb_vm_ci_target_class_set(ci, target_class);
|
|
967
|
+
return mrb_exec_irep(mrb, self, mrb_proc_ptr(blk));
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
static mrb_noreturn void
|
|
971
|
+
vis_error(mrb_state *mrb, mrb_sym mid, mrb_value args, mrb_value recv, mrb_bool priv)
|
|
972
|
+
{
|
|
973
|
+
mrb_no_method_error(mrb, mid, args, "%s method '%n' called for %T", (priv ? "private" : "protected"), mid, recv);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
static mrb_value
|
|
977
|
+
send_method(mrb_state *mrb, mrb_value self, mrb_bool pub)
|
|
978
|
+
{
|
|
979
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
980
|
+
int n = ci->n;
|
|
981
|
+
mrb_sym name;
|
|
982
|
+
|
|
983
|
+
if (ci->cci > CINFO_NONE) {
|
|
984
|
+
funcall:;
|
|
985
|
+
const mrb_value *argv;
|
|
986
|
+
mrb_int argc;
|
|
987
|
+
mrb_value block;
|
|
988
|
+
mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
|
|
989
|
+
return mrb_funcall_with_block(mrb, self, name, argc, argv, block);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
mrb_method_t m;
|
|
993
|
+
mrb_value *regs = mrb->c->ci->stack+1;
|
|
994
|
+
|
|
995
|
+
if (n == 0) {
|
|
996
|
+
argnum_error:
|
|
997
|
+
mrb_argnum_error(mrb, 0, 1, -1);
|
|
998
|
+
}
|
|
999
|
+
else if (n == 15) {
|
|
1000
|
+
if (RARRAY_LEN(regs[0]) == 0) goto argnum_error;
|
|
1001
|
+
name = mrb_obj_to_sym(mrb, RARRAY_PTR(regs[0])[0]);
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
1004
|
+
name = mrb_obj_to_sym(mrb, regs[0]);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
struct RClass *c = mrb_class(mrb, self);
|
|
1008
|
+
m = mrb_vm_find_method(mrb, c, &c, name);
|
|
1009
|
+
if (MRB_METHOD_UNDEF_P(m)) { /* call method_missing */
|
|
1010
|
+
goto funcall;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
if (pub) {
|
|
1014
|
+
mrb_bool priv = TRUE;
|
|
1015
|
+
if (m.flags & MRB_METHOD_PRIVATE_FL) {
|
|
1016
|
+
vis_err:;
|
|
1017
|
+
if (n == 15) {
|
|
1018
|
+
n = (int)(RARRAY_LEN(regs[0]) - 1);
|
|
1019
|
+
regs = RARRAY_PTR(regs[0]);
|
|
1020
|
+
}
|
|
1021
|
+
vis_error(mrb, name, mrb_ary_new_from_values(mrb, n, regs+1), self, priv);
|
|
1022
|
+
}
|
|
1023
|
+
else if ((m.flags & MRB_METHOD_PROTECTED_FL) && mrb_obj_is_kind_of(mrb, self, ci->u.target_class)) {
|
|
1024
|
+
priv = FALSE;
|
|
1025
|
+
goto vis_err;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
ci->mid = name;
|
|
1030
|
+
ci->u.target_class = c;
|
|
1031
|
+
/* remove first symbol from arguments */
|
|
1032
|
+
if (n == 15) { /* variable length arguments */
|
|
1033
|
+
regs[0] = mrb_ary_subseq(mrb, regs[0], 1, RARRAY_LEN(regs[0]) - 1);
|
|
1034
|
+
}
|
|
1035
|
+
else { /* n > 0 */
|
|
1036
|
+
for (int i=0; i<n; i++) {
|
|
1037
|
+
regs[i] = regs[i+1];
|
|
1038
|
+
}
|
|
1039
|
+
regs[n] = regs[n+1]; /* copy kdict or block */
|
|
1040
|
+
if (ci->nk > 0) {
|
|
1041
|
+
regs[n+1] = regs[n+2]; /* copy block */
|
|
1042
|
+
}
|
|
1043
|
+
ci->n--;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
if (MRB_METHOD_FUNC_P(m)) {
|
|
1047
|
+
check_argument_count(mrb, ci, MRB_MT_ASPEC(m.flags));
|
|
1048
|
+
return MRB_METHOD_FUNC(m)(mrb, self);
|
|
1049
|
+
}
|
|
1050
|
+
const struct RProc *p = MRB_METHOD_PROC(m);
|
|
1051
|
+
MRB_PROC_RESOLVE_ALIAS(ci, p);
|
|
1052
|
+
CI_PROC_SET(ci, p);
|
|
1053
|
+
if (MRB_PROC_CFUNC_P(p)) {
|
|
1054
|
+
if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
|
1055
|
+
check_argument_count(mrb, ci, 0);
|
|
1056
|
+
}
|
|
1057
|
+
return MRB_PROC_CFUNC(p)(mrb, self);
|
|
1058
|
+
}
|
|
1059
|
+
return exec_irep(mrb, self, p);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/* 15.3.1.3.4 */
|
|
1063
|
+
/* 15.3.1.3.44 */
|
|
1064
|
+
/*
|
|
1065
|
+
* call-seq:
|
|
1066
|
+
* obj.send(symbol [, args...]) -> obj
|
|
1067
|
+
* obj.__send__(symbol [, args...]) -> obj
|
|
1068
|
+
*
|
|
1069
|
+
* Invokes the method identified by _symbol_, passing it any
|
|
1070
|
+
* arguments specified. You can use `__send__` if the name
|
|
1071
|
+
* `send` clashes with an existing method in _obj_.
|
|
1072
|
+
*
|
|
1073
|
+
* class Klass
|
|
1074
|
+
* def hello(*args)
|
|
1075
|
+
* "Hello " + args.join(' ')
|
|
1076
|
+
* end
|
|
1077
|
+
* end
|
|
1078
|
+
* k = Klass.new
|
|
1079
|
+
* k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
|
|
1080
|
+
*/
|
|
1081
|
+
mrb_value
|
|
1082
|
+
mrb_f_send(mrb_state *mrb, mrb_value self)
|
|
1083
|
+
{
|
|
1084
|
+
return send_method(mrb, self, FALSE);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/*
|
|
1088
|
+
* call-seq:
|
|
1089
|
+
* obj.public_send(symbol [, args...]) -> obj
|
|
1090
|
+
*
|
|
1091
|
+
* Invokes the method identified by symbol, passing it any
|
|
1092
|
+
* arguments specified. Unlike send, public_send calls public methods only.
|
|
1093
|
+
* When the method is identified by a string, the string is converted to a
|
|
1094
|
+
* symbol.
|
|
1095
|
+
*
|
|
1096
|
+
* 1.public_send(:puts, "hello") # causes NoMethodError
|
|
1097
|
+
*/
|
|
1098
|
+
mrb_value
|
|
1099
|
+
mrb_f_public_send(mrb_state *mrb, mrb_value self)
|
|
1100
|
+
{
|
|
1101
|
+
return send_method(mrb, self, TRUE);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
static void
|
|
1105
|
+
check_block(mrb_state *mrb, mrb_value blk)
|
|
1106
|
+
{
|
|
1107
|
+
if (mrb_nil_p(blk)) {
|
|
1108
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
|
|
1109
|
+
}
|
|
1110
|
+
if (!mrb_proc_p(blk)) {
|
|
1111
|
+
mrb_raise(mrb, E_TYPE_ERROR, "not a block");
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
static mrb_value
|
|
1116
|
+
eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
|
|
1117
|
+
{
|
|
1118
|
+
check_block(mrb, blk);
|
|
1119
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1120
|
+
if (ci->cci == CINFO_DIRECT) {
|
|
1121
|
+
return mrb_yield_with_class(mrb, blk, 1, &self, self, c);
|
|
1122
|
+
}
|
|
1123
|
+
ci->u.target_class = c;
|
|
1124
|
+
const struct RProc *p = mrb_proc_ptr(blk);
|
|
1125
|
+
/* just in case irep is NULL; #6065 */
|
|
1126
|
+
if (p->body.irep == NULL) return mrb_nil_value();
|
|
1127
|
+
CI_PROC_SET(ci, p);
|
|
1128
|
+
ci->n = 1;
|
|
1129
|
+
ci->nk = 0;
|
|
1130
|
+
ci->mid = ci[-1].mid;
|
|
1131
|
+
MRB_CI_SET_VISIBILITY_BREAK(ci);
|
|
1132
|
+
if (MRB_PROC_CFUNC_P(p)) {
|
|
1133
|
+
stack_extend(mrb, 4);
|
|
1134
|
+
mrb->c->ci->stack[0] = self;
|
|
1135
|
+
mrb->c->ci->stack[1] = self;
|
|
1136
|
+
mrb->c->ci->stack[2] = mrb_nil_value();
|
|
1137
|
+
return MRB_PROC_CFUNC(p)(mrb, self);
|
|
1138
|
+
}
|
|
1139
|
+
int nregs = p->body.irep->nregs;
|
|
1140
|
+
if (nregs < 4) nregs = 4;
|
|
1141
|
+
stack_extend(mrb, nregs);
|
|
1142
|
+
mrb->c->ci->stack[0] = self;
|
|
1143
|
+
mrb->c->ci->stack[1] = self;
|
|
1144
|
+
stack_clear(mrb->c->ci->stack+2, nregs-2);
|
|
1145
|
+
cipush(mrb, 0, 0, NULL, NULL, NULL, 0, 0);
|
|
1146
|
+
|
|
1147
|
+
return self;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/* 15.2.2.4.35 */
|
|
1151
|
+
/*
|
|
1152
|
+
* call-seq:
|
|
1153
|
+
* mod.class_eval {| | block } -> obj
|
|
1154
|
+
* mod.module_eval {| | block } -> obj
|
|
1155
|
+
*
|
|
1156
|
+
* Evaluates block in the context of _mod_. This can
|
|
1157
|
+
* be used to add methods to a class. `module_eval` returns
|
|
1158
|
+
* the result of evaluating its argument.
|
|
1159
|
+
*/
|
|
1160
|
+
mrb_value
|
|
1161
|
+
mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
|
|
1162
|
+
{
|
|
1163
|
+
mrb_value a, b;
|
|
1164
|
+
|
|
1165
|
+
if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
|
|
1166
|
+
mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
|
|
1167
|
+
}
|
|
1168
|
+
return eval_under(mrb, mod, b, mrb_class_ptr(mod));
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
/* 15.3.1.3.18 */
|
|
1172
|
+
/*
|
|
1173
|
+
* call-seq:
|
|
1174
|
+
* obj.instance_eval {| | block } -> obj
|
|
1175
|
+
*
|
|
1176
|
+
* Evaluates the given block,within the context of the receiver (_obj_).
|
|
1177
|
+
* In order to set the context, the variable `self` is set to _obj_ while
|
|
1178
|
+
* the code is executing, giving the code access to _obj_'s
|
|
1179
|
+
* instance variables. In the version of `instance_eval`
|
|
1180
|
+
* that takes a `String`, the optional second and third
|
|
1181
|
+
* parameters supply a filename and starting line number that are used
|
|
1182
|
+
* when reporting compilation errors.
|
|
1183
|
+
*
|
|
1184
|
+
* class KlassWithSecret
|
|
1185
|
+
* def initialize
|
|
1186
|
+
* @secret = 99
|
|
1187
|
+
* end
|
|
1188
|
+
* end
|
|
1189
|
+
* k = KlassWithSecret.new
|
|
1190
|
+
* k.instance_eval { @secret } #=> 99
|
|
1191
|
+
*/
|
|
1192
|
+
mrb_value
|
|
1193
|
+
mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
|
|
1194
|
+
{
|
|
1195
|
+
mrb_value a, b;
|
|
1196
|
+
|
|
1197
|
+
if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
|
|
1198
|
+
mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
|
|
1199
|
+
}
|
|
1200
|
+
return eval_under(mrb, self, b, mrb_singleton_class_ptr(mrb, self));
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
static mrb_value
|
|
1204
|
+
yield_with_attr(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c,
|
|
1205
|
+
mrb_bool vis_break)
|
|
1206
|
+
{
|
|
1207
|
+
check_block(mrb, b);
|
|
1208
|
+
|
|
1209
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1210
|
+
mrb_int n = mrb_ci_nregs(ci);
|
|
1211
|
+
const struct RProc *p = mrb_proc_ptr(b);
|
|
1212
|
+
mrb_sym mid;
|
|
1213
|
+
|
|
1214
|
+
if (MRB_PROC_ENV_P(p)) {
|
|
1215
|
+
mid = p->e.env->mid;
|
|
1216
|
+
}
|
|
1217
|
+
else {
|
|
1218
|
+
mid = ci->mid;
|
|
1219
|
+
}
|
|
1220
|
+
ci = cipush(mrb, n, CINFO_DIRECT, NULL, NULL, NULL, mid, 0);
|
|
1221
|
+
funcall_args_capture(mrb, 0, argc, argv, mrb_nil_value(), ci);
|
|
1222
|
+
ci->u.target_class = c;
|
|
1223
|
+
ci->proc = p;
|
|
1224
|
+
if (vis_break) {
|
|
1225
|
+
MRB_CI_SET_VISIBILITY_BREAK(ci);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
mrb_value val;
|
|
1229
|
+
if (MRB_PROC_CFUNC_P(p)) {
|
|
1230
|
+
mrb->exc = NULL;
|
|
1231
|
+
ci->stack[0] = self;
|
|
1232
|
+
val = MRB_PROC_CFUNC(p)(mrb, self);
|
|
1233
|
+
cipop(mrb);
|
|
1234
|
+
if (mrb->exc && mrb->jmp) {
|
|
1235
|
+
mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
ci->cci = CINFO_SKIP;
|
|
1240
|
+
val = mrb_run(mrb, p, self);
|
|
1241
|
+
}
|
|
1242
|
+
return val;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* @brief Yields to a block with a specific `self` object and class context.
|
|
1247
|
+
*
|
|
1248
|
+
* This function executes a given block (`b`) with the provided arguments (`argv`).
|
|
1249
|
+
* The `self` object within the block will be `self`, and the class context
|
|
1250
|
+
* will be `c`. This allows for more control over the execution environment of
|
|
1251
|
+
* the block. The `vis_break` flag is set to TRUE, meaning visibility checks
|
|
1252
|
+
* (public/private/protected) are enforced.
|
|
1253
|
+
*
|
|
1254
|
+
* @param mrb The mruby state.
|
|
1255
|
+
* @param b The block (proc) to yield to.
|
|
1256
|
+
* @param argc The number of arguments in `argv`.
|
|
1257
|
+
* @param argv A pointer to an array of `mrb_value` arguments to pass to the block.
|
|
1258
|
+
* @param self The object that will be `self` inside the block.
|
|
1259
|
+
* @param c The class context for the block execution.
|
|
1260
|
+
* @return The result of the block execution.
|
|
1261
|
+
* @raise E_TYPE_ERROR if `b` is not a proc or nil.
|
|
1262
|
+
* @see mrb_yield_argv
|
|
1263
|
+
* @see mrb_yield
|
|
1264
|
+
*/
|
|
1265
|
+
MRB_API mrb_value
|
|
1266
|
+
mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c)
|
|
1267
|
+
{
|
|
1268
|
+
return yield_with_attr(mrb, b, argc, argv, self, c, TRUE);
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
/**
|
|
1272
|
+
* @brief Yields to a block with an array of arguments.
|
|
1273
|
+
*
|
|
1274
|
+
* This function executes a given block (`b`) with the provided arguments (`argv`).
|
|
1275
|
+
* The `self` object and class context for the block execution are determined
|
|
1276
|
+
* from the block itself (its captured environment).
|
|
1277
|
+
* Visibility checks (public/private/protected) are not strictly enforced
|
|
1278
|
+
* in the same way as `mrb_yield_with_class` (vis_break is FALSE).
|
|
1279
|
+
*
|
|
1280
|
+
* @param mrb The mruby state.
|
|
1281
|
+
* @param b The block (proc) to yield to.
|
|
1282
|
+
* @param argc The number of arguments in `argv`.
|
|
1283
|
+
* @param argv A pointer to an array of `mrb_value` arguments to pass to the block.
|
|
1284
|
+
* @return The result of the block execution.
|
|
1285
|
+
* @raise E_TYPE_ERROR if `b` is not a proc or nil.
|
|
1286
|
+
* @see mrb_yield_with_class
|
|
1287
|
+
* @see mrb_yield
|
|
1288
|
+
*/
|
|
1289
|
+
MRB_API mrb_value
|
|
1290
|
+
mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv)
|
|
1291
|
+
{
|
|
1292
|
+
const struct RProc *p = mrb_proc_ptr(b);
|
|
1293
|
+
struct RClass *tc;
|
|
1294
|
+
mrb_value self = mrb_proc_get_self(mrb, p, &tc);
|
|
1295
|
+
|
|
1296
|
+
return yield_with_attr(mrb, b, argc, argv, self, tc, FALSE);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* @brief Yields to a block with a single argument.
|
|
1301
|
+
*
|
|
1302
|
+
* This function executes a given block (`b`) with a single argument (`arg`).
|
|
1303
|
+
* It's a convenience function for the common case of yielding with one argument.
|
|
1304
|
+
* The `self` object and class context for the block execution are determined
|
|
1305
|
+
* from the block itself.
|
|
1306
|
+
* Visibility checks are not strictly enforced (vis_break is FALSE).
|
|
1307
|
+
*
|
|
1308
|
+
* @param mrb The mruby state.
|
|
1309
|
+
* @param b The block (proc) to yield to.
|
|
1310
|
+
* @param arg The single `mrb_value` argument to pass to the block.
|
|
1311
|
+
* @return The result of the block execution.
|
|
1312
|
+
* @raise E_TYPE_ERROR if `b` is not a proc or nil.
|
|
1313
|
+
* @see mrb_yield_with_class
|
|
1314
|
+
* @see mrb_yield_argv
|
|
1315
|
+
*/
|
|
1316
|
+
MRB_API mrb_value
|
|
1317
|
+
mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg)
|
|
1318
|
+
{
|
|
1319
|
+
const struct RProc *p = mrb_proc_ptr(b);
|
|
1320
|
+
struct RClass *tc;
|
|
1321
|
+
mrb_value self = mrb_proc_get_self(mrb, p, &tc);
|
|
1322
|
+
|
|
1323
|
+
return yield_with_attr(mrb, b, 1, &arg, self, tc, FALSE);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
mrb_value
|
|
1327
|
+
mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const mrb_value *argv)
|
|
1328
|
+
{
|
|
1329
|
+
check_block(mrb, b);
|
|
1330
|
+
|
|
1331
|
+
const struct RProc *p = mrb_proc_ptr(b);
|
|
1332
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1333
|
+
|
|
1334
|
+
stack_extend_adjust(mrb, 4, &argv);
|
|
1335
|
+
mrb->c->ci->stack[1] = mrb_ary_new_from_values(mrb, argc, argv);
|
|
1336
|
+
mrb->c->ci->stack[2] = mrb_nil_value();
|
|
1337
|
+
mrb->c->ci->stack[3] = mrb_nil_value();
|
|
1338
|
+
ci->n = 15;
|
|
1339
|
+
ci->nk = 0;
|
|
1340
|
+
return exec_irep(mrb, self, p);
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
#define RBREAK_TAG_FOREACH(f) \
|
|
1344
|
+
f(RBREAK_TAG_BREAK, 0) \
|
|
1345
|
+
f(RBREAK_TAG_JUMP, 1) \
|
|
1346
|
+
f(RBREAK_TAG_STOP, 2)
|
|
1347
|
+
|
|
1348
|
+
#define RBREAK_TAG_DEFINE(tag, i) tag = i,
|
|
1349
|
+
enum {
|
|
1350
|
+
RBREAK_TAG_FOREACH(RBREAK_TAG_DEFINE)
|
|
1351
|
+
};
|
|
1352
|
+
#undef RBREAK_TAG_DEFINE
|
|
1353
|
+
|
|
1354
|
+
#define RBREAK_TAG_BIT 3
|
|
1355
|
+
#define RBREAK_TAG_BIT_OFF 8
|
|
1356
|
+
#define RBREAK_TAG_MASK (~(~UINT32_C(0) << RBREAK_TAG_BIT))
|
|
1357
|
+
|
|
1358
|
+
static inline uint32_t
|
|
1359
|
+
mrb_break_tag_get(struct RBreak *brk)
|
|
1360
|
+
{
|
|
1361
|
+
return (brk->flags >> RBREAK_TAG_BIT_OFF) & RBREAK_TAG_MASK;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
static inline void
|
|
1365
|
+
mrb_break_tag_set(struct RBreak *brk, uint32_t tag)
|
|
1366
|
+
{
|
|
1367
|
+
brk->flags &= ~(RBREAK_TAG_MASK << RBREAK_TAG_BIT_OFF);
|
|
1368
|
+
brk->flags |= (tag & RBREAK_TAG_MASK) << RBREAK_TAG_BIT_OFF;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
static struct RBreak*
|
|
1372
|
+
break_new(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci, mrb_value val)
|
|
1373
|
+
{
|
|
1374
|
+
mrb_assert((size_t)(return_ci - mrb->c->cibase) <= (size_t)(mrb->c->ci - mrb->c->cibase));
|
|
1375
|
+
|
|
1376
|
+
struct RBreak *brk = MRB_OBJ_ALLOC(mrb, MRB_TT_BREAK, NULL);
|
|
1377
|
+
brk->ci_break_index = return_ci - mrb->c->cibase;
|
|
1378
|
+
mrb_break_value_set(brk, val);
|
|
1379
|
+
mrb_break_tag_set(brk, tag);
|
|
1380
|
+
|
|
1381
|
+
return brk;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
#define MRB_CATCH_FILTER_RESCUE (UINT32_C(1) << MRB_CATCH_RESCUE)
|
|
1385
|
+
#define MRB_CATCH_FILTER_ENSURE (UINT32_C(1) << MRB_CATCH_ENSURE)
|
|
1386
|
+
#define MRB_CATCH_FILTER_ALL (MRB_CATCH_FILTER_RESCUE | MRB_CATCH_FILTER_ENSURE)
|
|
1387
|
+
|
|
1388
|
+
static const struct mrb_irep_catch_handler *
|
|
1389
|
+
catch_handler_find(const mrb_irep *irep, const mrb_code *pc, uint32_t filter)
|
|
1390
|
+
{
|
|
1391
|
+
/* The comparison operators use `>` and `<=` because pc already points to the next instruction */
|
|
1392
|
+
#define catch_cover_p(pc, beg, end) ((pc) > (ptrdiff_t)(beg) && (pc) <= (ptrdiff_t)(end))
|
|
1393
|
+
|
|
1394
|
+
mrb_assert(irep && irep->clen > 0);
|
|
1395
|
+
ptrdiff_t xpc = pc - irep->iseq;
|
|
1396
|
+
/* If it retry at the top level, pc will be 0, so check with -1 as the start position */
|
|
1397
|
+
mrb_assert(catch_cover_p(xpc, -1, irep->ilen));
|
|
1398
|
+
if (!catch_cover_p(xpc, -1, irep->ilen)) return NULL;
|
|
1399
|
+
|
|
1400
|
+
/* Currently uses a simple linear search to avoid processing complexity. */
|
|
1401
|
+
size_t cnt = irep->clen;
|
|
1402
|
+
const struct mrb_irep_catch_handler *e = mrb_irep_catch_handler_table(irep) + cnt - 1;
|
|
1403
|
+
for (; cnt > 0; cnt--, e--) {
|
|
1404
|
+
if (((UINT32_C(1) << e->type) & filter) &&
|
|
1405
|
+
catch_cover_p(xpc, mrb_irep_catch_handler_unpack(e->begin), mrb_irep_catch_handler_unpack(e->end))) {
|
|
1406
|
+
return e;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
#undef catch_cover_p
|
|
1411
|
+
|
|
1412
|
+
return NULL;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
#define RAISE_EXC(mrb, exc) do { \
|
|
1416
|
+
mrb_value exc_value = (exc); \
|
|
1417
|
+
mrb_exc_set(mrb, exc_value); \
|
|
1418
|
+
goto L_RAISE; \
|
|
1419
|
+
} while (0)
|
|
1420
|
+
|
|
1421
|
+
#define RAISE_LIT(mrb, c, str) RAISE_EXC(mrb, mrb_exc_new_lit(mrb, c, str))
|
|
1422
|
+
#define RAISE_FORMAT(mrb, c, fmt, ...) RAISE_EXC(mrb, mrb_exc_new_str(mrb, c, mrb_format(mrb, fmt, __VA_ARGS__)))
|
|
1423
|
+
|
|
1424
|
+
static void
|
|
1425
|
+
argnum_error(mrb_state *mrb, mrb_int num)
|
|
1426
|
+
{
|
|
1427
|
+
mrb_int argc = mrb->c->ci->n;
|
|
1428
|
+
|
|
1429
|
+
if (argc == 15) {
|
|
1430
|
+
mrb_value args = mrb->c->ci->stack[1];
|
|
1431
|
+
if (mrb_array_p(args)) {
|
|
1432
|
+
argc = RARRAY_LEN(args);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
if (argc == 0 && mrb->c->ci->nk != 0 && !mrb_hash_empty_p(mrb, mrb->c->ci->stack[1])) {
|
|
1436
|
+
argc++;
|
|
1437
|
+
}
|
|
1438
|
+
mrb_value str = mrb_format(mrb, "wrong number of arguments (given %i, expected %i)", argc, num);
|
|
1439
|
+
mrb_value exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str);
|
|
1440
|
+
mrb_exc_set(mrb, exc);
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
static mrb_bool
|
|
1444
|
+
break_tag_p(struct RBreak *brk, uint32_t tag)
|
|
1445
|
+
{
|
|
1446
|
+
return (brk != NULL && brk->tt == MRB_TT_BREAK) ? TRUE : FALSE;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
static void
|
|
1450
|
+
prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci, mrb_value val)
|
|
1451
|
+
{
|
|
1452
|
+
if (break_tag_p((struct RBreak*)mrb->exc, tag)) {
|
|
1453
|
+
mrb_break_tag_set((struct RBreak*)mrb->exc, tag);
|
|
1454
|
+
}
|
|
1455
|
+
else {
|
|
1456
|
+
mrb->exc = (struct RObject*)break_new(mrb, tag, return_ci, val);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
#define THROW_TAGGED_BREAK(mrb, tag, return_ci, val) \
|
|
1461
|
+
do { \
|
|
1462
|
+
prepare_tagged_break(mrb, tag, return_ci, val); \
|
|
1463
|
+
goto L_CATCH_TAGGED_BREAK; \
|
|
1464
|
+
} while (0)
|
|
1465
|
+
|
|
1466
|
+
#define UNWIND_ENSURE(mrb, ci, pc, tag, return_ci, val) \
|
|
1467
|
+
do { \
|
|
1468
|
+
const struct RProc *proc = (ci)->proc; \
|
|
1469
|
+
if (proc && !MRB_PROC_CFUNC_P(proc) && (irep = proc->body.irep) && irep->clen > 0 && \
|
|
1470
|
+
(ch = catch_handler_find(irep, pc, MRB_CATCH_FILTER_ENSURE))) { \
|
|
1471
|
+
THROW_TAGGED_BREAK(mrb, tag, return_ci, val); \
|
|
1472
|
+
} \
|
|
1473
|
+
} while (0)
|
|
1474
|
+
|
|
1475
|
+
/*
|
|
1476
|
+
* CHECKPOINT_RESTORE(tag) {
|
|
1477
|
+
* This part is executed when jumping by the same "tag" of RBreak (it is not executed the first time).
|
|
1478
|
+
* Write the code required (initialization of variables, etc.) for the subsequent processing.
|
|
1479
|
+
* }
|
|
1480
|
+
* CHECKPOINT_MAIN(tag) {
|
|
1481
|
+
* This part is always executed.
|
|
1482
|
+
* }
|
|
1483
|
+
* CHECKPOINT_END(tag);
|
|
1484
|
+
*
|
|
1485
|
+
* ...
|
|
1486
|
+
*
|
|
1487
|
+
* // Jump to CHECKPOINT_RESTORE with the same "tag".
|
|
1488
|
+
* goto CHECKPOINT_LABEL_MAKE(tag);
|
|
1489
|
+
*/
|
|
1490
|
+
|
|
1491
|
+
#define CHECKPOINT_LABEL_MAKE(tag) L_CHECKPOINT_ ## tag
|
|
1492
|
+
|
|
1493
|
+
#define CHECKPOINT_RESTORE(tag) \
|
|
1494
|
+
do { \
|
|
1495
|
+
if (FALSE) { \
|
|
1496
|
+
CHECKPOINT_LABEL_MAKE(tag): \
|
|
1497
|
+
do {
|
|
1498
|
+
|
|
1499
|
+
#define CHECKPOINT_MAIN(tag) \
|
|
1500
|
+
} while (0); \
|
|
1501
|
+
} \
|
|
1502
|
+
do {
|
|
1503
|
+
|
|
1504
|
+
#define CHECKPOINT_END(tag) \
|
|
1505
|
+
} while (0); \
|
|
1506
|
+
} while (0)
|
|
1507
|
+
|
|
1508
|
+
#ifdef MRB_USE_DEBUG_HOOK
|
|
1509
|
+
#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
|
|
1510
|
+
#else
|
|
1511
|
+
#define CODE_FETCH_HOOK(mrb, irep, pc, regs)
|
|
1512
|
+
#endif
|
|
1513
|
+
|
|
1514
|
+
#ifdef MRB_BYTECODE_DECODE_OPTION
|
|
1515
|
+
#define BYTECODE_DECODER(x) ((mrb)->bytecode_decoder)?(mrb)->bytecode_decoder((mrb), (x)):(x)
|
|
1516
|
+
#else
|
|
1517
|
+
#define BYTECODE_DECODER(x) (x)
|
|
1518
|
+
#endif
|
|
1519
|
+
|
|
1520
|
+
#ifndef MRB_USE_VM_SWITCH_DISPATCH
|
|
1521
|
+
#if !defined __GNUC__ && !defined __clang__ && !defined __INTEL_COMPILER
|
|
1522
|
+
#define MRB_USE_VM_SWITCH_DISPATCH
|
|
1523
|
+
#endif
|
|
1524
|
+
#endif /* ifndef MRB_USE_VM_SWITCH_DISPATCH */
|
|
1525
|
+
|
|
1526
|
+
#ifdef MRB_USE_VM_SWITCH_DISPATCH
|
|
1527
|
+
|
|
1528
|
+
#define INIT_DISPATCH for (;;) { CALL_CODE_HOOKS(); switch (insn) {
|
|
1529
|
+
#define CASE(insn,ops) case insn: DECODE_OPERANDS(ops); L_ ## insn ## _BODY:
|
|
1530
|
+
#define NEXT goto L_END_DISPATCH
|
|
1531
|
+
#define JUMP NEXT
|
|
1532
|
+
#define END_DISPATCH L_END_DISPATCH: RETURN_IF_TASK_STOPPED(mrb);}}
|
|
1533
|
+
|
|
1534
|
+
#else
|
|
1535
|
+
|
|
1536
|
+
#define INIT_DISPATCH JUMP; return mrb_nil_value();
|
|
1537
|
+
#define CASE(insn,ops) L_ ## insn: DECODE_OPERANDS(ops); L_ ## insn ## _BODY:
|
|
1538
|
+
#define NEXT RETURN_IF_TASK_STOPPED(mrb); CALL_CODE_HOOKS(); goto *optable[insn]
|
|
1539
|
+
#define JUMP NEXT
|
|
1540
|
+
#define END_DISPATCH RETURN_IF_TASK_STOPPED(mrb)
|
|
1541
|
+
|
|
1542
|
+
#endif
|
|
1543
|
+
|
|
1544
|
+
#define DECODE_OPERANDS(ops) do { const mrb_code *pc = ci->pc+1; FETCH_ ## ops (); ci->pc = pc; } while (0)
|
|
1545
|
+
#define CALL_CODE_HOOKS() do { insn = BYTECODE_DECODER(*ci->pc); CODE_FETCH_HOOK(mrb, irep, ci->pc, regs); } while (0)
|
|
1546
|
+
|
|
1547
|
+
#ifdef MRB_USE_TASK_SCHEDULER
|
|
1548
|
+
#define RETURN_IF_TASK_STOPPED(mrb) do { \
|
|
1549
|
+
if ((mrb)->task.switching || (mrb)->c->status == MRB_TASK_STOPPED) \
|
|
1550
|
+
return mrb_nil_value(); \
|
|
1551
|
+
} while (0)
|
|
1552
|
+
#define TASK_STOP(mrb) do { \
|
|
1553
|
+
if (mrb->c->status != MRB_TASK_STOPPED) \
|
|
1554
|
+
mrb->c->status = MRB_TASK_STOPPED; \
|
|
1555
|
+
} while (0)
|
|
1556
|
+
#else
|
|
1557
|
+
#define RETURN_IF_TASK_STOPPED(mrb)
|
|
1558
|
+
#define TASK_STOP(mrb)
|
|
1559
|
+
#endif
|
|
1560
|
+
|
|
1561
|
+
/**
|
|
1562
|
+
* @brief Executes a mruby bytecode sequence (iseq) within the VM.
|
|
1563
|
+
*
|
|
1564
|
+
* This function is a core part of the mruby execution process. It sets up
|
|
1565
|
+
* the VM environment for executing the bytecode instructions associated with
|
|
1566
|
+
* the given proc (Ruby procedure/method).
|
|
1567
|
+
*
|
|
1568
|
+
* It initializes the stack if necessary, extends it to accommodate the
|
|
1569
|
+
* required number of registers for the proc, and then calls `mrb_vm_exec`
|
|
1570
|
+
* to actually execute the bytecode.
|
|
1571
|
+
*
|
|
1572
|
+
* @param mrb The mruby state.
|
|
1573
|
+
* @param proc The RProc object containing the bytecode (iseq) to execute.
|
|
1574
|
+
* This proc represents a Ruby method or block.
|
|
1575
|
+
* @param self The `self` object for the context of this execution.
|
|
1576
|
+
* @param stack_keep The number of values to preserve on the stack from the
|
|
1577
|
+
* previous context. This is used for managing nested calls
|
|
1578
|
+
* and ensuring that arguments or local variables from the
|
|
1579
|
+
* caller are accessible if needed, or that the stack is
|
|
1580
|
+
* correctly cleared.
|
|
1581
|
+
* @return The result of the bytecode execution (typically the value of the
|
|
1582
|
+
* last evaluated expression).
|
|
1583
|
+
* @see mrb_vm_exec
|
|
1584
|
+
* @see mrb_top_run
|
|
1585
|
+
*/
|
|
1586
|
+
MRB_API mrb_value
|
|
1587
|
+
mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep)
|
|
1588
|
+
{
|
|
1589
|
+
const mrb_irep *irep = proc->body.irep;
|
|
1590
|
+
struct mrb_context *c = mrb->c;
|
|
1591
|
+
#ifdef MRB_DEBUG
|
|
1592
|
+
ptrdiff_t cioff = c->ci - c->cibase;
|
|
1593
|
+
#endif
|
|
1594
|
+
mrb_int nregs = irep->nregs;
|
|
1595
|
+
|
|
1596
|
+
if (!c->stbase) {
|
|
1597
|
+
stack_init(mrb);
|
|
1598
|
+
}
|
|
1599
|
+
if (stack_keep > nregs)
|
|
1600
|
+
nregs = stack_keep;
|
|
1601
|
+
else {
|
|
1602
|
+
struct REnv *e = CI_ENV(mrb->c->ci);
|
|
1603
|
+
if (e && (stack_keep == 0 || irep->nlocals < MRB_ENV_LEN(e))) {
|
|
1604
|
+
ci_env_set(mrb->c->ci, NULL);
|
|
1605
|
+
mrb_env_unshare(mrb, e, FALSE);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
stack_extend(mrb, nregs);
|
|
1609
|
+
stack_clear(c->ci->stack + stack_keep, nregs - stack_keep);
|
|
1610
|
+
c->ci->stack[0] = self;
|
|
1611
|
+
mrb_value result = mrb_vm_exec(mrb, proc, irep->iseq);
|
|
1612
|
+
mrb_assert(mrb->c == c); /* do not switch fibers via mrb_vm_run(), unlike mrb_vm_exec() */
|
|
1613
|
+
mrb_assert(c->ci == c->cibase || (c->ci - c->cibase) == cioff - 1);
|
|
1614
|
+
return result;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
static struct RClass*
|
|
1618
|
+
check_target_class(mrb_state *mrb)
|
|
1619
|
+
{
|
|
1620
|
+
struct RClass *target = CI_TARGET_CLASS(mrb->c->ci);
|
|
1621
|
+
if (!target) {
|
|
1622
|
+
mrb_raise(mrb, E_TYPE_ERROR, "no class/module to add method");
|
|
1623
|
+
}
|
|
1624
|
+
return target;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
#define regs (ci->stack)
|
|
1628
|
+
|
|
1629
|
+
static mrb_value
|
|
1630
|
+
hash_new_from_regs(mrb_state *mrb, mrb_int argc, mrb_int idx)
|
|
1631
|
+
{
|
|
1632
|
+
mrb_value hash = mrb_hash_new_capa(mrb, argc);
|
|
1633
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1634
|
+
while (argc--) {
|
|
1635
|
+
mrb_hash_set(mrb, hash, regs[idx+0], regs[idx+1]);
|
|
1636
|
+
ci = mrb->c->ci;
|
|
1637
|
+
idx += 2;
|
|
1638
|
+
}
|
|
1639
|
+
return hash;
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
#define ary_new_from_regs(mrb, argc, idx) mrb_ary_new_from_values(mrb, (argc), ®s[idx]);
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* @brief Executes a sequence of mruby bytecode instructions.
|
|
1646
|
+
*
|
|
1647
|
+
* This is the main bytecode interpreter loop. It takes a starting proc
|
|
1648
|
+
* (`begin_proc`) and a pointer to the initial instruction (`iseq`) within
|
|
1649
|
+
* that proc's instruction sequence. It then enters a loop, fetching and
|
|
1650
|
+
* dispatching bytecode operations until an OP_STOP instruction is encountered,
|
|
1651
|
+
* an exception occurs, or a C function call returns.
|
|
1652
|
+
*
|
|
1653
|
+
* This function handles the low-level details of instruction decoding,
|
|
1654
|
+
* stack manipulation, exception handling (try/catch blocks within mruby code),
|
|
1655
|
+
* and calling C functions or other mruby methods.
|
|
1656
|
+
*
|
|
1657
|
+
* @param mrb The mruby state.
|
|
1658
|
+
* @param begin_proc The initial RProc whose bytecode is to be executed.
|
|
1659
|
+
* While the name suggests it's the "beginning" proc,
|
|
1660
|
+
* execution might involve other procs called from this one.
|
|
1661
|
+
* @param iseq A pointer to the first bytecode instruction to execute within
|
|
1662
|
+
* `begin_proc`'s instruction sequence.
|
|
1663
|
+
* @return The result of the execution. This could be the return value of
|
|
1664
|
+
* the executed Ruby code, an exception object if an unhandled
|
|
1665
|
+
* exception occurred, or the result of a fiber switch.
|
|
1666
|
+
* @note This function is highly complex and central to mruby's operation.
|
|
1667
|
+
* It uses a jump table (`optable`) for efficient instruction dispatch
|
|
1668
|
+
* when not using switch-based dispatch. It also manages the callinfo
|
|
1669
|
+
* stack (`ci`) for tracking method/block calls.
|
|
1670
|
+
*/
|
|
1671
|
+
MRB_API mrb_value
|
|
1672
|
+
mrb_vm_exec(mrb_state *mrb, const struct RProc *begin_proc, const mrb_code *iseq)
|
|
1673
|
+
{
|
|
1674
|
+
/* mrb_assert(MRB_PROC_CFUNC_P(begin_proc)) */
|
|
1675
|
+
const mrb_irep *irep = begin_proc->body.irep;
|
|
1676
|
+
mrb_code insn;
|
|
1677
|
+
int ai = mrb_gc_arena_save(mrb);
|
|
1678
|
+
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
|
1679
|
+
struct mrb_jmpbuf c_jmp;
|
|
1680
|
+
uint32_t a;
|
|
1681
|
+
uint16_t b;
|
|
1682
|
+
uint16_t c;
|
|
1683
|
+
mrb_sym mid;
|
|
1684
|
+
struct RClass *tc; /* target class for OP_TDEF/OP_SDEF */
|
|
1685
|
+
const struct mrb_irep_catch_handler *ch;
|
|
1686
|
+
|
|
1687
|
+
#ifndef MRB_USE_VM_SWITCH_DISPATCH
|
|
1688
|
+
static const void * const optable[] = {
|
|
1689
|
+
#define OPCODE(x,_) &&L_OP_ ## x,
|
|
1690
|
+
#include <mruby/ops.h>
|
|
1691
|
+
#undef OPCODE
|
|
1692
|
+
};
|
|
1693
|
+
#endif
|
|
1694
|
+
|
|
1695
|
+
mrb->exc = NULL;
|
|
1696
|
+
|
|
1697
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1698
|
+
CI_PROC_SET(ci, begin_proc);
|
|
1699
|
+
ci->pc = iseq;
|
|
1700
|
+
|
|
1701
|
+
RETRY_TRY_BLOCK:
|
|
1702
|
+
|
|
1703
|
+
MRB_TRY(&c_jmp) {
|
|
1704
|
+
|
|
1705
|
+
if (mrb_unlikely(mrb->exc)) {
|
|
1706
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
1707
|
+
if (mrb->exc->tt == MRB_TT_BREAK)
|
|
1708
|
+
goto L_BREAK;
|
|
1709
|
+
goto L_RAISE;
|
|
1710
|
+
}
|
|
1711
|
+
/* Intentionally store stack variable address for exception handling.
|
|
1712
|
+
* This is safe because the pointer is cleared before function returns.
|
|
1713
|
+
* Suppress GCC 12+ warning about dangling pointer. */
|
|
1714
|
+
#if defined(__GNUC__) && !defined(__clang__)
|
|
1715
|
+
#if __GNUC__ >= 12
|
|
1716
|
+
#pragma GCC diagnostic push
|
|
1717
|
+
#pragma GCC diagnostic ignored "-Wdangling-pointer"
|
|
1718
|
+
#endif
|
|
1719
|
+
#endif
|
|
1720
|
+
mrb->jmp = &c_jmp;
|
|
1721
|
+
#if defined(__GNUC__) && !defined(__clang__)
|
|
1722
|
+
#if __GNUC__ >= 12
|
|
1723
|
+
#pragma GCC diagnostic pop
|
|
1724
|
+
#endif
|
|
1725
|
+
#endif
|
|
1726
|
+
|
|
1727
|
+
INIT_DISPATCH {
|
|
1728
|
+
CASE(OP_NOP, Z) {
|
|
1729
|
+
/* do nothing */
|
|
1730
|
+
NEXT;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
CASE(OP_MOVE, BB) {
|
|
1734
|
+
regs[a] = regs[b];
|
|
1735
|
+
NEXT;
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
CASE(OP_LOADL, BB) {
|
|
1739
|
+
switch (irep->pool[b].tt) { /* number */
|
|
1740
|
+
case IREP_TT_INT32:
|
|
1741
|
+
regs[a] = mrb_int_value(mrb, (mrb_int)irep->pool[b].u.i32);
|
|
1742
|
+
break;
|
|
1743
|
+
case IREP_TT_INT64:
|
|
1744
|
+
#if defined(MRB_INT64)
|
|
1745
|
+
regs[a] = mrb_int_value(mrb, (mrb_int)irep->pool[b].u.i64);
|
|
1746
|
+
break;
|
|
1747
|
+
#else
|
|
1748
|
+
#if defined(MRB_64BIT)
|
|
1749
|
+
if (INT32_MIN <= irep->pool[b].u.i64 && irep->pool[b].u.i64 <= INT32_MAX) {
|
|
1750
|
+
regs[a] = mrb_int_value(mrb, (mrb_int)irep->pool[b].u.i64);
|
|
1751
|
+
break;
|
|
1752
|
+
}
|
|
1753
|
+
#endif
|
|
1754
|
+
goto L_INT_OVERFLOW;
|
|
1755
|
+
#endif
|
|
1756
|
+
case IREP_TT_BIGINT:
|
|
1757
|
+
#ifdef MRB_USE_BIGINT
|
|
1758
|
+
{
|
|
1759
|
+
const char *s = irep->pool[b].u.str;
|
|
1760
|
+
regs[a] = mrb_bint_new_str(mrb, s+2, (uint8_t)s[0], (int8_t)s[1]);
|
|
1761
|
+
}
|
|
1762
|
+
break;
|
|
1763
|
+
#else
|
|
1764
|
+
goto L_INT_OVERFLOW;
|
|
1765
|
+
#endif
|
|
1766
|
+
#ifndef MRB_NO_FLOAT
|
|
1767
|
+
case IREP_TT_FLOAT:
|
|
1768
|
+
regs[a] = mrb_float_value(mrb, irep->pool[b].u.f);
|
|
1769
|
+
break;
|
|
1770
|
+
#endif
|
|
1771
|
+
default:
|
|
1772
|
+
/* should not happen (tt:string) */
|
|
1773
|
+
regs[a] = mrb_nil_value();
|
|
1774
|
+
break;
|
|
1775
|
+
}
|
|
1776
|
+
NEXT;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
CASE(OP_LOADI8, BB) {
|
|
1780
|
+
SET_FIXNUM_VALUE(regs[a], b);
|
|
1781
|
+
NEXT;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
CASE(OP_LOADINEG, BB) {
|
|
1785
|
+
SET_FIXNUM_VALUE(regs[a], -b);
|
|
1786
|
+
NEXT;
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
CASE(OP_LOADI__1,B) goto L_LOADI;
|
|
1790
|
+
CASE(OP_LOADI_0,B) goto L_LOADI;
|
|
1791
|
+
CASE(OP_LOADI_1,B) goto L_LOADI;
|
|
1792
|
+
CASE(OP_LOADI_2,B) goto L_LOADI;
|
|
1793
|
+
CASE(OP_LOADI_3,B) goto L_LOADI;
|
|
1794
|
+
CASE(OP_LOADI_4,B) goto L_LOADI;
|
|
1795
|
+
CASE(OP_LOADI_5,B) goto L_LOADI;
|
|
1796
|
+
CASE(OP_LOADI_6,B) goto L_LOADI;
|
|
1797
|
+
CASE(OP_LOADI_7, B) {
|
|
1798
|
+
L_LOADI:
|
|
1799
|
+
SET_FIXNUM_VALUE(regs[a], (mrb_int)insn - (mrb_int)OP_LOADI_0);
|
|
1800
|
+
NEXT;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
CASE(OP_LOADI16, BS) {
|
|
1804
|
+
SET_FIXNUM_VALUE(regs[a], (mrb_int)(int16_t)b);
|
|
1805
|
+
NEXT;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
CASE(OP_LOADI32, BSS) {
|
|
1809
|
+
SET_INT_VALUE(mrb, regs[a], (int32_t)(((uint32_t)b<<16)+c));
|
|
1810
|
+
NEXT;
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
CASE(OP_LOADSYM, BB) {
|
|
1814
|
+
SET_SYM_VALUE(regs[a], irep->syms[b]);
|
|
1815
|
+
NEXT;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
CASE(OP_LOADNIL, B) {
|
|
1819
|
+
SET_NIL_VALUE(regs[a]);
|
|
1820
|
+
NEXT;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
CASE(OP_LOADSELF, B) {
|
|
1824
|
+
regs[a] = regs[0];
|
|
1825
|
+
NEXT;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
CASE(OP_LOADTRUE, B) {
|
|
1829
|
+
SET_TRUE_VALUE(regs[a]);
|
|
1830
|
+
NEXT;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
CASE(OP_LOADFALSE, B) {
|
|
1834
|
+
SET_FALSE_VALUE(regs[a]);
|
|
1835
|
+
NEXT;
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
CASE(OP_GETGV, BB) {
|
|
1839
|
+
mrb_value val = mrb_gv_get(mrb, irep->syms[b]);
|
|
1840
|
+
ci = mrb->c->ci;
|
|
1841
|
+
regs[a] = val;
|
|
1842
|
+
NEXT;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
CASE(OP_SETGV, BB) {
|
|
1846
|
+
mrb_gv_set(mrb, irep->syms[b], regs[a]);
|
|
1847
|
+
ci = mrb->c->ci;
|
|
1848
|
+
NEXT;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
CASE(OP_GETSV, BB) {
|
|
1852
|
+
mrb_value val = mrb_vm_special_get(mrb, irep->syms[b]);
|
|
1853
|
+
ci = mrb->c->ci;
|
|
1854
|
+
regs[a] = val;
|
|
1855
|
+
NEXT;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
CASE(OP_SETSV, BB) {
|
|
1859
|
+
mrb_vm_special_set(mrb, irep->syms[b], regs[a]);
|
|
1860
|
+
ci = mrb->c->ci;
|
|
1861
|
+
NEXT;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
CASE(OP_GETIV, BB) {
|
|
1865
|
+
regs[a] = mrb_iv_get(mrb, regs[0], irep->syms[b]);
|
|
1866
|
+
ci = mrb->c->ci;
|
|
1867
|
+
NEXT;
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
CASE(OP_SETIV, BB) {
|
|
1871
|
+
mrb_iv_set(mrb, regs[0], irep->syms[b], regs[a]);
|
|
1872
|
+
ci = mrb->c->ci;
|
|
1873
|
+
NEXT;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
CASE(OP_GETCV, BB) {
|
|
1877
|
+
mrb_value val;
|
|
1878
|
+
val = mrb_vm_cv_get(mrb, irep->syms[b]);
|
|
1879
|
+
ci = mrb->c->ci;
|
|
1880
|
+
regs[a] = val;
|
|
1881
|
+
NEXT;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
CASE(OP_SETCV, BB) {
|
|
1885
|
+
mrb_vm_cv_set(mrb, irep->syms[b], regs[a]);
|
|
1886
|
+
ci = mrb->c->ci;
|
|
1887
|
+
NEXT;
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
CASE(OP_GETIDX, B) {
|
|
1891
|
+
mrb_value va = regs[a], vb = regs[a+1];
|
|
1892
|
+
enum mrb_vtype tt = mrb_type(va);
|
|
1893
|
+
|
|
1894
|
+
/* Array case is most common - check first with branch hint */
|
|
1895
|
+
if (mrb_likely(tt == MRB_TT_ARRAY)) {
|
|
1896
|
+
struct RArray *ary = mrb_ary_ptr(va);
|
|
1897
|
+
/* optimize only for Array class; subclasses/singleton may override [] */
|
|
1898
|
+
if (mrb_unlikely(ary->c != mrb->array_class)) goto getidx_fallback;
|
|
1899
|
+
if (mrb_likely(mrb_integer_p(vb))) {
|
|
1900
|
+
mrb_int idx = mrb_integer(vb);
|
|
1901
|
+
mrb_int len;
|
|
1902
|
+
mrb_value *ptr;
|
|
1903
|
+
|
|
1904
|
+
/* Single ARY_EMBED_P check instead of two */
|
|
1905
|
+
if (ARY_EMBED_P(ary)) {
|
|
1906
|
+
len = ARY_EMBED_LEN(ary);
|
|
1907
|
+
ptr = ary->as.ary;
|
|
1908
|
+
}
|
|
1909
|
+
else {
|
|
1910
|
+
len = ary->as.heap.len;
|
|
1911
|
+
ptr = ary->as.heap.ptr;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
/* Unsigned comparison: handles negative idx as large positive */
|
|
1915
|
+
if (mrb_likely((mrb_uint)idx < (mrb_uint)len)) {
|
|
1916
|
+
regs[a] = ptr[idx];
|
|
1917
|
+
}
|
|
1918
|
+
else {
|
|
1919
|
+
regs[a] = mrb_ary_entry(va, idx);
|
|
1920
|
+
}
|
|
1921
|
+
NEXT;
|
|
1922
|
+
}
|
|
1923
|
+
goto getidx_fallback;
|
|
1924
|
+
}
|
|
1925
|
+
else if (tt == MRB_TT_HASH) {
|
|
1926
|
+
/* optimize only for Hash class; subclasses/singleton may override [] */
|
|
1927
|
+
if (mrb_obj_ptr(va)->c != mrb->hash_class) goto getidx_fallback;
|
|
1928
|
+
va = mrb_hash_get(mrb, va, vb);
|
|
1929
|
+
ci = mrb->c->ci;
|
|
1930
|
+
regs[a] = va;
|
|
1931
|
+
NEXT;
|
|
1932
|
+
}
|
|
1933
|
+
else if (tt == MRB_TT_STRING) {
|
|
1934
|
+
/* optimize only for String class; subclasses/singleton may override [] */
|
|
1935
|
+
if (mrb_obj_ptr(va)->c != mrb->string_class) goto getidx_fallback;
|
|
1936
|
+
switch (mrb_type(vb)) {
|
|
1937
|
+
case MRB_TT_INTEGER:
|
|
1938
|
+
case MRB_TT_STRING:
|
|
1939
|
+
case MRB_TT_RANGE:
|
|
1940
|
+
va = mrb_str_aref(mrb, va, vb, mrb_undef_value());
|
|
1941
|
+
regs[a] = va;
|
|
1942
|
+
NEXT;
|
|
1943
|
+
default:
|
|
1944
|
+
break;
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
getidx_fallback:
|
|
1948
|
+
mid = MRB_OPSYM(aref);
|
|
1949
|
+
goto L_SEND_SYM;
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
CASE(OP_GETIDX0, BB) {
|
|
1953
|
+
mrb_value recv = regs[b];
|
|
1954
|
+
enum mrb_vtype tt = mrb_type(recv);
|
|
1955
|
+
|
|
1956
|
+
if (mrb_likely(tt == MRB_TT_ARRAY)) {
|
|
1957
|
+
struct RArray *ary = mrb_ary_ptr(recv);
|
|
1958
|
+
if (mrb_unlikely(ary->c != mrb->array_class)) goto getidx0_fallback;
|
|
1959
|
+
if (ARY_EMBED_P(ary)) {
|
|
1960
|
+
regs[a] = ARY_EMBED_LEN(ary) > 0 ? ary->as.ary[0] : mrb_nil_value();
|
|
1961
|
+
}
|
|
1962
|
+
else {
|
|
1963
|
+
regs[a] = ary->as.heap.len > 0 ? ary->as.heap.ptr[0] : mrb_nil_value();
|
|
1964
|
+
}
|
|
1965
|
+
NEXT;
|
|
1966
|
+
}
|
|
1967
|
+
else if (tt == MRB_TT_HASH) {
|
|
1968
|
+
if (mrb_obj_ptr(recv)->c != mrb->hash_class) goto getidx0_fallback;
|
|
1969
|
+
regs[a] = mrb_hash_get(mrb, recv, mrb_fixnum_value(0));
|
|
1970
|
+
NEXT;
|
|
1971
|
+
}
|
|
1972
|
+
getidx0_fallback:
|
|
1973
|
+
regs[a] = recv;
|
|
1974
|
+
SET_FIXNUM_VALUE(regs[a+1], 0);
|
|
1975
|
+
mid = MRB_OPSYM(aref);
|
|
1976
|
+
goto L_SEND_SYM;
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
CASE(OP_SETIDX, B) {
|
|
1980
|
+
mrb_value va = regs[a], vb = regs[a+1], vc = regs[a+2];
|
|
1981
|
+
switch (mrb_type(va)) {
|
|
1982
|
+
case MRB_TT_ARRAY:
|
|
1983
|
+
/* optimize only for Array class; subclasses/singleton may override []= */
|
|
1984
|
+
if (mrb_obj_ptr(va)->c != mrb->array_class) goto setidx_fallback;
|
|
1985
|
+
if (!mrb_integer_p(vb)) goto setidx_fallback;
|
|
1986
|
+
mrb_ary_set(mrb, va, mrb_integer(vb), vc);
|
|
1987
|
+
ci = mrb->c->ci;
|
|
1988
|
+
regs[a] = vc;
|
|
1989
|
+
NEXT;
|
|
1990
|
+
case MRB_TT_HASH:
|
|
1991
|
+
/* optimize only for Hash class; subclasses/singleton may override []= */
|
|
1992
|
+
if (mrb_obj_ptr(va)->c != mrb->hash_class) goto setidx_fallback;
|
|
1993
|
+
mrb_hash_set(mrb, va, vb, vc);
|
|
1994
|
+
ci = mrb->c->ci;
|
|
1995
|
+
regs[a] = vc;
|
|
1996
|
+
NEXT;
|
|
1997
|
+
default:
|
|
1998
|
+
setidx_fallback:
|
|
1999
|
+
c = 2;
|
|
2000
|
+
mid = MRB_OPSYM(aset);
|
|
2001
|
+
SET_NIL_VALUE(regs[a+3]);
|
|
2002
|
+
goto L_SENDB_SYM;
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
CASE(OP_GETCONST, BB) {
|
|
2007
|
+
mrb_value v = mrb_vm_const_get(mrb, irep->syms[b]);
|
|
2008
|
+
ci = mrb->c->ci;
|
|
2009
|
+
regs[a] = v;
|
|
2010
|
+
NEXT;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
CASE(OP_SETCONST, BB) {
|
|
2014
|
+
ci = mrb->c->ci;
|
|
2015
|
+
struct RClass *c = MRB_PROC_TARGET_CLASS(ci->proc);
|
|
2016
|
+
if (!c) c = mrb->object_class;
|
|
2017
|
+
mrb_const_set(mrb, mrb_obj_value(c), irep->syms[b], regs[a]);
|
|
2018
|
+
NEXT;
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
CASE(OP_GETMCNST, BB) {
|
|
2022
|
+
mrb_value v = mrb_const_get(mrb, regs[a], irep->syms[b]);
|
|
2023
|
+
ci = mrb->c->ci;
|
|
2024
|
+
regs[a] = v;
|
|
2025
|
+
NEXT;
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
CASE(OP_SETMCNST, BB) {
|
|
2029
|
+
mrb_const_set(mrb, regs[a+1], irep->syms[b], regs[a]);
|
|
2030
|
+
ci = mrb->c->ci;
|
|
2031
|
+
NEXT;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
CASE(OP_GETUPVAR, BBB) {
|
|
2035
|
+
struct REnv *e = uvenv(mrb, c);
|
|
2036
|
+
|
|
2037
|
+
if (e && b < MRB_ENV_LEN(e)) {
|
|
2038
|
+
regs[a] = e->stack[b];
|
|
2039
|
+
}
|
|
2040
|
+
else {
|
|
2041
|
+
regs[a] = mrb_nil_value();
|
|
2042
|
+
}
|
|
2043
|
+
NEXT;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
CASE(OP_SETUPVAR, BBB) {
|
|
2047
|
+
struct REnv *e = uvenv(mrb, c);
|
|
2048
|
+
|
|
2049
|
+
if (e) {
|
|
2050
|
+
if (b < MRB_ENV_LEN(e)) {
|
|
2051
|
+
e->stack[b] = regs[a];
|
|
2052
|
+
mrb_write_barrier(mrb, (struct RBasic*)e);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
NEXT;
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
CASE(OP_JMP, S) {
|
|
2059
|
+
ci->pc += (int16_t)a;
|
|
2060
|
+
JUMP;
|
|
2061
|
+
}
|
|
2062
|
+
CASE(OP_JMPIF, BS) {
|
|
2063
|
+
if (mrb_test(regs[a])) {
|
|
2064
|
+
ci->pc += (int16_t)b;
|
|
2065
|
+
JUMP;
|
|
2066
|
+
}
|
|
2067
|
+
NEXT;
|
|
2068
|
+
}
|
|
2069
|
+
CASE(OP_JMPNOT, BS) {
|
|
2070
|
+
if (!mrb_test(regs[a])) {
|
|
2071
|
+
ci->pc += (int16_t)b;
|
|
2072
|
+
JUMP;
|
|
2073
|
+
}
|
|
2074
|
+
NEXT;
|
|
2075
|
+
}
|
|
2076
|
+
CASE(OP_JMPNIL, BS) {
|
|
2077
|
+
if (mrb_nil_p(regs[a])) {
|
|
2078
|
+
ci->pc += (int16_t)b;
|
|
2079
|
+
JUMP;
|
|
2080
|
+
}
|
|
2081
|
+
NEXT;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
CASE(OP_JMPUW, S) {
|
|
2085
|
+
a = (uint32_t)((ci->pc - irep->iseq) + (int16_t)a);
|
|
2086
|
+
CHECKPOINT_RESTORE(RBREAK_TAG_JUMP) {
|
|
2087
|
+
struct RBreak *brk = (struct RBreak*)mrb->exc;
|
|
2088
|
+
mrb_value target = mrb_break_value_get(brk);
|
|
2089
|
+
mrb_assert(mrb_integer_p(target));
|
|
2090
|
+
a = (uint32_t)mrb_integer(target);
|
|
2091
|
+
mrb_assert(a >= 0 && a < irep->ilen);
|
|
2092
|
+
}
|
|
2093
|
+
CHECKPOINT_MAIN(RBREAK_TAG_JUMP) {
|
|
2094
|
+
if (irep->clen > 0 &&
|
|
2095
|
+
(ch = catch_handler_find(irep, ci->pc, MRB_CATCH_FILTER_ENSURE))) {
|
|
2096
|
+
/* avoiding a jump from a catch handler into the same handler */
|
|
2097
|
+
if (a < mrb_irep_catch_handler_unpack(ch->begin) || a > mrb_irep_catch_handler_unpack(ch->end)) {
|
|
2098
|
+
THROW_TAGGED_BREAK(mrb, RBREAK_TAG_JUMP, mrb->c->ci, mrb_fixnum_value(a));
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
CHECKPOINT_END(RBREAK_TAG_JUMP);
|
|
2103
|
+
|
|
2104
|
+
mrb->exc = NULL; /* clear break object */
|
|
2105
|
+
ci->pc = irep->iseq + a;
|
|
2106
|
+
JUMP;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
CASE(OP_EXCEPT, B) {
|
|
2110
|
+
mrb_value exc;
|
|
2111
|
+
|
|
2112
|
+
if (mrb->exc == NULL) {
|
|
2113
|
+
exc = mrb_nil_value();
|
|
2114
|
+
}
|
|
2115
|
+
else {
|
|
2116
|
+
switch (mrb->exc->tt) {
|
|
2117
|
+
case MRB_TT_BREAK:
|
|
2118
|
+
case MRB_TT_EXCEPTION:
|
|
2119
|
+
exc = mrb_obj_value(mrb->exc);
|
|
2120
|
+
break;
|
|
2121
|
+
default:
|
|
2122
|
+
mrb_assert(!"bad mrb_type");
|
|
2123
|
+
exc = mrb_nil_value();
|
|
2124
|
+
break;
|
|
2125
|
+
}
|
|
2126
|
+
mrb->exc = NULL;
|
|
2127
|
+
}
|
|
2128
|
+
regs[a] = exc;
|
|
2129
|
+
NEXT;
|
|
2130
|
+
}
|
|
2131
|
+
CASE(OP_RESCUE, BB) {
|
|
2132
|
+
mrb_value exc = regs[a]; /* exc on stack */
|
|
2133
|
+
mrb_value e = regs[b];
|
|
2134
|
+
struct RClass *ec;
|
|
2135
|
+
|
|
2136
|
+
switch (mrb_type(e)) {
|
|
2137
|
+
case MRB_TT_CLASS:
|
|
2138
|
+
case MRB_TT_MODULE:
|
|
2139
|
+
break;
|
|
2140
|
+
default:
|
|
2141
|
+
RAISE_LIT(mrb, E_TYPE_ERROR, "class or module required for rescue clause");
|
|
2142
|
+
}
|
|
2143
|
+
ec = mrb_class_ptr(e);
|
|
2144
|
+
regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec));
|
|
2145
|
+
NEXT;
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
CASE(OP_RAISEIF, B) {
|
|
2149
|
+
mrb_value exc;
|
|
2150
|
+
exc = regs[a];
|
|
2151
|
+
if (mrb_likely(mrb_nil_p(exc))) {
|
|
2152
|
+
mrb->exc = NULL;
|
|
2153
|
+
}
|
|
2154
|
+
else if (mrb_break_p(exc)) {
|
|
2155
|
+
struct RBreak *brk;
|
|
2156
|
+
mrb->exc = mrb_obj_ptr(exc);
|
|
2157
|
+
L_BREAK:
|
|
2158
|
+
brk = (struct RBreak*)mrb->exc;
|
|
2159
|
+
switch (mrb_break_tag_get(brk)) {
|
|
2160
|
+
#define DISPATCH_CHECKPOINTS(n, i) case n: goto CHECKPOINT_LABEL_MAKE(n);
|
|
2161
|
+
RBREAK_TAG_FOREACH(DISPATCH_CHECKPOINTS)
|
|
2162
|
+
#undef DISPATCH_CHECKPOINTS
|
|
2163
|
+
default:
|
|
2164
|
+
mrb_assert(!"wrong break tag");
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
else {
|
|
2168
|
+
mrb_exc_set(mrb, exc);
|
|
2169
|
+
L_RAISE:
|
|
2170
|
+
ci = mrb->c->ci;
|
|
2171
|
+
while (!ci->proc || MRB_PROC_CFUNC_P(ci->proc) || !(irep = ci->proc->body.irep) || irep->clen < 1 ||
|
|
2172
|
+
(ch = catch_handler_find(irep, ci->pc, MRB_CATCH_FILTER_ALL)) == NULL) {
|
|
2173
|
+
if (ci != mrb->c->cibase) {
|
|
2174
|
+
ci = cipop(mrb);
|
|
2175
|
+
if (ci[1].cci == CINFO_SKIP) {
|
|
2176
|
+
mrb_assert(prev_jmp != NULL);
|
|
2177
|
+
mrb->jmp = prev_jmp;
|
|
2178
|
+
MRB_THROW(prev_jmp);
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
else if (mrb->c == mrb->root_c) {
|
|
2182
|
+
ci->stack = mrb->c->stbase;
|
|
2183
|
+
mrb->jmp = prev_jmp;
|
|
2184
|
+
return mrb_obj_value(mrb->exc);
|
|
2185
|
+
}
|
|
2186
|
+
else {
|
|
2187
|
+
struct mrb_context *c = mrb->c;
|
|
2188
|
+
|
|
2189
|
+
fiber_terminate(mrb, c, ci);
|
|
2190
|
+
if (mrb_unlikely(!c->vmexec)) goto L_RAISE;
|
|
2191
|
+
mrb->jmp = prev_jmp;
|
|
2192
|
+
if (!prev_jmp) return mrb_obj_value(mrb->exc);
|
|
2193
|
+
MRB_THROW(prev_jmp);
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
if (FALSE) {
|
|
2198
|
+
L_CATCH_TAGGED_BREAK: /* from THROW_TAGGED_BREAK() or UNWIND_ENSURE() */
|
|
2199
|
+
ci = mrb->c->ci;
|
|
2200
|
+
}
|
|
2201
|
+
irep = ci->proc->body.irep;
|
|
2202
|
+
stack_extend(mrb, irep->nregs);
|
|
2203
|
+
ci->pc = irep->iseq + mrb_irep_catch_handler_unpack(ch->target);
|
|
2204
|
+
}
|
|
2205
|
+
NEXT;
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
CASE(OP_MATCHERR, B) {
|
|
2209
|
+
if (mrb_unlikely(!mrb_test(regs[a]))) {
|
|
2210
|
+
RAISE_LIT(mrb, mrb_exc_get_id(mrb, MRB_ERROR_SYM(NoMatchingPatternError)), "pattern not matched");
|
|
2211
|
+
}
|
|
2212
|
+
NEXT;
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
CASE(OP_SSEND, BBB) {
|
|
2216
|
+
regs[a] = regs[0];
|
|
2217
|
+
}
|
|
2218
|
+
goto L_SENDB;
|
|
2219
|
+
|
|
2220
|
+
CASE(OP_SSEND0, BB) {
|
|
2221
|
+
regs[a] = regs[0];
|
|
2222
|
+
c = 0;
|
|
2223
|
+
}
|
|
2224
|
+
goto L_SENDB;
|
|
2225
|
+
|
|
2226
|
+
CASE(OP_SSENDB, BBB) {
|
|
2227
|
+
regs[a] = regs[0];
|
|
2228
|
+
}
|
|
2229
|
+
goto L_SENDB;
|
|
2230
|
+
|
|
2231
|
+
CASE(OP_SEND, BBB)
|
|
2232
|
+
goto L_SENDB;
|
|
2233
|
+
|
|
2234
|
+
CASE(OP_SEND0, BB) {
|
|
2235
|
+
c = 0;
|
|
2236
|
+
}
|
|
2237
|
+
goto L_SENDB;
|
|
2238
|
+
|
|
2239
|
+
L_SEND_SYM:
|
|
2240
|
+
c = 1;
|
|
2241
|
+
/* push nil after arguments */
|
|
2242
|
+
SET_NIL_VALUE(regs[a+2]);
|
|
2243
|
+
goto L_SENDB_SYM;
|
|
2244
|
+
|
|
2245
|
+
CASE(OP_SENDB, BBB)
|
|
2246
|
+
L_SENDB:
|
|
2247
|
+
mid = irep->syms[b];
|
|
2248
|
+
L_SENDB_SYM:
|
|
2249
|
+
{
|
|
2250
|
+
mrb_method_t m;
|
|
2251
|
+
mrb_value recv, blk;
|
|
2252
|
+
mrb_int bidx, new_bidx;
|
|
2253
|
+
|
|
2254
|
+
if (mrb_likely(c < CALL_MAXARGS)) {
|
|
2255
|
+
/* fast path limited to fixed length arguments of less than 15 */
|
|
2256
|
+
bidx = a + c + 1 /* self */;
|
|
2257
|
+
new_bidx = bidx;
|
|
2258
|
+
}
|
|
2259
|
+
else {
|
|
2260
|
+
int n = c&0xf;
|
|
2261
|
+
int nk = (c>>4)&0xf;
|
|
2262
|
+
bidx = a + mrb_bidx(n,nk);
|
|
2263
|
+
new_bidx = bidx;
|
|
2264
|
+
if (nk == CALL_MAXARGS) {
|
|
2265
|
+
mrb_ensure_hash_type(mrb, regs[a+(n==CALL_MAXARGS?1:n)+1]);
|
|
2266
|
+
}
|
|
2267
|
+
else if (nk > 0) { /* pack keyword arguments */
|
|
2268
|
+
mrb_int kidx = a+(n==CALL_MAXARGS?1:n)+1;
|
|
2269
|
+
mrb_value kdict = hash_new_from_regs(mrb, nk, kidx);
|
|
2270
|
+
ci = mrb->c->ci;
|
|
2271
|
+
regs[kidx] = kdict;
|
|
2272
|
+
nk = CALL_MAXARGS;
|
|
2273
|
+
c = n | (nk<<4);
|
|
2274
|
+
new_bidx = a+mrb_bidx(n, nk);
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
mrb_assert(bidx < irep->nregs);
|
|
2279
|
+
if (insn == OP_SEND || insn == OP_SEND0 || insn == OP_SSEND || insn == OP_SSEND0) {
|
|
2280
|
+
/* clear block argument */
|
|
2281
|
+
SET_NIL_VALUE(regs[new_bidx]);
|
|
2282
|
+
SET_NIL_VALUE(blk);
|
|
2283
|
+
}
|
|
2284
|
+
else {
|
|
2285
|
+
blk = ensure_block(mrb, regs[bidx]);
|
|
2286
|
+
ci = mrb->c->ci;
|
|
2287
|
+
regs[new_bidx] = blk;
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
ci = cipush(mrb, a, CINFO_DIRECT, NULL, NULL, BLK_PTR(blk), 0, c);
|
|
2291
|
+
recv = regs[0];
|
|
2292
|
+
ci->u.target_class = (insn == OP_SUPER) ? CI_TARGET_CLASS(ci - 1)->super : mrb_class(mrb, recv);
|
|
2293
|
+
m = mrb_vm_find_method(mrb, ci->u.target_class, &ci->u.target_class, mid);
|
|
2294
|
+
if (mrb_unlikely(MRB_METHOD_UNDEF_P(m))) {
|
|
2295
|
+
m = prepare_missing(mrb, ci, recv, mid, blk, (insn == OP_SUPER));
|
|
2296
|
+
}
|
|
2297
|
+
else {
|
|
2298
|
+
ci->mid = mid;
|
|
2299
|
+
}
|
|
2300
|
+
if (insn == OP_SEND || insn == OP_SEND0 || insn == OP_SENDB) {
|
|
2301
|
+
mrb_bool priv = TRUE;
|
|
2302
|
+
if (m.flags & MRB_METHOD_PRIVATE_FL) {
|
|
2303
|
+
vis_err:;
|
|
2304
|
+
mrb_value args = (ci->n == 15) ? regs[1] : mrb_ary_new_from_values(mrb, ci->n, regs+1);
|
|
2305
|
+
vis_error(mrb, mid, args, recv, priv);
|
|
2306
|
+
}
|
|
2307
|
+
else if ((m.flags & MRB_METHOD_PROTECTED_FL) && mrb_obj_is_kind_of(mrb, recv, ci->u.target_class)) {
|
|
2308
|
+
priv = FALSE;
|
|
2309
|
+
goto vis_err;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
ci->cci = CINFO_NONE;
|
|
2313
|
+
|
|
2314
|
+
if (MRB_METHOD_PROC_P(m)) {
|
|
2315
|
+
const struct RProc *p = MRB_METHOD_PROC(m);
|
|
2316
|
+
/* handle alias */
|
|
2317
|
+
MRB_PROC_RESOLVE_ALIAS(ci, p);
|
|
2318
|
+
CI_PROC_SET(ci, p);
|
|
2319
|
+
if (!MRB_PROC_CFUNC_P(p)) {
|
|
2320
|
+
/* setup environment for calling method */
|
|
2321
|
+
irep = p->body.irep;
|
|
2322
|
+
stack_extend(mrb, (irep->nregs < 4) ? 4 : irep->nregs);
|
|
2323
|
+
ci->pc = irep->iseq;
|
|
2324
|
+
JUMP;
|
|
2325
|
+
}
|
|
2326
|
+
else {
|
|
2327
|
+
if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
|
2328
|
+
check_argument_count(mrb, ci, 0);
|
|
2329
|
+
}
|
|
2330
|
+
recv = MRB_PROC_CFUNC(p)(mrb, recv);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
else {
|
|
2334
|
+
check_argument_count(mrb, ci, MRB_MT_ASPEC(m.flags));
|
|
2335
|
+
recv = MRB_METHOD_FUNC(m)(mrb, recv);
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
/* cfunc epilogue */
|
|
2339
|
+
mrb_gc_arena_shrink(mrb, ai);
|
|
2340
|
+
if (mrb_unlikely(mrb->exc)) goto L_RAISE;
|
|
2341
|
+
ci = mrb->c->ci;
|
|
2342
|
+
if (!ci->u.keep_context) { /* return from context modifying method (resume/yield) */
|
|
2343
|
+
if (ci->cci == CINFO_RESUMED) {
|
|
2344
|
+
mrb->jmp = prev_jmp;
|
|
2345
|
+
return recv;
|
|
2346
|
+
}
|
|
2347
|
+
else {
|
|
2348
|
+
mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
|
|
2349
|
+
irep = ci[-1].proc->body.irep;
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
mrb_assert(ci > mrb->c->cibase);
|
|
2353
|
+
ci->stack[0] = recv;
|
|
2354
|
+
/* pop stackpos */
|
|
2355
|
+
ci = cipop(mrb);
|
|
2356
|
+
JUMP;
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
CASE(OP_CALL, Z) {
|
|
2360
|
+
mrb_value recv = ci->stack[0];
|
|
2361
|
+
const struct RProc *p = mrb_proc_ptr(recv);
|
|
2362
|
+
|
|
2363
|
+
/* handle alias */
|
|
2364
|
+
MRB_PROC_RESOLVE_ALIAS(ci, p);
|
|
2365
|
+
if (MRB_PROC_ENV_P(p)) {
|
|
2366
|
+
ci->mid = MRB_PROC_ENV(p)->mid;
|
|
2367
|
+
}
|
|
2368
|
+
/* replace callinfo */
|
|
2369
|
+
ci->u.target_class = MRB_PROC_TARGET_CLASS(p);
|
|
2370
|
+
CI_PROC_SET(ci, p);
|
|
2371
|
+
|
|
2372
|
+
/* prepare stack */
|
|
2373
|
+
if (MRB_PROC_CFUNC_P(p)) {
|
|
2374
|
+
recv = MRB_PROC_CFUNC(p)(mrb, recv);
|
|
2375
|
+
mrb_gc_arena_shrink(mrb, ai);
|
|
2376
|
+
if (mrb_unlikely(mrb->exc)) goto L_RAISE;
|
|
2377
|
+
/* pop stackpos */
|
|
2378
|
+
ci = cipop(mrb);
|
|
2379
|
+
ci[1].stack[0] = recv;
|
|
2380
|
+
irep = ci->proc->body.irep;
|
|
2381
|
+
}
|
|
2382
|
+
else {
|
|
2383
|
+
/* setup environment for calling method */
|
|
2384
|
+
irep = p->body.irep;
|
|
2385
|
+
if (!irep) {
|
|
2386
|
+
ci->stack[0] = mrb_nil_value();
|
|
2387
|
+
a = 0;
|
|
2388
|
+
goto L_OP_RETURN_BODY;
|
|
2389
|
+
}
|
|
2390
|
+
mrb_int nargs = ci_bidx(ci)+1;
|
|
2391
|
+
if (nargs < irep->nregs) {
|
|
2392
|
+
stack_extend(mrb, irep->nregs);
|
|
2393
|
+
stack_clear(regs+nargs, irep->nregs-nargs);
|
|
2394
|
+
}
|
|
2395
|
+
if (MRB_PROC_ENV_P(p)) {
|
|
2396
|
+
regs[0] = MRB_PROC_ENV(p)->stack[0];
|
|
2397
|
+
}
|
|
2398
|
+
ci->pc = irep->iseq;
|
|
2399
|
+
}
|
|
2400
|
+
JUMP;
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
CASE(OP_BLKCALL, BB) {
|
|
2404
|
+
/* Direct block call: R[a] = R[a].call(R[a+1],...,R[a+b]) */
|
|
2405
|
+
/* Skip method dispatch - directly invoke the proc */
|
|
2406
|
+
mrb_value recv = regs[a];
|
|
2407
|
+
const struct RProc *p;
|
|
2408
|
+
|
|
2409
|
+
if (mrb_unlikely(!mrb_proc_p(recv))) {
|
|
2410
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "wrong type %T (expected Proc)", recv);
|
|
2411
|
+
}
|
|
2412
|
+
p = mrb_proc_ptr(recv);
|
|
2413
|
+
|
|
2414
|
+
/* push callinfo */
|
|
2415
|
+
ci = cipush(mrb, a, CINFO_DIRECT, NULL, NULL, NULL, 0, b);
|
|
2416
|
+
ci->cci = CINFO_NONE; /* mark as VM-to-VM call for proper break handling */
|
|
2417
|
+
|
|
2418
|
+
/* handle alias */
|
|
2419
|
+
MRB_PROC_RESOLVE_ALIAS(ci, p);
|
|
2420
|
+
if (MRB_PROC_ENV_P(p)) {
|
|
2421
|
+
ci->mid = MRB_PROC_ENV(p)->mid;
|
|
2422
|
+
}
|
|
2423
|
+
ci->u.target_class = MRB_PROC_TARGET_CLASS(p);
|
|
2424
|
+
CI_PROC_SET(ci, p);
|
|
2425
|
+
|
|
2426
|
+
if (MRB_PROC_CFUNC_P(p)) {
|
|
2427
|
+
recv = MRB_PROC_CFUNC(p)(mrb, recv);
|
|
2428
|
+
mrb_gc_arena_shrink(mrb, ai);
|
|
2429
|
+
if (mrb_unlikely(mrb->exc)) goto L_RAISE;
|
|
2430
|
+
ci = cipop(mrb);
|
|
2431
|
+
ci[1].stack[0] = recv;
|
|
2432
|
+
irep = ci->proc->body.irep;
|
|
2433
|
+
}
|
|
2434
|
+
else {
|
|
2435
|
+
irep = p->body.irep;
|
|
2436
|
+
if (!irep) {
|
|
2437
|
+
ci->stack[0] = mrb_nil_value();
|
|
2438
|
+
a = 0;
|
|
2439
|
+
goto L_OP_RETURN_BODY;
|
|
2440
|
+
}
|
|
2441
|
+
mrb_int nargs = b + 1; /* args + self */
|
|
2442
|
+
if (nargs < irep->nregs) {
|
|
2443
|
+
stack_extend(mrb, irep->nregs);
|
|
2444
|
+
stack_clear(regs+nargs, irep->nregs-nargs);
|
|
2445
|
+
}
|
|
2446
|
+
if (MRB_PROC_ENV_P(p)) {
|
|
2447
|
+
regs[0] = MRB_PROC_ENV(p)->stack[0];
|
|
2448
|
+
}
|
|
2449
|
+
ci->pc = irep->iseq;
|
|
2450
|
+
}
|
|
2451
|
+
JUMP;
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
CASE(OP_SUPER, BB) {
|
|
2455
|
+
mrb_value recv;
|
|
2456
|
+
struct RClass* target_class = CI_TARGET_CLASS(ci);
|
|
2457
|
+
|
|
2458
|
+
mid = ci->mid;
|
|
2459
|
+
if (mid == 0 || !target_class) {
|
|
2460
|
+
RAISE_LIT(mrb, E_NOMETHOD_ERROR, "super called outside of method");
|
|
2461
|
+
}
|
|
2462
|
+
if ((target_class->flags & MRB_FL_CLASS_IS_PREPENDED) || target_class->tt == MRB_TT_MODULE) {
|
|
2463
|
+
goto super_typeerror;
|
|
2464
|
+
}
|
|
2465
|
+
recv = regs[0];
|
|
2466
|
+
if (!mrb_obj_is_kind_of(mrb, recv, target_class)) {
|
|
2467
|
+
super_typeerror:
|
|
2468
|
+
RAISE_LIT(mrb, E_TYPE_ERROR, "self has wrong type to call super in this context");
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
c = b; // arg info
|
|
2472
|
+
regs[a] = recv;
|
|
2473
|
+
goto L_SENDB_SYM;
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
CASE(OP_ARGARY, BS) {
|
|
2477
|
+
mrb_int m1 = (b>>11)&0x3f;
|
|
2478
|
+
mrb_int r = (b>>10)&0x1;
|
|
2479
|
+
mrb_int m2 = (b>>5)&0x1f;
|
|
2480
|
+
mrb_int kd = (b>>4)&0x1;
|
|
2481
|
+
mrb_int lv = (b>>0)&0xf;
|
|
2482
|
+
mrb_value *stack;
|
|
2483
|
+
|
|
2484
|
+
if (ci->mid == 0 || CI_TARGET_CLASS(ci) == NULL) {
|
|
2485
|
+
L_NOSUPER:
|
|
2486
|
+
RAISE_LIT(mrb, E_NOMETHOD_ERROR, "super called outside of method");
|
|
2487
|
+
}
|
|
2488
|
+
if (lv == 0) stack = regs + 1;
|
|
2489
|
+
else {
|
|
2490
|
+
struct REnv *e = uvenv(mrb, lv-1);
|
|
2491
|
+
if (!e) goto L_NOSUPER;
|
|
2492
|
+
if (MRB_ENV_LEN(e) <= m1+r+m2+1)
|
|
2493
|
+
goto L_NOSUPER;
|
|
2494
|
+
stack = e->stack + 1;
|
|
2495
|
+
}
|
|
2496
|
+
if (r == 0) {
|
|
2497
|
+
regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack);
|
|
2498
|
+
}
|
|
2499
|
+
else {
|
|
2500
|
+
mrb_value *pp = NULL;
|
|
2501
|
+
struct RArray *rest;
|
|
2502
|
+
mrb_int len = 0;
|
|
2503
|
+
|
|
2504
|
+
if (mrb_array_p(stack[m1])) {
|
|
2505
|
+
struct RArray *ary = mrb_ary_ptr(stack[m1]);
|
|
2506
|
+
|
|
2507
|
+
pp = ARY_PTR(ary);
|
|
2508
|
+
len = ARY_LEN(ary);
|
|
2509
|
+
}
|
|
2510
|
+
regs[a] = mrb_ary_new_capa(mrb, m1+len+m2);
|
|
2511
|
+
rest = mrb_ary_ptr(regs[a]);
|
|
2512
|
+
if (m1 > 0) {
|
|
2513
|
+
stack_copy(ARY_PTR(rest), stack, m1);
|
|
2514
|
+
}
|
|
2515
|
+
if (len > 0) {
|
|
2516
|
+
stack_copy(ARY_PTR(rest)+m1, pp, len);
|
|
2517
|
+
}
|
|
2518
|
+
if (m2 > 0) {
|
|
2519
|
+
stack_copy(ARY_PTR(rest)+m1+len, stack+m1+1, m2);
|
|
2520
|
+
}
|
|
2521
|
+
ARY_SET_LEN(rest, m1+len+m2);
|
|
2522
|
+
}
|
|
2523
|
+
if (kd) {
|
|
2524
|
+
regs[a+1] = stack[m1+r+m2];
|
|
2525
|
+
regs[a+2] = stack[m1+r+m2+1];
|
|
2526
|
+
}
|
|
2527
|
+
else {
|
|
2528
|
+
regs[a+1] = stack[m1+r+m2];
|
|
2529
|
+
}
|
|
2530
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2531
|
+
NEXT;
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
CASE(OP_ENTER, W) {
|
|
2535
|
+
mrb_int argc = ci->n;
|
|
2536
|
+
mrb_value *argv = regs+1;
|
|
2537
|
+
|
|
2538
|
+
mrb_int m1 = MRB_ASPEC_REQ(a);
|
|
2539
|
+
|
|
2540
|
+
/* no other args */
|
|
2541
|
+
if ((a & ~0x7c0001) == 0 && argc < 15 && MRB_PROC_STRICT_P(ci->proc)) {
|
|
2542
|
+
if (mrb_unlikely(argc+(ci->nk==15) != m1)) { /* count kdict too */
|
|
2543
|
+
argnum_error(mrb, m1);
|
|
2544
|
+
goto L_RAISE;
|
|
2545
|
+
}
|
|
2546
|
+
/* clear local (but non-argument) variables */
|
|
2547
|
+
mrb_int pos = m1+2; /* self+m1+blk */
|
|
2548
|
+
if (irep->nlocals-pos > 0) {
|
|
2549
|
+
stack_clear(®s[pos], irep->nlocals-pos);
|
|
2550
|
+
}
|
|
2551
|
+
NEXT;
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
mrb_int o = MRB_ASPEC_OPT(a);
|
|
2555
|
+
mrb_int r = MRB_ASPEC_REST(a);
|
|
2556
|
+
mrb_int m2 = MRB_ASPEC_POST(a);
|
|
2557
|
+
mrb_int kd = (MRB_ASPEC_KEY(a) > 0 || MRB_ASPEC_KDICT(a))? 1 : 0;
|
|
2558
|
+
/* unused
|
|
2559
|
+
int b = MRB_ASPEC_BLOCK(a);
|
|
2560
|
+
*/
|
|
2561
|
+
mrb_int const len = m1 + o + r + m2;
|
|
2562
|
+
|
|
2563
|
+
mrb_value * const argv0 = argv;
|
|
2564
|
+
mrb_value blk = regs[ci_bidx(ci)];
|
|
2565
|
+
|
|
2566
|
+
/* &nil: reject block */
|
|
2567
|
+
if (MRB_ASPEC_NOBLOCK(a) && !mrb_nil_p(blk)) {
|
|
2568
|
+
RAISE_LIT(mrb, E_ARGUMENT_ERROR, "no block accepted");
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
mrb_value kdict = mrb_nil_value();
|
|
2572
|
+
|
|
2573
|
+
/* keyword arguments */
|
|
2574
|
+
if (ci->nk == 15) {
|
|
2575
|
+
kdict = regs[mrb_ci_kidx(ci)];
|
|
2576
|
+
}
|
|
2577
|
+
if (!kd) {
|
|
2578
|
+
if (!mrb_nil_p(kdict) && mrb_hash_p(kdict) && mrb_hash_size(mrb, kdict) > 0) {
|
|
2579
|
+
if (argc < 14) {
|
|
2580
|
+
ci->n++;
|
|
2581
|
+
argc++; /* include kdict in normal arguments */
|
|
2582
|
+
}
|
|
2583
|
+
else if (argc == 14) {
|
|
2584
|
+
/* pack arguments and kdict */
|
|
2585
|
+
regs[1] = ary_new_from_regs(mrb, argc+1, 1);
|
|
2586
|
+
argc = ci->n = 15;
|
|
2587
|
+
}
|
|
2588
|
+
else {/* argc == 15 */
|
|
2589
|
+
/* push kdict to packed arguments */
|
|
2590
|
+
mrb_ary_push(mrb, regs[1], kdict);
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
kdict = mrb_nil_value();
|
|
2594
|
+
ci->nk = 0;
|
|
2595
|
+
}
|
|
2596
|
+
else if (!mrb_nil_p(kdict)) {
|
|
2597
|
+
mrb_gc_protect(mrb, kdict);
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
/* arguments is passed with Array */
|
|
2601
|
+
if (argc == 15) {
|
|
2602
|
+
struct RArray *ary = mrb_ary_ptr(regs[1]);
|
|
2603
|
+
argv = ARY_PTR(ary);
|
|
2604
|
+
argc = (int)ARY_LEN(ary);
|
|
2605
|
+
mrb_gc_protect(mrb, regs[1]);
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
/* strict argument check */
|
|
2609
|
+
if (ci->proc && MRB_PROC_STRICT_P(ci->proc)) {
|
|
2610
|
+
if (mrb_unlikely(argc < m1 + m2 || (r == 0 && argc > len))) {
|
|
2611
|
+
argnum_error(mrb, m1+m2);
|
|
2612
|
+
goto L_RAISE;
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
/* extract first argument array to arguments */
|
|
2616
|
+
else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
|
|
2617
|
+
mrb_gc_protect(mrb, argv[0]);
|
|
2618
|
+
argc = (int)RARRAY_LEN(argv[0]);
|
|
2619
|
+
argv = RARRAY_PTR(argv[0]);
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
/* rest arguments */
|
|
2623
|
+
mrb_value rest;
|
|
2624
|
+
if (argc < len) {
|
|
2625
|
+
mrb_int mlen = m2;
|
|
2626
|
+
if (argc < m1+m2) {
|
|
2627
|
+
mlen = m1 < argc ? argc - m1 : 0;
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
/* copy mandatory and optional arguments */
|
|
2631
|
+
if (argv0 != argv && argv) {
|
|
2632
|
+
value_move(®s[1], argv, argc-mlen); /* m1 + o */
|
|
2633
|
+
}
|
|
2634
|
+
if (argc < m1) {
|
|
2635
|
+
stack_clear(®s[argc+1], m1-argc);
|
|
2636
|
+
}
|
|
2637
|
+
/* copy post mandatory arguments */
|
|
2638
|
+
if (mlen) {
|
|
2639
|
+
value_move(®s[len-m2+1], &argv[argc-mlen], mlen);
|
|
2640
|
+
}
|
|
2641
|
+
if (mlen < m2) {
|
|
2642
|
+
stack_clear(®s[len-m2+mlen+1], m2-mlen);
|
|
2643
|
+
}
|
|
2644
|
+
/* initialize rest arguments with empty Array */
|
|
2645
|
+
if (r) {
|
|
2646
|
+
rest = mrb_ary_new_capa(mrb, 0);
|
|
2647
|
+
regs[m1+o+1] = rest;
|
|
2648
|
+
}
|
|
2649
|
+
/* skip initializer of passed arguments */
|
|
2650
|
+
if (o > 0 && argc > m1+m2)
|
|
2651
|
+
ci->pc += (argc - m1 - m2)*3;
|
|
2652
|
+
}
|
|
2653
|
+
else {
|
|
2654
|
+
mrb_int rnum = 0;
|
|
2655
|
+
if (argv0 != argv) {
|
|
2656
|
+
mrb_gc_protect(mrb, blk);
|
|
2657
|
+
value_move(®s[1], argv, m1+o);
|
|
2658
|
+
}
|
|
2659
|
+
if (r) {
|
|
2660
|
+
rnum = argc-m1-o-m2;
|
|
2661
|
+
rest = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
|
|
2662
|
+
regs[m1+o+1] = rest;
|
|
2663
|
+
}
|
|
2664
|
+
if (m2 > 0 && argc-m2 > m1) {
|
|
2665
|
+
value_move(®s[m1+o+r+1], &argv[m1+o+rnum], m2);
|
|
2666
|
+
}
|
|
2667
|
+
ci->pc += o*3;
|
|
2668
|
+
}
|
|
2669
|
+
|
|
2670
|
+
/* need to be update blk first to protect blk from GC */
|
|
2671
|
+
mrb_int const kw_pos = len + kd; /* where kwhash should be */
|
|
2672
|
+
mrb_int const blk_pos = kw_pos + 1; /* where block should be */
|
|
2673
|
+
regs[blk_pos] = blk; /* move block */
|
|
2674
|
+
if (kd) {
|
|
2675
|
+
if (mrb_nil_p(kdict)) {
|
|
2676
|
+
kdict = mrb_hash_new_capa(mrb, 0);
|
|
2677
|
+
}
|
|
2678
|
+
regs[kw_pos] = kdict; /* set kwhash */
|
|
2679
|
+
ci->nk = 15;
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
/* format arguments for generated code */
|
|
2683
|
+
ci->n = (uint8_t)len;
|
|
2684
|
+
|
|
2685
|
+
/* clear local (but non-argument) variables */
|
|
2686
|
+
if (irep->nlocals-blk_pos-1 > 0) {
|
|
2687
|
+
stack_clear(®s[blk_pos+1], irep->nlocals-blk_pos-1);
|
|
2688
|
+
}
|
|
2689
|
+
JUMP;
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
CASE(OP_KARG, BB) {
|
|
2693
|
+
mrb_value k = mrb_symbol_value(irep->syms[b]);
|
|
2694
|
+
mrb_int kidx = mrb_ci_kidx(ci);
|
|
2695
|
+
mrb_value kdict, v;
|
|
2696
|
+
|
|
2697
|
+
if (kidx < 0 || !mrb_hash_p(kdict=regs[kidx]) || !mrb_hash_key_p(mrb, kdict, k)) {
|
|
2698
|
+
RAISE_FORMAT(mrb, E_ARGUMENT_ERROR, "missing keyword: %v", k);
|
|
2699
|
+
}
|
|
2700
|
+
v = mrb_hash_get(mrb, kdict, k);
|
|
2701
|
+
ci = mrb->c->ci;
|
|
2702
|
+
regs[a] = v;
|
|
2703
|
+
mrb_hash_delete_key(mrb, kdict, k);
|
|
2704
|
+
ci = mrb->c->ci;
|
|
2705
|
+
NEXT;
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
CASE(OP_KEY_P, BB) {
|
|
2709
|
+
mrb_value k = mrb_symbol_value(irep->syms[b]);
|
|
2710
|
+
mrb_int kidx = mrb_ci_kidx(ci);
|
|
2711
|
+
mrb_value kdict;
|
|
2712
|
+
mrb_bool key_p = FALSE;
|
|
2713
|
+
|
|
2714
|
+
if (kidx >= 0 && mrb_hash_p(kdict=regs[kidx])) {
|
|
2715
|
+
key_p = mrb_hash_key_p(mrb, kdict, k);
|
|
2716
|
+
ci = mrb->c->ci;
|
|
2717
|
+
}
|
|
2718
|
+
regs[a] = mrb_bool_value(key_p);
|
|
2719
|
+
NEXT;
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2722
|
+
CASE(OP_KEYEND, Z) {
|
|
2723
|
+
mrb_int kidx = mrb_ci_kidx(ci);
|
|
2724
|
+
mrb_value kdict;
|
|
2725
|
+
|
|
2726
|
+
if (kidx >= 0 && mrb_hash_p(kdict=regs[kidx]) && !mrb_hash_empty_p(mrb, kdict)) {
|
|
2727
|
+
mrb_value key1 = mrb_hash_first_key(mrb, kdict);
|
|
2728
|
+
RAISE_FORMAT(mrb, E_ARGUMENT_ERROR, "unknown keyword: %v", key1);
|
|
2729
|
+
}
|
|
2730
|
+
NEXT;
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
CASE(OP_BREAK, B) {
|
|
2734
|
+
if (MRB_PROC_STRICT_P(ci->proc)) goto NORMAL_RETURN;
|
|
2735
|
+
if (!MRB_PROC_ORPHAN_P(ci->proc) && MRB_PROC_ENV_P(ci->proc) && ci->proc->e.env->cxt == mrb->c) {
|
|
2736
|
+
const struct RProc *dst = ci->proc->upper;
|
|
2737
|
+
for (ptrdiff_t i = ci - mrb->c->cibase; i > 0; i--, ci--) {
|
|
2738
|
+
if (ci[-1].proc == dst) {
|
|
2739
|
+
goto L_UNWINDING;
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "break from proc-closure");
|
|
2744
|
+
/* not reached */
|
|
2745
|
+
}
|
|
2746
|
+
CASE(OP_RETURN_BLK, B) {
|
|
2747
|
+
if (!MRB_PROC_ENV_P(ci->proc) || MRB_PROC_STRICT_P(ci->proc)) {
|
|
2748
|
+
goto NORMAL_RETURN;
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
const struct REnv *env = ci->u.env;
|
|
2752
|
+
const struct RProc *dst = top_proc(mrb, ci->proc, &env);
|
|
2753
|
+
if (!MRB_PROC_ENV_P(dst) || dst->e.env->cxt == mrb->c) {
|
|
2754
|
+
/* check jump destination */
|
|
2755
|
+
for (ptrdiff_t i = ci - mrb->c->cibase; i >= 0; i--, ci--) {
|
|
2756
|
+
if (ci->u.env == env) {
|
|
2757
|
+
goto L_UNWINDING;
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
/* no jump destination */
|
|
2762
|
+
RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "unexpected return");
|
|
2763
|
+
/* not reached */
|
|
2764
|
+
}
|
|
2765
|
+
CASE(OP_RETSELF, Z) {
|
|
2766
|
+
a = 0;
|
|
2767
|
+
goto NORMAL_RETURN;
|
|
2768
|
+
}
|
|
2769
|
+
CASE(OP_RETNIL, Z) {
|
|
2770
|
+
a = 0;
|
|
2771
|
+
goto L_RETURN_NIL;
|
|
2772
|
+
}
|
|
2773
|
+
CASE(OP_RETTRUE, Z) {
|
|
2774
|
+
a = 0;
|
|
2775
|
+
goto L_RETURN_TRUE;
|
|
2776
|
+
}
|
|
2777
|
+
CASE(OP_RETFALSE, Z) {
|
|
2778
|
+
a = 0;
|
|
2779
|
+
goto L_RETURN_FALSE;
|
|
2780
|
+
}
|
|
2781
|
+
CASE(OP_RETURN, B) {
|
|
2782
|
+
mrb_int acc;
|
|
2783
|
+
mrb_value v;
|
|
2784
|
+
mrb_callinfo *return_ci;
|
|
2785
|
+
|
|
2786
|
+
NORMAL_RETURN:
|
|
2787
|
+
v = regs[a];
|
|
2788
|
+
goto L_RETURN;
|
|
2789
|
+
L_RETURN_NIL:
|
|
2790
|
+
v = mrb_nil_value();
|
|
2791
|
+
goto L_RETURN;
|
|
2792
|
+
L_RETURN_TRUE:
|
|
2793
|
+
v = mrb_true_value();
|
|
2794
|
+
goto L_RETURN;
|
|
2795
|
+
L_RETURN_FALSE:
|
|
2796
|
+
v = mrb_false_value();
|
|
2797
|
+
L_RETURN:
|
|
2798
|
+
mrb_gc_protect(mrb, v);
|
|
2799
|
+
return_ci = ci;
|
|
2800
|
+
CHECKPOINT_RESTORE(RBREAK_TAG_BREAK) {
|
|
2801
|
+
if (TRUE) {
|
|
2802
|
+
struct RBreak *brk = (struct RBreak*)mrb->exc;
|
|
2803
|
+
return_ci = &mrb->c->cibase[brk->ci_break_index];
|
|
2804
|
+
v = mrb_break_value_get(brk);
|
|
2805
|
+
}
|
|
2806
|
+
else {
|
|
2807
|
+
L_UNWINDING:
|
|
2808
|
+
return_ci = ci;
|
|
2809
|
+
ci = mrb->c->ci;
|
|
2810
|
+
v = ci->stack[a];
|
|
2811
|
+
}
|
|
2812
|
+
mrb_gc_protect(mrb, v);
|
|
2813
|
+
}
|
|
2814
|
+
CHECKPOINT_MAIN(RBREAK_TAG_BREAK) {
|
|
2815
|
+
for (;;) {
|
|
2816
|
+
UNWIND_ENSURE(mrb, ci, ci->pc, RBREAK_TAG_BREAK, return_ci, v);
|
|
2817
|
+
|
|
2818
|
+
if (ci == return_ci) {
|
|
2819
|
+
break;
|
|
2820
|
+
}
|
|
2821
|
+
ci = cipop(mrb);
|
|
2822
|
+
if (ci[1].cci != CINFO_NONE) {
|
|
2823
|
+
mrb_assert(prev_jmp != NULL);
|
|
2824
|
+
mrb->exc = (struct RObject*)break_new(mrb, RBREAK_TAG_BREAK, return_ci, v);
|
|
2825
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2826
|
+
mrb->c->vmexec = FALSE;
|
|
2827
|
+
mrb->jmp = prev_jmp;
|
|
2828
|
+
MRB_THROW(prev_jmp);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
CHECKPOINT_END(RBREAK_TAG_BREAK);
|
|
2833
|
+
mrb->exc = NULL; /* clear break object */
|
|
2834
|
+
|
|
2835
|
+
if (ci == mrb->c->cibase) {
|
|
2836
|
+
struct mrb_context *c = mrb->c;
|
|
2837
|
+
if (c == mrb->root_c) {
|
|
2838
|
+
/* toplevel return */
|
|
2839
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2840
|
+
mrb->jmp = prev_jmp;
|
|
2841
|
+
return v;
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
#ifdef MRB_USE_TASK_SCHEDULER
|
|
2845
|
+
if (mrb->c->status == MRB_TASK_CREATED) {
|
|
2846
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2847
|
+
mrb->jmp = prev_jmp;
|
|
2848
|
+
TASK_STOP(mrb);
|
|
2849
|
+
return v;
|
|
2850
|
+
}
|
|
2851
|
+
#endif
|
|
2852
|
+
|
|
2853
|
+
fiber_terminate(mrb, c, ci);
|
|
2854
|
+
if (c->vmexec ||
|
|
2855
|
+
(mrb->c == mrb->root_c && mrb->c->ci == mrb->c->cibase) /* case using Fiber#transfer in mrb_fiber_resume() */) {
|
|
2856
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2857
|
+
c->vmexec = FALSE;
|
|
2858
|
+
mrb->jmp = prev_jmp;
|
|
2859
|
+
return v;
|
|
2860
|
+
}
|
|
2861
|
+
ci = mrb->c->ci;
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2864
|
+
if (mrb->c->vmexec && !ci->u.keep_context) {
|
|
2865
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2866
|
+
mrb->c->vmexec = FALSE;
|
|
2867
|
+
mrb->jmp = prev_jmp;
|
|
2868
|
+
return v;
|
|
2869
|
+
}
|
|
2870
|
+
acc = ci->cci;
|
|
2871
|
+
ci = cipop(mrb);
|
|
2872
|
+
if (acc == CINFO_SKIP || acc == CINFO_DIRECT) {
|
|
2873
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2874
|
+
mrb->jmp = prev_jmp;
|
|
2875
|
+
return v;
|
|
2876
|
+
}
|
|
2877
|
+
DEBUG(fprintf(stderr, "from :%s\n", mrb_sym_name(mrb, ci->mid)));
|
|
2878
|
+
irep = ci->proc->body.irep;
|
|
2879
|
+
|
|
2880
|
+
ci[1].stack[0] = v;
|
|
2881
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2882
|
+
JUMP;
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
CASE(OP_BLKPUSH, BS) {
|
|
2886
|
+
int m1 = (b>>11)&0x3f;
|
|
2887
|
+
int r = (b>>10)&0x1;
|
|
2888
|
+
int m2 = (b>>5)&0x1f;
|
|
2889
|
+
int kd = (b>>4)&0x1;
|
|
2890
|
+
int lv = (b>>0)&0xf;
|
|
2891
|
+
int offset = m1+r+m2+kd;
|
|
2892
|
+
mrb_value *stack;
|
|
2893
|
+
|
|
2894
|
+
if (lv == 0) stack = regs + 1;
|
|
2895
|
+
else {
|
|
2896
|
+
struct REnv *e = uvenv(mrb, lv-1);
|
|
2897
|
+
if (!e || (!MRB_ENV_ONSTACK_P(e) && e->mid == 0) ||
|
|
2898
|
+
MRB_ENV_LEN(e) <= offset+1) {
|
|
2899
|
+
RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "unexpected yield");
|
|
2900
|
+
}
|
|
2901
|
+
stack = e->stack + 1;
|
|
2902
|
+
}
|
|
2903
|
+
if (mrb_nil_p(stack[offset])) {
|
|
2904
|
+
RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "unexpected yield");
|
|
2905
|
+
}
|
|
2906
|
+
regs[a] = stack[offset];
|
|
2907
|
+
NEXT;
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
#if !defined(MRB_USE_BIGINT) || defined(MRB_INT32)
|
|
2911
|
+
L_INT_OVERFLOW:
|
|
2912
|
+
RAISE_LIT(mrb, E_RANGE_ERROR, "integer overflow");
|
|
2913
|
+
#endif
|
|
2914
|
+
|
|
2915
|
+
#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
|
|
2916
|
+
#define OP_MATH(op_name) do { \
|
|
2917
|
+
/* need to check if op is overridden */ \
|
|
2918
|
+
uint16_t tt = TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1])); \
|
|
2919
|
+
if (mrb_likely(tt == TYPES2(MRB_TT_INTEGER, MRB_TT_INTEGER))) { \
|
|
2920
|
+
mrb_int x = mrb_integer(regs[a]), y = mrb_integer(regs[a+1]), z; \
|
|
2921
|
+
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
|
2922
|
+
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
|
2923
|
+
} \
|
|
2924
|
+
else \
|
|
2925
|
+
SET_INT_VALUE(mrb,regs[a], z); \
|
|
2926
|
+
} \
|
|
2927
|
+
else switch (tt) { \
|
|
2928
|
+
OP_MATH_CASE_FLOAT(op_name, integer, float); \
|
|
2929
|
+
OP_MATH_CASE_FLOAT(op_name, float, integer); \
|
|
2930
|
+
OP_MATH_CASE_FLOAT(op_name, float, float); \
|
|
2931
|
+
OP_MATH_CASE_STRING_##op_name(); \
|
|
2932
|
+
default: \
|
|
2933
|
+
mid = MRB_OPSYM(op_name); \
|
|
2934
|
+
goto L_SEND_SYM; \
|
|
2935
|
+
} \
|
|
2936
|
+
} while(0); \
|
|
2937
|
+
NEXT;
|
|
2938
|
+
#define OP_MATH_CASE_INTEGER(op_name) \
|
|
2939
|
+
case TYPES2(MRB_TT_INTEGER, MRB_TT_INTEGER): \
|
|
2940
|
+
{ \
|
|
2941
|
+
mrb_int x = mrb_integer(regs[a]), y = mrb_integer(regs[a+1]), z; \
|
|
2942
|
+
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
|
2943
|
+
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
|
2944
|
+
} \
|
|
2945
|
+
else \
|
|
2946
|
+
SET_INT_VALUE(mrb,regs[a], z); \
|
|
2947
|
+
} \
|
|
2948
|
+
break
|
|
2949
|
+
#ifdef MRB_NO_FLOAT
|
|
2950
|
+
#define OP_MATH_CASE_FLOAT(op_name, t1, t2) (void)0
|
|
2951
|
+
#else
|
|
2952
|
+
#define OP_MATH_CASE_FLOAT(op_name, t1, t2) \
|
|
2953
|
+
case TYPES2(OP_MATH_TT_##t1, OP_MATH_TT_##t2): \
|
|
2954
|
+
{ \
|
|
2955
|
+
mrb_float z = mrb_##t1(regs[a]) OP_MATH_OP_##op_name mrb_##t2(regs[a+1]); \
|
|
2956
|
+
SET_FLOAT_VALUE(mrb, regs[a], z); \
|
|
2957
|
+
} \
|
|
2958
|
+
break
|
|
2959
|
+
#endif
|
|
2960
|
+
#ifdef MRB_USE_BIGINT
|
|
2961
|
+
#define OP_MATH_OVERFLOW_INT(op,x,y) regs[a] = mrb_bint_##op##_ii(mrb,x,y)
|
|
2962
|
+
#else
|
|
2963
|
+
#define OP_MATH_OVERFLOW_INT(op,x,y) goto L_INT_OVERFLOW
|
|
2964
|
+
#endif
|
|
2965
|
+
#define OP_MATH_CASE_STRING_add() \
|
|
2966
|
+
case TYPES2(MRB_TT_STRING, MRB_TT_STRING): \
|
|
2967
|
+
regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); \
|
|
2968
|
+
mrb_gc_arena_restore(mrb, ai); \
|
|
2969
|
+
break
|
|
2970
|
+
#define OP_MATH_CASE_STRING_sub() (void)0
|
|
2971
|
+
#define OP_MATH_CASE_STRING_mul() (void)0
|
|
2972
|
+
#define OP_MATH_OP_add +
|
|
2973
|
+
#define OP_MATH_OP_sub -
|
|
2974
|
+
#define OP_MATH_OP_mul *
|
|
2975
|
+
#define OP_MATH_TT_integer MRB_TT_INTEGER
|
|
2976
|
+
#define OP_MATH_TT_float MRB_TT_FLOAT
|
|
2977
|
+
|
|
2978
|
+
CASE(OP_ADD, B) {
|
|
2979
|
+
OP_MATH(add);
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
CASE(OP_SUB, B) {
|
|
2983
|
+
OP_MATH(sub);
|
|
2984
|
+
}
|
|
2985
|
+
|
|
2986
|
+
CASE(OP_MUL, B) {
|
|
2987
|
+
OP_MATH(mul);
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2990
|
+
CASE(OP_DIV, B) {
|
|
2991
|
+
#ifndef MRB_NO_FLOAT
|
|
2992
|
+
mrb_float x, y, f;
|
|
2993
|
+
#endif
|
|
2994
|
+
|
|
2995
|
+
/* need to check if op is overridden */
|
|
2996
|
+
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
|
|
2997
|
+
case TYPES2(MRB_TT_INTEGER,MRB_TT_INTEGER):
|
|
2998
|
+
{
|
|
2999
|
+
mrb_int x = mrb_integer(regs[a]);
|
|
3000
|
+
mrb_int y = mrb_integer(regs[a+1]);
|
|
3001
|
+
regs[a] = mrb_div_int_value(mrb, x, y);
|
|
3002
|
+
}
|
|
3003
|
+
NEXT;
|
|
3004
|
+
#ifndef MRB_NO_FLOAT
|
|
3005
|
+
case TYPES2(MRB_TT_INTEGER,MRB_TT_FLOAT):
|
|
3006
|
+
x = (mrb_float)mrb_integer(regs[a]);
|
|
3007
|
+
y = mrb_float(regs[a+1]);
|
|
3008
|
+
break;
|
|
3009
|
+
case TYPES2(MRB_TT_FLOAT,MRB_TT_INTEGER):
|
|
3010
|
+
x = mrb_float(regs[a]);
|
|
3011
|
+
y = (mrb_float)mrb_integer(regs[a+1]);
|
|
3012
|
+
break;
|
|
3013
|
+
case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
|
|
3014
|
+
x = mrb_float(regs[a]);
|
|
3015
|
+
y = mrb_float(regs[a+1]);
|
|
3016
|
+
break;
|
|
3017
|
+
#endif
|
|
3018
|
+
default:
|
|
3019
|
+
mid = MRB_OPSYM(div);
|
|
3020
|
+
goto L_SEND_SYM;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
#ifndef MRB_NO_FLOAT
|
|
3024
|
+
f = mrb_div_float(x, y);
|
|
3025
|
+
SET_FLOAT_VALUE(mrb, regs[a], f);
|
|
3026
|
+
#endif
|
|
3027
|
+
NEXT;
|
|
3028
|
+
}
|
|
3029
|
+
|
|
3030
|
+
#define OP_MATHI(op_name) do { \
|
|
3031
|
+
/* need to check if op is overridden */ \
|
|
3032
|
+
if (mrb_likely(mrb_integer_p(regs[a]))) { \
|
|
3033
|
+
mrb_int x = mrb_integer(regs[a]), y = (mrb_int)b, z; \
|
|
3034
|
+
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
|
3035
|
+
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
|
3036
|
+
} \
|
|
3037
|
+
else \
|
|
3038
|
+
SET_INT_VALUE(mrb,regs[a], z); \
|
|
3039
|
+
} \
|
|
3040
|
+
else switch (mrb_type(regs[a])) { \
|
|
3041
|
+
OP_MATHI_CASE_FLOAT(op_name); \
|
|
3042
|
+
default: \
|
|
3043
|
+
SET_INT_VALUE(mrb,regs[a+1], b); \
|
|
3044
|
+
mid = MRB_OPSYM(op_name); \
|
|
3045
|
+
goto L_SEND_SYM; \
|
|
3046
|
+
} \
|
|
3047
|
+
} while(0); \
|
|
3048
|
+
NEXT;
|
|
3049
|
+
#define OP_MATHI_CASE_INTEGER(op_name) \
|
|
3050
|
+
case MRB_TT_INTEGER: \
|
|
3051
|
+
{ \
|
|
3052
|
+
mrb_int x = mrb_integer(regs[a]), y = (mrb_int)b, z; \
|
|
3053
|
+
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
|
3054
|
+
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
|
3055
|
+
} \
|
|
3056
|
+
else \
|
|
3057
|
+
SET_INT_VALUE(mrb,regs[a], z); \
|
|
3058
|
+
} \
|
|
3059
|
+
break
|
|
3060
|
+
#ifdef MRB_NO_FLOAT
|
|
3061
|
+
#define OP_MATHI_CASE_FLOAT(op_name) (void)0
|
|
3062
|
+
#else
|
|
3063
|
+
#define OP_MATHI_CASE_FLOAT(op_name) \
|
|
3064
|
+
case MRB_TT_FLOAT: \
|
|
3065
|
+
{ \
|
|
3066
|
+
mrb_float z = mrb_float(regs[a]) OP_MATH_OP_##op_name b; \
|
|
3067
|
+
SET_FLOAT_VALUE(mrb, regs[a], z); \
|
|
3068
|
+
} \
|
|
3069
|
+
break
|
|
3070
|
+
#endif
|
|
3071
|
+
|
|
3072
|
+
CASE(OP_ADDI, BB) {
|
|
3073
|
+
OP_MATHI(add);
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
CASE(OP_SUBI, BB) {
|
|
3077
|
+
OP_MATHI(sub);
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
#ifdef MRB_NO_FLOAT
|
|
3081
|
+
#define OP_MATHILV_CASE_FLOAT(op_name) (void)0
|
|
3082
|
+
#else
|
|
3083
|
+
#define OP_MATHILV_CASE_FLOAT(op_name) \
|
|
3084
|
+
case MRB_TT_FLOAT: \
|
|
3085
|
+
{ \
|
|
3086
|
+
mrb_float z = mrb_float(regs[a]) OP_MATH_OP_##op_name c; \
|
|
3087
|
+
SET_FLOAT_VALUE(mrb, regs[a], z); \
|
|
3088
|
+
} \
|
|
3089
|
+
break
|
|
3090
|
+
#endif
|
|
3091
|
+
#define OP_MATHILV(op_name) \
|
|
3092
|
+
/* a=local, b=working space, c=immediate */ \
|
|
3093
|
+
switch (mrb_type(regs[a])) { \
|
|
3094
|
+
case MRB_TT_INTEGER: \
|
|
3095
|
+
{ \
|
|
3096
|
+
mrb_int x = mrb_integer(regs[a]), y = (mrb_int)c, z; \
|
|
3097
|
+
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
|
3098
|
+
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
|
3099
|
+
} \
|
|
3100
|
+
else { \
|
|
3101
|
+
SET_INT_VALUE(mrb,regs[a], z); \
|
|
3102
|
+
} \
|
|
3103
|
+
} \
|
|
3104
|
+
break; \
|
|
3105
|
+
OP_MATHILV_CASE_FLOAT(op_name); \
|
|
3106
|
+
default: \
|
|
3107
|
+
{ \
|
|
3108
|
+
mrb_value arg = mrb_int_value(mrb, c); \
|
|
3109
|
+
mrb_sym mid = MRB_OPSYM(op_name); \
|
|
3110
|
+
regs[a] = mrb_funcall_argv(mrb, regs[a], mid, 1, &arg); \
|
|
3111
|
+
mrb_gc_arena_restore(mrb, ai); \
|
|
3112
|
+
} \
|
|
3113
|
+
break; \
|
|
3114
|
+
} \
|
|
3115
|
+
NEXT
|
|
3116
|
+
|
|
3117
|
+
CASE(OP_ADDILV, BBB) {
|
|
3118
|
+
OP_MATHILV(add);
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
CASE(OP_SUBILV, BBB) {
|
|
3122
|
+
OP_MATHILV(sub);
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
|
|
3126
|
+
|
|
3127
|
+
#ifdef MRB_NO_FLOAT
|
|
3128
|
+
#define OP_CMP(op,sym) do {\
|
|
3129
|
+
int result;\
|
|
3130
|
+
/* need to check if op is overridden */\
|
|
3131
|
+
if (mrb_likely(TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1])) == \
|
|
3132
|
+
TYPES2(MRB_TT_INTEGER,MRB_TT_INTEGER))) {\
|
|
3133
|
+
result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\
|
|
3134
|
+
}\
|
|
3135
|
+
else {\
|
|
3136
|
+
mid = MRB_OPSYM(sym);\
|
|
3137
|
+
goto L_SEND_SYM;\
|
|
3138
|
+
}\
|
|
3139
|
+
if (result) {\
|
|
3140
|
+
SET_TRUE_VALUE(regs[a]);\
|
|
3141
|
+
}\
|
|
3142
|
+
else {\
|
|
3143
|
+
SET_FALSE_VALUE(regs[a]);\
|
|
3144
|
+
}\
|
|
3145
|
+
} while(0)
|
|
3146
|
+
#else
|
|
3147
|
+
#define OP_CMP(op, sym) do {\
|
|
3148
|
+
int result;\
|
|
3149
|
+
/* need to check if op is overridden */\
|
|
3150
|
+
uint16_t tt = TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]));\
|
|
3151
|
+
if (mrb_likely(tt == TYPES2(MRB_TT_INTEGER,MRB_TT_INTEGER))) {\
|
|
3152
|
+
result = OP_CMP_BODY(op,mrb_integer,mrb_integer);\
|
|
3153
|
+
}\
|
|
3154
|
+
else switch (tt) {\
|
|
3155
|
+
case TYPES2(MRB_TT_INTEGER,MRB_TT_FLOAT):\
|
|
3156
|
+
result = OP_CMP_BODY(op,mrb_integer,mrb_float);\
|
|
3157
|
+
break;\
|
|
3158
|
+
case TYPES2(MRB_TT_FLOAT,MRB_TT_INTEGER):\
|
|
3159
|
+
result = OP_CMP_BODY(op,mrb_float,mrb_integer);\
|
|
3160
|
+
break;\
|
|
3161
|
+
case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
|
|
3162
|
+
result = OP_CMP_BODY(op,mrb_float,mrb_float);\
|
|
3163
|
+
break;\
|
|
3164
|
+
default:\
|
|
3165
|
+
mid = MRB_OPSYM(sym);\
|
|
3166
|
+
goto L_SEND_SYM;\
|
|
3167
|
+
}\
|
|
3168
|
+
if (result) {\
|
|
3169
|
+
SET_TRUE_VALUE(regs[a]);\
|
|
3170
|
+
}\
|
|
3171
|
+
else {\
|
|
3172
|
+
SET_FALSE_VALUE(regs[a]);\
|
|
3173
|
+
}\
|
|
3174
|
+
} while(0)
|
|
3175
|
+
#endif
|
|
3176
|
+
|
|
3177
|
+
CASE(OP_EQ, B) {
|
|
3178
|
+
if (mrb_obj_eq(mrb, regs[a], regs[a+1])) {
|
|
3179
|
+
SET_TRUE_VALUE(regs[a]);
|
|
3180
|
+
}
|
|
3181
|
+
else if (mrb_symbol_p(regs[a])) {
|
|
3182
|
+
SET_FALSE_VALUE(regs[a]);
|
|
3183
|
+
}
|
|
3184
|
+
else {
|
|
3185
|
+
OP_CMP(==,eq);
|
|
3186
|
+
}
|
|
3187
|
+
NEXT;
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
CASE(OP_LT, B) {
|
|
3191
|
+
OP_CMP(<,lt);
|
|
3192
|
+
NEXT;
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
CASE(OP_LE, B) {
|
|
3196
|
+
OP_CMP(<=,le);
|
|
3197
|
+
NEXT;
|
|
3198
|
+
}
|
|
3199
|
+
|
|
3200
|
+
CASE(OP_GT, B) {
|
|
3201
|
+
OP_CMP(>,gt);
|
|
3202
|
+
NEXT;
|
|
3203
|
+
}
|
|
3204
|
+
|
|
3205
|
+
CASE(OP_GE, B) {
|
|
3206
|
+
OP_CMP(>=,ge);
|
|
3207
|
+
NEXT;
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3210
|
+
CASE(OP_ARRAY, BB) {
|
|
3211
|
+
regs[a] = ary_new_from_regs(mrb, b, a);
|
|
3212
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3213
|
+
NEXT;
|
|
3214
|
+
}
|
|
3215
|
+
CASE(OP_ARRAY2, BBB) {
|
|
3216
|
+
regs[a] = ary_new_from_regs(mrb, c, b);
|
|
3217
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3218
|
+
NEXT;
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
CASE(OP_ARYCAT, B) {
|
|
3222
|
+
mrb_value splat = mrb_ary_splat(mrb, regs[a+1]);
|
|
3223
|
+
ci = mrb->c->ci;
|
|
3224
|
+
if (mrb_nil_p(regs[a])) {
|
|
3225
|
+
regs[a] = splat;
|
|
3226
|
+
}
|
|
3227
|
+
else {
|
|
3228
|
+
mrb_ensure_array_type(mrb, regs[a]);
|
|
3229
|
+
mrb_ary_concat(mrb, regs[a], splat);
|
|
3230
|
+
}
|
|
3231
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3232
|
+
NEXT;
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
CASE(OP_ARYPUSH, BB) {
|
|
3236
|
+
mrb_ensure_array_type(mrb, regs[a]);
|
|
3237
|
+
for (mrb_int i=0; i<b; i++) {
|
|
3238
|
+
mrb_ary_push(mrb, regs[a], regs[a+i+1]);
|
|
3239
|
+
}
|
|
3240
|
+
NEXT;
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3243
|
+
CASE(OP_ARYSPLAT, B) {
|
|
3244
|
+
mrb_value ary = mrb_ary_splat(mrb, regs[a]);
|
|
3245
|
+
ci = mrb->c->ci;
|
|
3246
|
+
regs[a] = ary;
|
|
3247
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3248
|
+
NEXT;
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
CASE(OP_AREF, BBB) {
|
|
3252
|
+
mrb_value v = regs[b];
|
|
3253
|
+
|
|
3254
|
+
if (!mrb_array_p(v)) {
|
|
3255
|
+
if (c == 0) {
|
|
3256
|
+
regs[a] = v;
|
|
3257
|
+
}
|
|
3258
|
+
else {
|
|
3259
|
+
SET_NIL_VALUE(regs[a]);
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
else {
|
|
3263
|
+
v = mrb_ary_ref(mrb, v, c);
|
|
3264
|
+
regs[a] = v;
|
|
3265
|
+
}
|
|
3266
|
+
NEXT;
|
|
3267
|
+
}
|
|
3268
|
+
|
|
3269
|
+
CASE(OP_ASET, BBB) {
|
|
3270
|
+
mrb_ensure_array_type(mrb, regs[b]);
|
|
3271
|
+
mrb_ary_set(mrb, regs[b], c, regs[a]);
|
|
3272
|
+
NEXT;
|
|
3273
|
+
}
|
|
3274
|
+
|
|
3275
|
+
CASE(OP_APOST, BBB) {
|
|
3276
|
+
mrb_value v = regs[a];
|
|
3277
|
+
int pre = b;
|
|
3278
|
+
int post = c;
|
|
3279
|
+
|
|
3280
|
+
if (!mrb_array_p(v)) {
|
|
3281
|
+
v = ary_new_from_regs(mrb, 1, a);
|
|
3282
|
+
}
|
|
3283
|
+
struct RArray *ary = mrb_ary_ptr(v);
|
|
3284
|
+
int len = (int)ARY_LEN(ary);
|
|
3285
|
+
if (len > pre + post) {
|
|
3286
|
+
v = mrb_ary_new_from_values(mrb, len - pre - post, ARY_PTR(ary)+pre);
|
|
3287
|
+
regs[a++] = v;
|
|
3288
|
+
while (post--) {
|
|
3289
|
+
regs[a++] = ARY_PTR(ary)[len-post-1];
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
else {
|
|
3293
|
+
v = mrb_ary_new_capa(mrb, 0);
|
|
3294
|
+
regs[a++] = v;
|
|
3295
|
+
|
|
3296
|
+
int idx;
|
|
3297
|
+
for (idx=0; idx+pre<len; idx++) {
|
|
3298
|
+
regs[a+idx] = ARY_PTR(ary)[pre+idx];
|
|
3299
|
+
}
|
|
3300
|
+
while (idx < post) {
|
|
3301
|
+
SET_NIL_VALUE(regs[a+idx]);
|
|
3302
|
+
idx++;
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3305
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3306
|
+
NEXT;
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
CASE(OP_INTERN, B) {
|
|
3310
|
+
mrb_ensure_string_type(mrb, regs[a]);
|
|
3311
|
+
mrb_sym sym = mrb_intern_str(mrb, regs[a]);
|
|
3312
|
+
regs[a] = mrb_symbol_value(sym);
|
|
3313
|
+
NEXT;
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3316
|
+
CASE(OP_SYMBOL, BB) {
|
|
3317
|
+
size_t len;
|
|
3318
|
+
mrb_sym sym;
|
|
3319
|
+
|
|
3320
|
+
mrb_assert((irep->pool[b].tt&IREP_TT_NFLAG)==0);
|
|
3321
|
+
len = irep->pool[b].tt >> 2;
|
|
3322
|
+
if (irep->pool[b].tt & IREP_TT_SFLAG) {
|
|
3323
|
+
sym = mrb_intern_static(mrb, irep->pool[b].u.str, len);
|
|
3324
|
+
}
|
|
3325
|
+
else {
|
|
3326
|
+
sym = mrb_intern(mrb, irep->pool[b].u.str, len);
|
|
3327
|
+
}
|
|
3328
|
+
regs[a] = mrb_symbol_value(sym);
|
|
3329
|
+
NEXT;
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
CASE(OP_STRING, BB) {
|
|
3333
|
+
mrb_int len;
|
|
3334
|
+
|
|
3335
|
+
mrb_assert((irep->pool[b].tt&IREP_TT_NFLAG)==0);
|
|
3336
|
+
len = irep->pool[b].tt >> 2;
|
|
3337
|
+
if (irep->pool[b].tt & IREP_TT_SFLAG) {
|
|
3338
|
+
regs[a] = mrb_str_new_static(mrb, irep->pool[b].u.str, len);
|
|
3339
|
+
}
|
|
3340
|
+
else {
|
|
3341
|
+
regs[a] = mrb_str_new(mrb, irep->pool[b].u.str, len);
|
|
3342
|
+
}
|
|
3343
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3344
|
+
NEXT;
|
|
3345
|
+
}
|
|
3346
|
+
|
|
3347
|
+
CASE(OP_STRCAT, B) {
|
|
3348
|
+
mrb_ensure_string_type(mrb, regs[a]);
|
|
3349
|
+
mrb_str_concat(mrb, regs[a], regs[a+1]);
|
|
3350
|
+
ci = mrb->c->ci;
|
|
3351
|
+
NEXT;
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3354
|
+
CASE(OP_HASH, BB) {
|
|
3355
|
+
mrb_value hash = mrb_hash_new_capa(mrb, b);
|
|
3356
|
+
int lim = a+b*2;
|
|
3357
|
+
|
|
3358
|
+
for (int i=a; i<lim; i+=2) {
|
|
3359
|
+
mrb_hash_set(mrb, hash, regs[i], regs[i+1]);
|
|
3360
|
+
ci = mrb->c->ci;
|
|
3361
|
+
}
|
|
3362
|
+
regs[a] = hash;
|
|
3363
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3364
|
+
NEXT;
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3367
|
+
CASE(OP_HASHADD, BB) {
|
|
3368
|
+
mrb_value hash;
|
|
3369
|
+
int lim = a+b*2+1;
|
|
3370
|
+
|
|
3371
|
+
hash = regs[a];
|
|
3372
|
+
mrb_ensure_hash_type(mrb, hash);
|
|
3373
|
+
for (int i=a+1; i<lim; i+=2) {
|
|
3374
|
+
mrb_hash_set(mrb, hash, regs[i], regs[i+1]);
|
|
3375
|
+
ci = mrb->c->ci;
|
|
3376
|
+
}
|
|
3377
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3378
|
+
NEXT;
|
|
3379
|
+
}
|
|
3380
|
+
CASE(OP_HASHCAT, B) {
|
|
3381
|
+
mrb_value hash = regs[a];
|
|
3382
|
+
|
|
3383
|
+
mrb_ensure_hash_type(mrb, hash);
|
|
3384
|
+
mrb_hash_merge(mrb, hash, regs[a+1]);
|
|
3385
|
+
ci = mrb->c->ci;
|
|
3386
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3387
|
+
NEXT;
|
|
3388
|
+
}
|
|
3389
|
+
|
|
3390
|
+
CASE(OP_LAMBDA, BB)
|
|
3391
|
+
c = OP_L_LAMBDA;
|
|
3392
|
+
L_MAKE_LAMBDA:
|
|
3393
|
+
{
|
|
3394
|
+
struct RProc *p;
|
|
3395
|
+
const mrb_irep *nirep = irep->reps[b];
|
|
3396
|
+
|
|
3397
|
+
if (c & OP_L_CAPTURE) {
|
|
3398
|
+
p = mrb_closure_new(mrb, nirep);
|
|
3399
|
+
}
|
|
3400
|
+
else {
|
|
3401
|
+
p = mrb_proc_new(mrb, nirep);
|
|
3402
|
+
p->flags |= MRB_PROC_SCOPE;
|
|
3403
|
+
}
|
|
3404
|
+
if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
|
|
3405
|
+
regs[a] = mrb_obj_value(p);
|
|
3406
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3407
|
+
NEXT;
|
|
3408
|
+
}
|
|
3409
|
+
CASE(OP_BLOCK, BB) {
|
|
3410
|
+
c = OP_L_BLOCK;
|
|
3411
|
+
goto L_MAKE_LAMBDA;
|
|
3412
|
+
}
|
|
3413
|
+
CASE(OP_METHOD, BB) {
|
|
3414
|
+
c = OP_L_METHOD;
|
|
3415
|
+
goto L_MAKE_LAMBDA;
|
|
3416
|
+
}
|
|
3417
|
+
|
|
3418
|
+
CASE(OP_RANGE_INC, B) {
|
|
3419
|
+
mrb_value v = mrb_range_new(mrb, regs[a], regs[a+1], FALSE);
|
|
3420
|
+
ci = mrb->c->ci;
|
|
3421
|
+
regs[a] = v;
|
|
3422
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3423
|
+
NEXT;
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
CASE(OP_RANGE_EXC, B) {
|
|
3427
|
+
mrb_value v = mrb_range_new(mrb, regs[a], regs[a+1], TRUE);
|
|
3428
|
+
ci = mrb->c->ci;
|
|
3429
|
+
regs[a] = v;
|
|
3430
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3431
|
+
NEXT;
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
CASE(OP_OCLASS, B) {
|
|
3435
|
+
regs[a] = mrb_obj_value(mrb->object_class);
|
|
3436
|
+
NEXT;
|
|
3437
|
+
}
|
|
3438
|
+
|
|
3439
|
+
CASE(OP_CLASS, BB) {
|
|
3440
|
+
struct RClass *c = 0, *baseclass;
|
|
3441
|
+
mrb_sym id = irep->syms[b];
|
|
3442
|
+
mrb_value base = regs[a];
|
|
3443
|
+
mrb_value super = regs[a+1];
|
|
3444
|
+
|
|
3445
|
+
if (mrb_nil_p(base)) {
|
|
3446
|
+
baseclass = MRB_PROC_TARGET_CLASS(ci->proc);
|
|
3447
|
+
if (!baseclass) baseclass = mrb->object_class;
|
|
3448
|
+
base = mrb_obj_value(baseclass);
|
|
3449
|
+
}
|
|
3450
|
+
c = mrb_vm_define_class(mrb, base, super, id);
|
|
3451
|
+
ci = mrb->c->ci;
|
|
3452
|
+
regs[a] = mrb_obj_value(c);
|
|
3453
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3454
|
+
NEXT;
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
CASE(OP_MODULE, BB) {
|
|
3458
|
+
struct RClass *cls = 0, *baseclass;
|
|
3459
|
+
mrb_sym id = irep->syms[b];
|
|
3460
|
+
mrb_value base = regs[a];
|
|
3461
|
+
|
|
3462
|
+
if (mrb_nil_p(base)) {
|
|
3463
|
+
baseclass = MRB_PROC_TARGET_CLASS(ci->proc);
|
|
3464
|
+
if (!baseclass) baseclass = mrb->object_class;
|
|
3465
|
+
base = mrb_obj_value(baseclass);
|
|
3466
|
+
}
|
|
3467
|
+
cls = mrb_vm_define_module(mrb, base, id);
|
|
3468
|
+
ci = mrb->c->ci;
|
|
3469
|
+
regs[a] = mrb_obj_value(cls);
|
|
3470
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3471
|
+
NEXT;
|
|
3472
|
+
}
|
|
3473
|
+
|
|
3474
|
+
CASE(OP_EXEC, BB)
|
|
3475
|
+
{
|
|
3476
|
+
mrb_value recv = regs[a];
|
|
3477
|
+
struct RClass *c = mrb_class_ptr(recv);
|
|
3478
|
+
const mrb_irep *nirep = irep->reps[b];
|
|
3479
|
+
|
|
3480
|
+
/* prepare closure */
|
|
3481
|
+
struct RProc *p = mrb_proc_new(mrb, nirep);
|
|
3482
|
+
p->c = NULL;
|
|
3483
|
+
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)ci->proc);
|
|
3484
|
+
MRB_PROC_SET_TARGET_CLASS(p, c);
|
|
3485
|
+
p->flags |= MRB_PROC_SCOPE;
|
|
3486
|
+
|
|
3487
|
+
/* prepare call stack */
|
|
3488
|
+
ci = cipush(mrb, a, 0, c, p, NULL, 0, 0);
|
|
3489
|
+
|
|
3490
|
+
irep = p->body.irep;
|
|
3491
|
+
stack_extend(mrb, irep->nregs);
|
|
3492
|
+
stack_clear(regs+1, irep->nregs-1);
|
|
3493
|
+
ci->pc = irep->iseq;
|
|
3494
|
+
JUMP;
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
CASE(OP_DEF, BB) {
|
|
3498
|
+
struct RClass *target = mrb_class_ptr(regs[a]);
|
|
3499
|
+
const struct RProc *p = mrb_proc_ptr(regs[a+1]);
|
|
3500
|
+
mrb_method_t m;
|
|
3501
|
+
mrb_sym mid = irep->syms[b];
|
|
3502
|
+
|
|
3503
|
+
MRB_METHOD_FROM_PROC(m, p);
|
|
3504
|
+
MRB_METHOD_SET_VISIBILITY(m, MRB_METHOD_VDEFAULT_FL);
|
|
3505
|
+
mrb_define_method_raw(mrb, target, mid, m);
|
|
3506
|
+
mrb_method_added(mrb, target, mid);
|
|
3507
|
+
ci = mrb->c->ci;
|
|
3508
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3509
|
+
regs[a] = mrb_symbol_value(mid);
|
|
3510
|
+
NEXT;
|
|
3511
|
+
}
|
|
3512
|
+
|
|
3513
|
+
CASE(OP_TDEF, BBB) {
|
|
3514
|
+
tc = check_target_class(mrb);
|
|
3515
|
+
if (mrb_unlikely(!tc)) goto L_RAISE;
|
|
3516
|
+
}
|
|
3517
|
+
goto L_DEF_METHOD;
|
|
3518
|
+
|
|
3519
|
+
CASE(OP_SDEF, BBB) {
|
|
3520
|
+
tc = mrb_class_ptr(mrb_singleton_class(mrb, regs[a]));
|
|
3521
|
+
}
|
|
3522
|
+
L_DEF_METHOD:
|
|
3523
|
+
{
|
|
3524
|
+
struct RProc *p = mrb_proc_new(mrb, irep->reps[c]);
|
|
3525
|
+
mrb_method_t m;
|
|
3526
|
+
|
|
3527
|
+
mid = irep->syms[b];
|
|
3528
|
+
p->flags |= MRB_PROC_SCOPE | MRB_PROC_STRICT;
|
|
3529
|
+
MRB_METHOD_FROM_PROC(m, p);
|
|
3530
|
+
MRB_METHOD_SET_VISIBILITY(m, MRB_METHOD_VDEFAULT_FL);
|
|
3531
|
+
mrb_define_method_raw(mrb, tc, mid, m);
|
|
3532
|
+
mrb_method_added(mrb, tc, mid);
|
|
3533
|
+
ci = mrb->c->ci;
|
|
3534
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3535
|
+
regs[a] = mrb_symbol_value(mid);
|
|
3536
|
+
NEXT;
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
CASE(OP_SCLASS, B) {
|
|
3540
|
+
regs[a] = mrb_singleton_class(mrb, regs[a]);
|
|
3541
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3542
|
+
NEXT;
|
|
3543
|
+
}
|
|
3544
|
+
|
|
3545
|
+
CASE(OP_TCLASS, B) {
|
|
3546
|
+
struct RClass *target = check_target_class(mrb);
|
|
3547
|
+
if (mrb_unlikely(!target)) goto L_RAISE;
|
|
3548
|
+
regs[a] = mrb_obj_value(target);
|
|
3549
|
+
NEXT;
|
|
3550
|
+
}
|
|
3551
|
+
|
|
3552
|
+
CASE(OP_ALIAS, BB) {
|
|
3553
|
+
struct RClass *target = check_target_class(mrb);
|
|
3554
|
+
|
|
3555
|
+
if (mrb_unlikely(!target)) goto L_RAISE;
|
|
3556
|
+
mrb_alias_method(mrb, target, irep->syms[a], irep->syms[b]);
|
|
3557
|
+
mrb_method_added(mrb, target, irep->syms[a]);
|
|
3558
|
+
ci = mrb->c->ci;
|
|
3559
|
+
NEXT;
|
|
3560
|
+
}
|
|
3561
|
+
CASE(OP_UNDEF, B) {
|
|
3562
|
+
struct RClass *target = check_target_class(mrb);
|
|
3563
|
+
|
|
3564
|
+
if (mrb_unlikely(!target)) goto L_RAISE;
|
|
3565
|
+
mrb_undef_method_id(mrb, target, irep->syms[a]);
|
|
3566
|
+
ci = mrb->c->ci;
|
|
3567
|
+
NEXT;
|
|
3568
|
+
}
|
|
3569
|
+
|
|
3570
|
+
CASE(OP_DEBUG, BBB) {
|
|
3571
|
+
#ifdef MRB_USE_DEBUG_HOOK
|
|
3572
|
+
if (mrb->debug_op_hook) mrb->debug_op_hook(mrb, irep, ci->pc, regs);
|
|
3573
|
+
#else
|
|
3574
|
+
#ifndef MRB_NO_STDIO
|
|
3575
|
+
printf("OP_DEBUG %d %d %d\n", a, b, c);
|
|
3576
|
+
#else
|
|
3577
|
+
abort();
|
|
3578
|
+
#endif
|
|
3579
|
+
#endif
|
|
3580
|
+
NEXT;
|
|
3581
|
+
}
|
|
3582
|
+
|
|
3583
|
+
CASE(OP_ERR, B) {
|
|
3584
|
+
size_t len = irep->pool[a].tt >> 2;
|
|
3585
|
+
mrb_value exc;
|
|
3586
|
+
|
|
3587
|
+
mrb_assert((irep->pool[a].tt&IREP_TT_NFLAG)==0);
|
|
3588
|
+
exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, irep->pool[a].u.str, len);
|
|
3589
|
+
RAISE_EXC(mrb, exc);
|
|
3590
|
+
}
|
|
3591
|
+
|
|
3592
|
+
CASE(OP_EXT1, Z) {
|
|
3593
|
+
const mrb_code *pc = ci->pc;
|
|
3594
|
+
insn = READ_B();
|
|
3595
|
+
switch (insn) {
|
|
3596
|
+
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
|
3597
|
+
#include <mruby/ops.h>
|
|
3598
|
+
#undef OPCODE
|
|
3599
|
+
}
|
|
3600
|
+
NEXT;
|
|
3601
|
+
}
|
|
3602
|
+
CASE(OP_EXT2, Z) {
|
|
3603
|
+
const mrb_code *pc = ci->pc;
|
|
3604
|
+
insn = READ_B();
|
|
3605
|
+
switch (insn) {
|
|
3606
|
+
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
|
3607
|
+
#include <mruby/ops.h>
|
|
3608
|
+
#undef OPCODE
|
|
3609
|
+
}
|
|
3610
|
+
NEXT;
|
|
3611
|
+
}
|
|
3612
|
+
CASE(OP_EXT3, Z) {
|
|
3613
|
+
const mrb_code *pc = ci->pc;
|
|
3614
|
+
insn = READ_B();
|
|
3615
|
+
switch (insn) {
|
|
3616
|
+
#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); ci->pc = pc; goto L_OP_ ## insn ## _BODY;
|
|
3617
|
+
#include <mruby/ops.h>
|
|
3618
|
+
#undef OPCODE
|
|
3619
|
+
}
|
|
3620
|
+
NEXT;
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
CASE(OP_STOP, Z) {
|
|
3624
|
+
/* stop VM */
|
|
3625
|
+
mrb_value v;
|
|
3626
|
+
v = mrb->exc ? mrb_obj_value(mrb->exc) : mrb_nil_value();
|
|
3627
|
+
CHECKPOINT_RESTORE(RBREAK_TAG_STOP) {
|
|
3628
|
+
struct RBreak *brk = (struct RBreak*)mrb->exc;
|
|
3629
|
+
v = mrb_break_value_get(brk);
|
|
3630
|
+
}
|
|
3631
|
+
CHECKPOINT_MAIN(RBREAK_TAG_STOP) {
|
|
3632
|
+
UNWIND_ENSURE(mrb, ci, ci->pc, RBREAK_TAG_STOP, ci, v);
|
|
3633
|
+
}
|
|
3634
|
+
CHECKPOINT_END(RBREAK_TAG_STOP);
|
|
3635
|
+
mrb->jmp = prev_jmp;
|
|
3636
|
+
if (!mrb_nil_p(v)) {
|
|
3637
|
+
mrb->exc = mrb_obj_ptr(v);
|
|
3638
|
+
TASK_STOP(mrb);
|
|
3639
|
+
return v;
|
|
3640
|
+
}
|
|
3641
|
+
mrb->exc = NULL;
|
|
3642
|
+
TASK_STOP(mrb);
|
|
3643
|
+
return regs[irep->nlocals];
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
END_DISPATCH;
|
|
3647
|
+
#undef regs
|
|
3648
|
+
}
|
|
3649
|
+
MRB_CATCH(&c_jmp) {
|
|
3650
|
+
mrb_assert(mrb->exc != NULL);
|
|
3651
|
+
|
|
3652
|
+
ci = mrb->c->ci;
|
|
3653
|
+
while (ci > mrb->c->cibase && ci->cci == CINFO_DIRECT) {
|
|
3654
|
+
ci = cipop(mrb);
|
|
3655
|
+
}
|
|
3656
|
+
goto RETRY_TRY_BLOCK;
|
|
3657
|
+
}
|
|
3658
|
+
MRB_END_EXC(&c_jmp);
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3661
|
+
static mrb_value
|
|
3662
|
+
mrb_run(mrb_state *mrb, const struct RProc *proc, mrb_value self)
|
|
3663
|
+
{
|
|
3664
|
+
return mrb_vm_run(mrb, proc, self, ci_bidx(mrb->c->ci) + 1);
|
|
3665
|
+
}
|
|
3666
|
+
|
|
3667
|
+
/**
|
|
3668
|
+
* @brief Executes a mruby proc in the top-level environment.
|
|
3669
|
+
*
|
|
3670
|
+
* This function is used to execute a proc (like a script loaded from a file
|
|
3671
|
+
* or a string) at the top level of the mruby environment. It's similar to
|
|
3672
|
+
* `mrb_vm_run` but is specifically designed for top-level execution.
|
|
3673
|
+
*
|
|
3674
|
+
* It ensures that if there's an existing callinfo stack, the new execution
|
|
3675
|
+
* is pushed on top with `CINFO_SKIP`, indicating it's a new, distinct
|
|
3676
|
+
* execution context rather than a nested call from within the VM.
|
|
3677
|
+
*
|
|
3678
|
+
* @param mrb The mruby state.
|
|
3679
|
+
* @param proc The RProc object (representing the script or code) to execute.
|
|
3680
|
+
* @param self The `self` object for this top-level execution. Typically,
|
|
3681
|
+
* this is the main `top_self` object in mruby.
|
|
3682
|
+
* @param stack_keep The number of values to preserve on the stack. For
|
|
3683
|
+
* top-level execution, this is often 0 or a small number
|
|
3684
|
+
* to set up initial local variables if any.
|
|
3685
|
+
* @return The result of the proc's execution.
|
|
3686
|
+
* @see mrb_vm_run
|
|
3687
|
+
*/
|
|
3688
|
+
MRB_API mrb_value
|
|
3689
|
+
mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep)
|
|
3690
|
+
{
|
|
3691
|
+
if (mrb->c->cibase && mrb->c->ci > mrb->c->cibase) {
|
|
3692
|
+
cipush(mrb, 0, CINFO_SKIP, mrb->object_class, NULL, NULL, 0, 0);
|
|
3693
|
+
}
|
|
3694
|
+
return mrb_vm_run(mrb, proc, self, stack_keep);
|
|
3695
|
+
}
|
|
3696
|
+
#undef CASE
|