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,4394 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** class.c - Class class
|
|
3
|
+
**
|
|
4
|
+
** See Copyright Notice in mruby.h
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <mruby.h>
|
|
8
|
+
#include <mruby/array.h>
|
|
9
|
+
#include <mruby/hash.h>
|
|
10
|
+
#include <mruby/class.h>
|
|
11
|
+
#include <mruby/numeric.h>
|
|
12
|
+
#include <mruby/proc.h>
|
|
13
|
+
#include <mruby/string.h>
|
|
14
|
+
#include <mruby/variable.h>
|
|
15
|
+
#include <mruby/error.h>
|
|
16
|
+
#include <mruby/data.h>
|
|
17
|
+
#include <mruby/istruct.h>
|
|
18
|
+
#include <mruby/opcode.h>
|
|
19
|
+
#include <mruby/internal.h>
|
|
20
|
+
#include <mruby/presym.h>
|
|
21
|
+
|
|
22
|
+
/* mrb_mt_tbl, union mrb_mt_ptr, mrb_mt_entry defined in internal.h */
|
|
23
|
+
#define MT_PROTECTED MRB_METHOD_PROTECTED_FL
|
|
24
|
+
#define MT_VDEFAULT MRB_METHOD_VDEFAULT_FL
|
|
25
|
+
#define MT_VMASK MRB_METHOD_VISIBILITY_MASK
|
|
26
|
+
|
|
27
|
+
#define MRB_MT_FLAG_BITS (MRB_MT_READONLY_BIT | MRB_MT_FROZEN_BIT)
|
|
28
|
+
#define MT_ALLOC(t) ((t)->alloc & ~MRB_MT_FLAG_BITS)
|
|
29
|
+
#define mt_readonly_p(t) ((t)->alloc & MRB_MT_READONLY_BIT)
|
|
30
|
+
#define mt_frozen_p(t) ((t)->alloc & MRB_MT_FROZEN_BIT)
|
|
31
|
+
|
|
32
|
+
/* Allocates or grows the method table to exactly new_alloc entries */
|
|
33
|
+
static void
|
|
34
|
+
mt_grow(mrb_state *mrb, mrb_mt_tbl *t, int new_alloc)
|
|
35
|
+
{
|
|
36
|
+
t->ptr = (mrb_mt_entry*)mrb_realloc(mrb, t->ptr,
|
|
37
|
+
new_alloc * sizeof(mrb_mt_entry));
|
|
38
|
+
t->alloc = (t->alloc & MRB_MT_FLAG_BITS) | new_alloc;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Creates a new empty method table */
|
|
42
|
+
static mrb_mt_tbl*
|
|
43
|
+
mt_new(mrb_state *mrb)
|
|
44
|
+
{
|
|
45
|
+
mrb_mt_tbl *t;
|
|
46
|
+
|
|
47
|
+
t = (mrb_mt_tbl*)mrb_malloc(mrb, sizeof(mrb_mt_tbl));
|
|
48
|
+
t->size = 0;
|
|
49
|
+
t->alloc = 0;
|
|
50
|
+
t->ptr = NULL;
|
|
51
|
+
t->next = NULL;
|
|
52
|
+
|
|
53
|
+
return t;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Inserts or updates an entry in the method table (linear scan) */
|
|
57
|
+
static void
|
|
58
|
+
mt_put(mrb_state *mrb, mrb_mt_tbl *t, mrb_sym sym, uint32_t flags, union mrb_mt_ptr ptrval)
|
|
59
|
+
{
|
|
60
|
+
mrb_mt_entry *entries = t->ptr;
|
|
61
|
+
|
|
62
|
+
/* Linear scan for existing key */
|
|
63
|
+
for (int i = 0; i < t->size; i++) {
|
|
64
|
+
if (entries[i].key == sym) {
|
|
65
|
+
entries[i].flags = flags;
|
|
66
|
+
entries[i].val = ptrval;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Not found — append to end */
|
|
72
|
+
if (MT_ALLOC(t) == 0) {
|
|
73
|
+
mt_grow(mrb, t, 8);
|
|
74
|
+
}
|
|
75
|
+
else if (t->size == MT_ALLOC(t)) {
|
|
76
|
+
mt_grow(mrb, t, MT_ALLOC(t) * 2);
|
|
77
|
+
}
|
|
78
|
+
entries = t->ptr;
|
|
79
|
+
entries[t->size].key = sym;
|
|
80
|
+
entries[t->size].flags = flags;
|
|
81
|
+
entries[t->size].val = ptrval;
|
|
82
|
+
t->size++;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Retrieves a value from the method table (walks chain, linear scan).
|
|
86
|
+
Returns TRUE if found, FALSE if not found.
|
|
87
|
+
On success, *pp and *fp are set. */
|
|
88
|
+
static mrb_bool
|
|
89
|
+
mt_get(mrb_state *mrb, mrb_mt_tbl *t, mrb_sym sym, union mrb_mt_ptr *pp, uint32_t *fp)
|
|
90
|
+
{
|
|
91
|
+
while (t) {
|
|
92
|
+
mrb_mt_entry *entries = t->ptr;
|
|
93
|
+
for (int i = 0; i < t->size; i++) {
|
|
94
|
+
if (entries[i].key == sym) {
|
|
95
|
+
if (MRB_MT_REMOVED_P(entries[i])) return FALSE;
|
|
96
|
+
*pp = entries[i].val;
|
|
97
|
+
*fp = entries[i].flags;
|
|
98
|
+
return TRUE;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
t = t->next;
|
|
102
|
+
}
|
|
103
|
+
return FALSE;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Deletes an entry from the method table (swap with last) */
|
|
107
|
+
static mrb_bool
|
|
108
|
+
mt_del(mrb_state *mrb, mrb_mt_tbl *t, mrb_sym sym)
|
|
109
|
+
{
|
|
110
|
+
if (!t || t->size == 0) return FALSE;
|
|
111
|
+
|
|
112
|
+
mrb_mt_entry *entries = t->ptr;
|
|
113
|
+
for (int i = 0; i < t->size; i++) {
|
|
114
|
+
if (entries[i].key == sym) {
|
|
115
|
+
t->size--;
|
|
116
|
+
if (i < t->size) {
|
|
117
|
+
entries[i] = entries[t->size];
|
|
118
|
+
}
|
|
119
|
+
return TRUE;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return FALSE;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* Checks if any layer in the chain contains the given symbol */
|
|
126
|
+
static mrb_bool
|
|
127
|
+
mt_chain_has(mrb_mt_tbl *t, mrb_sym sym)
|
|
128
|
+
{
|
|
129
|
+
while (t) {
|
|
130
|
+
mrb_mt_entry *entries = t->ptr;
|
|
131
|
+
for (int i = 0; i < t->size; i++) {
|
|
132
|
+
if (entries[i].key == sym) return TRUE;
|
|
133
|
+
}
|
|
134
|
+
t = t->next;
|
|
135
|
+
}
|
|
136
|
+
return FALSE;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Creates a copy of the method table */
|
|
140
|
+
static mrb_mt_tbl*
|
|
141
|
+
mt_copy(mrb_state *mrb, mrb_mt_tbl *t)
|
|
142
|
+
{
|
|
143
|
+
if (!t) return NULL;
|
|
144
|
+
if (mt_readonly_p(t)) {
|
|
145
|
+
/* source is ROM — new class gets empty mutable top + shared ROM chain */
|
|
146
|
+
if (t->size == 0 && !t->next) return NULL;
|
|
147
|
+
mrb_mt_tbl *t2 = mt_new(mrb);
|
|
148
|
+
t2->next = t;
|
|
149
|
+
return t2;
|
|
150
|
+
}
|
|
151
|
+
if (t->size == 0 && !t->next) return NULL;
|
|
152
|
+
mrb_mt_tbl *t2 = mt_new(mrb);
|
|
153
|
+
if (t->size > 0) {
|
|
154
|
+
mt_grow(mrb, t2, t->size);
|
|
155
|
+
memcpy(t2->ptr, t->ptr, t->size * sizeof(mrb_mt_entry));
|
|
156
|
+
t2->size = t->size;
|
|
157
|
+
}
|
|
158
|
+
t2->next = t->next; /* share ROM chain */
|
|
159
|
+
return t2;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Frees memory of the method table (mutable layers only).
|
|
163
|
+
Stops at the first readonly (ROM) layer; ROM wrappers are
|
|
164
|
+
shared (by iclasses, dup, etc.) and freed via mrb->rom_mt
|
|
165
|
+
at state close. */
|
|
166
|
+
static void
|
|
167
|
+
mt_free(mrb_state *mrb, mrb_mt_tbl *t)
|
|
168
|
+
{
|
|
169
|
+
while (t && !mt_readonly_p(t)) {
|
|
170
|
+
mrb_mt_tbl *next = t->next;
|
|
171
|
+
mrb_free(mrb, t->ptr);
|
|
172
|
+
mrb_free(mrb, t);
|
|
173
|
+
t = next;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Allocates a per-state ROM wrapper for the const entries array
|
|
178
|
+
and pushes it onto the class's method table chain.
|
|
179
|
+
The wrapper is also registered in mrb->rom_mt for cleanup
|
|
180
|
+
at mrb_close, since ROM layers are shared and must not be
|
|
181
|
+
freed by mt_free during normal GC. */
|
|
182
|
+
void
|
|
183
|
+
mrb_mt_init_rom(mrb_state *mrb, struct RClass *c,
|
|
184
|
+
const mrb_mt_entry *entries, int size)
|
|
185
|
+
{
|
|
186
|
+
mrb_mt_tbl *rom = (mrb_mt_tbl*)mrb_malloc(mrb, sizeof(mrb_mt_tbl));
|
|
187
|
+
rom->size = size;
|
|
188
|
+
rom->alloc = size | MRB_MT_READONLY_BIT;
|
|
189
|
+
rom->ptr = (mrb_mt_entry*)entries;
|
|
190
|
+
|
|
191
|
+
/* register for cleanup at mrb_close */
|
|
192
|
+
struct mrb_mt_rom_list *node =
|
|
193
|
+
(struct mrb_mt_rom_list*)mrb_malloc(mrb, sizeof(struct mrb_mt_rom_list));
|
|
194
|
+
node->tbl = rom;
|
|
195
|
+
node->next = mrb->rom_mt;
|
|
196
|
+
mrb->rom_mt = node;
|
|
197
|
+
|
|
198
|
+
/* push ROM layer */
|
|
199
|
+
mrb_mt_tbl *t = c->mt;
|
|
200
|
+
if (!t || mt_readonly_p(t)) {
|
|
201
|
+
rom->next = t;
|
|
202
|
+
c->mt = rom;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
/* freeze mutable top, insert ROM behind it;
|
|
206
|
+
* c->mt must not change because iclasses (module inclusion)
|
|
207
|
+
* hold a copy of the mt pointer */
|
|
208
|
+
t->alloc |= MRB_MT_FROZEN_BIT;
|
|
209
|
+
rom->next = t->next;
|
|
210
|
+
t->next = rom;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* Creates a method value structure from flags and pointer */
|
|
215
|
+
static inline mrb_method_t
|
|
216
|
+
create_method_value(mrb_state *mrb, uint32_t flags, union mrb_mt_ptr val)
|
|
217
|
+
{
|
|
218
|
+
mrb_method_t m = { flags, { val.proc } };
|
|
219
|
+
return m;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* Iterates over methods in a class's method table with callback function */
|
|
223
|
+
MRB_API void
|
|
224
|
+
mrb_mt_foreach(mrb_state *mrb, struct RClass *c, mrb_mt_foreach_func *fn, void *p)
|
|
225
|
+
{
|
|
226
|
+
mrb_mt_tbl *t = c->mt;
|
|
227
|
+
if (!t) return;
|
|
228
|
+
|
|
229
|
+
/* fast path: single layer */
|
|
230
|
+
if (!t->next) {
|
|
231
|
+
mrb_mt_entry *entries = t->ptr;
|
|
232
|
+
for (int i = 0; i < t->size; i++) {
|
|
233
|
+
if (MRB_MT_REMOVED_P(entries[i])) continue;
|
|
234
|
+
if (fn(mrb, entries[i].key,
|
|
235
|
+
create_method_value(mrb, entries[i].flags, entries[i].val), p) != 0)
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* multi-layer: iterate each layer, skip if shadowed by a higher one */
|
|
242
|
+
for (mrb_mt_tbl *layer = t; layer; layer = layer->next) {
|
|
243
|
+
mrb_mt_entry *entries = layer->ptr;
|
|
244
|
+
for (int i = 0; i < layer->size; i++) {
|
|
245
|
+
if (MRB_MT_REMOVED_P(entries[i])) continue;
|
|
246
|
+
mrb_sym sym = entries[i].key;
|
|
247
|
+
/* check if shadowed by a higher layer */
|
|
248
|
+
if (layer != t) {
|
|
249
|
+
mrb_bool shadowed = FALSE;
|
|
250
|
+
for (mrb_mt_tbl *upper = t; upper != layer; upper = upper->next) {
|
|
251
|
+
mrb_mt_entry *up = upper->ptr;
|
|
252
|
+
for (int j = 0; j < upper->size; j++) {
|
|
253
|
+
if (up[j].key == sym) {
|
|
254
|
+
shadowed = TRUE;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (shadowed) break;
|
|
259
|
+
}
|
|
260
|
+
if (shadowed) continue;
|
|
261
|
+
}
|
|
262
|
+
if (fn(mrb, sym, create_method_value(mrb, entries[i].flags, entries[i].val), p) != 0)
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* Marks method table entries for garbage collection */
|
|
269
|
+
size_t
|
|
270
|
+
mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
|
|
271
|
+
{
|
|
272
|
+
size_t children = 0;
|
|
273
|
+
for (mrb_mt_tbl *t = c->mt; t; t = t->next) {
|
|
274
|
+
if (mt_readonly_p(t)) continue; /* ROM layers need no GC marking */
|
|
275
|
+
if (t->size == 0) continue;
|
|
276
|
+
mrb_mt_entry *entries = t->ptr;
|
|
277
|
+
for (int i = 0; i < t->size; i++) {
|
|
278
|
+
if (entries[i].key != 0 && (entries[i].flags & MRB_MT_FUNC) == 0) {
|
|
279
|
+
mrb_gc_mark(mrb, (struct RBasic*)entries[i].val.proc);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
children += (size_t)t->size;
|
|
283
|
+
}
|
|
284
|
+
return children;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* Returns memory size of class method table (mutable layers only) */
|
|
288
|
+
size_t
|
|
289
|
+
mrb_class_mt_memsize(mrb_state *mrb, struct RClass *c)
|
|
290
|
+
{
|
|
291
|
+
size_t total = 0;
|
|
292
|
+
for (mrb_mt_tbl *h = c->mt; h && !mt_readonly_p(h); h = h->next)
|
|
293
|
+
total += sizeof(mrb_mt_tbl) + (size_t)MT_ALLOC(h) * sizeof(mrb_mt_entry);
|
|
294
|
+
return total;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* Frees mutable layers of the class method table for GC.
|
|
298
|
+
ROM layers are left intact (freed via mrb->rom_mt at close). */
|
|
299
|
+
void
|
|
300
|
+
mrb_gc_free_mt(mrb_state *mrb, struct RClass *c)
|
|
301
|
+
{
|
|
302
|
+
if (c->mt) mt_free(mrb, c->mt);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* Sets the name of a class within an outer namespace */
|
|
306
|
+
void
|
|
307
|
+
mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
|
|
308
|
+
{
|
|
309
|
+
mrb_value name;
|
|
310
|
+
mrb_sym nsym = MRB_SYM(__classname__);
|
|
311
|
+
|
|
312
|
+
if (mrb_obj_iv_defined(mrb, (struct RObject*)c, nsym)) return;
|
|
313
|
+
if (outer == NULL || outer == mrb->object_class) {
|
|
314
|
+
name = mrb_symbol_value(id);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
name = mrb_class_path(mrb, outer);
|
|
318
|
+
if (mrb_nil_p(name)) { /* unnamed outer class */
|
|
319
|
+
if (outer != mrb->object_class && outer != c) {
|
|
320
|
+
mrb_obj_iv_set_force(mrb, (struct RObject*)c, MRB_SYM(__outer__),
|
|
321
|
+
mrb_obj_value(outer));
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
mrb_int len;
|
|
327
|
+
const char *n = mrb_sym_name_len(mrb, id, &len);
|
|
328
|
+
|
|
329
|
+
mrb_str_cat_lit(mrb, name, "::");
|
|
330
|
+
mrb_str_cat(mrb, name, n, len);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
mrb_obj_iv_set_force(mrb, (struct RObject*)c, nsym, name);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* Checks if a name is a valid constant name */
|
|
337
|
+
mrb_bool
|
|
338
|
+
mrb_const_name_p(mrb_state *mrb, const char *name, mrb_int len)
|
|
339
|
+
{
|
|
340
|
+
return len > 0 && ISUPPER(name[0]) && mrb_ident_p(name+1, len-1);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Sets up a class by defining it as a constant in the outer namespace */
|
|
344
|
+
static void
|
|
345
|
+
setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
|
|
346
|
+
{
|
|
347
|
+
mrb_const_set(mrb, mrb_obj_value(outer), id, mrb_obj_value(c));
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
|
|
351
|
+
|
|
352
|
+
/* Prepares and creates a singleton class for an object */
|
|
353
|
+
static void
|
|
354
|
+
prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
|
|
355
|
+
{
|
|
356
|
+
struct RClass *c;
|
|
357
|
+
|
|
358
|
+
mrb_assert(o->c);
|
|
359
|
+
if (o->c->tt == MRB_TT_SCLASS) return;
|
|
360
|
+
struct RClass *sc = MRB_OBJ_ALLOC(mrb, MRB_TT_SCLASS, mrb->class_class);
|
|
361
|
+
sc->flags |= MRB_FL_CLASS_IS_INHERITED;
|
|
362
|
+
sc->mt = NULL;
|
|
363
|
+
sc->iv = NULL;
|
|
364
|
+
if (o->tt == MRB_TT_CLASS) {
|
|
365
|
+
c = (struct RClass*)o;
|
|
366
|
+
if (!c->super) {
|
|
367
|
+
sc->super = mrb->class_class;
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
sc->super = c->super->c;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else if (o->tt == MRB_TT_SCLASS) {
|
|
374
|
+
c = (struct RClass*)o;
|
|
375
|
+
while (c->super->tt == MRB_TT_ICLASS)
|
|
376
|
+
c = c->super;
|
|
377
|
+
make_metaclass(mrb, c->super);
|
|
378
|
+
sc->super = c->super->c;
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
sc->super = o->c;
|
|
382
|
+
prepare_singleton_class(mrb, (struct RBasic*)sc);
|
|
383
|
+
}
|
|
384
|
+
o->c = sc;
|
|
385
|
+
mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
|
|
386
|
+
mrb_obj_iv_set(mrb, (struct RObject*)sc, MRB_SYM(__attached__), mrb_obj_value(o));
|
|
387
|
+
sc->frozen = o->frozen;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* Returns a string representation of a class name */
|
|
391
|
+
static mrb_value
|
|
392
|
+
class_name_str(mrb_state *mrb, struct RClass* c)
|
|
393
|
+
{
|
|
394
|
+
mrb_value path = mrb_class_path(mrb, c);
|
|
395
|
+
if (mrb_nil_p(path)) {
|
|
396
|
+
path = c->tt == MRB_TT_MODULE ? mrb_str_new_lit(mrb, "#<Module:") :
|
|
397
|
+
mrb_str_new_lit(mrb, "#<Class:");
|
|
398
|
+
mrb_str_cat_str(mrb, path, mrb_ptr_to_str(mrb, c));
|
|
399
|
+
mrb_str_cat_lit(mrb, path, ">");
|
|
400
|
+
}
|
|
401
|
+
return path;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* Gets a class from a constant symbol, ensuring it's a class */
|
|
405
|
+
static struct RClass*
|
|
406
|
+
class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
|
|
407
|
+
{
|
|
408
|
+
mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
|
|
409
|
+
|
|
410
|
+
mrb_check_type(mrb, c, MRB_TT_CLASS);
|
|
411
|
+
return mrb_class_ptr(c);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/* Gets a module from a constant symbol, ensuring it's a module */
|
|
415
|
+
static struct RClass*
|
|
416
|
+
module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
|
|
417
|
+
{
|
|
418
|
+
mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
|
|
419
|
+
|
|
420
|
+
mrb_check_type(mrb, c, MRB_TT_MODULE);
|
|
421
|
+
return mrb_class_ptr(c);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* Checks if an object is a class or module */
|
|
425
|
+
static mrb_bool
|
|
426
|
+
class_ptr_p(mrb_value obj)
|
|
427
|
+
{
|
|
428
|
+
switch (mrb_type(obj)) {
|
|
429
|
+
case MRB_TT_CLASS:
|
|
430
|
+
case MRB_TT_SCLASS:
|
|
431
|
+
case MRB_TT_MODULE:
|
|
432
|
+
return TRUE;
|
|
433
|
+
default:
|
|
434
|
+
return FALSE;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/* Checks if object is class/module and raises TypeError if not */
|
|
439
|
+
static void
|
|
440
|
+
check_if_class_or_module(mrb_state *mrb, mrb_value obj)
|
|
441
|
+
{
|
|
442
|
+
if (!class_ptr_p(obj)) {
|
|
443
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a class/module", obj);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/* Defines a new module or returns existing one */
|
|
448
|
+
static struct RClass*
|
|
449
|
+
define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer)
|
|
450
|
+
{
|
|
451
|
+
if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
|
|
452
|
+
return module_from_sym(mrb, outer, name);
|
|
453
|
+
}
|
|
454
|
+
struct RClass *m = mrb_module_new(mrb);
|
|
455
|
+
setup_class(mrb, outer, m, name);
|
|
456
|
+
|
|
457
|
+
return m;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/*
|
|
461
|
+
* Defines a new module in the top-level scope (Object) using a symbol for the name.
|
|
462
|
+
*
|
|
463
|
+
* @param mrb The mruby state.
|
|
464
|
+
* @param name The symbol representing the name of the module to define.
|
|
465
|
+
* @return A pointer to the newly defined or existing RClass structure for the module.
|
|
466
|
+
* @sideeffect Creates a new module or returns an existing one if already defined.
|
|
467
|
+
* The module is set as a constant in Object.
|
|
468
|
+
*/
|
|
469
|
+
MRB_API struct RClass*
|
|
470
|
+
mrb_define_module_id(mrb_state *mrb, mrb_sym name)
|
|
471
|
+
{
|
|
472
|
+
return define_module(mrb, name, mrb->object_class);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/*
|
|
476
|
+
* Defines a new module in the top-level scope (Object).
|
|
477
|
+
*
|
|
478
|
+
* @param mrb The mruby state.
|
|
479
|
+
* @param name The name of the module to define.
|
|
480
|
+
* @return A pointer to the newly defined or existing RClass structure for the module.
|
|
481
|
+
* @sideeffect Creates a new module or returns an existing one if already defined.
|
|
482
|
+
* The module is set as a constant in Object.
|
|
483
|
+
*/
|
|
484
|
+
MRB_API struct RClass*
|
|
485
|
+
mrb_define_module(mrb_state *mrb, const char *name)
|
|
486
|
+
{
|
|
487
|
+
return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
struct RClass*
|
|
491
|
+
mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
|
|
492
|
+
{
|
|
493
|
+
check_if_class_or_module(mrb, outer);
|
|
494
|
+
if (mrb_const_defined_at(mrb, outer, id)) {
|
|
495
|
+
mrb_value old = mrb_const_get(mrb, outer, id);
|
|
496
|
+
|
|
497
|
+
if (!mrb_module_p(old)) {
|
|
498
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a module", old);
|
|
499
|
+
}
|
|
500
|
+
return mrb_class_ptr(old);
|
|
501
|
+
}
|
|
502
|
+
return define_module(mrb, id, mrb_class_ptr(outer));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/*
|
|
506
|
+
* Defines a new module under the given outer module/class using a symbol for the name.
|
|
507
|
+
*
|
|
508
|
+
* @param mrb The mruby state.
|
|
509
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
510
|
+
* @param name The symbol representing the name of the module to define.
|
|
511
|
+
* @return A pointer to the newly defined or existing RClass structure for the module.
|
|
512
|
+
* @sideeffect Creates a new module or returns an existing one if already defined under `outer`.
|
|
513
|
+
* The module is set as a constant in `outer`.
|
|
514
|
+
*/
|
|
515
|
+
MRB_API struct RClass*
|
|
516
|
+
mrb_define_module_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name)
|
|
517
|
+
{
|
|
518
|
+
struct RClass * c = define_module(mrb, name, outer);
|
|
519
|
+
|
|
520
|
+
setup_class(mrb, outer, c, name);
|
|
521
|
+
return c;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/*
|
|
525
|
+
* Defines a new module under the given outer module/class using a C string for the name.
|
|
526
|
+
*
|
|
527
|
+
* @param mrb The mruby state.
|
|
528
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
529
|
+
* @param name The C string representing the name of the module to define.
|
|
530
|
+
* @return A pointer to the newly defined or existing RClass structure for the module.
|
|
531
|
+
* @sideeffect Creates a new module or returns an existing one if already defined under `outer`.
|
|
532
|
+
* The module is set as a constant in `outer`.
|
|
533
|
+
*/
|
|
534
|
+
MRB_API struct RClass*
|
|
535
|
+
mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
|
|
536
|
+
{
|
|
537
|
+
mrb_sym id = mrb_intern_cstr(mrb, name);
|
|
538
|
+
struct RClass * c = define_module(mrb, id, outer);
|
|
539
|
+
|
|
540
|
+
setup_class(mrb, outer, c, id);
|
|
541
|
+
return c;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
static struct RClass*
|
|
545
|
+
find_origin(struct RClass *c)
|
|
546
|
+
{
|
|
547
|
+
MRB_CLASS_ORIGIN(c);
|
|
548
|
+
return c;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
static struct RClass*
|
|
552
|
+
define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer)
|
|
553
|
+
{
|
|
554
|
+
struct RClass * c;
|
|
555
|
+
|
|
556
|
+
if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
|
|
557
|
+
c = class_from_sym(mrb, outer, name);
|
|
558
|
+
MRB_CLASS_ORIGIN(c);
|
|
559
|
+
if (super && mrb_class_real(c->super) != super) {
|
|
560
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %n (%C not %C)",
|
|
561
|
+
name, c->super, super);
|
|
562
|
+
}
|
|
563
|
+
return c;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
c = mrb_class_new(mrb, super);
|
|
567
|
+
setup_class(mrb, outer, c, name);
|
|
568
|
+
|
|
569
|
+
return c;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/*
|
|
573
|
+
* Defines a new class in the top-level scope (Object) using a symbol for the name.
|
|
574
|
+
*
|
|
575
|
+
* @param mrb The mruby state.
|
|
576
|
+
* @param name The symbol representing the name of the class to define.
|
|
577
|
+
* @param super A pointer to the RClass structure of the superclass.
|
|
578
|
+
* If NULL, Object is assumed as the superclass, and a warning is issued.
|
|
579
|
+
* @return A pointer to the newly defined or existing RClass structure for the class.
|
|
580
|
+
* @sideeffect Creates a new class or returns an existing one if already defined.
|
|
581
|
+
* The class is set as a constant in Object.
|
|
582
|
+
* Issues a warning if `super` is NULL.
|
|
583
|
+
*/
|
|
584
|
+
MRB_API struct RClass*
|
|
585
|
+
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
|
|
586
|
+
{
|
|
587
|
+
if (!super) {
|
|
588
|
+
mrb_warn(mrb, "no super class for '%n', Object assumed", name);
|
|
589
|
+
}
|
|
590
|
+
return define_class(mrb, name, super, mrb->object_class);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/*
|
|
594
|
+
* Defines a new class in the top-level scope (Object).
|
|
595
|
+
*
|
|
596
|
+
* @param mrb The mruby state.
|
|
597
|
+
* @param name The name of the class to define.
|
|
598
|
+
* @param super A pointer to the RClass structure of the superclass.
|
|
599
|
+
* If NULL, Object is assumed as the superclass.
|
|
600
|
+
* @return A pointer to the newly defined or existing RClass structure for the class.
|
|
601
|
+
* @sideeffect Creates a new class or returns an existing one if already defined.
|
|
602
|
+
* The class is set as a constant in Object.
|
|
603
|
+
*/
|
|
604
|
+
MRB_API struct RClass*
|
|
605
|
+
mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
|
|
606
|
+
{
|
|
607
|
+
return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
static mrb_value mrb_do_nothing(mrb_state *mrb, mrb_value);
|
|
611
|
+
#ifndef MRB_NO_METHOD_CACHE
|
|
612
|
+
static void mc_clear_by_id(mrb_state *mrb, mrb_sym mid);
|
|
613
|
+
#else
|
|
614
|
+
#define mc_clear(mrb)
|
|
615
|
+
#define mc_clear_by_id(mrb,mid)
|
|
616
|
+
#endif
|
|
617
|
+
|
|
618
|
+
static void
|
|
619
|
+
mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
|
|
620
|
+
{
|
|
621
|
+
|
|
622
|
+
if (!super)
|
|
623
|
+
super = mrb->object_class;
|
|
624
|
+
super->flags |= MRB_FL_CLASS_IS_INHERITED;
|
|
625
|
+
|
|
626
|
+
mrb_value s = mrb_obj_value(super);
|
|
627
|
+
mrb_sym mid = MRB_SYM(inherited);
|
|
628
|
+
|
|
629
|
+
if (!mrb_func_basic_p(mrb, s, mid, mrb_do_nothing)) {
|
|
630
|
+
mrb_value c = mrb_obj_value(klass);
|
|
631
|
+
mrb_funcall_argv(mrb, s, mid, 1, &c);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
struct RClass*
|
|
636
|
+
mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
|
|
637
|
+
{
|
|
638
|
+
struct RClass *s;
|
|
639
|
+
struct RClass *c;
|
|
640
|
+
|
|
641
|
+
if (!mrb_nil_p(super)) {
|
|
642
|
+
if (!mrb_class_p(super)) {
|
|
643
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%!v given)", super);
|
|
644
|
+
}
|
|
645
|
+
s = mrb_class_ptr(super);
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
s = NULL;
|
|
649
|
+
}
|
|
650
|
+
check_if_class_or_module(mrb, outer);
|
|
651
|
+
if (mrb_const_defined_at(mrb, outer, id)) {
|
|
652
|
+
mrb_value old = mrb_const_get(mrb, outer, id);
|
|
653
|
+
|
|
654
|
+
if (!mrb_class_p(old)) {
|
|
655
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a class", old);
|
|
656
|
+
}
|
|
657
|
+
c = mrb_class_ptr(old);
|
|
658
|
+
if (s) {
|
|
659
|
+
/* check super class */
|
|
660
|
+
if (mrb_class_real(c->super) != s) {
|
|
661
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for %v", old);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return c;
|
|
665
|
+
}
|
|
666
|
+
c = define_class(mrb, id, s, mrb_class_ptr(outer));
|
|
667
|
+
mrb_class_inherited(mrb, mrb_class_real(c->super), c);
|
|
668
|
+
|
|
669
|
+
return c;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/*
|
|
673
|
+
* Checks if a class is defined in the top-level scope (Object).
|
|
674
|
+
*
|
|
675
|
+
* @param mrb The mruby state.
|
|
676
|
+
* @param name The name of the class to check.
|
|
677
|
+
* @return TRUE if the class is defined, FALSE otherwise.
|
|
678
|
+
* Returns FALSE if the name is not a valid symbol.
|
|
679
|
+
*/
|
|
680
|
+
MRB_API mrb_bool
|
|
681
|
+
mrb_class_defined(mrb_state *mrb, const char *name)
|
|
682
|
+
{
|
|
683
|
+
mrb_sym sym = mrb_intern_check_cstr(mrb, name);
|
|
684
|
+
if (!sym) return FALSE;
|
|
685
|
+
return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), sym);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/*
|
|
689
|
+
* Checks if a class is defined in the top-level scope (Object) using a symbol for the name.
|
|
690
|
+
*
|
|
691
|
+
* @param mrb The mruby state.
|
|
692
|
+
* @param name The symbol representing the name of the class to check.
|
|
693
|
+
* @return TRUE if the class is defined, FALSE otherwise.
|
|
694
|
+
*/
|
|
695
|
+
MRB_API mrb_bool
|
|
696
|
+
mrb_class_defined_id(mrb_state *mrb, mrb_sym name)
|
|
697
|
+
{
|
|
698
|
+
return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), name);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/*
|
|
702
|
+
* Checks if a class is defined under the given outer module/class.
|
|
703
|
+
*
|
|
704
|
+
* @param mrb The mruby state.
|
|
705
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
706
|
+
* @param name The name of the class to check.
|
|
707
|
+
* @return TRUE if the class is defined under `outer`, FALSE otherwise.
|
|
708
|
+
* Returns FALSE if the name is not a valid symbol.
|
|
709
|
+
*/
|
|
710
|
+
MRB_API mrb_bool
|
|
711
|
+
mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name)
|
|
712
|
+
{
|
|
713
|
+
mrb_sym sym = mrb_intern_check_cstr(mrb, name);
|
|
714
|
+
if (!sym) return FALSE;
|
|
715
|
+
return mrb_const_defined_at(mrb, mrb_obj_value(outer), sym);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/*
|
|
719
|
+
* Checks if a class is defined under the given outer module/class using a symbol for the name.
|
|
720
|
+
*
|
|
721
|
+
* @param mrb The mruby state.
|
|
722
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
723
|
+
* @param name The symbol representing the name of the class to check.
|
|
724
|
+
* @return TRUE if the class is defined under `outer`, FALSE otherwise.
|
|
725
|
+
*/
|
|
726
|
+
MRB_API mrb_bool
|
|
727
|
+
mrb_class_defined_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name)
|
|
728
|
+
{
|
|
729
|
+
return mrb_const_defined_at(mrb, mrb_obj_value(outer), name);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/*
|
|
733
|
+
* Retrieves a class defined under an outer module/class.
|
|
734
|
+
*
|
|
735
|
+
* @param mrb The mruby state.
|
|
736
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
737
|
+
* If NULL, Object is assumed.
|
|
738
|
+
* @param name The name of the class to retrieve.
|
|
739
|
+
* @return A pointer to the RClass structure of the found class.
|
|
740
|
+
* @raise TypeError if the constant found is not a class.
|
|
741
|
+
* @raise NameError if the constant is not found.
|
|
742
|
+
*/
|
|
743
|
+
MRB_API struct RClass*
|
|
744
|
+
mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
|
|
745
|
+
{
|
|
746
|
+
return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/*
|
|
750
|
+
* Retrieves a class defined under an outer module/class using a symbol for the name.
|
|
751
|
+
*
|
|
752
|
+
* @param mrb The mruby state.
|
|
753
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
754
|
+
* If NULL, Object is assumed.
|
|
755
|
+
* @param name The symbol representing the name of the class to retrieve.
|
|
756
|
+
* @return A pointer to the RClass structure of the found class.
|
|
757
|
+
* @raise TypeError if the constant found is not a class.
|
|
758
|
+
* @raise NameError if the constant is not found.
|
|
759
|
+
*/
|
|
760
|
+
MRB_API struct RClass*
|
|
761
|
+
mrb_class_get_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name)
|
|
762
|
+
{
|
|
763
|
+
return class_from_sym(mrb, outer, name);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/*
|
|
767
|
+
* Retrieves a class defined in the top-level scope (Object).
|
|
768
|
+
*
|
|
769
|
+
* @param mrb The mruby state.
|
|
770
|
+
* @param name The name of the class to retrieve.
|
|
771
|
+
* @return A pointer to the RClass structure of the found class.
|
|
772
|
+
* @raise TypeError if the constant found is not a class.
|
|
773
|
+
* @raise NameError if the constant is not found.
|
|
774
|
+
*/
|
|
775
|
+
MRB_API struct RClass*
|
|
776
|
+
mrb_class_get(mrb_state *mrb, const char *name)
|
|
777
|
+
{
|
|
778
|
+
return mrb_class_get_under(mrb, mrb->object_class, name);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/*
|
|
782
|
+
* Retrieves a class defined in the top-level scope (Object) using a symbol for the name.
|
|
783
|
+
*
|
|
784
|
+
* @param mrb The mruby state.
|
|
785
|
+
* @param name The symbol representing the name of the class to retrieve.
|
|
786
|
+
* @return A pointer to the RClass structure of the found class.
|
|
787
|
+
* @raise TypeError if the constant found is not a class.
|
|
788
|
+
* @raise NameError if the constant is not found.
|
|
789
|
+
*/
|
|
790
|
+
MRB_API struct RClass*
|
|
791
|
+
mrb_class_get_id(mrb_state *mrb, mrb_sym name)
|
|
792
|
+
{
|
|
793
|
+
return mrb_class_get_under_id(mrb, mrb->object_class, name);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/*
|
|
797
|
+
* Retrieves an exception class by its symbol name.
|
|
798
|
+
* This function specifically searches for exception classes.
|
|
799
|
+
*
|
|
800
|
+
* @param mrb The mruby state.
|
|
801
|
+
* @param name The symbol representing the name of the exception class.
|
|
802
|
+
* @return A pointer to the RClass structure of the found exception class.
|
|
803
|
+
* @raise TypeError if the constant found is not a class.
|
|
804
|
+
* @raise NameError if the constant is not found.
|
|
805
|
+
* @raise Exception if the found class is not an exception (does not inherit from E_EXCEPTION).
|
|
806
|
+
* @raise Exception if the exception system is corrupted.
|
|
807
|
+
*/
|
|
808
|
+
MRB_API struct RClass*
|
|
809
|
+
mrb_exc_get_id(mrb_state *mrb, mrb_sym name)
|
|
810
|
+
{
|
|
811
|
+
mrb_value c = mrb_exc_const_get(mrb, name);
|
|
812
|
+
|
|
813
|
+
if (!mrb_class_p(c)) {
|
|
814
|
+
mrb_raise(mrb, E_EXCEPTION, "exception corrupted");
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
struct RClass *exc = mrb_class_ptr(c);
|
|
818
|
+
for (struct RClass *e = exc; e; e = e->super) {
|
|
819
|
+
if (e == E_EXCEPTION)
|
|
820
|
+
return exc;
|
|
821
|
+
}
|
|
822
|
+
mrb_raise(mrb, E_EXCEPTION, "non-exception raised");
|
|
823
|
+
/* not reached */
|
|
824
|
+
return NULL;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/*
|
|
828
|
+
* Retrieves a module defined under an outer module/class.
|
|
829
|
+
*
|
|
830
|
+
* @param mrb The mruby state.
|
|
831
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
832
|
+
* @param name The name of the module to retrieve.
|
|
833
|
+
* @return A pointer to the RClass structure of the found module.
|
|
834
|
+
* @raise TypeError if the constant found is not a module.
|
|
835
|
+
* @raise NameError if the constant is not found.
|
|
836
|
+
*/
|
|
837
|
+
MRB_API struct RClass*
|
|
838
|
+
mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
|
|
839
|
+
{
|
|
840
|
+
return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/*
|
|
844
|
+
* Retrieves a module defined under an outer module/class using a symbol for the name.
|
|
845
|
+
*
|
|
846
|
+
* @param mrb The mruby state.
|
|
847
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
848
|
+
* @param name The symbol representing the name of the module to retrieve.
|
|
849
|
+
* @return A pointer to the RClass structure of the found module.
|
|
850
|
+
* @raise TypeError if the constant found is not a module.
|
|
851
|
+
* @raise NameError if the constant is not found.
|
|
852
|
+
*/
|
|
853
|
+
MRB_API struct RClass*
|
|
854
|
+
mrb_module_get_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name)
|
|
855
|
+
{
|
|
856
|
+
return module_from_sym(mrb, outer, name);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/*
|
|
860
|
+
* Retrieves a module defined in the top-level scope (Object).
|
|
861
|
+
*
|
|
862
|
+
* @param mrb The mruby state.
|
|
863
|
+
* @param name The name of the module to retrieve.
|
|
864
|
+
* @return A pointer to the RClass structure of the found module.
|
|
865
|
+
* @raise TypeError if the constant found is not a module.
|
|
866
|
+
* @raise NameError if the constant is not found.
|
|
867
|
+
*/
|
|
868
|
+
MRB_API struct RClass*
|
|
869
|
+
mrb_module_get(mrb_state *mrb, const char *name)
|
|
870
|
+
{
|
|
871
|
+
return mrb_module_get_under(mrb, mrb->object_class, name);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/*
|
|
875
|
+
* Retrieves a module defined in the top-level scope (Object) using a symbol for the name.
|
|
876
|
+
*
|
|
877
|
+
* @param mrb The mruby state.
|
|
878
|
+
* @param name The symbol representing the name of the module to retrieve.
|
|
879
|
+
* @return A pointer to the RClass structure of the found module.
|
|
880
|
+
* @raise TypeError if the constant found is not a module.
|
|
881
|
+
* @raise NameError if the constant is not found.
|
|
882
|
+
*/
|
|
883
|
+
MRB_API struct RClass*
|
|
884
|
+
mrb_module_get_id(mrb_state *mrb, mrb_sym name)
|
|
885
|
+
{
|
|
886
|
+
return mrb_module_get_under_id(mrb, mrb->object_class, name);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/*
|
|
890
|
+
* Defines a class under the namespace of outer.
|
|
891
|
+
*
|
|
892
|
+
* @param mrb The mruby state.
|
|
893
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
894
|
+
* @param name The symbol representing the name of the class to define.
|
|
895
|
+
* @param super A pointer to the RClass structure of the superclass.
|
|
896
|
+
* If NULL, Object is assumed as the superclass.
|
|
897
|
+
* @return A pointer to the newly defined or existing RClass structure for the class.
|
|
898
|
+
* @raise TypeError if a constant with the same name exists but is not a class.
|
|
899
|
+
* @raise NameError if the class is already defined but with a different superclass.
|
|
900
|
+
* @sideeffect Creates a new class or returns an existing one if compatible.
|
|
901
|
+
* The class is set as a constant in `outer`.
|
|
902
|
+
* If a class with the same name is already defined and its superclass
|
|
903
|
+
* matches `super`, the existing class is returned.
|
|
904
|
+
*/
|
|
905
|
+
MRB_API struct RClass*
|
|
906
|
+
mrb_define_class_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name, struct RClass *super)
|
|
907
|
+
{
|
|
908
|
+
struct RClass * c;
|
|
909
|
+
|
|
910
|
+
#if 0 /* Warning is disabled by default, but can be enabled for debugging. */
|
|
911
|
+
if (!super) {
|
|
912
|
+
/* Emits a warning if no superclass is provided, assuming Object. */
|
|
913
|
+
mrb_warn(mrb, "no super class for '%C::%n', Object assumed", outer, name);
|
|
914
|
+
}
|
|
915
|
+
#endif
|
|
916
|
+
c = define_class(mrb, name, super, outer);
|
|
917
|
+
setup_class(mrb, outer, c, name); /* This sets the constant in outer */
|
|
918
|
+
return c;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/*
|
|
922
|
+
* Defines a class under the namespace of outer using a C string for the name.
|
|
923
|
+
*
|
|
924
|
+
* @param mrb The mruby state.
|
|
925
|
+
* @param outer A pointer to the RClass structure of the outer module/class.
|
|
926
|
+
* @param name The C string representing the name of the class to define.
|
|
927
|
+
* @param super A pointer to the RClass structure of the superclass.
|
|
928
|
+
* If NULL, Object is assumed as the superclass.
|
|
929
|
+
* @return A pointer to the newly defined or existing RClass structure for the class.
|
|
930
|
+
* @raise TypeError if a constant with the same name exists but is not a class.
|
|
931
|
+
* @raise NameError if the class is already defined but with a different superclass.
|
|
932
|
+
* @sideeffect Creates a new class or returns an existing one if compatible.
|
|
933
|
+
* The class is set as a constant in `outer`.
|
|
934
|
+
*/
|
|
935
|
+
MRB_API struct RClass*
|
|
936
|
+
mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
|
|
937
|
+
{
|
|
938
|
+
return mrb_define_class_under_id(mrb, outer, mrb_intern_cstr(mrb, name), super);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
static mrb_bool
|
|
942
|
+
check_visibility_break(const struct RProc *p, const struct RClass *c, mrb_callinfo *ci, struct REnv *env)
|
|
943
|
+
{
|
|
944
|
+
if (!p || p->upper == NULL || MRB_PROC_SCOPE_P(p) || p->e.env == NULL || !MRB_PROC_ENV_P(p)) {
|
|
945
|
+
return TRUE;
|
|
946
|
+
}
|
|
947
|
+
if (env) {
|
|
948
|
+
return p->e.env->c != c || MRB_ENV_VISIBILITY_BREAK_P(env);
|
|
949
|
+
}
|
|
950
|
+
return mrb_vm_ci_target_class(ci) != c || MRB_CI_VISIBILITY_BREAK_P(ci);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
static void
|
|
954
|
+
find_visibility_scope(mrb_state *mrb, const struct RClass *c, int n, mrb_callinfo **cp, struct REnv **ep)
|
|
955
|
+
{
|
|
956
|
+
const struct mrb_context *ec = mrb->c;
|
|
957
|
+
mrb_callinfo *ci = ec->ci - n;
|
|
958
|
+
const struct RProc *p = ci->proc;
|
|
959
|
+
|
|
960
|
+
if (c == NULL) c = mrb_vm_ci_target_class(ci);
|
|
961
|
+
|
|
962
|
+
if (check_visibility_break(p, c, ci, NULL)) {
|
|
963
|
+
*ep = (ci->u.env && ci->u.env->tt == MRB_TT_ENV) ? ci->u.env : NULL;
|
|
964
|
+
*cp = ci;
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
for (;;) {
|
|
969
|
+
struct REnv *env = p->e.env;
|
|
970
|
+
p = p->upper;
|
|
971
|
+
if (check_visibility_break(p, c, ci, env)) {
|
|
972
|
+
*ep = env;
|
|
973
|
+
*cp = NULL;
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/*
|
|
980
|
+
* Defines a method with raw mrb_method_t structure.
|
|
981
|
+
* This is a low-level function for method definition.
|
|
982
|
+
*
|
|
983
|
+
* @param mrb The mruby state.
|
|
984
|
+
* @param c The class/module in which to define the method.
|
|
985
|
+
* @param mid The symbol ID of the method name.
|
|
986
|
+
* @param m The mrb_method_t structure representing the method.
|
|
987
|
+
* @sideeffect Modifies the method table of the class/module `c`.
|
|
988
|
+
* Clears the method cache for `mid`.
|
|
989
|
+
* If `mid` is `initialize`, the method is automatically set to private.
|
|
990
|
+
* If the method visibility is default, it's determined by the current scope.
|
|
991
|
+
* @raise TypeError if the class/module or its attached object (for singleton classes) is frozen.
|
|
992
|
+
*/
|
|
993
|
+
MRB_API void
|
|
994
|
+
mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_t m)
|
|
995
|
+
{
|
|
996
|
+
union mrb_mt_ptr ptr;
|
|
997
|
+
|
|
998
|
+
MRB_CLASS_ORIGIN(c);
|
|
999
|
+
|
|
1000
|
+
mrb_mt_tbl *h = c->mt;
|
|
1001
|
+
if (c->tt == MRB_TT_SCLASS && mrb_frozen_p(c)) {
|
|
1002
|
+
mrb_value v = mrb_iv_get(mrb, mrb_obj_value(c), MRB_SYM(__attached__));
|
|
1003
|
+
mrb_check_frozen_value(mrb, v);
|
|
1004
|
+
}
|
|
1005
|
+
else {
|
|
1006
|
+
mrb_check_frozen(mrb, c);
|
|
1007
|
+
}
|
|
1008
|
+
if (!h) {
|
|
1009
|
+
h = c->mt = mt_new(mrb);
|
|
1010
|
+
}
|
|
1011
|
+
else if (mt_frozen_p(h)) {
|
|
1012
|
+
/* unfreeze heap-allocated frozen layer to preserve c->mt pointer
|
|
1013
|
+
* (iclasses hold a copy of the mt pointer for included modules) */
|
|
1014
|
+
h->alloc &= ~MRB_MT_FROZEN_BIT;
|
|
1015
|
+
}
|
|
1016
|
+
else if (mt_readonly_p(h)) {
|
|
1017
|
+
/* COW: create mutable top layer, chain to ROM */
|
|
1018
|
+
mrb_mt_tbl *top = mt_new(mrb);
|
|
1019
|
+
top->next = h;
|
|
1020
|
+
h = c->mt = top;
|
|
1021
|
+
}
|
|
1022
|
+
if (MRB_METHOD_PROC_P(m)) {
|
|
1023
|
+
struct RProc *p = (struct RProc*)MRB_METHOD_PROC(m);
|
|
1024
|
+
|
|
1025
|
+
ptr.proc = p;
|
|
1026
|
+
if (p) {
|
|
1027
|
+
if (p->gc_color != MRB_GC_RED) {
|
|
1028
|
+
p->flags |= MRB_PROC_SCOPE;
|
|
1029
|
+
p->c = NULL;
|
|
1030
|
+
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)p);
|
|
1031
|
+
if (!MRB_PROC_ENV_P(p)) {
|
|
1032
|
+
MRB_PROC_SET_TARGET_CLASS(p, c);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
else {
|
|
1036
|
+
mrb_assert(mrb_frozen_p(p) && MRB_PROC_SCOPE_P(p));
|
|
1037
|
+
mrb_assert(p->c == NULL && p->upper == NULL && p->e.target_class == NULL);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
else {
|
|
1042
|
+
ptr.func = MRB_METHOD_FUNC(m);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
int flags = m.flags;
|
|
1046
|
+
if (mid == MRB_SYM(initialize) ||
|
|
1047
|
+
mid == MRB_SYM(initialize_copy) ||
|
|
1048
|
+
mid == MRB_SYM_Q(respond_to_missing)) {
|
|
1049
|
+
MRB_SET_VISIBILITY_FLAGS(flags, MRB_METHOD_PRIVATE_FL);
|
|
1050
|
+
}
|
|
1051
|
+
else if ((flags & MT_VMASK) == MT_VDEFAULT) {
|
|
1052
|
+
/* singleton methods are always public */
|
|
1053
|
+
if (c->tt == MRB_TT_SCLASS) {
|
|
1054
|
+
MRB_SET_VISIBILITY_FLAGS(flags, MRB_METHOD_PUBLIC_FL);
|
|
1055
|
+
}
|
|
1056
|
+
else {
|
|
1057
|
+
mrb_callinfo *ci;
|
|
1058
|
+
struct REnv *e;
|
|
1059
|
+
find_visibility_scope(mrb, c, 0, &ci, &e);
|
|
1060
|
+
mrb_assert(ci || e);
|
|
1061
|
+
MRB_SET_VISIBILITY_FLAGS(flags, (uint32_t)(e ? MRB_ENV_VISIBILITY(e) : MRB_CI_VISIBILITY(ci)) << 25);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
mt_put(mrb, h, mid, flags, ptr);
|
|
1065
|
+
if (!mrb->bootstrapping) mc_clear_by_id(mrb, mid);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
static void
|
|
1069
|
+
define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec, int vis)
|
|
1070
|
+
{
|
|
1071
|
+
mrb_method_t m;
|
|
1072
|
+
int ai = mrb_gc_arena_save(mrb);
|
|
1073
|
+
|
|
1074
|
+
MRB_METHOD_FROM_FUNC(m, func);
|
|
1075
|
+
m.flags |= aspec;
|
|
1076
|
+
MRB_METHOD_SET_VISIBILITY(m, vis);
|
|
1077
|
+
mrb_define_method_raw(mrb, c, mid, m);
|
|
1078
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/*
|
|
1082
|
+
* Defines a public C function as a method for a class/module using a symbol for the name.
|
|
1083
|
+
*
|
|
1084
|
+
* @param mrb The mruby state.
|
|
1085
|
+
* @param c The class/module in which to define the method.
|
|
1086
|
+
* @param mid The symbol ID of the method name.
|
|
1087
|
+
* @param func The C function pointer (mrb_func_t) for the method body.
|
|
1088
|
+
* @param aspec The argument specification for the method (e.g., MRB_ARGS_REQ(1)).
|
|
1089
|
+
* @sideeffect Modifies the method table of the class/module `c`.
|
|
1090
|
+
* Clears the method cache for `mid`.
|
|
1091
|
+
*/
|
|
1092
|
+
MRB_API void
|
|
1093
|
+
mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
|
|
1094
|
+
{
|
|
1095
|
+
define_method_id(mrb, c, mid, func, aspec, MRB_METHOD_PUBLIC_FL);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
/*
|
|
1099
|
+
* Defines a public C function as a method for a class/module.
|
|
1100
|
+
*
|
|
1101
|
+
* @param mrb The mruby state.
|
|
1102
|
+
* @param c The class/module in which to define the method.
|
|
1103
|
+
* @param name The C string name of the method.
|
|
1104
|
+
* @param func The C function pointer (mrb_func_t) for the method body.
|
|
1105
|
+
* @param aspec The argument specification for the method (e.g., MRB_ARGS_REQ(1)).
|
|
1106
|
+
* @sideeffect Modifies the method table of the class/module `c`.
|
|
1107
|
+
* Interns the method name string.
|
|
1108
|
+
* Clears the method cache for the interned method name.
|
|
1109
|
+
*/
|
|
1110
|
+
MRB_API void
|
|
1111
|
+
mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
|
|
1112
|
+
{
|
|
1113
|
+
mrb_define_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/*
|
|
1117
|
+
* Defines a private C function as a method for a class/module using a symbol for the name.
|
|
1118
|
+
*
|
|
1119
|
+
* @param mrb The mruby state.
|
|
1120
|
+
* @param c The class/module in which to define the method.
|
|
1121
|
+
* @param mid The symbol ID of the method name.
|
|
1122
|
+
* @param func The C function pointer (mrb_func_t) for the method body.
|
|
1123
|
+
* @param aspec The argument specification for the method (e.g., MRB_ARGS_REQ(1)).
|
|
1124
|
+
* @sideeffect Modifies the method table of the class/module `c`.
|
|
1125
|
+
* Clears the method cache for `mid`.
|
|
1126
|
+
*/
|
|
1127
|
+
MRB_API void
|
|
1128
|
+
mrb_define_private_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
|
|
1129
|
+
{
|
|
1130
|
+
define_method_id(mrb, c, mid, func, aspec, MRB_METHOD_PRIVATE_FL);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
/*
|
|
1134
|
+
* Defines a private C function as a method for a class/module.
|
|
1135
|
+
*
|
|
1136
|
+
* @param mrb The mruby state.
|
|
1137
|
+
* @param c The class/module in which to define the method.
|
|
1138
|
+
* @param name The C string name of the method.
|
|
1139
|
+
* @param func The C function pointer (mrb_func_t) for the method body.
|
|
1140
|
+
* @param aspec The argument specification for the method (e.g., MRB_ARGS_REQ(1)).
|
|
1141
|
+
* @sideeffect Modifies the method table of the class/module `c`.
|
|
1142
|
+
* Interns the method name string.
|
|
1143
|
+
* Clears the method cache for the interned method name.
|
|
1144
|
+
*/
|
|
1145
|
+
MRB_API void
|
|
1146
|
+
mrb_define_private_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
|
|
1147
|
+
{
|
|
1148
|
+
mrb_define_private_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/*
|
|
1152
|
+
* Raises a NotImplementedError, typically indicating that the C function
|
|
1153
|
+
* called by Ruby is not implemented for the current platform or build.
|
|
1154
|
+
* The error message will include the name of the Ruby method that called this C function.
|
|
1155
|
+
*
|
|
1156
|
+
* @param mrb The mruby state.
|
|
1157
|
+
* @sideeffect Raises a NotImplementedError exception. This function does not return.
|
|
1158
|
+
* If a method name is available from the callinfo, it's included
|
|
1159
|
+
* in the error message (e.g., "foo() function is unimplemented on this machine").
|
|
1160
|
+
*/
|
|
1161
|
+
MRB_API void
|
|
1162
|
+
mrb_notimplement(mrb_state *mrb)
|
|
1163
|
+
{
|
|
1164
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1165
|
+
|
|
1166
|
+
if (ci->mid) {
|
|
1167
|
+
mrb_raisef(mrb, E_NOTIMP_ERROR, "%n() function is unimplemented on this machine", ci->mid);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
/*
|
|
1172
|
+
* A C function suitable for use as a method body (mrb_func_t)
|
|
1173
|
+
* that raises a NotImplementedError.
|
|
1174
|
+
*
|
|
1175
|
+
* @param mrb The mruby state.
|
|
1176
|
+
* @param self The receiver of the method call (unused).
|
|
1177
|
+
* @return This function does not return, as it raises an exception.
|
|
1178
|
+
* @sideeffect Raises a NotImplementedError exception via `mrb_notimplement`.
|
|
1179
|
+
*/
|
|
1180
|
+
MRB_API mrb_value
|
|
1181
|
+
mrb_notimplement_m(mrb_state *mrb, mrb_value self)
|
|
1182
|
+
{
|
|
1183
|
+
mrb_notimplement(mrb);
|
|
1184
|
+
/* not reached */
|
|
1185
|
+
return mrb_nil_value();
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
static void
|
|
1189
|
+
ensure_class_type(mrb_state *mrb, mrb_value val)
|
|
1190
|
+
{
|
|
1191
|
+
if (!class_ptr_p(val)) {
|
|
1192
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "%v is not class/module", val);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
#define to_sym(mrb, ss) mrb_obj_to_sym(mrb, ss)
|
|
1197
|
+
|
|
1198
|
+
/*
|
|
1199
|
+
* Gets the number of arguments passed to the current C function call.
|
|
1200
|
+
*
|
|
1201
|
+
* This function retrieves the argument count from the current callinfo (`ci`)
|
|
1202
|
+
* in the mruby state. It correctly handles the case where arguments might be
|
|
1203
|
+
* packed into an array by the caller (indicated by `ci->n == 15`), in which
|
|
1204
|
+
* case it gets the length of that array.
|
|
1205
|
+
*
|
|
1206
|
+
* @param mrb The mruby state.
|
|
1207
|
+
* @return The number of arguments passed to the C function.
|
|
1208
|
+
*/
|
|
1209
|
+
MRB_API mrb_int
|
|
1210
|
+
mrb_get_argc(mrb_state *mrb)
|
|
1211
|
+
{
|
|
1212
|
+
mrb_int argc = mrb->c->ci->n;
|
|
1213
|
+
|
|
1214
|
+
if (argc == 15) {
|
|
1215
|
+
struct RArray *a = mrb_ary_ptr(mrb->c->ci->stack[1]);
|
|
1216
|
+
|
|
1217
|
+
a->c = NULL; /* hide from ObjectSpace.each_object */
|
|
1218
|
+
argc = ARY_LEN(a);
|
|
1219
|
+
}
|
|
1220
|
+
return argc;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
/*
|
|
1224
|
+
* Gets a pointer to the array of arguments passed to the current C function call.
|
|
1225
|
+
*
|
|
1226
|
+
* This function retrieves the arguments from the current callinfo stack.
|
|
1227
|
+
* It handles the case where arguments might be packed into an array
|
|
1228
|
+
* (when `ci->n == 15`), returning a pointer to the elements of that array.
|
|
1229
|
+
* Otherwise, it returns a pointer to the arguments on the stack.
|
|
1230
|
+
*
|
|
1231
|
+
* @param mrb The mruby state.
|
|
1232
|
+
* @return A const pointer to the array of mrb_value arguments.
|
|
1233
|
+
* The caller should not modify the contents of this array.
|
|
1234
|
+
* @note If arguments were packed, the RArray object on stack has its class pointer
|
|
1235
|
+
* temporarily set to NULL to hide it from `ObjectSpace.each_object`.
|
|
1236
|
+
*/
|
|
1237
|
+
MRB_API const mrb_value*
|
|
1238
|
+
mrb_get_argv(mrb_state *mrb)
|
|
1239
|
+
{
|
|
1240
|
+
mrb_int argc = mrb->c->ci->n;
|
|
1241
|
+
mrb_value *array_argv = mrb->c->ci->stack + 1;
|
|
1242
|
+
if (argc == 15) {
|
|
1243
|
+
struct RArray *a = mrb_ary_ptr(*array_argv);
|
|
1244
|
+
|
|
1245
|
+
a->c = NULL; /* hide from ObjectSpace.each_object */
|
|
1246
|
+
array_argv = ARY_PTR(a);
|
|
1247
|
+
}
|
|
1248
|
+
return array_argv;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/*
|
|
1252
|
+
* Gets the first argument passed to the current C function call.
|
|
1253
|
+
*
|
|
1254
|
+
* This is a convenience function for directly accessing the first argument.
|
|
1255
|
+
* It handles cases where arguments might be packed into an array or
|
|
1256
|
+
* if the first argument is a keyword hash.
|
|
1257
|
+
*
|
|
1258
|
+
* @param mrb The mruby state.
|
|
1259
|
+
* @return The first mrb_value argument.
|
|
1260
|
+
* @raise ArgumentError if the number of positional arguments is not 1,
|
|
1261
|
+
* unless there are no positional arguments but a keyword hash is present,
|
|
1262
|
+
* in which case the keyword hash is returned.
|
|
1263
|
+
*/
|
|
1264
|
+
MRB_API mrb_value
|
|
1265
|
+
mrb_get_arg1(mrb_state *mrb)
|
|
1266
|
+
{
|
|
1267
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1268
|
+
mrb_int argc = ci->n;
|
|
1269
|
+
mrb_value *array_argv = ci->stack + 1;
|
|
1270
|
+
if (argc == 15) {
|
|
1271
|
+
struct RArray *a = mrb_ary_ptr(*array_argv);
|
|
1272
|
+
|
|
1273
|
+
argc = ARY_LEN(a);
|
|
1274
|
+
array_argv = ARY_PTR(a);
|
|
1275
|
+
}
|
|
1276
|
+
if (argc == 0 && ci->nk == 15) {
|
|
1277
|
+
mrb_int n = ci->n;
|
|
1278
|
+
if (n == 15) n = 1;
|
|
1279
|
+
return ci->stack[n+1]; /* kwhash next to positional arguments */
|
|
1280
|
+
}
|
|
1281
|
+
if (argc != 1) {
|
|
1282
|
+
mrb_argnum_error(mrb, argc, 1, 1);
|
|
1283
|
+
}
|
|
1284
|
+
return array_argv[0];
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/*
|
|
1288
|
+
* Checks if a block was passed to the current C function call.
|
|
1289
|
+
*
|
|
1290
|
+
* It inspects the current callinfo stack for a block argument.
|
|
1291
|
+
*
|
|
1292
|
+
* @param mrb The mruby state.
|
|
1293
|
+
* @return TRUE if a block is present (i.e., not nil), FALSE otherwise.
|
|
1294
|
+
*/
|
|
1295
|
+
MRB_API mrb_bool
|
|
1296
|
+
mrb_block_given_p(mrb_state *mrb)
|
|
1297
|
+
{
|
|
1298
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1299
|
+
mrb_value b = ci->stack[mrb_ci_bidx(ci)];
|
|
1300
|
+
|
|
1301
|
+
return !mrb_nil_p(b);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
#define GET_ARG(_type) (ptr ? ((_type)(*ptr++)) : va_arg((*ap), _type))
|
|
1305
|
+
|
|
1306
|
+
static mrb_int
|
|
1307
|
+
get_args_v(mrb_state *mrb, mrb_args_format format, void** ptr, va_list *ap)
|
|
1308
|
+
{
|
|
1309
|
+
const char *fmt = format;
|
|
1310
|
+
char c;
|
|
1311
|
+
mrb_int i = 0;
|
|
1312
|
+
mrb_callinfo *ci = mrb->c->ci;
|
|
1313
|
+
mrb_int argc = ci->n;
|
|
1314
|
+
const mrb_value *argv = ci->stack+1;
|
|
1315
|
+
mrb_bool argv_on_stack;
|
|
1316
|
+
mrb_bool opt = FALSE;
|
|
1317
|
+
mrb_bool opt_skip = TRUE;
|
|
1318
|
+
const mrb_value *pickarg = NULL; /* arguments currently being processed */
|
|
1319
|
+
mrb_value kdict = mrb_nil_value();
|
|
1320
|
+
mrb_bool reqkarg = FALSE;
|
|
1321
|
+
int argc_min = 0, argc_max = 0;
|
|
1322
|
+
|
|
1323
|
+
while ((c = *fmt++)) {
|
|
1324
|
+
switch (c) {
|
|
1325
|
+
case '|':
|
|
1326
|
+
opt = TRUE;
|
|
1327
|
+
break;
|
|
1328
|
+
case '*':
|
|
1329
|
+
opt_skip = FALSE;
|
|
1330
|
+
argc_max = -1;
|
|
1331
|
+
if (!reqkarg) reqkarg = strchr(fmt, ':') ? TRUE : FALSE;
|
|
1332
|
+
goto check_exit;
|
|
1333
|
+
case '!':
|
|
1334
|
+
case '+':
|
|
1335
|
+
break;
|
|
1336
|
+
case ':':
|
|
1337
|
+
reqkarg = TRUE;
|
|
1338
|
+
/* fall through */
|
|
1339
|
+
case '&': case '?':
|
|
1340
|
+
if (opt) opt_skip = FALSE;
|
|
1341
|
+
break;
|
|
1342
|
+
default:
|
|
1343
|
+
if (!opt) argc_min++;
|
|
1344
|
+
argc_max++;
|
|
1345
|
+
break;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
check_exit:
|
|
1350
|
+
if (!reqkarg && ci->nk > 0) {
|
|
1351
|
+
mrb_assert(ci->nk == 15);
|
|
1352
|
+
kdict = ci->stack[mrb_ci_bidx(ci)-1];
|
|
1353
|
+
if (mrb_hash_p(kdict) && mrb_hash_size(mrb, kdict) > 0) {
|
|
1354
|
+
if (argc < 14) {
|
|
1355
|
+
ci->n++;
|
|
1356
|
+
argc++; /* include kdict in normal arguments */
|
|
1357
|
+
}
|
|
1358
|
+
else {
|
|
1359
|
+
/* 14+1 == 15 so pack first */
|
|
1360
|
+
if (argc == 14) {
|
|
1361
|
+
/* pack arguments and kdict */
|
|
1362
|
+
ci->stack[1] = mrb_ary_new_from_values(mrb, argc+1, &ci->stack[1]);
|
|
1363
|
+
argc = ci->n = 15;
|
|
1364
|
+
}
|
|
1365
|
+
else {
|
|
1366
|
+
/* push kdict to packed arguments */
|
|
1367
|
+
mrb_ary_push(mrb, ci->stack[1], kdict);
|
|
1368
|
+
}
|
|
1369
|
+
ci->stack[2] = ci->stack[mrb_ci_bidx(ci)];
|
|
1370
|
+
}
|
|
1371
|
+
ci->nk = 0;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (reqkarg && ci->nk > 0) {
|
|
1375
|
+
kdict = ci->stack[mrb_ci_bidx(ci)-1];
|
|
1376
|
+
mrb_assert(ci->nk == 15);
|
|
1377
|
+
mrb_assert(mrb_hash_p(kdict));
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
argv_on_stack = argc < 15;
|
|
1381
|
+
if (!argv_on_stack) {
|
|
1382
|
+
struct RArray *a = mrb_ary_ptr(*argv);
|
|
1383
|
+
argv = ARY_PTR(a);
|
|
1384
|
+
argc = ARY_LEN(a);
|
|
1385
|
+
a->c = NULL; /* hide from ObjectSpace.each_object */
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
opt = FALSE;
|
|
1389
|
+
i = 0;
|
|
1390
|
+
while ((c = *format++)) {
|
|
1391
|
+
mrb_bool altmode = FALSE;
|
|
1392
|
+
mrb_bool needmodify = FALSE;
|
|
1393
|
+
|
|
1394
|
+
for (; *format; format++) {
|
|
1395
|
+
switch (*format) {
|
|
1396
|
+
case '!':
|
|
1397
|
+
if (altmode) goto modifier_exit; /* not accept for multiple '!' */
|
|
1398
|
+
altmode = TRUE;
|
|
1399
|
+
break;
|
|
1400
|
+
case '+':
|
|
1401
|
+
if (needmodify) goto modifier_exit; /* not accept for multiple '+' */
|
|
1402
|
+
needmodify = TRUE;
|
|
1403
|
+
break;
|
|
1404
|
+
default:
|
|
1405
|
+
goto modifier_exit;
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
modifier_exit:
|
|
1410
|
+
switch (c) {
|
|
1411
|
+
case '|': case '*': case '&': case '?': case ':':
|
|
1412
|
+
if (needmodify) {
|
|
1413
|
+
bad_needmodify:
|
|
1414
|
+
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong `%c+` modified specifier`", c);
|
|
1415
|
+
}
|
|
1416
|
+
break;
|
|
1417
|
+
default:
|
|
1418
|
+
if (i < argc) {
|
|
1419
|
+
pickarg = &argv[i++];
|
|
1420
|
+
if (needmodify && !mrb_nil_p(*pickarg)) {
|
|
1421
|
+
mrb_check_frozen_value(mrb, *pickarg);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
else {
|
|
1425
|
+
if (opt) {
|
|
1426
|
+
pickarg = NULL;
|
|
1427
|
+
}
|
|
1428
|
+
else {
|
|
1429
|
+
mrb_argnum_error(mrb, argc, argc_min, argc_max);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
break;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
switch (c) {
|
|
1436
|
+
case 'o':
|
|
1437
|
+
case 'C':
|
|
1438
|
+
case 'S':
|
|
1439
|
+
case 'A':
|
|
1440
|
+
case 'H':
|
|
1441
|
+
{
|
|
1442
|
+
mrb_value *p;
|
|
1443
|
+
|
|
1444
|
+
p = GET_ARG(mrb_value*);
|
|
1445
|
+
if (pickarg) {
|
|
1446
|
+
if (!(altmode && mrb_nil_p(*pickarg))) {
|
|
1447
|
+
switch (c) {
|
|
1448
|
+
case 'C': ensure_class_type(mrb, *pickarg); break;
|
|
1449
|
+
case 'S': mrb_ensure_string_type(mrb, *pickarg); break;
|
|
1450
|
+
case 'A': mrb_ensure_array_type(mrb, *pickarg); break;
|
|
1451
|
+
case 'H': mrb_ensure_hash_type(mrb, *pickarg); break;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
*p = *pickarg;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
break;
|
|
1458
|
+
case 'c':
|
|
1459
|
+
{
|
|
1460
|
+
struct RClass **p;
|
|
1461
|
+
|
|
1462
|
+
p = GET_ARG(struct RClass**);
|
|
1463
|
+
if (pickarg) {
|
|
1464
|
+
if (altmode && mrb_nil_p(*pickarg)) {
|
|
1465
|
+
*p = NULL;
|
|
1466
|
+
}
|
|
1467
|
+
else {
|
|
1468
|
+
ensure_class_type(mrb, *pickarg);
|
|
1469
|
+
*p = mrb_class_ptr(*pickarg);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
break;
|
|
1474
|
+
case 's':
|
|
1475
|
+
{
|
|
1476
|
+
const char **ps = NULL;
|
|
1477
|
+
mrb_int *pl = NULL;
|
|
1478
|
+
|
|
1479
|
+
ps = GET_ARG(const char**);
|
|
1480
|
+
pl = GET_ARG(mrb_int*);
|
|
1481
|
+
if (needmodify) goto bad_needmodify;
|
|
1482
|
+
if (pickarg) {
|
|
1483
|
+
if (altmode && mrb_nil_p(*pickarg)) {
|
|
1484
|
+
*ps = NULL;
|
|
1485
|
+
*pl = 0;
|
|
1486
|
+
}
|
|
1487
|
+
else {
|
|
1488
|
+
mrb_ensure_string_type(mrb, *pickarg);
|
|
1489
|
+
*ps = RSTRING_PTR(*pickarg);
|
|
1490
|
+
*pl = RSTRING_LEN(*pickarg);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
break;
|
|
1495
|
+
case 'z':
|
|
1496
|
+
{
|
|
1497
|
+
const char **ps;
|
|
1498
|
+
|
|
1499
|
+
ps = GET_ARG(const char**);
|
|
1500
|
+
if (needmodify) goto bad_needmodify;
|
|
1501
|
+
if (pickarg) {
|
|
1502
|
+
if (altmode && mrb_nil_p(*pickarg)) {
|
|
1503
|
+
*ps = NULL;
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
mrb_ensure_string_type(mrb, *pickarg);
|
|
1507
|
+
*ps = RSTRING_CSTR(mrb, *pickarg);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
break;
|
|
1512
|
+
case 'a':
|
|
1513
|
+
{
|
|
1514
|
+
struct RArray *a;
|
|
1515
|
+
const mrb_value **pb;
|
|
1516
|
+
mrb_int *pl;
|
|
1517
|
+
|
|
1518
|
+
pb = GET_ARG(const mrb_value**);
|
|
1519
|
+
pl = GET_ARG(mrb_int*);
|
|
1520
|
+
if (needmodify) goto bad_needmodify;
|
|
1521
|
+
if (pickarg) {
|
|
1522
|
+
if (altmode && mrb_nil_p(*pickarg)) {
|
|
1523
|
+
*pb = NULL;
|
|
1524
|
+
*pl = 0;
|
|
1525
|
+
}
|
|
1526
|
+
else {
|
|
1527
|
+
mrb_ensure_array_type(mrb, *pickarg);
|
|
1528
|
+
a = mrb_ary_ptr(*pickarg);
|
|
1529
|
+
*pb = ARY_PTR(a);
|
|
1530
|
+
*pl = ARY_LEN(a);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
break;
|
|
1535
|
+
#ifndef MRB_NO_FLOAT
|
|
1536
|
+
case 'f':
|
|
1537
|
+
{
|
|
1538
|
+
mrb_float *p;
|
|
1539
|
+
|
|
1540
|
+
p = GET_ARG(mrb_float*);
|
|
1541
|
+
if (pickarg) {
|
|
1542
|
+
*p = mrb_as_float(mrb, *pickarg);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
break;
|
|
1546
|
+
#endif
|
|
1547
|
+
case 'i':
|
|
1548
|
+
{
|
|
1549
|
+
mrb_int *p;
|
|
1550
|
+
|
|
1551
|
+
p = GET_ARG(mrb_int*);
|
|
1552
|
+
if (pickarg) {
|
|
1553
|
+
*p = mrb_as_int(mrb, *pickarg);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
break;
|
|
1557
|
+
case 'b':
|
|
1558
|
+
{
|
|
1559
|
+
mrb_bool *boolp = GET_ARG(mrb_bool*);
|
|
1560
|
+
|
|
1561
|
+
if (pickarg) {
|
|
1562
|
+
*boolp = mrb_test(*pickarg);
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
break;
|
|
1566
|
+
case 'n':
|
|
1567
|
+
{
|
|
1568
|
+
mrb_sym *symp;
|
|
1569
|
+
|
|
1570
|
+
symp = GET_ARG(mrb_sym*);
|
|
1571
|
+
if (pickarg) {
|
|
1572
|
+
*symp = to_sym(mrb, *pickarg);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
break;
|
|
1576
|
+
case 'd':
|
|
1577
|
+
{
|
|
1578
|
+
void** datap;
|
|
1579
|
+
struct mrb_data_type const* type;
|
|
1580
|
+
|
|
1581
|
+
datap = GET_ARG(void**);
|
|
1582
|
+
type = GET_ARG(struct mrb_data_type const*);
|
|
1583
|
+
if (pickarg) {
|
|
1584
|
+
if (altmode && mrb_nil_p(*pickarg)) {
|
|
1585
|
+
*datap = NULL;
|
|
1586
|
+
}
|
|
1587
|
+
else {
|
|
1588
|
+
*datap = mrb_data_get_ptr(mrb, *pickarg, type);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
break;
|
|
1593
|
+
|
|
1594
|
+
case '&':
|
|
1595
|
+
{
|
|
1596
|
+
mrb_value *p, *bp;
|
|
1597
|
+
|
|
1598
|
+
p = GET_ARG(mrb_value*);
|
|
1599
|
+
bp = ci->stack + mrb_ci_bidx(ci);
|
|
1600
|
+
if (altmode && mrb_nil_p(*bp)) {
|
|
1601
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
|
|
1602
|
+
}
|
|
1603
|
+
*p = *bp;
|
|
1604
|
+
}
|
|
1605
|
+
break;
|
|
1606
|
+
case '|':
|
|
1607
|
+
if (opt_skip && i == argc) goto finish;
|
|
1608
|
+
opt = TRUE;
|
|
1609
|
+
break;
|
|
1610
|
+
case '?':
|
|
1611
|
+
{
|
|
1612
|
+
mrb_bool *p;
|
|
1613
|
+
|
|
1614
|
+
p = GET_ARG(mrb_bool*);
|
|
1615
|
+
*p = pickarg ? TRUE : FALSE;
|
|
1616
|
+
}
|
|
1617
|
+
break;
|
|
1618
|
+
|
|
1619
|
+
case '*':
|
|
1620
|
+
{
|
|
1621
|
+
const mrb_value **var;
|
|
1622
|
+
mrb_int *pl;
|
|
1623
|
+
mrb_bool nocopy = (altmode || !argv_on_stack) ? TRUE : FALSE;
|
|
1624
|
+
|
|
1625
|
+
var = GET_ARG(const mrb_value**);
|
|
1626
|
+
pl = GET_ARG(mrb_int*);
|
|
1627
|
+
if (argc > i) {
|
|
1628
|
+
*pl = argc-i;
|
|
1629
|
+
if (*pl > 0) {
|
|
1630
|
+
if (nocopy) {
|
|
1631
|
+
*var = argv+i;
|
|
1632
|
+
}
|
|
1633
|
+
else {
|
|
1634
|
+
mrb_value args = mrb_ary_new_from_values(mrb, *pl, argv+i);
|
|
1635
|
+
RARRAY(args)->c = NULL;
|
|
1636
|
+
*var = RARRAY_PTR(args);
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
i = argc;
|
|
1640
|
+
}
|
|
1641
|
+
else {
|
|
1642
|
+
*pl = 0;
|
|
1643
|
+
*var = NULL;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
break;
|
|
1647
|
+
|
|
1648
|
+
case ':':
|
|
1649
|
+
{
|
|
1650
|
+
mrb_value ksrc = mrb_hash_p(kdict) ? kdict : mrb_hash_new(mrb);
|
|
1651
|
+
const mrb_kwargs *kwargs = GET_ARG(const mrb_kwargs*);
|
|
1652
|
+
mrb_value *rest;
|
|
1653
|
+
|
|
1654
|
+
if (kwargs == NULL) {
|
|
1655
|
+
rest = NULL;
|
|
1656
|
+
}
|
|
1657
|
+
else {
|
|
1658
|
+
mrb_int kwnum = kwargs->num;
|
|
1659
|
+
mrb_int required = kwargs->required;
|
|
1660
|
+
const mrb_sym *kname = kwargs->table;
|
|
1661
|
+
mrb_value *values = kwargs->values;
|
|
1662
|
+
const mrb_int keyword_max = 40;
|
|
1663
|
+
|
|
1664
|
+
mrb_assert(kwnum >= 0);
|
|
1665
|
+
mrb_assert(required >= 0);
|
|
1666
|
+
if (kwnum > keyword_max || required > kwnum) {
|
|
1667
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "keyword number is too large");
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
for (mrb_int j = required; j > 0; j--, kname++, values++) {
|
|
1671
|
+
mrb_value k = mrb_symbol_value(*kname);
|
|
1672
|
+
if (!mrb_hash_key_p(mrb, ksrc, k)) {
|
|
1673
|
+
mrb_raisef(mrb, E_ARGUMENT_ERROR, "missing keyword: %n", *kname);
|
|
1674
|
+
}
|
|
1675
|
+
*values = mrb_hash_delete_key(mrb, ksrc, k);
|
|
1676
|
+
mrb_gc_protect(mrb, *values);
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
for (mrb_int j = kwnum - required; j > 0; j--, kname++, values++) {
|
|
1680
|
+
mrb_value k = mrb_symbol_value(*kname);
|
|
1681
|
+
if (mrb_hash_key_p(mrb, ksrc, k)) {
|
|
1682
|
+
*values = mrb_hash_delete_key(mrb, ksrc, k);
|
|
1683
|
+
mrb_gc_protect(mrb, *values);
|
|
1684
|
+
}
|
|
1685
|
+
else {
|
|
1686
|
+
*values = mrb_undef_value();
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
rest = kwargs->rest;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
if (rest) {
|
|
1694
|
+
*rest = ksrc;
|
|
1695
|
+
}
|
|
1696
|
+
else if (!mrb_hash_empty_p(mrb, ksrc)) {
|
|
1697
|
+
ksrc = mrb_hash_first_key(mrb, ksrc);
|
|
1698
|
+
mrb_raisef(mrb, E_ARGUMENT_ERROR, "unknown keyword: %v", ksrc);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
break;
|
|
1702
|
+
|
|
1703
|
+
default:
|
|
1704
|
+
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c);
|
|
1705
|
+
break;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
if (!c && argc > i) {
|
|
1710
|
+
mrb_argnum_error(mrb, argc, argc_min, argc_max);
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
finish:
|
|
1714
|
+
return i;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
/*
|
|
1718
|
+
retrieve arguments from mrb_state.
|
|
1719
|
+
|
|
1720
|
+
mrb_get_args(mrb, format, ...)
|
|
1721
|
+
|
|
1722
|
+
returns number of arguments parsed.
|
|
1723
|
+
|
|
1724
|
+
format specifiers:
|
|
1725
|
+
|
|
1726
|
+
string mruby type C type note
|
|
1727
|
+
----------------------------------------------------------------------------------------------
|
|
1728
|
+
o: Object [mrb_value]
|
|
1729
|
+
C: Class/Module [mrb_value] when ! follows, the value may be nil
|
|
1730
|
+
S: String [mrb_value] when ! follows, the value may be nil
|
|
1731
|
+
A: Array [mrb_value] when ! follows, the value may be nil
|
|
1732
|
+
H: Hash [mrb_value] when ! follows, the value may be nil
|
|
1733
|
+
s: String [const char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil
|
|
1734
|
+
z: String [const char*] NUL terminated string; z! gives NULL for nil
|
|
1735
|
+
a: Array [const mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil
|
|
1736
|
+
c: Class/Module [struct RClass*] c! gives NULL for nil
|
|
1737
|
+
f: Integer/Float [mrb_float]
|
|
1738
|
+
i: Integer/Float [mrb_int]
|
|
1739
|
+
b: boolean [mrb_bool]
|
|
1740
|
+
n: String/Symbol [mrb_sym]
|
|
1741
|
+
d: data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified; when ! follows, the value may be nil
|
|
1742
|
+
&: block [mrb_value] &! raises exception if no block given
|
|
1743
|
+
*: rest argument [const mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack
|
|
1744
|
+
|: optional Following arguments are optional
|
|
1745
|
+
?: optional given [mrb_bool] true if preceding argument (optional) is given
|
|
1746
|
+
':': keyword args [mrb_kwargs const] Get keyword arguments
|
|
1747
|
+
|
|
1748
|
+
format modifiers:
|
|
1749
|
+
|
|
1750
|
+
string note
|
|
1751
|
+
----------------------------------------------------------------------------------------------
|
|
1752
|
+
!: Switch to the alternate mode; The behaviour changes depending on the specifier
|
|
1753
|
+
+: Request a not frozen object; However, except nil value
|
|
1754
|
+
*/
|
|
1755
|
+
/*
|
|
1756
|
+
* Retrieves and parses arguments passed to a C function based on a given format string.
|
|
1757
|
+
* This is the primary and most flexible way for C extensions to handle arguments
|
|
1758
|
+
* passed from Ruby method calls.
|
|
1759
|
+
*
|
|
1760
|
+
* @param mrb The mruby state.
|
|
1761
|
+
* @param format A C string that specifies the expected arguments and their types.
|
|
1762
|
+
* See below for detailed format specifiers and modifiers.
|
|
1763
|
+
* @param ... A variable number of pointer arguments, corresponding to the types
|
|
1764
|
+
* specified in the format string, where the parsed values will be stored.
|
|
1765
|
+
* @return The number of arguments successfully parsed and assigned from the Ruby stack
|
|
1766
|
+
* to the C variables.
|
|
1767
|
+
* @raise ArgumentError if the passed arguments do not match the format string,
|
|
1768
|
+
* if there are type mismatches, or if required arguments are missing.
|
|
1769
|
+
* @sideeffect Arguments from the mruby stack are converted and stored in the C variables
|
|
1770
|
+
* provided via `...`. The mruby garbage collector arena might be saved
|
|
1771
|
+
* and restored during this process. Keyword argument processing might
|
|
1772
|
+
* involve hash duplication or key deletion.
|
|
1773
|
+
*
|
|
1774
|
+
* Format Specifiers (within the `format` string):
|
|
1775
|
+
* 'o': Object (expects mrb_value*)
|
|
1776
|
+
* 'C': Class/Module (expects mrb_value*). Use 'c' for `struct RClass*`.
|
|
1777
|
+
* 'S': String (expects mrb_value*)
|
|
1778
|
+
* 'A': Array (expects mrb_value*)
|
|
1779
|
+
* 'H': Hash (expects mrb_value*)
|
|
1780
|
+
* 's': String (expects const char**, mrb_int* for pointer and length)
|
|
1781
|
+
* 'z': String (expects const char** for a NUL-terminated string)
|
|
1782
|
+
* 'a': Array (expects const mrb_value**, mrb_int* for pointer and length)
|
|
1783
|
+
* 'c': Class/Module (expects struct RClass**)
|
|
1784
|
+
* 'f': Float (expects mrb_float*) - available if MRB_NO_FLOAT is not defined.
|
|
1785
|
+
* 'i': Integer (expects mrb_int*)
|
|
1786
|
+
* 'b': Boolean (expects mrb_bool*)
|
|
1787
|
+
* 'n': Symbol (expects mrb_sym*) - converts from String or Symbol argument.
|
|
1788
|
+
* 'd': Data (expects void**, const struct mrb_data_type*). The second argument is used
|
|
1789
|
+
* for type checking and is not modified.
|
|
1790
|
+
* '&': Block (expects mrb_value*) - retrieves the block passed to the method.
|
|
1791
|
+
* '*': Rest arguments (expects const mrb_value**, mrb_int*) - captures all remaining
|
|
1792
|
+
* positional arguments into an array.
|
|
1793
|
+
* '|': Optional arguments separator. Arguments following this are optional.
|
|
1794
|
+
* '?': Optional given (expects mrb_bool*) - sets to TRUE if the preceding optional
|
|
1795
|
+
* argument was provided, FALSE otherwise.
|
|
1796
|
+
* ':': Keyword arguments (expects const mrb_kwargs*). Used to retrieve keyword arguments.
|
|
1797
|
+
* See mrb_kwargs structure for details.
|
|
1798
|
+
*
|
|
1799
|
+
* Format Modifiers (prefix the specifier, e.g., "!s" or "c!"):
|
|
1800
|
+
* '!': Alternate mode. Behavior changes depending on the specifier.
|
|
1801
|
+
* For example, 's!' gives (NULL, 0) for a nil string. 'c!' gives NULL for nil.
|
|
1802
|
+
* '&!' raises an ArgumentError if no block is given.
|
|
1803
|
+
* '*!' avoids copying the rest arguments from the stack if possible.
|
|
1804
|
+
* '+': Request a modifiable (not frozen) object. Raises a FrozenError if the
|
|
1805
|
+
* retrieved object is frozen (this check does not apply to nil values).
|
|
1806
|
+
*/
|
|
1807
|
+
MRB_API mrb_int
|
|
1808
|
+
mrb_get_args(mrb_state *mrb, mrb_args_format format, ...)
|
|
1809
|
+
{
|
|
1810
|
+
va_list ap;
|
|
1811
|
+
va_start(ap, format);
|
|
1812
|
+
mrb_int rc = get_args_v(mrb, format, NULL, &ap);
|
|
1813
|
+
va_end(ap);
|
|
1814
|
+
return rc;
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
/*
|
|
1818
|
+
* Retrieves and parses arguments passed to a C function according to a format string,
|
|
1819
|
+
* taking a `void**` array for the output variables instead of `va_list`.
|
|
1820
|
+
* This version is useful when the argument parsing needs to be done in a more
|
|
1821
|
+
* programmatic way, or when wrapping `mrb_get_args`.
|
|
1822
|
+
*
|
|
1823
|
+
* @param mrb The mruby state.
|
|
1824
|
+
* @param format A C string specifying the expected arguments. See `mrb_get_args`
|
|
1825
|
+
* documentation for format specifiers and modifiers.
|
|
1826
|
+
* @param args An array of `void*` pointers to variables where the parsed arguments
|
|
1827
|
+
* will be stored. The types of these variables must correspond to the
|
|
1828
|
+
* specifiers in the `format` string.
|
|
1829
|
+
* @return The number of arguments successfully parsed and assigned.
|
|
1830
|
+
* @raise ArgumentError if arguments do not match the format string, or if there are
|
|
1831
|
+
* type mismatches.
|
|
1832
|
+
* @sideeffect Arguments from the mruby stack are converted and stored in the C variables
|
|
1833
|
+
* pointed to by the elements of the `args` array.
|
|
1834
|
+
* (See `mrb_get_args` for more details on side effects like GC arena handling
|
|
1835
|
+
* and keyword argument processing).
|
|
1836
|
+
*/
|
|
1837
|
+
MRB_API mrb_int
|
|
1838
|
+
mrb_get_args_a(mrb_state *mrb, mrb_args_format format, void **args)
|
|
1839
|
+
{
|
|
1840
|
+
return get_args_v(mrb, format, args, NULL);
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
static struct RClass*
|
|
1844
|
+
boot_defclass(mrb_state *mrb, struct RClass *super, enum mrb_vtype tt)
|
|
1845
|
+
{
|
|
1846
|
+
struct RClass *c = MRB_OBJ_ALLOC(mrb, MRB_TT_CLASS, mrb->class_class);
|
|
1847
|
+
MRB_SET_INSTANCE_TT(c, tt);
|
|
1848
|
+
|
|
1849
|
+
if (super) {
|
|
1850
|
+
c->super = super;
|
|
1851
|
+
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
|
|
1852
|
+
c->flags |= MRB_FL_CLASS_IS_INHERITED;
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
// limited to cases where BasicObject class is defined during mruby initialization
|
|
1856
|
+
mrb_assert(mrb->object_class == NULL);
|
|
1857
|
+
}
|
|
1858
|
+
c->mt = mt_new(mrb);
|
|
1859
|
+
return c;
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
static void
|
|
1863
|
+
boot_initmod(mrb_state *mrb, struct RClass *mod)
|
|
1864
|
+
{
|
|
1865
|
+
if (!mod->mt) {
|
|
1866
|
+
mod->mt = mt_new(mrb);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
static struct RClass*
|
|
1871
|
+
include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super)
|
|
1872
|
+
{
|
|
1873
|
+
struct RClass *ic = MRB_OBJ_ALLOC(mrb, MRB_TT_ICLASS, mrb->class_class);
|
|
1874
|
+
if (m->tt == MRB_TT_ICLASS) {
|
|
1875
|
+
m = m->c;
|
|
1876
|
+
}
|
|
1877
|
+
MRB_CLASS_ORIGIN(m);
|
|
1878
|
+
ic->mt = m->mt;
|
|
1879
|
+
ic->super = super;
|
|
1880
|
+
if (m->tt == MRB_TT_ICLASS) {
|
|
1881
|
+
ic->c = m->c;
|
|
1882
|
+
}
|
|
1883
|
+
else {
|
|
1884
|
+
ic->c = m;
|
|
1885
|
+
}
|
|
1886
|
+
return ic;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
static int
|
|
1890
|
+
include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super)
|
|
1891
|
+
{
|
|
1892
|
+
struct RClass *ic;
|
|
1893
|
+
void *klass_mt = find_origin(c)->mt;
|
|
1894
|
+
|
|
1895
|
+
while (m) {
|
|
1896
|
+
struct RClass *p = c->super;
|
|
1897
|
+
int original_seen = FALSE;
|
|
1898
|
+
int superclass_seen = FALSE;
|
|
1899
|
+
|
|
1900
|
+
if (c == ins_pos) original_seen = TRUE;
|
|
1901
|
+
if (m->flags & MRB_FL_CLASS_IS_PREPENDED)
|
|
1902
|
+
goto skip;
|
|
1903
|
+
if (klass_mt && klass_mt == m->mt)
|
|
1904
|
+
return -1;
|
|
1905
|
+
|
|
1906
|
+
while (p) {
|
|
1907
|
+
if (c == p) original_seen = TRUE;
|
|
1908
|
+
if (p->tt == MRB_TT_ICLASS) {
|
|
1909
|
+
if (p->mt == m->mt) {
|
|
1910
|
+
if (!superclass_seen && original_seen) {
|
|
1911
|
+
ins_pos = p; /* move insert point */
|
|
1912
|
+
}
|
|
1913
|
+
goto skip;
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
else if (p->tt == MRB_TT_CLASS) {
|
|
1917
|
+
if (!search_super) break;
|
|
1918
|
+
superclass_seen = TRUE;
|
|
1919
|
+
}
|
|
1920
|
+
p = p->super;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
ic = include_class_new(mrb, m, ins_pos->super);
|
|
1924
|
+
m->flags |= MRB_FL_CLASS_IS_INHERITED;
|
|
1925
|
+
ins_pos->super = ic;
|
|
1926
|
+
mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
|
|
1927
|
+
ins_pos = ic;
|
|
1928
|
+
skip:
|
|
1929
|
+
m = m->super;
|
|
1930
|
+
}
|
|
1931
|
+
if (!mrb->bootstrapping) mrb_method_cache_clear(mrb);
|
|
1932
|
+
return 0;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
static int
|
|
1936
|
+
fix_include_module(mrb_state *mrb, struct RBasic *obj, void *data)
|
|
1937
|
+
{
|
|
1938
|
+
struct RClass **m = (struct RClass**)data;
|
|
1939
|
+
|
|
1940
|
+
if (obj->tt == MRB_TT_ICLASS && obj->c == m[0] && !MRB_FLAG_TEST(obj, MRB_FL_CLASS_IS_ORIGIN)) {
|
|
1941
|
+
struct RClass *ic = (struct RClass*)obj;
|
|
1942
|
+
include_module_at(mrb, ic, ic, m[1], 1);
|
|
1943
|
+
}
|
|
1944
|
+
return MRB_EACH_OBJ_OK;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
/*
|
|
1948
|
+
* Includes a module into a class or another module.
|
|
1949
|
+
* This adds the methods and constants of module `m` to class `c` (or module `c`).
|
|
1950
|
+
* The included module's instance methods become instance methods of `c`.
|
|
1951
|
+
*
|
|
1952
|
+
* @param mrb The mruby state.
|
|
1953
|
+
* @param c The target class or module into which module `m` will be included.
|
|
1954
|
+
* @param m The module to include. Must be a module (MRB_TT_MODULE).
|
|
1955
|
+
* @raise ArgumentError if `m` is not a module or if a cyclic include is detected.
|
|
1956
|
+
* @raise FrozenError if class/module `c` is frozen.
|
|
1957
|
+
* @sideeffect Modifies the ancestor chain of `c` by inserting an ICLASS (inclusion class)
|
|
1958
|
+
* that references `m`'s method table.
|
|
1959
|
+
* Clears the method cache.
|
|
1960
|
+
* If `m` defines an `included` hook, it will be called with `c` as an argument.
|
|
1961
|
+
* If `c` is a module that has itself been included in other classes/modules,
|
|
1962
|
+
* this operation will also propagate the inclusion of `m` to those descendants.
|
|
1963
|
+
*/
|
|
1964
|
+
MRB_API void
|
|
1965
|
+
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
|
|
1966
|
+
{
|
|
1967
|
+
mrb_check_frozen(mrb, c);
|
|
1968
|
+
if (include_module_at(mrb, c, find_origin(c), m, 1) < 0) {
|
|
1969
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
|
|
1970
|
+
}
|
|
1971
|
+
if (c->tt == MRB_TT_MODULE && (c->flags & MRB_FL_CLASS_IS_INHERITED)) {
|
|
1972
|
+
struct RClass *data[2];
|
|
1973
|
+
data[0] = c;
|
|
1974
|
+
data[1] = m;
|
|
1975
|
+
mrb_objspace_each_objects(mrb, fix_include_module, data);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
static int
|
|
1980
|
+
fix_prepend_module(mrb_state *mrb, struct RBasic *obj, void *data)
|
|
1981
|
+
{
|
|
1982
|
+
struct RClass **m = (struct RClass**)data;
|
|
1983
|
+
struct RClass *c = (struct RClass*)obj;
|
|
1984
|
+
|
|
1985
|
+
if (c->tt == MRB_TT_CLASS || c->tt == MRB_TT_MODULE) {
|
|
1986
|
+
struct RClass *p = c->super;
|
|
1987
|
+
struct RClass *ins_pos = c;
|
|
1988
|
+
while (p) {
|
|
1989
|
+
if (c == m[0]) break;
|
|
1990
|
+
if (p == m[0]->super->c) {
|
|
1991
|
+
ins_pos = c;
|
|
1992
|
+
}
|
|
1993
|
+
if (p->tt == MRB_TT_CLASS) break;
|
|
1994
|
+
if (p->c == m[0]) {
|
|
1995
|
+
include_module_at(mrb, ins_pos, ins_pos, m[1], 0);
|
|
1996
|
+
break;
|
|
1997
|
+
}
|
|
1998
|
+
c = p;
|
|
1999
|
+
p = p->super;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
return MRB_EACH_OBJ_OK;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
/*
|
|
2006
|
+
* Prepends a module to a class or another module.
|
|
2007
|
+
* Methods in the prepended module `m` will override methods of the same name in `c`.
|
|
2008
|
+
* In the ancestor chain, the prepended module appears before the class/module itself.
|
|
2009
|
+
*
|
|
2010
|
+
* @param mrb The mruby state.
|
|
2011
|
+
* @param c The target class or module to which module `m` will be prepended.
|
|
2012
|
+
* @param m The module to prepend. Must be a module (MRB_TT_MODULE).
|
|
2013
|
+
* @raise ArgumentError if `m` is not a module or if a cyclic prepend is detected.
|
|
2014
|
+
* @raise FrozenError if class/module `c` is frozen.
|
|
2015
|
+
* @sideeffect Modifies the ancestor chain of `c`. If `c` hasn't been prepended before,
|
|
2016
|
+
* an "origin" ICLASS is created to hold `c`'s original methods, and `c`'s
|
|
2017
|
+
* method table is cleared. Then, an ICLASS for `m` is inserted above `c`.
|
|
2018
|
+
* Clears the method cache.
|
|
2019
|
+
* If `m` defines a `prepended` hook, it will be called with `c` as an argument.
|
|
2020
|
+
* If `c` is a module that has been included/prepended elsewhere, this
|
|
2021
|
+
* operation propagates the prepending of `m` to those descendants.
|
|
2022
|
+
*/
|
|
2023
|
+
MRB_API void
|
|
2024
|
+
mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
|
|
2025
|
+
{
|
|
2026
|
+
mrb_check_frozen(mrb, c);
|
|
2027
|
+
if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) {
|
|
2028
|
+
struct RClass *origin = MRB_OBJ_ALLOC(mrb, MRB_TT_ICLASS, c);
|
|
2029
|
+
origin->flags |= MRB_FL_CLASS_IS_ORIGIN | MRB_FL_CLASS_IS_INHERITED;
|
|
2030
|
+
origin->super = c->super;
|
|
2031
|
+
c->super = origin;
|
|
2032
|
+
origin->mt = c->mt;
|
|
2033
|
+
c->mt = NULL;
|
|
2034
|
+
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin);
|
|
2035
|
+
c->flags |= MRB_FL_CLASS_IS_PREPENDED;
|
|
2036
|
+
}
|
|
2037
|
+
if (include_module_at(mrb, c, c, m, 0) < 0) {
|
|
2038
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic prepend detected");
|
|
2039
|
+
}
|
|
2040
|
+
if (c->tt == MRB_TT_MODULE &&
|
|
2041
|
+
(c->flags & (MRB_FL_CLASS_IS_INHERITED|MRB_FL_CLASS_IS_PREPENDED))) {
|
|
2042
|
+
struct RClass *data[2];
|
|
2043
|
+
data[0] = c;
|
|
2044
|
+
data[1] = m;
|
|
2045
|
+
mrb_objspace_each_objects(mrb, fix_prepend_module, data);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
/*
|
|
2050
|
+
* call-seq:
|
|
2051
|
+
* mod.prepend(module, ...) -> self
|
|
2052
|
+
*
|
|
2053
|
+
* Invokes Module.prepend_features on each parameter in reverse order.
|
|
2054
|
+
*
|
|
2055
|
+
* module Mod
|
|
2056
|
+
* def hello
|
|
2057
|
+
* "Hello from Mod.\n"
|
|
2058
|
+
* end
|
|
2059
|
+
* end
|
|
2060
|
+
*
|
|
2061
|
+
* class Klass
|
|
2062
|
+
* def hello
|
|
2063
|
+
* "Hello from Klass.\n"
|
|
2064
|
+
* end
|
|
2065
|
+
* prepend Mod
|
|
2066
|
+
* end
|
|
2067
|
+
* Klass.new.hello #=> "Hello from Mod.\n"
|
|
2068
|
+
*/
|
|
2069
|
+
static mrb_value
|
|
2070
|
+
mrb_mod_prepend(mrb_state *mrb, mrb_value mod)
|
|
2071
|
+
{
|
|
2072
|
+
struct RClass *c = mrb_class_ptr(mod);
|
|
2073
|
+
mrb_int argc;
|
|
2074
|
+
mrb_value *argv;
|
|
2075
|
+
mrb_sym prepended = MRB_SYM(prepended);
|
|
2076
|
+
|
|
2077
|
+
mrb_get_args(mrb, "*", &argv, &argc);
|
|
2078
|
+
while (argc--) {
|
|
2079
|
+
mrb_value m = argv[argc];
|
|
2080
|
+
mrb_check_type(mrb, m, MRB_TT_MODULE);
|
|
2081
|
+
mrb_prepend_module(mrb, c, mrb_class_ptr(m));
|
|
2082
|
+
if (!mrb_func_basic_p(mrb, m, prepended, mrb_do_nothing)) {
|
|
2083
|
+
mrb_funcall_argv(mrb, m, prepended, 1, &mod);
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
return mod;
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
/*
|
|
2090
|
+
* call-seq:
|
|
2091
|
+
* mod.include(module, ...) -> self
|
|
2092
|
+
*
|
|
2093
|
+
* Invokes Module.append_features on each parameter in reverse order.
|
|
2094
|
+
*
|
|
2095
|
+
* module Mod
|
|
2096
|
+
* def hello
|
|
2097
|
+
* "Hello from Mod.\n"
|
|
2098
|
+
* end
|
|
2099
|
+
* end
|
|
2100
|
+
*
|
|
2101
|
+
* class Klass
|
|
2102
|
+
* include Mod
|
|
2103
|
+
* end
|
|
2104
|
+
* Klass.new.hello #=> "Hello from Mod.\n"
|
|
2105
|
+
*/
|
|
2106
|
+
static mrb_value
|
|
2107
|
+
mrb_mod_include(mrb_state *mrb, mrb_value mod)
|
|
2108
|
+
{
|
|
2109
|
+
struct RClass *c = mrb_class_ptr(mod);
|
|
2110
|
+
mrb_int argc;
|
|
2111
|
+
mrb_value *argv;
|
|
2112
|
+
mrb_sym included = MRB_SYM(included);
|
|
2113
|
+
|
|
2114
|
+
mrb_get_args(mrb, "*", &argv, &argc);
|
|
2115
|
+
while (argc--) {
|
|
2116
|
+
mrb_value m = argv[argc];
|
|
2117
|
+
mrb_check_type(mrb, m, MRB_TT_MODULE);
|
|
2118
|
+
mrb_include_module(mrb, c, mrb_class_ptr(m));
|
|
2119
|
+
if (!mrb_func_basic_p(mrb, m, included, mrb_do_nothing)) {
|
|
2120
|
+
mrb_funcall_argv(mrb, m, included, 1, &mod);
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
return mod;
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
/* 15.3.1.3.13 */
|
|
2127
|
+
/*
|
|
2128
|
+
* call-seq:
|
|
2129
|
+
* obj.extend(module, ...) -> obj
|
|
2130
|
+
*
|
|
2131
|
+
* Adds to _obj_ the instance methods from each module given as a
|
|
2132
|
+
* parameter.
|
|
2133
|
+
*
|
|
2134
|
+
* module Mod
|
|
2135
|
+
* def hello
|
|
2136
|
+
* "Hello from Mod.\n"
|
|
2137
|
+
* end
|
|
2138
|
+
* end
|
|
2139
|
+
*
|
|
2140
|
+
* class Klass
|
|
2141
|
+
* def hello
|
|
2142
|
+
* "Hello from Klass.\n"
|
|
2143
|
+
* end
|
|
2144
|
+
* end
|
|
2145
|
+
*
|
|
2146
|
+
* k = Klass.new
|
|
2147
|
+
* k.hello #=> "Hello from Klass.\n"
|
|
2148
|
+
* k.extend(Mod) #=> #<Klass:0x401b3bc8>
|
|
2149
|
+
* k.hello #=> "Hello from Mod.\n"
|
|
2150
|
+
*
|
|
2151
|
+
*/
|
|
2152
|
+
/*
|
|
2153
|
+
* Adds the instance methods from one or more modules to the given object `obj`.
|
|
2154
|
+
* This is achieved by including the specified modules into `obj`'s singleton class.
|
|
2155
|
+
*
|
|
2156
|
+
* @param mrb The mruby state.
|
|
2157
|
+
* @param obj The object to extend.
|
|
2158
|
+
* @return The extended object `obj`.
|
|
2159
|
+
* @raise TypeError if any of the arguments passed for extension are not modules.
|
|
2160
|
+
* @sideeffect Modifies the singleton class of `obj`. If the singleton class doesn't exist,
|
|
2161
|
+
* it is created. The given modules are included into this singleton class.
|
|
2162
|
+
* If any of the included modules define an `extended` hook, it is called
|
|
2163
|
+
* with `obj` as an argument.
|
|
2164
|
+
*/
|
|
2165
|
+
mrb_value
|
|
2166
|
+
mrb_obj_extend(mrb_state *mrb, mrb_value obj)
|
|
2167
|
+
{
|
|
2168
|
+
mrb_int argc;
|
|
2169
|
+
mrb_value *argv;
|
|
2170
|
+
mrb_sym extended = MRB_SYM(extended);
|
|
2171
|
+
|
|
2172
|
+
mrb_get_args(mrb, "*", &argv, &argc);
|
|
2173
|
+
|
|
2174
|
+
mrb_value cc = mrb_singleton_class(mrb, obj);
|
|
2175
|
+
while (argc--) {
|
|
2176
|
+
mrb_value mod = argv[argc];
|
|
2177
|
+
mrb_check_type(mrb, mod, MRB_TT_MODULE);
|
|
2178
|
+
mrb_include_module(mrb, mrb_class_ptr(cc), mrb_class_ptr(mod));
|
|
2179
|
+
if (!mrb_func_basic_p(mrb, mod, extended, mrb_do_nothing)) {
|
|
2180
|
+
mrb_funcall_argv(mrb, mod, extended, 1, &obj);
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
return obj;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
/* 15.2.2.4.28 */
|
|
2187
|
+
/*
|
|
2188
|
+
* call-seq:
|
|
2189
|
+
* mod.include?(module) -> true or false
|
|
2190
|
+
*
|
|
2191
|
+
* Returns `true` if *module* is included in
|
|
2192
|
+
* *mod* or one of *mod*'s ancestors.
|
|
2193
|
+
*
|
|
2194
|
+
* module A
|
|
2195
|
+
* end
|
|
2196
|
+
* class B
|
|
2197
|
+
* include A
|
|
2198
|
+
* end
|
|
2199
|
+
* class C < B
|
|
2200
|
+
* end
|
|
2201
|
+
* B.include?(A) #=> true
|
|
2202
|
+
* C.include?(A) #=> true
|
|
2203
|
+
* A.include?(A) #=> false
|
|
2204
|
+
*/
|
|
2205
|
+
static mrb_value
|
|
2206
|
+
mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
|
|
2207
|
+
{
|
|
2208
|
+
mrb_value mod2;
|
|
2209
|
+
struct RClass *c = mrb_class_ptr(mod);
|
|
2210
|
+
|
|
2211
|
+
mrb_get_args(mrb, "C", &mod2);
|
|
2212
|
+
mrb_check_type(mrb, mod2, MRB_TT_MODULE);
|
|
2213
|
+
|
|
2214
|
+
while (c) {
|
|
2215
|
+
if (c->tt == MRB_TT_ICLASS) {
|
|
2216
|
+
if (c->c == mrb_class_ptr(mod2)) return mrb_true_value();
|
|
2217
|
+
}
|
|
2218
|
+
c = c->super;
|
|
2219
|
+
}
|
|
2220
|
+
return mrb_false_value();
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
/*
|
|
2224
|
+
* call-seq:
|
|
2225
|
+
* mod.ancestors -> array
|
|
2226
|
+
*
|
|
2227
|
+
* Returns a list of modules included/prepended in mod (including mod itself).
|
|
2228
|
+
*
|
|
2229
|
+
* module Mod
|
|
2230
|
+
* include Math
|
|
2231
|
+
* include Comparable
|
|
2232
|
+
* prepend Enumerable
|
|
2233
|
+
* end
|
|
2234
|
+
*
|
|
2235
|
+
* Mod.ancestors #=> [Enumerable, Mod, Comparable, Math]
|
|
2236
|
+
* Math.ancestors #=> [Math]
|
|
2237
|
+
* Numeric.ancestors #=> [Numeric, Comparable]
|
|
2238
|
+
*/
|
|
2239
|
+
static mrb_value
|
|
2240
|
+
mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
|
|
2241
|
+
{
|
|
2242
|
+
struct RClass *c = mrb_class_ptr(self);
|
|
2243
|
+
mrb_value result = mrb_ary_new(mrb);
|
|
2244
|
+
|
|
2245
|
+
while (c) {
|
|
2246
|
+
if (c->tt == MRB_TT_ICLASS) {
|
|
2247
|
+
mrb_ary_push(mrb, result, mrb_obj_value(c->c));
|
|
2248
|
+
}
|
|
2249
|
+
else if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) {
|
|
2250
|
+
mrb_ary_push(mrb, result, mrb_obj_value(c));
|
|
2251
|
+
}
|
|
2252
|
+
c = c->super;
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
return result;
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
static mrb_value
|
|
2259
|
+
mrb_mod_initialize(mrb_state *mrb, mrb_value mod)
|
|
2260
|
+
{
|
|
2261
|
+
mrb_value b;
|
|
2262
|
+
struct RClass *m = mrb_class_ptr(mod);
|
|
2263
|
+
boot_initmod(mrb, m); /* bootstrap a newly initialized module */
|
|
2264
|
+
mrb_get_args(mrb, "|&", &b);
|
|
2265
|
+
if (!mrb_nil_p(b)) {
|
|
2266
|
+
mrb_yield_with_class(mrb, b, 1, &mod, mod, m);
|
|
2267
|
+
}
|
|
2268
|
+
return mod;
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
static void
|
|
2272
|
+
mrb_mod_visibility(mrb_state *mrb, mrb_value mod, int vis)
|
|
2273
|
+
{
|
|
2274
|
+
mrb_assert((vis&MT_VMASK)==vis);
|
|
2275
|
+
mrb_int argc;
|
|
2276
|
+
mrb_value *argv;
|
|
2277
|
+
struct RClass *c = mrb_class_ptr(mod);
|
|
2278
|
+
|
|
2279
|
+
mrb_get_args(mrb, "*!", &argv, &argc);
|
|
2280
|
+
if (argc == 0) {
|
|
2281
|
+
mrb_callinfo *ci;
|
|
2282
|
+
struct REnv *e;
|
|
2283
|
+
find_visibility_scope(mrb, NULL, 1, &ci, &e);
|
|
2284
|
+
if (e) {
|
|
2285
|
+
MRB_ENV_SET_VISIBILITY(e, vis >> 25);
|
|
2286
|
+
}
|
|
2287
|
+
else {
|
|
2288
|
+
MRB_CI_SET_VISIBILITY(ci, vis >> 25);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
else {
|
|
2292
|
+
mrb_mt_tbl *h = c->mt;
|
|
2293
|
+
for (int i=0; i<argc; i++) {
|
|
2294
|
+
mrb_check_type(mrb, argv[i], MRB_TT_SYMBOL);
|
|
2295
|
+
mrb_sym mid = mrb_symbol(argv[i]);
|
|
2296
|
+
mrb_method_t m = mrb_method_search(mrb, c, mid);
|
|
2297
|
+
MRB_METHOD_SET_VISIBILITY(m, vis);
|
|
2298
|
+
union mrb_mt_ptr ptr;
|
|
2299
|
+
if (MRB_METHOD_PROC_P(m)) {
|
|
2300
|
+
ptr.proc = MRB_METHOD_PROC(m);
|
|
2301
|
+
}
|
|
2302
|
+
else {
|
|
2303
|
+
ptr.func = MRB_METHOD_FUNC(m);
|
|
2304
|
+
}
|
|
2305
|
+
mt_put(mrb, h, mid, m.flags, ptr);
|
|
2306
|
+
mc_clear_by_id(mrb, mid);
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
static mrb_value
|
|
2312
|
+
mrb_mod_public(mrb_state *mrb, mrb_value mod)
|
|
2313
|
+
{
|
|
2314
|
+
mrb_mod_visibility(mrb, mod, MRB_METHOD_PUBLIC_FL);
|
|
2315
|
+
return mod;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
static mrb_value
|
|
2319
|
+
mrb_mod_private(mrb_state *mrb, mrb_value mod)
|
|
2320
|
+
{
|
|
2321
|
+
mrb_mod_visibility(mrb, mod, MRB_METHOD_PRIVATE_FL);
|
|
2322
|
+
return mod;
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
static mrb_value
|
|
2326
|
+
mrb_mod_protected(mrb_state *mrb, mrb_value mod)
|
|
2327
|
+
{
|
|
2328
|
+
mrb_mod_visibility(mrb, mod, MT_PROTECTED);
|
|
2329
|
+
return mod;
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
static mrb_value
|
|
2333
|
+
top_public(mrb_state *mrb, mrb_value self)
|
|
2334
|
+
{
|
|
2335
|
+
self = mrb_obj_value(mrb->object_class);
|
|
2336
|
+
mrb_mod_visibility(mrb, self, MRB_METHOD_PUBLIC_FL);
|
|
2337
|
+
return self;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
static mrb_value
|
|
2341
|
+
top_private(mrb_state *mrb, mrb_value self)
|
|
2342
|
+
{
|
|
2343
|
+
self = mrb_obj_value(mrb->object_class);
|
|
2344
|
+
mrb_mod_visibility(mrb, self, MRB_METHOD_PRIVATE_FL);
|
|
2345
|
+
return self;
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
static mrb_value
|
|
2349
|
+
top_protected(mrb_state *mrb, mrb_value self)
|
|
2350
|
+
{
|
|
2351
|
+
self = mrb_obj_value(mrb->object_class);
|
|
2352
|
+
mrb_mod_visibility(mrb, self, MT_PROTECTED);
|
|
2353
|
+
return self;
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
/*
|
|
2357
|
+
* Retrieves a pointer to the singleton class (also known as metaclass or eigenclass)
|
|
2358
|
+
* of a given object `v`. If the singleton class does not yet exist, it is created.
|
|
2359
|
+
*
|
|
2360
|
+
* Singleton classes are anonymous classes associated with a specific object,
|
|
2361
|
+
* allowing that object to have its own unique methods.
|
|
2362
|
+
*
|
|
2363
|
+
* @param mrb The mruby state.
|
|
2364
|
+
* @param v The `mrb_value` for which to get the singleton class.
|
|
2365
|
+
* @return A pointer to the `RClass` structure of the singleton class.
|
|
2366
|
+
* Returns `NULL` for immediate values (e.g., Symbols, Integers,
|
|
2367
|
+
* Floats if not word-boxed, C pointers) as they cannot have singleton classes.
|
|
2368
|
+
* For `nil`, `true`, and `false`, it returns their respective predefined
|
|
2369
|
+
* classes (`mrb->nil_class`, `mrb->true_class`, `mrb->false_class`),
|
|
2370
|
+
* which effectively act as their singleton classes.
|
|
2371
|
+
* @sideeffect If the singleton class doesn't exist for `v` (and `v` can have one,
|
|
2372
|
+
* i.e., it's not an immediate value or one of the special singletons),
|
|
2373
|
+
* this function will:
|
|
2374
|
+
* 1. Allocate a new `RClass` of type `MRB_TT_SCLASS`.
|
|
2375
|
+
* 2. Set its superclass appropriately (e.g., the object's original class,
|
|
2376
|
+
* or the class of the superclass for class singletons).
|
|
2377
|
+
* 3. Link this new singleton class to the object `v`.
|
|
2378
|
+
* 4. Set an internal `__attached__` instance variable on the singleton
|
|
2379
|
+
* class to point back to `v`.
|
|
2380
|
+
* 5. The `MRB_FL_CLASS_IS_INHERITED` flag is set on the new singleton class.
|
|
2381
|
+
*/
|
|
2382
|
+
MRB_API struct RClass*
|
|
2383
|
+
mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v)
|
|
2384
|
+
{
|
|
2385
|
+
struct RBasic *obj;
|
|
2386
|
+
|
|
2387
|
+
switch (mrb_type(v)) {
|
|
2388
|
+
case MRB_TT_FALSE:
|
|
2389
|
+
if (mrb_nil_p(v))
|
|
2390
|
+
return mrb->nil_class;
|
|
2391
|
+
return mrb->false_class;
|
|
2392
|
+
case MRB_TT_TRUE:
|
|
2393
|
+
return mrb->true_class;
|
|
2394
|
+
case MRB_TT_CPTR:
|
|
2395
|
+
case MRB_TT_SYMBOL:
|
|
2396
|
+
case MRB_TT_INTEGER:
|
|
2397
|
+
#ifndef MRB_NO_FLOAT
|
|
2398
|
+
case MRB_TT_FLOAT:
|
|
2399
|
+
#endif
|
|
2400
|
+
return NULL;
|
|
2401
|
+
default:
|
|
2402
|
+
break;
|
|
2403
|
+
}
|
|
2404
|
+
obj = mrb_basic_ptr(v);
|
|
2405
|
+
if (obj->c == NULL) return NULL;
|
|
2406
|
+
prepare_singleton_class(mrb, obj);
|
|
2407
|
+
return obj->c;
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
/*
|
|
2411
|
+
* Retrieves the singleton class (also known as metaclass or eigenclass) of a given object
|
|
2412
|
+
* as an mrb_value. If the singleton class does not exist, it is created.
|
|
2413
|
+
*
|
|
2414
|
+
* This function is a wrapper around `mrb_singleton_class_ptr` that returns the
|
|
2415
|
+
* singleton class as an `mrb_value`.
|
|
2416
|
+
*
|
|
2417
|
+
* @param mrb The mruby state.
|
|
2418
|
+
* @param v The `mrb_value` for which to get the singleton class.
|
|
2419
|
+
* @return An `mrb_value` representing the singleton class.
|
|
2420
|
+
* @raise TypeError if `v` is an object that cannot have a singleton class
|
|
2421
|
+
* (e.g., immediate values like Symbols or Integers under certain configurations,
|
|
2422
|
+
* or C pointers). This exception is raised by the underlying
|
|
2423
|
+
* `mrb_singleton_class_ptr` if it returns NULL.
|
|
2424
|
+
* @sideeffect If the singleton class doesn't exist for `v` (and `v` can have one),
|
|
2425
|
+
* it will be created via `mrb_singleton_class_ptr`, which involves
|
|
2426
|
+
* memory allocation and modification of the object's class pointer.
|
|
2427
|
+
*/
|
|
2428
|
+
MRB_API mrb_value
|
|
2429
|
+
mrb_singleton_class(mrb_state *mrb, mrb_value v)
|
|
2430
|
+
{
|
|
2431
|
+
struct RClass *c = mrb_singleton_class_ptr(mrb, v);
|
|
2432
|
+
|
|
2433
|
+
if (c == NULL) {
|
|
2434
|
+
mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
|
|
2435
|
+
}
|
|
2436
|
+
return mrb_obj_value(c);
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
/*
|
|
2440
|
+
* Defines a singleton method for a specific object `o`.
|
|
2441
|
+
* A singleton method is a method that belongs only to a single object,
|
|
2442
|
+
* not to all instances of its class. It's defined in the object's singleton class.
|
|
2443
|
+
*
|
|
2444
|
+
* @param mrb The mruby state.
|
|
2445
|
+
* @param o A pointer to the RObject for which the singleton method is being defined.
|
|
2446
|
+
* @param name The C string name of the method.
|
|
2447
|
+
* @param func The C function (mrb_func_t) that implements the method.
|
|
2448
|
+
* @param aspec The argument specification for the method (e.g., MRB_ARGS_REQ(1)).
|
|
2449
|
+
* @sideeffect
|
|
2450
|
+
* 1. Ensures that the singleton class for object `o` exists, creating it if necessary.
|
|
2451
|
+
* This might involve memory allocation.
|
|
2452
|
+
* 2. Defines the method specified by `name`, `func`, and `aspec` into this
|
|
2453
|
+
* singleton class.
|
|
2454
|
+
* 3. The method name `name` is interned into a symbol.
|
|
2455
|
+
* 4. The method cache for the newly defined method is cleared.
|
|
2456
|
+
* @raise TypeError if `o` is an object that cannot have a singleton class (e.g., immediate values).
|
|
2457
|
+
*/
|
|
2458
|
+
MRB_API void
|
|
2459
|
+
mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec)
|
|
2460
|
+
{
|
|
2461
|
+
prepare_singleton_class(mrb, (struct RBasic*)o);
|
|
2462
|
+
mrb_define_method_id(mrb, o->c, mrb_intern_cstr(mrb, name), func, aspec);
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
/*
|
|
2466
|
+
* Defines a singleton method for a specific object `o` using a symbol for the method name.
|
|
2467
|
+
* A singleton method is a method that belongs only to a single object,
|
|
2468
|
+
* not to all instances of its class. It's defined in the object's singleton class.
|
|
2469
|
+
*
|
|
2470
|
+
* @param mrb The mruby state.
|
|
2471
|
+
* @param o A pointer to the RObject for which the singleton method is being defined.
|
|
2472
|
+
* @param name The symbol ID (`mrb_sym`) of the method name.
|
|
2473
|
+
* @param func The C function (mrb_func_t) that implements the method.
|
|
2474
|
+
* @param aspec The argument specification for the method (e.g., MRB_ARGS_REQ(1)).
|
|
2475
|
+
* @sideeffect
|
|
2476
|
+
* 1. Ensures that the singleton class for object `o` exists, creating it if necessary.
|
|
2477
|
+
* This might involve memory allocation.
|
|
2478
|
+
* 2. Defines the method specified by `name`, `func`, and `aspec` into this
|
|
2479
|
+
* singleton class.
|
|
2480
|
+
* 3. The method cache for the method `name` is cleared.
|
|
2481
|
+
* @raise TypeError if `o` is an object that cannot have a singleton class (e.g., immediate values).
|
|
2482
|
+
*/
|
|
2483
|
+
MRB_API void
|
|
2484
|
+
mrb_define_singleton_method_id(mrb_state *mrb, struct RObject *o, mrb_sym name, mrb_func_t func, mrb_aspec aspec)
|
|
2485
|
+
{
|
|
2486
|
+
prepare_singleton_class(mrb, (struct RBasic*)o);
|
|
2487
|
+
mrb_define_method_id(mrb, o->c, name, func, aspec);
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
/*
|
|
2491
|
+
* Defines a class method for a class/module `c`.
|
|
2492
|
+
* Class methods are effectively singleton methods defined on the class object itself.
|
|
2493
|
+
*
|
|
2494
|
+
* @param mrb The mruby state.
|
|
2495
|
+
* @param c The class/module (`RClass*`) for which to define the class method.
|
|
2496
|
+
* @param name The C string name of the class method.
|
|
2497
|
+
* @param func The C function (mrb_func_t) that implements the method.
|
|
2498
|
+
* @param aspec The argument specification for the method.
|
|
2499
|
+
* @sideeffect This function internally calls `mrb_define_singleton_method` on the
|
|
2500
|
+
* class object `c`. This involves:
|
|
2501
|
+
* 1. Ensuring `c`'s singleton class exists (creating it if needed).
|
|
2502
|
+
* 2. Defining the method in `c`'s singleton class.
|
|
2503
|
+
* 3. Interning the `name` string.
|
|
2504
|
+
* 4. Clearing the relevant method cache.
|
|
2505
|
+
* @raise TypeError if `c` itself is an object that cannot have a singleton class (highly unlikely for RClass).
|
|
2506
|
+
*/
|
|
2507
|
+
MRB_API void
|
|
2508
|
+
mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
|
|
2509
|
+
{
|
|
2510
|
+
mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
/*
|
|
2514
|
+
* Defines a class method for a class/module `c` using a symbol for the method name.
|
|
2515
|
+
* Class methods are effectively singleton methods defined on the class object itself.
|
|
2516
|
+
*
|
|
2517
|
+
* @param mrb The mruby state.
|
|
2518
|
+
* @param c The class/module (`RClass*`) for which to define the class method.
|
|
2519
|
+
* @param name The symbol ID (`mrb_sym`) of the class method name.
|
|
2520
|
+
* @param func The C function (mrb_func_t) that implements the method.
|
|
2521
|
+
* @param aspec The argument specification for the method.
|
|
2522
|
+
* @sideeffect This function internally calls `mrb_define_singleton_method_id` on the
|
|
2523
|
+
* class object `c`. This involves:
|
|
2524
|
+
* 1. Ensuring `c`'s singleton class exists (creating it if needed).
|
|
2525
|
+
* 2. Defining the method in `c`'s singleton class.
|
|
2526
|
+
* 3. Clearing the relevant method cache.
|
|
2527
|
+
* @raise TypeError if `c` itself is an object that cannot have a singleton class (highly unlikely for RClass).
|
|
2528
|
+
*/
|
|
2529
|
+
MRB_API void
|
|
2530
|
+
mrb_define_class_method_id(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_func_t func, mrb_aspec aspec)
|
|
2531
|
+
{
|
|
2532
|
+
mrb_define_singleton_method_id(mrb, (struct RObject*)c, name, func, aspec);
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
/*
|
|
2536
|
+
* Defines a module function for a module `c` using a symbol for the name.
|
|
2537
|
+
* A module function is a shorthand for defining a method that is both a
|
|
2538
|
+
* public class method (callable on the module itself) and a private
|
|
2539
|
+
* instance method (callable within the context of classes that include the module).
|
|
2540
|
+
*
|
|
2541
|
+
* @param mrb The mruby state.
|
|
2542
|
+
* @param c The module (`RClass*` where `c->tt` should be `MRB_TT_MODULE`)
|
|
2543
|
+
* for which to define the module function.
|
|
2544
|
+
* @param name The symbol ID (`mrb_sym`) of the module function name.
|
|
2545
|
+
* @param func The C function (mrb_func_t) that implements the function.
|
|
2546
|
+
* @param aspec The argument specification for the function.
|
|
2547
|
+
* @sideeffect
|
|
2548
|
+
* 1. Defines a public class method on `c` with the given `name`, `func`, and `aspec`.
|
|
2549
|
+
* This involves creating/accessing `c`'s singleton class.
|
|
2550
|
+
* 2. Defines a private instance method on `c` with the same `name`, `func`, and `aspec`.
|
|
2551
|
+
* 3. Clears the method cache for `name` in both contexts.
|
|
2552
|
+
*/
|
|
2553
|
+
MRB_API void
|
|
2554
|
+
mrb_define_module_function_id(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_func_t func, mrb_aspec aspec)
|
|
2555
|
+
{
|
|
2556
|
+
mrb_define_class_method_id(mrb, c, name, func, aspec);
|
|
2557
|
+
mrb_define_private_method_id(mrb, c, name, func, aspec);
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
/*
|
|
2561
|
+
* Defines a module function for a module `c` using a C string for the name.
|
|
2562
|
+
* A module function is a shorthand for defining a method that is both a
|
|
2563
|
+
* public class method (callable on the module itself) and a private
|
|
2564
|
+
* instance method (callable within the context of classes that include the module).
|
|
2565
|
+
*
|
|
2566
|
+
* @param mrb The mruby state.
|
|
2567
|
+
* @param c The module (`RClass*` where `c->tt` should be `MRB_TT_MODULE`)
|
|
2568
|
+
* for which to define the module function.
|
|
2569
|
+
* @param name The C string name of the module function. This name will be interned.
|
|
2570
|
+
* @param func The C function (mrb_func_t) that implements the function.
|
|
2571
|
+
* @param aspec The argument specification for the function.
|
|
2572
|
+
* @sideeffect
|
|
2573
|
+
* 1. Interns the `name` string to a symbol.
|
|
2574
|
+
* 2. Calls `mrb_define_module_function_id` with the interned symbol, which in turn:
|
|
2575
|
+
* a. Defines a public class method on `c`.
|
|
2576
|
+
* b. Defines a private instance method on `c`.
|
|
2577
|
+
* 3. Clears the method cache for the method name in both contexts.
|
|
2578
|
+
*/
|
|
2579
|
+
MRB_API void
|
|
2580
|
+
mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
|
|
2581
|
+
{
|
|
2582
|
+
mrb_define_module_function_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec);
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
#ifndef MRB_NO_METHOD_CACHE
|
|
2586
|
+
/* clear whole method cache table */
|
|
2587
|
+
MRB_API void
|
|
2588
|
+
mrb_method_cache_clear(mrb_state *mrb)
|
|
2589
|
+
{
|
|
2590
|
+
static const struct mrb_cache_entry ce_zero ={0};
|
|
2591
|
+
|
|
2592
|
+
for (int i=0; i<MRB_METHOD_CACHE_SIZE; i++) {
|
|
2593
|
+
mrb->cache[i] = ce_zero;
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
/* clear method cache for a class */
|
|
2598
|
+
void
|
|
2599
|
+
mrb_mc_clear_by_class(mrb_state *mrb, struct RClass *c)
|
|
2600
|
+
{
|
|
2601
|
+
struct mrb_cache_entry *mc = mrb->cache;
|
|
2602
|
+
|
|
2603
|
+
for (int i=0; i<MRB_METHOD_CACHE_SIZE; mc++,i++) {
|
|
2604
|
+
if (mc->c == c || mc->c0 == c) mc->c = NULL;
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
static void
|
|
2609
|
+
mc_clear_by_id(mrb_state *mrb, mrb_sym id)
|
|
2610
|
+
{
|
|
2611
|
+
struct mrb_cache_entry *mc = mrb->cache;
|
|
2612
|
+
|
|
2613
|
+
for (int i=0; i<MRB_METHOD_CACHE_SIZE; mc++,i++) {
|
|
2614
|
+
if (mc->mid == id) mc->c = NULL;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
#endif // MRB_NO_METHOD_CACHE
|
|
2618
|
+
|
|
2619
|
+
mrb_method_t
|
|
2620
|
+
mrb_vm_find_method(mrb_state *mrb, struct RClass *c, struct RClass **cp, mrb_sym mid)
|
|
2621
|
+
{
|
|
2622
|
+
mrb_method_t m;
|
|
2623
|
+
#ifndef MRB_NO_METHOD_CACHE
|
|
2624
|
+
struct RClass *oc = c;
|
|
2625
|
+
int h = mrb_int_hash_func(mrb, ((intptr_t)oc) ^ mid) & (MRB_METHOD_CACHE_SIZE-1);
|
|
2626
|
+
struct mrb_cache_entry *mc = &mrb->cache[h];
|
|
2627
|
+
|
|
2628
|
+
if (mc->c == c && mc->mid == mid) {
|
|
2629
|
+
*cp = mc->c0;
|
|
2630
|
+
return mc->m;
|
|
2631
|
+
}
|
|
2632
|
+
#endif
|
|
2633
|
+
|
|
2634
|
+
while (c) {
|
|
2635
|
+
mrb_mt_tbl *h = c->mt;
|
|
2636
|
+
|
|
2637
|
+
if (h) {
|
|
2638
|
+
union mrb_mt_ptr ptr;
|
|
2639
|
+
uint32_t flags;
|
|
2640
|
+
if (mt_get(mrb, h, mid, &ptr, &flags)) {
|
|
2641
|
+
if (ptr.proc == 0) break;
|
|
2642
|
+
*cp = c;
|
|
2643
|
+
m = create_method_value(mrb, flags, ptr);
|
|
2644
|
+
#ifndef MRB_NO_METHOD_CACHE
|
|
2645
|
+
mc->c = oc;
|
|
2646
|
+
mc->c0 = c;
|
|
2647
|
+
mc->mid = mid;
|
|
2648
|
+
mc->m = m;
|
|
2649
|
+
#endif
|
|
2650
|
+
return m;
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
c = c->super;
|
|
2654
|
+
}
|
|
2655
|
+
MRB_METHOD_FROM_PROC(m, NULL);
|
|
2656
|
+
return m; /* no method */
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
/*
|
|
2660
|
+
* Searches for a method in the method table of a class and its ancestors
|
|
2661
|
+
* within the context of the current virtual machine.
|
|
2662
|
+
* This function is primarily used internally by the VM and dispatch mechanism.
|
|
2663
|
+
*
|
|
2664
|
+
* @param mrb The mruby state.
|
|
2665
|
+
* @param cp A pointer to a pointer to the class (`RClass*`) from which to start
|
|
2666
|
+
* the method search. On successful find, the `RClass*` pointed to by `cp`
|
|
2667
|
+
* is updated to the class where the method was actually found.
|
|
2668
|
+
* @param mid The symbol ID of the method name to search for.
|
|
2669
|
+
* @return An `mrb_method_t` structure representing the found method.
|
|
2670
|
+
* If the method is not found or is undefined, the returned `mrb_method_t`
|
|
2671
|
+
* will have its `proc` field set to NULL (use `MRB_METHOD_UNDEF_P` to check).
|
|
2672
|
+
* @sideeffect If the method is found and method caching is enabled (i.e.,
|
|
2673
|
+
* `MRB_NO_METHOD_CACHE` is not defined), this function will update
|
|
2674
|
+
* the VM's method cache with the found method for the original class
|
|
2675
|
+
* in `*cp` and the method ID `mid`.
|
|
2676
|
+
*/
|
|
2677
|
+
MRB_API mrb_method_t
|
|
2678
|
+
mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
|
|
2679
|
+
{
|
|
2680
|
+
return mrb_vm_find_method(mrb, *cp, cp, mid);
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
/*
|
|
2684
|
+
* Searches for a method in a class `c` and its ancestors.
|
|
2685
|
+
* This is a higher-level wrapper around `mrb_method_search_vm`.
|
|
2686
|
+
*
|
|
2687
|
+
* @param mrb The mruby state.
|
|
2688
|
+
* @param c The class (`RClass*`) in which to start the search.
|
|
2689
|
+
* @param mid The symbol ID (`mrb_sym`) of the method name.
|
|
2690
|
+
* @return An `mrb_method_t` structure for the found method.
|
|
2691
|
+
* @raise NameError if the method specified by `mid` is not found or is undefined
|
|
2692
|
+
* in class `c` or its ancestors.
|
|
2693
|
+
* @sideeffect May update the method cache if the method is found (via the
|
|
2694
|
+
* internal call to `mrb_method_search_vm`).
|
|
2695
|
+
*/
|
|
2696
|
+
MRB_API mrb_method_t
|
|
2697
|
+
mrb_method_search(mrb_state *mrb, struct RClass *c, mrb_sym mid)
|
|
2698
|
+
{
|
|
2699
|
+
mrb_method_t m;
|
|
2700
|
+
|
|
2701
|
+
m = mrb_method_search_vm(mrb, &c, mid);
|
|
2702
|
+
if (MRB_METHOD_UNDEF_P(m)) {
|
|
2703
|
+
mrb_name_error(mrb, mid, "undefined method '%n' for class %C", mid, c);
|
|
2704
|
+
}
|
|
2705
|
+
return m;
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
#define ONSTACK_ALLOC_MAX 32
|
|
2709
|
+
|
|
2710
|
+
static mrb_sym
|
|
2711
|
+
prepare_name_common(mrb_state *mrb, mrb_sym sym, const char *prefix, const char *suffix)
|
|
2712
|
+
{
|
|
2713
|
+
char onstack[ONSTACK_ALLOC_MAX];
|
|
2714
|
+
mrb_int sym_len;
|
|
2715
|
+
const char *sym_str = mrb_sym_name_len(mrb, sym, &sym_len);
|
|
2716
|
+
size_t prefix_len = prefix ? strlen(prefix) : 0;
|
|
2717
|
+
size_t suffix_len = suffix ? strlen(suffix) : 0;
|
|
2718
|
+
size_t name_len = sym_len + prefix_len + suffix_len;
|
|
2719
|
+
char *buf = name_len > sizeof(onstack) ? (char*)mrb_alloca(mrb, name_len) : onstack;
|
|
2720
|
+
char *p = buf;
|
|
2721
|
+
|
|
2722
|
+
if (prefix_len > 0) {
|
|
2723
|
+
memcpy(p, prefix, prefix_len);
|
|
2724
|
+
p += prefix_len;
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
memcpy(p, sym_str, sym_len);
|
|
2728
|
+
p += sym_len;
|
|
2729
|
+
|
|
2730
|
+
if (suffix_len > 0) {
|
|
2731
|
+
memcpy(p, suffix, suffix_len);
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
return mrb_intern(mrb, buf, name_len);
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
static mrb_value
|
|
2738
|
+
prepare_ivar_name(mrb_state *mrb, mrb_sym sym)
|
|
2739
|
+
{
|
|
2740
|
+
sym = prepare_name_common(mrb, sym, "@", NULL);
|
|
2741
|
+
mrb_iv_name_sym_check(mrb, sym);
|
|
2742
|
+
return mrb_symbol_value(sym);
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
static mrb_sym
|
|
2746
|
+
prepare_writer_name(mrb_state *mrb, mrb_sym sym)
|
|
2747
|
+
{
|
|
2748
|
+
return prepare_name_common(mrb, sym, NULL, "=");
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
static mrb_value
|
|
2752
|
+
mod_attr_define(mrb_state *mrb, mrb_value mod, mrb_value (*accessor)(mrb_state*, mrb_value), mrb_sym (*access_name)(mrb_state*, mrb_sym))
|
|
2753
|
+
{
|
|
2754
|
+
struct RClass *c = mrb_class_ptr(mod);
|
|
2755
|
+
const mrb_value *argv;
|
|
2756
|
+
mrb_int argc;
|
|
2757
|
+
|
|
2758
|
+
mrb_get_args(mrb, "*", &argv, &argc);
|
|
2759
|
+
|
|
2760
|
+
int ai = mrb_gc_arena_save(mrb);
|
|
2761
|
+
for (int i=0; i<argc; i++) {
|
|
2762
|
+
mrb_sym method = to_sym(mrb, argv[i]);
|
|
2763
|
+
mrb_value name = prepare_ivar_name(mrb, method);
|
|
2764
|
+
if (access_name) {
|
|
2765
|
+
method = access_name(mrb, method);
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
struct RProc *p = mrb_proc_new_cfunc_with_env(mrb, accessor, 1, &name);
|
|
2769
|
+
mrb_method_t m;
|
|
2770
|
+
MRB_METHOD_FROM_PROC(m, p);
|
|
2771
|
+
mrb_define_method_raw(mrb, c, method, m);
|
|
2772
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
2773
|
+
}
|
|
2774
|
+
return mrb_nil_value();
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
static mrb_value
|
|
2778
|
+
attr_reader(mrb_state *mrb, mrb_value obj)
|
|
2779
|
+
{
|
|
2780
|
+
mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
|
|
2781
|
+
return mrb_iv_get(mrb, obj, to_sym(mrb, name));
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
static mrb_value
|
|
2785
|
+
mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
|
|
2786
|
+
{
|
|
2787
|
+
return mod_attr_define(mrb, mod, attr_reader, NULL);
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
static mrb_value
|
|
2791
|
+
attr_writer(mrb_state *mrb, mrb_value obj)
|
|
2792
|
+
{
|
|
2793
|
+
mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
|
|
2794
|
+
mrb_value val = mrb_get_arg1(mrb);
|
|
2795
|
+
|
|
2796
|
+
mrb_iv_set(mrb, obj, to_sym(mrb, name), val);
|
|
2797
|
+
return val;
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
static mrb_value
|
|
2801
|
+
mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
|
|
2802
|
+
{
|
|
2803
|
+
return mod_attr_define(mrb, mod, attr_writer, prepare_writer_name);
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2806
|
+
static mrb_value
|
|
2807
|
+
mrb_mod_attr_accessor(mrb_state *mrb, mrb_value mod)
|
|
2808
|
+
{
|
|
2809
|
+
mrb_mod_attr_reader(mrb, mod);
|
|
2810
|
+
return mrb_mod_attr_writer(mrb, mod);
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2813
|
+
static mrb_value
|
|
2814
|
+
mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
|
|
2815
|
+
{
|
|
2816
|
+
struct RClass *c = mrb_class_ptr(cv);
|
|
2817
|
+
enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
|
|
2818
|
+
|
|
2819
|
+
if (c->tt == MRB_TT_SCLASS)
|
|
2820
|
+
mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class");
|
|
2821
|
+
|
|
2822
|
+
if (c == mrb->nil_class || c == mrb->false_class) {
|
|
2823
|
+
mrb_assert(ttype == 0);
|
|
2824
|
+
}
|
|
2825
|
+
else if (ttype == 0) {
|
|
2826
|
+
ttype = MRB_TT_OBJECT;
|
|
2827
|
+
}
|
|
2828
|
+
if (MRB_UNDEF_ALLOCATOR_P(c)) {
|
|
2829
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "allocator undefined for %v", cv);
|
|
2830
|
+
}
|
|
2831
|
+
if (ttype <= MRB_TT_CPTR) {
|
|
2832
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %v", cv);
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
struct RObject *o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
|
|
2836
|
+
return mrb_obj_value(o);
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
/*
|
|
2840
|
+
* call-seq:
|
|
2841
|
+
* class.new(args, ...) -> obj
|
|
2842
|
+
*
|
|
2843
|
+
* Creates a new object of *class*'s class, then
|
|
2844
|
+
* invokes that object's `initialize` method,
|
|
2845
|
+
* passing it *args*. This is the method that ends
|
|
2846
|
+
* up getting called whenever an object is constructed using
|
|
2847
|
+
* `.new`.
|
|
2848
|
+
*
|
|
2849
|
+
*/
|
|
2850
|
+
|
|
2851
|
+
mrb_value
|
|
2852
|
+
mrb_instance_new(mrb_state *mrb, mrb_value cv)
|
|
2853
|
+
{
|
|
2854
|
+
const mrb_value *argv;
|
|
2855
|
+
mrb_int argc;
|
|
2856
|
+
mrb_value blk;
|
|
2857
|
+
|
|
2858
|
+
mrb_get_args(mrb, "*!&", &argv, &argc, &blk);
|
|
2859
|
+
mrb_value obj = mrb_instance_alloc(mrb, cv);
|
|
2860
|
+
mrb_sym init = MRB_SYM(initialize);
|
|
2861
|
+
if (!mrb_func_basic_p(mrb, obj, init, mrb_do_nothing)) {
|
|
2862
|
+
mrb_funcall_with_block(mrb, obj, init, argc, argv, blk);
|
|
2863
|
+
}
|
|
2864
|
+
return obj;
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
/*
|
|
2868
|
+
* Creates a new instance of class `c` and initializes it by calling its `initialize` method.
|
|
2869
|
+
*
|
|
2870
|
+
* This function first allocates a new object of the given class `c`.
|
|
2871
|
+
* Then, it calls the `initialize` method on this new object, passing
|
|
2872
|
+
* `argc` and `argv` as arguments. If the `initialize` method is not
|
|
2873
|
+
* explicitly defined or is the default (empty) one, it is not called.
|
|
2874
|
+
*
|
|
2875
|
+
* @param mrb The mruby state.
|
|
2876
|
+
* @param c A pointer to the `RClass` structure of the class to instantiate.
|
|
2877
|
+
* @param argc The number of arguments to pass to the `initialize` method.
|
|
2878
|
+
* @param argv A pointer to an array of `mrb_value` arguments for `initialize`.
|
|
2879
|
+
* @return The newly created and initialized `mrb_value` object.
|
|
2880
|
+
* @raise TypeError if `c` is a singleton class, or if its allocator is undefined,
|
|
2881
|
+
* or if it's a built-in type that cannot be instantiated this way
|
|
2882
|
+
* (e.g., `MRB_TT_CPTR`). This check occurs in `mrb_instance_alloc`.
|
|
2883
|
+
* @sideeffect
|
|
2884
|
+
* 1. Allocates a new object on the mruby heap.
|
|
2885
|
+
* 2. Calls the `initialize` method of the new object if it's a user-defined one.
|
|
2886
|
+
* This `initialize` call can have arbitrary side effects.
|
|
2887
|
+
*/
|
|
2888
|
+
MRB_API mrb_value
|
|
2889
|
+
mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv)
|
|
2890
|
+
{
|
|
2891
|
+
mrb_value obj = mrb_instance_alloc(mrb, mrb_obj_value(c));
|
|
2892
|
+
mrb_sym mid = MRB_SYM(initialize);
|
|
2893
|
+
|
|
2894
|
+
if (!mrb_func_basic_p(mrb, obj, mid, mrb_do_nothing)) {
|
|
2895
|
+
mrb_funcall_argv(mrb, obj, mid, argc, argv);
|
|
2896
|
+
}
|
|
2897
|
+
return obj;
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
static mrb_value
|
|
2901
|
+
mrb_class_initialize(mrb_state *mrb, mrb_value obj)
|
|
2902
|
+
{
|
|
2903
|
+
struct RClass *c = mrb_class_ptr(obj);
|
|
2904
|
+
|
|
2905
|
+
if (c->iv) {
|
|
2906
|
+
mrb_raise(mrb, E_TYPE_ERROR, "already initialized class");
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
mrb_value a, b;
|
|
2910
|
+
mrb_get_args(mrb, "|C&", &a, &b);
|
|
2911
|
+
if (!mrb_nil_p(b)) {
|
|
2912
|
+
mrb_yield_with_class(mrb, b, 1, &obj, obj, c);
|
|
2913
|
+
}
|
|
2914
|
+
return obj;
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2917
|
+
static mrb_value
|
|
2918
|
+
mrb_class_new_class(mrb_state *mrb, mrb_value cv)
|
|
2919
|
+
{
|
|
2920
|
+
mrb_value super, blk;
|
|
2921
|
+
mrb_int n = mrb_get_args(mrb, "|C&", &super, &blk);
|
|
2922
|
+
|
|
2923
|
+
if (n == 0) {
|
|
2924
|
+
super = mrb_obj_value(mrb->object_class);
|
|
2925
|
+
}
|
|
2926
|
+
mrb_value new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
|
|
2927
|
+
mrb_sym mid = MRB_SYM(initialize);
|
|
2928
|
+
if (mrb_func_basic_p(mrb, new_class, mid, mrb_class_initialize)) {
|
|
2929
|
+
mrb_class_initialize(mrb, new_class);
|
|
2930
|
+
}
|
|
2931
|
+
else {
|
|
2932
|
+
mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk);
|
|
2933
|
+
}
|
|
2934
|
+
mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
|
|
2935
|
+
return new_class;
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
static mrb_value
|
|
2939
|
+
mrb_class_superclass(mrb_state *mrb, mrb_value klass)
|
|
2940
|
+
{
|
|
2941
|
+
struct RClass *c = mrb_class_ptr(klass);
|
|
2942
|
+
|
|
2943
|
+
c = find_origin(c)->super;
|
|
2944
|
+
while (c && c->tt == MRB_TT_ICLASS) {
|
|
2945
|
+
c = find_origin(c)->super;
|
|
2946
|
+
}
|
|
2947
|
+
if (!c) return mrb_nil_value();
|
|
2948
|
+
return mrb_obj_value(c);
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2951
|
+
static mrb_value
|
|
2952
|
+
mrb_do_nothing(mrb_state *mrb, mrb_value cv)
|
|
2953
|
+
{
|
|
2954
|
+
return mrb_nil_value();
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
static mrb_value
|
|
2958
|
+
mrb_bob_not(mrb_state *mrb, mrb_value cv)
|
|
2959
|
+
{
|
|
2960
|
+
return mrb_bool_value(!mrb_test(cv));
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
/* 15.3.1.3.1 */
|
|
2964
|
+
/* 15.3.1.3.10 */
|
|
2965
|
+
/* 15.3.1.3.11 */
|
|
2966
|
+
/*
|
|
2967
|
+
* call-seq:
|
|
2968
|
+
* obj == other -> true or false
|
|
2969
|
+
* obj.equal?(other) -> true or false
|
|
2970
|
+
* obj.eql?(other) -> true or false
|
|
2971
|
+
*
|
|
2972
|
+
* Equality---At the `Object` level, `==` returns
|
|
2973
|
+
* `true` only if *obj* and *other* are the
|
|
2974
|
+
* same object. Typically, this method is overridden in descendant
|
|
2975
|
+
* classes to provide class-specific meaning.
|
|
2976
|
+
*
|
|
2977
|
+
* Unlike `==`, the `equal?` method should never be
|
|
2978
|
+
* overridden by subclasses: it is used to determine object identity
|
|
2979
|
+
* (that is, `a.equal?(b)` iff `a` is the same
|
|
2980
|
+
* object as `b`).
|
|
2981
|
+
*
|
|
2982
|
+
* The `eql?` method returns `true` if
|
|
2983
|
+
* *obj* and *anObject* have the same value. Used by
|
|
2984
|
+
* `Hash` to test members for equality. For objects of
|
|
2985
|
+
* class `Object`, `eql?` is synonymous with
|
|
2986
|
+
* `==`. Subclasses normally continue this tradition, but
|
|
2987
|
+
* there are exceptions. `Numeric` types, for example,
|
|
2988
|
+
* perform type conversion across `==`, but not across
|
|
2989
|
+
* `eql?`, so:
|
|
2990
|
+
*
|
|
2991
|
+
* 1 == 1.0 #=> true
|
|
2992
|
+
* 1.eql? 1.0 #=> false
|
|
2993
|
+
*/
|
|
2994
|
+
mrb_value
|
|
2995
|
+
mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
|
|
2996
|
+
{
|
|
2997
|
+
mrb_value arg = mrb_get_arg1(mrb);
|
|
2998
|
+
|
|
2999
|
+
return mrb_bool_value(mrb_obj_equal(mrb, self, arg));
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
/*
|
|
3003
|
+
* Checks if instances of a class `c` (or its ancestors) respond to a given method.
|
|
3004
|
+
*
|
|
3005
|
+
* This function searches for the method `mid` in the method table of class `c`
|
|
3006
|
+
* and its ancestor classes and included modules.
|
|
3007
|
+
*
|
|
3008
|
+
* @param mrb The mruby state.
|
|
3009
|
+
* @param c The `RClass*` representing the class of the object.
|
|
3010
|
+
* @param mid The symbol ID (`mrb_sym`) of the method name.
|
|
3011
|
+
* @return `TRUE` if an object of class `c` would respond to the method `mid`
|
|
3012
|
+
* (i.e., the method is found and not undefined).
|
|
3013
|
+
* `FALSE` otherwise.
|
|
3014
|
+
* @sideeffect May update the method cache if the method is found (due to the
|
|
3015
|
+
* internal call to `mrb_method_search_vm`).
|
|
3016
|
+
*/
|
|
3017
|
+
MRB_API mrb_bool
|
|
3018
|
+
mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
|
|
3019
|
+
{
|
|
3020
|
+
mrb_method_t m = mrb_method_search_vm(mrb, &c, mid);
|
|
3021
|
+
|
|
3022
|
+
if (MRB_METHOD_UNDEF_P(m)) {
|
|
3023
|
+
return FALSE;
|
|
3024
|
+
}
|
|
3025
|
+
return TRUE;
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
/*
|
|
3029
|
+
* Checks if a given mruby object `obj` responds to a method specified by `mid`.
|
|
3030
|
+
*
|
|
3031
|
+
* This function first determines the class of `obj` and then calls
|
|
3032
|
+
* `mrb_obj_respond_to` to perform the method lookup.
|
|
3033
|
+
*
|
|
3034
|
+
* @param mrb The mruby state.
|
|
3035
|
+
* @param obj The `mrb_value` object to check.
|
|
3036
|
+
* @param mid The symbol ID (`mrb_sym`) of the method name.
|
|
3037
|
+
* @return `TRUE` if the object `obj` responds to the method `mid`, `FALSE` otherwise.
|
|
3038
|
+
* @sideeffect This function calls `mrb_class(mrb, obj)` which might have side effects
|
|
3039
|
+
* if `obj` is a proxy object or has unusual class resolution.
|
|
3040
|
+
* It also has the side effects of `mrb_obj_respond_to` (e.g., method
|
|
3041
|
+
* cache updates).
|
|
3042
|
+
*/
|
|
3043
|
+
MRB_API mrb_bool
|
|
3044
|
+
mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid)
|
|
3045
|
+
{
|
|
3046
|
+
return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid);
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
/*
|
|
3050
|
+
* Returns the name (path) of a class or module `c`.
|
|
3051
|
+
*
|
|
3052
|
+
* If the class/module has a cached name (typically set when it's assigned to a
|
|
3053
|
+
* constant), that name is returned.
|
|
3054
|
+
* For top-level classes/modules, this is their direct name.
|
|
3055
|
+
* For nested classes/modules, it's the fully qualified name (e.g., `Outer::Inner`).
|
|
3056
|
+
* If no name is cached (e.g., for anonymous classes/modules), this function
|
|
3057
|
+
* attempts to find or construct a path representation (e.g., `#<Class:0xPTR>`).
|
|
3058
|
+
*
|
|
3059
|
+
* @param mrb The mruby state.
|
|
3060
|
+
* @param c The `RClass*` structure of the class or module.
|
|
3061
|
+
* @return An `mrb_value` (String) representing the path of the class/module.
|
|
3062
|
+
* - If a name is cached as a symbol (toplevel), it returns the symbol's string representation.
|
|
3063
|
+
* - If a name is cached as a string (nested), it returns a duplicate of that string.
|
|
3064
|
+
* - If no name is cached, it calls `mrb_class_find_path` to get or construct one.
|
|
3065
|
+
* The returned string is suitable for modification by the caller as it's either
|
|
3066
|
+
* a new string or a duplicate of an internal one.
|
|
3067
|
+
* @sideeffect May allocate a new string on the mruby heap if duplication or construction
|
|
3068
|
+
* of the path string is necessary.
|
|
3069
|
+
*/
|
|
3070
|
+
MRB_API mrb_value
|
|
3071
|
+
mrb_class_path(mrb_state *mrb, struct RClass *c)
|
|
3072
|
+
{
|
|
3073
|
+
mrb_sym nsym = MRB_SYM(__classname__);
|
|
3074
|
+
mrb_value path = mrb_obj_iv_get(mrb, (struct RObject*)c, nsym);
|
|
3075
|
+
|
|
3076
|
+
if (mrb_nil_p(path)) {
|
|
3077
|
+
/* no name (yet) */
|
|
3078
|
+
return mrb_class_find_path(mrb, c);
|
|
3079
|
+
}
|
|
3080
|
+
else if (mrb_symbol_p(path)) {
|
|
3081
|
+
/* toplevel class/module */
|
|
3082
|
+
return mrb_sym_str(mrb, mrb_symbol(path));
|
|
3083
|
+
}
|
|
3084
|
+
return mrb_str_dup(mrb, path);
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
/*
|
|
3088
|
+
* Returns the "real" class of a given class pointer `cl`.
|
|
3089
|
+
*
|
|
3090
|
+
* The "real" class is the underlying, non-singleton, non-iclass `RClass`.
|
|
3091
|
+
* This function traverses up the superclass chain, skipping any `MRB_TT_SCLASS`
|
|
3092
|
+
* (singleton class) or `MRB_TT_ICLASS` (module inclusion class / i-class)
|
|
3093
|
+
* encountered, until it finds an `RClass` that is a `MRB_TT_CLASS` or
|
|
3094
|
+
* `MRB_TT_MODULE`.
|
|
3095
|
+
*
|
|
3096
|
+
* @param cl A pointer to an `RClass` structure.
|
|
3097
|
+
* @return A pointer to the "real" `RClass` structure.
|
|
3098
|
+
* Returns `NULL` if the input `cl` is `NULL` or if the superclass
|
|
3099
|
+
* chain leads to `NULL` before a real class is found (which typically
|
|
3100
|
+
* should not happen for valid class structures).
|
|
3101
|
+
*/
|
|
3102
|
+
MRB_API struct RClass*
|
|
3103
|
+
mrb_class_real(struct RClass* cl)
|
|
3104
|
+
{
|
|
3105
|
+
if (cl == 0) return NULL;
|
|
3106
|
+
while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) {
|
|
3107
|
+
cl = cl->super;
|
|
3108
|
+
if (cl == 0) return NULL;
|
|
3109
|
+
}
|
|
3110
|
+
return cl;
|
|
3111
|
+
}
|
|
3112
|
+
|
|
3113
|
+
/*
|
|
3114
|
+
* Returns the name of a class/module `c` as a C string.
|
|
3115
|
+
*
|
|
3116
|
+
* This function provides a C string representation of the class/module name.
|
|
3117
|
+
* It typically calls `mrb_class_path` internally and then returns a pointer
|
|
3118
|
+
* to the string data of the resulting `mrb_value`.
|
|
3119
|
+
*
|
|
3120
|
+
* @param mrb The mruby state.
|
|
3121
|
+
* @param c The `RClass*` structure of the class or module.
|
|
3122
|
+
* @return A `const char*` pointing to the name of the class/module.
|
|
3123
|
+
* This could be the class name, a fully qualified name for nested
|
|
3124
|
+
* modules/classes, or a representation like "#<Class:0xPTR>" for
|
|
3125
|
+
* anonymous ones. Returns `NULL` if `c` is `NULL`.
|
|
3126
|
+
* @sideeffect This function may allocate memory on the mruby heap if `mrb_class_path`
|
|
3127
|
+
* needs to construct the name string (e.g., for anonymous classes or
|
|
3128
|
+
* if the name is not cached). The returned pointer is to the internal
|
|
3129
|
+
* buffer of an `mrb_value` string; its validity is tied to the lifetime
|
|
3130
|
+
* of that string value, which is subject to garbage collection unless
|
|
3131
|
+
* explicitly protected.
|
|
3132
|
+
*/
|
|
3133
|
+
MRB_API const char*
|
|
3134
|
+
mrb_class_name(mrb_state *mrb, struct RClass* c)
|
|
3135
|
+
{
|
|
3136
|
+
if (c == NULL) return NULL;
|
|
3137
|
+
|
|
3138
|
+
mrb_value name = class_name_str(mrb, c);
|
|
3139
|
+
return RSTRING_PTR(name);
|
|
3140
|
+
}
|
|
3141
|
+
|
|
3142
|
+
/*
|
|
3143
|
+
* Returns the class name of a given mruby object `obj` as a C string.
|
|
3144
|
+
*
|
|
3145
|
+
* This function first retrieves the class of the object using `mrb_obj_class`
|
|
3146
|
+
* (which gets the "real" class, traversing SCLASS/ICLASS), and then
|
|
3147
|
+
* gets the name of that class using `mrb_class_name`.
|
|
3148
|
+
*
|
|
3149
|
+
* @param mrb The mruby state.
|
|
3150
|
+
* @param obj The `mrb_value` object whose class name is to be retrieved.
|
|
3151
|
+
* @return A `const char*` pointing to the name of the object's class.
|
|
3152
|
+
* See `mrb_class_name` for details on the format of the name.
|
|
3153
|
+
* @sideeffect This function has the combined side effects of `mrb_obj_class`
|
|
3154
|
+
* and `mrb_class_name`. This may include memory allocation on the
|
|
3155
|
+
* mruby heap for constructing the class name string or for class
|
|
3156
|
+
* structure creation if the object's class or metaclass components
|
|
3157
|
+
* are not yet fully initialized. The lifetime of the returned pointer
|
|
3158
|
+
* is tied to the underlying string `mrb_value`.
|
|
3159
|
+
*/
|
|
3160
|
+
MRB_API const char*
|
|
3161
|
+
mrb_obj_classname(mrb_state *mrb, mrb_value obj)
|
|
3162
|
+
{
|
|
3163
|
+
return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3166
|
+
/*
|
|
3167
|
+
* Ensures a class can be derived from super.
|
|
3168
|
+
*
|
|
3169
|
+
* \param super a reference to an object.
|
|
3170
|
+
* \exception TypeError if \a super is not a Class or \a super is a singleton class.
|
|
3171
|
+
*/
|
|
3172
|
+
static void
|
|
3173
|
+
mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
|
|
3174
|
+
{
|
|
3175
|
+
if (super->tt != MRB_TT_CLASS) {
|
|
3176
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%C given)", super);
|
|
3177
|
+
}
|
|
3178
|
+
if (super->tt == MRB_TT_SCLASS) {
|
|
3179
|
+
mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class");
|
|
3180
|
+
}
|
|
3181
|
+
if (super == mrb->class_class) {
|
|
3182
|
+
mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of Class");
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3186
|
+
/*
|
|
3187
|
+
* Creates a new, unnamed class.
|
|
3188
|
+
*
|
|
3189
|
+
* This function is the core mechanism for creating new classes in mruby.
|
|
3190
|
+
* The created class will not have a name (i.e., it's anonymous) until it is
|
|
3191
|
+
* assigned to a constant.
|
|
3192
|
+
*
|
|
3193
|
+
* @param mrb The mruby state.
|
|
3194
|
+
* @param super A pointer to the `RClass` structure of the superclass.
|
|
3195
|
+
* If `super` is `NULL`, `Object` (mrb->object_class) will be used
|
|
3196
|
+
* as the superclass by default (though `boot_defclass` handles this).
|
|
3197
|
+
* @return A pointer to the `RClass` structure of the newly created class.
|
|
3198
|
+
* @raise TypeError if `super` is not a valid class to inherit from (e.g., it's a
|
|
3199
|
+
* singleton class, or it's the `Class` class itself).
|
|
3200
|
+
* This check is performed by `mrb_check_inheritable`.
|
|
3201
|
+
* @sideeffect
|
|
3202
|
+
* 1. Allocates a new `RClass` object on the mruby heap.
|
|
3203
|
+
* 2. Initializes its method table (`mt`).
|
|
3204
|
+
* 3. Sets its superclass to the provided `super` (or `Object` if `super` is `NULL`).
|
|
3205
|
+
* 4. Copies instance type information (`MRB_INSTANCE_TT`) and the
|
|
3206
|
+
* `MRB_FL_UNDEF_ALLOCATE` flag from the superclass if `super` is provided.
|
|
3207
|
+
* 5. Creates and attaches a metaclass (singleton class) to the new class.
|
|
3208
|
+
*/
|
|
3209
|
+
MRB_API struct RClass*
|
|
3210
|
+
mrb_class_new(mrb_state *mrb, struct RClass *super)
|
|
3211
|
+
{
|
|
3212
|
+
if (super) {
|
|
3213
|
+
mrb_check_inheritable(mrb, super);
|
|
3214
|
+
}
|
|
3215
|
+
else {
|
|
3216
|
+
super = mrb->object_class;
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3219
|
+
struct RClass *c = boot_defclass(mrb, super, MRB_INSTANCE_TT(super));
|
|
3220
|
+
c->flags |= super->flags & MRB_FL_UNDEF_ALLOCATE;
|
|
3221
|
+
make_metaclass(mrb, c);
|
|
3222
|
+
|
|
3223
|
+
return c;
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
/*
|
|
3227
|
+
* Creates a new, unnamed module.
|
|
3228
|
+
*
|
|
3229
|
+
* This function is the core mechanism for creating new modules in mruby.
|
|
3230
|
+
* The created module will not have a name (i.e., it's anonymous) until it is
|
|
3231
|
+
* assigned to a constant.
|
|
3232
|
+
*
|
|
3233
|
+
* @param mrb The mruby state.
|
|
3234
|
+
* @return A pointer to the `RClass` structure of the newly created module.
|
|
3235
|
+
* The `tt` field of this `RClass` will be `MRB_TT_MODULE`.
|
|
3236
|
+
* @sideeffect
|
|
3237
|
+
* 1. Allocates a new `RClass` object on the mruby heap.
|
|
3238
|
+
* 2. Sets its class to `mrb->module_class`.
|
|
3239
|
+
* 3. Initializes its method table (`mt`).
|
|
3240
|
+
*/
|
|
3241
|
+
MRB_API struct RClass*
|
|
3242
|
+
mrb_module_new(mrb_state *mrb)
|
|
3243
|
+
{
|
|
3244
|
+
struct RClass *m = MRB_OBJ_ALLOC(mrb, MRB_TT_MODULE, mrb->module_class);
|
|
3245
|
+
boot_initmod(mrb, m);
|
|
3246
|
+
return m;
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3249
|
+
/*
|
|
3250
|
+
* call-seq:
|
|
3251
|
+
* obj.class => class
|
|
3252
|
+
*
|
|
3253
|
+
* Returns the class of *obj*, now preferred over
|
|
3254
|
+
* `Object#type`, as an object's type in Ruby is only
|
|
3255
|
+
* loosely tied to that object's class. This method must always be
|
|
3256
|
+
* called with an explicit receiver, as `class` is also a
|
|
3257
|
+
* reserved word in Ruby.
|
|
3258
|
+
*
|
|
3259
|
+
* 1.class #=> Integer
|
|
3260
|
+
* self.class #=> Object
|
|
3261
|
+
*/
|
|
3262
|
+
|
|
3263
|
+
/*
|
|
3264
|
+
* Returns the "real" class of an object.
|
|
3265
|
+
* This is the preferred way to get the class of an object in C extension code.
|
|
3266
|
+
* It correctly handles various mruby internal object structures by first calling
|
|
3267
|
+
* `mrb_class` (which gets the direct class, potentially a singleton or i-class)
|
|
3268
|
+
* and then `mrb_class_real` to resolve it to the actual user-facing class.
|
|
3269
|
+
*
|
|
3270
|
+
* @param mrb The mruby state.
|
|
3271
|
+
* @param obj The `mrb_value` object whose class is to be retrieved.
|
|
3272
|
+
* @return A pointer to the `RClass` structure of the object's "real" class.
|
|
3273
|
+
* For example, for an instance of a regular class, it returns the class itself.
|
|
3274
|
+
* For an instance of a class that includes modules, it still returns the class itself,
|
|
3275
|
+
* not the i-classes. For a class object, it returns `Class`.
|
|
3276
|
+
* @sideeffect This function itself has minimal side effects, but the underlying
|
|
3277
|
+
* `mrb_class` and `mrb_class_real` might perform lookups or traversals.
|
|
3278
|
+
*/
|
|
3279
|
+
MRB_API struct RClass*
|
|
3280
|
+
mrb_obj_class(mrb_state *mrb, mrb_value obj)
|
|
3281
|
+
{
|
|
3282
|
+
return mrb_class_real(mrb_class(mrb, obj));
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
/*
|
|
3286
|
+
* Defines an alias for an existing method within a class or module `c`.
|
|
3287
|
+
* The new method `a` will be an alias of the old method `b`.
|
|
3288
|
+
*
|
|
3289
|
+
* @param mrb The mruby state.
|
|
3290
|
+
* @param c The class or module (`RClass*`) in which to define the alias.
|
|
3291
|
+
* @param a The symbol ID (`mrb_sym`) for the new method name (the alias).
|
|
3292
|
+
* @param b The symbol ID (`mrb_sym`) for the original method name to be aliased.
|
|
3293
|
+
* @return This function does not return a value.
|
|
3294
|
+
* @raise NameError if the original method `b` is not found in class `c` or its ancestors.
|
|
3295
|
+
* @sideeffect
|
|
3296
|
+
* 1. Searches for the original method `b` in class `c` and its ancestors.
|
|
3297
|
+
* 2. If `b` is found:
|
|
3298
|
+
* a. If `b` is a C function (`MRB_METHOD_CFUNC_P` is true), or if `b` is already
|
|
3299
|
+
* an alias proc (`MRB_PROC_ALIAS_P` is true for the proc body), the method `m`
|
|
3300
|
+
* (representing `b`) is directly used for the new alias `a`.
|
|
3301
|
+
* b. If `b` is a Ruby-defined method (a non-CFUNC, non-alias `RProc`), a new `RProc`
|
|
3302
|
+
* of type `MRB_PROC_ALIAS` is created. This new proc stores the original
|
|
3303
|
+
* method's symbol `b` and its `RProc` as its `upper`. This ensures that
|
|
3304
|
+
* the alias `a` continues to point to the definition of `b` at the time of
|
|
3305
|
+
* aliasing, even if `b` is later redefined. The visibility of `b` is copied
|
|
3306
|
+
* to this new alias proc.
|
|
3307
|
+
* c. The method (either the original `m` or the new alias proc) is then defined
|
|
3308
|
+
* in class `c` under the new name `a` using `mrb_define_method_raw`.
|
|
3309
|
+
* 3. The method cache for the new alias name `a` is cleared.
|
|
3310
|
+
* 4. If `a` and `b` are the same, the function does nothing and returns early.
|
|
3311
|
+
*/
|
|
3312
|
+
MRB_API void
|
|
3313
|
+
mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b)
|
|
3314
|
+
{
|
|
3315
|
+
if (a == b) return;
|
|
3316
|
+
mrb_method_t m = mrb_method_search(mrb, c, b);
|
|
3317
|
+
|
|
3318
|
+
if (!MRB_METHOD_CFUNC_P(m)) {
|
|
3319
|
+
const struct RProc *p = MRB_METHOD_PROC(m);
|
|
3320
|
+
if (!MRB_PROC_CFUNC_P(p) && !MRB_PROC_ALIAS_P(p)) {
|
|
3321
|
+
struct RProc *pnew = MRB_OBJ_ALLOC(mrb, MRB_TT_PROC, mrb->proc_class);
|
|
3322
|
+
int vis = MRB_METHOD_VISIBILITY(m);
|
|
3323
|
+
|
|
3324
|
+
pnew->body.mid = b;
|
|
3325
|
+
pnew->upper = p;
|
|
3326
|
+
pnew->e.env = NULL;
|
|
3327
|
+
pnew->flags |= MRB_PROC_ALIAS;
|
|
3328
|
+
MRB_METHOD_FROM_PROC(m, pnew);
|
|
3329
|
+
MRB_METHOD_SET_VISIBILITY(m, vis);
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
mrb_define_method_raw(mrb, c, a, m);
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
/*
|
|
3336
|
+
* Defines an alias for an existing method within a class or module `klass`.
|
|
3337
|
+
* This version takes C string names for both the new alias and the original method.
|
|
3338
|
+
*
|
|
3339
|
+
* @param mrb The mruby state.
|
|
3340
|
+
* @param klass The class or module (`RClass*`) in which to define the alias.
|
|
3341
|
+
* @param name1 The C string for the new method name (the alias).
|
|
3342
|
+
* @param name2 The C string for the original method name to be aliased.
|
|
3343
|
+
* @return This function does not return a value.
|
|
3344
|
+
* @raise NameError if the original method `name2` (after being interned) is not found.
|
|
3345
|
+
* @sideeffect
|
|
3346
|
+
* 1. Interns both `name1` and `name2` to get their `mrb_sym` IDs.
|
|
3347
|
+
* 2. Calls `mrb_alias_method` with the class `klass` and the obtained symbols.
|
|
3348
|
+
* (See `mrb_alias_method` for further side effects like method table modification
|
|
3349
|
+
* and cache clearing).
|
|
3350
|
+
*/
|
|
3351
|
+
MRB_API void
|
|
3352
|
+
mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2)
|
|
3353
|
+
{
|
|
3354
|
+
mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2));
|
|
3355
|
+
}
|
|
3356
|
+
|
|
3357
|
+
/*
|
|
3358
|
+
* Defines an alias for an existing method within a class or module `klass`,
|
|
3359
|
+
* using symbol IDs for both names.
|
|
3360
|
+
*
|
|
3361
|
+
* This function is a direct call to `mrb_alias_method`.
|
|
3362
|
+
*
|
|
3363
|
+
* @param mrb The mruby state.
|
|
3364
|
+
* @param klass The class or module (`RClass*`) in which to define the alias.
|
|
3365
|
+
* @param a The symbol ID (`mrb_sym`) for the new method name (the alias).
|
|
3366
|
+
* @param b The symbol ID (`mrb_sym`) for the original method name to be aliased.
|
|
3367
|
+
* @return This function does not return a value.
|
|
3368
|
+
* @raise NameError if the original method `b` is not found in `klass` or its ancestors.
|
|
3369
|
+
* @sideeffect Calls `mrb_alias_method`, which modifies the method table of `klass`
|
|
3370
|
+
* and clears the method cache for the new alias `a`.
|
|
3371
|
+
* (See `mrb_alias_method` for more detailed side effects).
|
|
3372
|
+
*/
|
|
3373
|
+
MRB_API void
|
|
3374
|
+
mrb_define_alias_id(mrb_state *mrb, struct RClass *klass, mrb_sym a, mrb_sym b)
|
|
3375
|
+
{
|
|
3376
|
+
mrb_alias_method(mrb, klass, a, b);
|
|
3377
|
+
}
|
|
3378
|
+
|
|
3379
|
+
/*
|
|
3380
|
+
* call-seq:
|
|
3381
|
+
* mod.to_s -> string
|
|
3382
|
+
*
|
|
3383
|
+
* Return a string representing this module or class. For basic
|
|
3384
|
+
* classes and modules, this is the name. For singletons, we
|
|
3385
|
+
* show information on the thing we're attached to as well.
|
|
3386
|
+
*/
|
|
3387
|
+
|
|
3388
|
+
mrb_value
|
|
3389
|
+
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
|
|
3390
|
+
{
|
|
3391
|
+
if (mrb_sclass_p(klass)) {
|
|
3392
|
+
mrb_value v = mrb_iv_get(mrb, klass, MRB_SYM(__attached__));
|
|
3393
|
+
mrb_value str = mrb_str_new_lit(mrb, "#<Class:");
|
|
3394
|
+
|
|
3395
|
+
if (class_ptr_p(v)) {
|
|
3396
|
+
mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v));
|
|
3397
|
+
}
|
|
3398
|
+
else {
|
|
3399
|
+
mrb_str_cat_str(mrb, str, mrb_any_to_s(mrb, v));
|
|
3400
|
+
}
|
|
3401
|
+
return mrb_str_cat_lit(mrb, str, ">");
|
|
3402
|
+
}
|
|
3403
|
+
else {
|
|
3404
|
+
return class_name_str(mrb, mrb_class_ptr(klass));
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
|
|
3408
|
+
static mrb_value
|
|
3409
|
+
mrb_mod_alias(mrb_state *mrb, mrb_value mod)
|
|
3410
|
+
{
|
|
3411
|
+
struct RClass *c = mrb_class_ptr(mod);
|
|
3412
|
+
mrb_sym new_name, old_name;
|
|
3413
|
+
|
|
3414
|
+
mrb_get_args(mrb, "nn", &new_name, &old_name);
|
|
3415
|
+
mrb_alias_method(mrb, c, new_name, old_name);
|
|
3416
|
+
mrb_method_added(mrb, c, new_name);
|
|
3417
|
+
return mod;
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3420
|
+
static void
|
|
3421
|
+
undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
|
|
3422
|
+
{
|
|
3423
|
+
mrb_sym undefined;
|
|
3424
|
+
mrb_value recv;
|
|
3425
|
+
mrb_method_t m;
|
|
3426
|
+
|
|
3427
|
+
MRB_METHOD_FROM_PROC(m, NULL);
|
|
3428
|
+
mrb_define_method_raw(mrb, c, a, m);
|
|
3429
|
+
if (c->tt == MRB_TT_SCLASS) {
|
|
3430
|
+
undefined = MRB_SYM(singleton_method_undefined);
|
|
3431
|
+
recv = mrb_iv_get(mrb, mrb_obj_value(c), MRB_SYM(__attached__));
|
|
3432
|
+
}
|
|
3433
|
+
else {
|
|
3434
|
+
undefined = MRB_SYM(method_undefined);
|
|
3435
|
+
recv = mrb_obj_value(c);
|
|
3436
|
+
}
|
|
3437
|
+
if (!mrb_func_basic_p(mrb, recv, undefined, mrb_do_nothing)) {
|
|
3438
|
+
mrb_value sym = mrb_symbol_value(a);
|
|
3439
|
+
mrb_funcall_argv(mrb, recv, undefined, 1, &sym);
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
|
|
3443
|
+
/*
|
|
3444
|
+
* Undefines a method specified by symbol `a` in class/module `c`.
|
|
3445
|
+
*
|
|
3446
|
+
* This action prevents objects of class `c` (or classes including module `c`)
|
|
3447
|
+
* from responding to the method `a`. If the method was inherited, the version
|
|
3448
|
+
* in the superclass will no longer be accessible through `c`.
|
|
3449
|
+
* A special "undefined" entry is added to `c`'s method table for `a`.
|
|
3450
|
+
*
|
|
3451
|
+
* @param mrb The mruby state.
|
|
3452
|
+
* @param c The class or module (`RClass*`) in which to undefine the method.
|
|
3453
|
+
* @param a The symbol ID (`mrb_sym`) of the method to undefine.
|
|
3454
|
+
* @return This function does not return a value.
|
|
3455
|
+
* @raise NameError if the method `a` is not defined in `c` or its ancestors
|
|
3456
|
+
* (i.e., if `c` does not respond to `a` before undefinition).
|
|
3457
|
+
* @sideeffect
|
|
3458
|
+
* 1. Modifies the method table of `c` by adding an entry that marks `a` as undefined.
|
|
3459
|
+
* 2. Triggers `method_undefined` (for regular classes/modules) or
|
|
3460
|
+
* `singleton_method_undefined` (for singleton classes) callbacks on `c`
|
|
3461
|
+
* or its attached object, if these hooks are defined.
|
|
3462
|
+
* 3. Clears the method cache for the method symbol `a`.
|
|
3463
|
+
*/
|
|
3464
|
+
MRB_API void
|
|
3465
|
+
mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a)
|
|
3466
|
+
{
|
|
3467
|
+
if (!mrb_obj_respond_to(mrb, c, a)) {
|
|
3468
|
+
mrb_name_error(mrb, a, "undefined method '%n' for class '%C'", a, c);
|
|
3469
|
+
}
|
|
3470
|
+
undef_method(mrb, c, a);
|
|
3471
|
+
}
|
|
3472
|
+
|
|
3473
|
+
/*
|
|
3474
|
+
* Undefines a method specified by a C string `name` in class/module `c`.
|
|
3475
|
+
*
|
|
3476
|
+
* This function interns the C string `name` to a symbol and then calls
|
|
3477
|
+
* `mrb_undef_method_id` to perform the undefinition.
|
|
3478
|
+
*
|
|
3479
|
+
* @param mrb The mruby state.
|
|
3480
|
+
* @param c The class or module (`RClass*`) in which to undefine the method.
|
|
3481
|
+
* @param name The C string name of the method to undefine.
|
|
3482
|
+
* @return This function does not return a value.
|
|
3483
|
+
* @raise NameError if the method `name` (after interned to a symbol) is not
|
|
3484
|
+
* defined in `c` or its ancestors.
|
|
3485
|
+
* @sideeffect
|
|
3486
|
+
* 1. Interns the `name` string.
|
|
3487
|
+
* 2. All side effects of `mrb_undef_method_id` apply (method table modification,
|
|
3488
|
+
* callback triggering, cache clearing).
|
|
3489
|
+
*/
|
|
3490
|
+
MRB_API void
|
|
3491
|
+
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
|
|
3492
|
+
{
|
|
3493
|
+
undef_method(mrb, c, mrb_intern_cstr(mrb, name));
|
|
3494
|
+
}
|
|
3495
|
+
|
|
3496
|
+
/*
|
|
3497
|
+
* Undefines a class method specified by symbol `name` for class/module `c`.
|
|
3498
|
+
*
|
|
3499
|
+
* Class methods are singleton methods of the class object. This function
|
|
3500
|
+
* retrieves the singleton class of `c` and then undefines the method there.
|
|
3501
|
+
*
|
|
3502
|
+
* @param mrb The mruby state.
|
|
3503
|
+
* @param c The class or module (`RClass*`) whose class method is to be undefined.
|
|
3504
|
+
* @param name The symbol ID (`mrb_sym`) of the class method to undefine.
|
|
3505
|
+
* @return This function does not return a value.
|
|
3506
|
+
* @raise TypeError if `c` cannot have a singleton class (e.g., if it's an
|
|
3507
|
+
* immediate value, though highly unlikely for an `RClass*`).
|
|
3508
|
+
* @raise NameError if the class method `name` is not defined on `c`.
|
|
3509
|
+
* @sideeffect
|
|
3510
|
+
* 1. Retrieves or creates the singleton class of `c`.
|
|
3511
|
+
* 2. All side effects of `mrb_undef_method_id` apply to this singleton class
|
|
3512
|
+
* (method table modification, callback triggering, cache clearing).
|
|
3513
|
+
*/
|
|
3514
|
+
MRB_API void
|
|
3515
|
+
mrb_undef_class_method_id(mrb_state *mrb, struct RClass *c, mrb_sym name)
|
|
3516
|
+
{
|
|
3517
|
+
mrb_undef_method_id(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name);
|
|
3518
|
+
}
|
|
3519
|
+
|
|
3520
|
+
/*
|
|
3521
|
+
* Undefines a class method specified by a C string `name` for class/module `c`.
|
|
3522
|
+
*
|
|
3523
|
+
* This function interns the C string `name` to a symbol and then calls
|
|
3524
|
+
* `mrb_undef_class_method_id` (which undefines the method on `c`'s singleton class).
|
|
3525
|
+
*
|
|
3526
|
+
* @param mrb The mruby state.
|
|
3527
|
+
* @param c The class or module (`RClass*`) whose class method is to be undefined.
|
|
3528
|
+
* @param name The C string name of the class method to undefine.
|
|
3529
|
+
* @return This function does not return a value.
|
|
3530
|
+
* @raise TypeError if `c` cannot have a singleton class.
|
|
3531
|
+
* @raise NameError if the class method `name` (after interned) is not defined on `c`.
|
|
3532
|
+
* @sideeffect
|
|
3533
|
+
* 1. Interns the `name` string.
|
|
3534
|
+
* 2. Retrieves or creates the singleton class of `c`.
|
|
3535
|
+
* 3. All side effects of `mrb_undef_method_id` apply to this singleton class.
|
|
3536
|
+
*/
|
|
3537
|
+
MRB_API void
|
|
3538
|
+
mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name)
|
|
3539
|
+
{
|
|
3540
|
+
mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name);
|
|
3541
|
+
}
|
|
3542
|
+
|
|
3543
|
+
/*
|
|
3544
|
+
* Removes a method specified by symbol `mid` directly from class/module `c0`.
|
|
3545
|
+
*
|
|
3546
|
+
* Unlike `mrb_undef_method_id`, this function only removes the method definition
|
|
3547
|
+
* from the specified class/module `c0`. If the method is defined in an ancestor,
|
|
3548
|
+
* that inherited method will become active after the removal from `c0`.
|
|
3549
|
+
*
|
|
3550
|
+
* @param mrb The mruby state.
|
|
3551
|
+
* @param c0 The class or module (`RClass*`) from which to remove the method.
|
|
3552
|
+
* The method is removed from the "origin" of this class if it's an ICLASS/SCLASS.
|
|
3553
|
+
* @param mid The symbol ID (`mrb_sym`) of the method to remove.
|
|
3554
|
+
* @return This function does not return a value.
|
|
3555
|
+
* @raise NameError if the method `mid` is not defined directly in the method
|
|
3556
|
+
* table of `c0` (or its origin).
|
|
3557
|
+
* @sideeffect
|
|
3558
|
+
* 1. Removes the method entry for `mid` from `c0`'s (or its origin's) method table.
|
|
3559
|
+
* 2. Triggers `method_removed` (for regular classes/modules) or
|
|
3560
|
+
* `singleton_method_removed` (for singleton classes) callbacks on `c0`
|
|
3561
|
+
* or its attached object, if these hooks are defined.
|
|
3562
|
+
* 3. Clears the method cache for the method symbol `mid`.
|
|
3563
|
+
*/
|
|
3564
|
+
MRB_API void
|
|
3565
|
+
mrb_remove_method(mrb_state *mrb, struct RClass *c0, mrb_sym mid)
|
|
3566
|
+
{
|
|
3567
|
+
struct RClass *c = c0;
|
|
3568
|
+
mrb_bool found = FALSE;
|
|
3569
|
+
|
|
3570
|
+
MRB_CLASS_ORIGIN(c);
|
|
3571
|
+
mrb_mt_tbl *h = c->mt;
|
|
3572
|
+
if (h) {
|
|
3573
|
+
found = mt_del(mrb, h, mid);
|
|
3574
|
+
/* insert removed tombstone to block ROM chain lookup */
|
|
3575
|
+
if (h->next && mt_chain_has(h->next, mid)) {
|
|
3576
|
+
union mrb_mt_ptr tombstone;
|
|
3577
|
+
tombstone.func = NULL;
|
|
3578
|
+
found = TRUE;
|
|
3579
|
+
if (mt_frozen_p(h)) {
|
|
3580
|
+
h->alloc &= ~MRB_MT_FROZEN_BIT;
|
|
3581
|
+
}
|
|
3582
|
+
else if (mt_readonly_p(h)) {
|
|
3583
|
+
mrb_mt_tbl *top = mt_new(mrb);
|
|
3584
|
+
top->next = h;
|
|
3585
|
+
h = c->mt = top;
|
|
3586
|
+
}
|
|
3587
|
+
mt_put(mrb, h, mid, MRB_MT_FUNC, tombstone);
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
if (!found) {
|
|
3591
|
+
mrb_name_error(mrb, mid, "method '%n' not defined in %C", mid, c);
|
|
3592
|
+
}
|
|
3593
|
+
mc_clear_by_id(mrb, mid);
|
|
3594
|
+
if (c0->tt == MRB_TT_SCLASS) {
|
|
3595
|
+
mrb_sym cb = MRB_SYM(singleton_method_removed);
|
|
3596
|
+
mrb_value recv = mrb_iv_get(mrb, mrb_obj_value(c0), MRB_SYM(__attached__));
|
|
3597
|
+
if (!mrb_func_basic_p(mrb, recv, cb, mrb_do_nothing)) {
|
|
3598
|
+
mrb_value sym = mrb_symbol_value(mid);
|
|
3599
|
+
mrb_funcall_argv(mrb, recv, cb, 1, &sym);
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3602
|
+
else {
|
|
3603
|
+
mrb_sym cb = MRB_SYM(method_removed);
|
|
3604
|
+
mrb_value recv = mrb_obj_value(c0);
|
|
3605
|
+
if (!mrb_func_basic_p(mrb, recv, cb, mrb_do_nothing)) {
|
|
3606
|
+
mrb_value sym = mrb_symbol_value(mid);
|
|
3607
|
+
mrb_funcall_argv(mrb, recv, cb, 1, &sym);
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
|
|
3612
|
+
static mrb_value
|
|
3613
|
+
mrb_mod_undef(mrb_state *mrb, mrb_value mod)
|
|
3614
|
+
{
|
|
3615
|
+
struct RClass *c = mrb_class_ptr(mod);
|
|
3616
|
+
mrb_int argc;
|
|
3617
|
+
const mrb_value *argv;
|
|
3618
|
+
|
|
3619
|
+
mrb_get_args(mrb, "*", &argv, &argc);
|
|
3620
|
+
while (argc--) {
|
|
3621
|
+
mrb_undef_method_id(mrb, c, to_sym(mrb, *argv));
|
|
3622
|
+
argv++;
|
|
3623
|
+
}
|
|
3624
|
+
return mrb_nil_value();
|
|
3625
|
+
}
|
|
3626
|
+
|
|
3627
|
+
static void
|
|
3628
|
+
check_const_name_sym(mrb_state *mrb, mrb_sym id)
|
|
3629
|
+
{
|
|
3630
|
+
mrb_int len;
|
|
3631
|
+
const char *name = mrb_sym_name_len(mrb, id, &len);
|
|
3632
|
+
if (!mrb_const_name_p(mrb, name, len)) {
|
|
3633
|
+
mrb_name_error(mrb, id, "wrong constant name %n", id);
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
|
|
3637
|
+
static mrb_value
|
|
3638
|
+
mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
|
|
3639
|
+
{
|
|
3640
|
+
mrb_sym id;
|
|
3641
|
+
mrb_bool inherit = TRUE;
|
|
3642
|
+
|
|
3643
|
+
mrb_get_args(mrb, "n|b", &id, &inherit);
|
|
3644
|
+
check_const_name_sym(mrb, id);
|
|
3645
|
+
if (inherit) {
|
|
3646
|
+
return mrb_bool_value(mrb_const_defined(mrb, mod, id));
|
|
3647
|
+
}
|
|
3648
|
+
return mrb_bool_value(mrb_const_defined_at(mrb, mod, id));
|
|
3649
|
+
}
|
|
3650
|
+
|
|
3651
|
+
static mrb_value
|
|
3652
|
+
mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id)
|
|
3653
|
+
{
|
|
3654
|
+
check_const_name_sym(mrb, id);
|
|
3655
|
+
return mrb_const_get(mrb, mod, id);
|
|
3656
|
+
}
|
|
3657
|
+
|
|
3658
|
+
static mrb_value
|
|
3659
|
+
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
|
|
3660
|
+
{
|
|
3661
|
+
mrb_value path = mrb_get_arg1(mrb);
|
|
3662
|
+
|
|
3663
|
+
if (mrb_symbol_p(path)) {
|
|
3664
|
+
/* const get with symbol */
|
|
3665
|
+
return mrb_const_get_sym(mrb, mod, mrb_symbol(path));
|
|
3666
|
+
}
|
|
3667
|
+
|
|
3668
|
+
/* const get with class path string */
|
|
3669
|
+
mrb_ensure_string_type(mrb, path);
|
|
3670
|
+
|
|
3671
|
+
char *ptr = RSTRING_PTR(path);
|
|
3672
|
+
mrb_int len = RSTRING_LEN(path);
|
|
3673
|
+
mrb_int off = 0;
|
|
3674
|
+
|
|
3675
|
+
while (off < len) {
|
|
3676
|
+
mrb_int end = mrb_str_index_lit(mrb, path, "::", off);
|
|
3677
|
+
if (end == -1) end = len;
|
|
3678
|
+
mrb_sym id = mrb_intern(mrb, ptr+off, end-off);
|
|
3679
|
+
mod = mrb_const_get_sym(mrb, mod, id);
|
|
3680
|
+
if (end == len)
|
|
3681
|
+
off = end;
|
|
3682
|
+
else {
|
|
3683
|
+
off = end + 2;
|
|
3684
|
+
if (off == len) { /* trailing "::" */
|
|
3685
|
+
mrb_name_error(mrb, id, "wrong constant name '%v'", path);
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
|
|
3690
|
+
return mod;
|
|
3691
|
+
}
|
|
3692
|
+
|
|
3693
|
+
static mrb_value
|
|
3694
|
+
mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
|
|
3695
|
+
{
|
|
3696
|
+
mrb_sym id;
|
|
3697
|
+
mrb_value value;
|
|
3698
|
+
|
|
3699
|
+
mrb_get_args(mrb, "no", &id, &value);
|
|
3700
|
+
check_const_name_sym(mrb, id);
|
|
3701
|
+
mrb_const_set(mrb, mod, id, value);
|
|
3702
|
+
return value;
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
static mrb_value
|
|
3706
|
+
mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
|
|
3707
|
+
{
|
|
3708
|
+
mrb_sym id;
|
|
3709
|
+
|
|
3710
|
+
mrb_get_args(mrb, "n", &id);
|
|
3711
|
+
check_const_name_sym(mrb, id);
|
|
3712
|
+
|
|
3713
|
+
mrb_value val = mrb_iv_remove(mrb, mod, id);
|
|
3714
|
+
if (mrb_undef_p(val)) {
|
|
3715
|
+
mrb_name_error(mrb, id, "constant %n not defined", id);
|
|
3716
|
+
}
|
|
3717
|
+
return val;
|
|
3718
|
+
}
|
|
3719
|
+
|
|
3720
|
+
mrb_value
|
|
3721
|
+
mrb_const_missing(mrb_state *mrb, mrb_value mod, mrb_sym sym)
|
|
3722
|
+
{
|
|
3723
|
+
if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) {
|
|
3724
|
+
mrb_name_error(mrb, sym, "uninitialized constant %v::%n", mod, sym);
|
|
3725
|
+
}
|
|
3726
|
+
else {
|
|
3727
|
+
mrb_name_error(mrb, sym, "uninitialized constant %n", sym);
|
|
3728
|
+
}
|
|
3729
|
+
/* not reached */
|
|
3730
|
+
return mrb_nil_value();
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
mrb_value
|
|
3734
|
+
mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
|
|
3735
|
+
{
|
|
3736
|
+
mrb_sym sym;
|
|
3737
|
+
|
|
3738
|
+
mrb_get_args(mrb, "n", &sym);
|
|
3739
|
+
mrb->c->ci->mid = 0;
|
|
3740
|
+
return mrb_const_missing(mrb, mod, sym);
|
|
3741
|
+
}
|
|
3742
|
+
|
|
3743
|
+
/* 15.2.2.4.34 */
|
|
3744
|
+
/*
|
|
3745
|
+
* call-seq:
|
|
3746
|
+
* mod.method_defined?(symbol) -> true or false
|
|
3747
|
+
*
|
|
3748
|
+
* Returns `true` if the named method is defined by
|
|
3749
|
+
* _mod_ (or its included modules and, if _mod_ is a class,
|
|
3750
|
+
* its ancestors). Public and protected methods are matched.
|
|
3751
|
+
*
|
|
3752
|
+
* module A
|
|
3753
|
+
* def method1() end
|
|
3754
|
+
* end
|
|
3755
|
+
* class B
|
|
3756
|
+
* def method2() end
|
|
3757
|
+
* end
|
|
3758
|
+
* class C < B
|
|
3759
|
+
* include A
|
|
3760
|
+
* def method3() end
|
|
3761
|
+
* end
|
|
3762
|
+
*
|
|
3763
|
+
* A.method_defined? :method1 #=> true
|
|
3764
|
+
* C.method_defined? "method1" #=> true
|
|
3765
|
+
* C.method_defined? "method2" #=> true
|
|
3766
|
+
* C.method_defined? "method3" #=> true
|
|
3767
|
+
* C.method_defined? "method4" #=> false
|
|
3768
|
+
*/
|
|
3769
|
+
|
|
3770
|
+
static mrb_value
|
|
3771
|
+
mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
|
|
3772
|
+
{
|
|
3773
|
+
mrb_sym id;
|
|
3774
|
+
|
|
3775
|
+
mrb_get_args(mrb, "n", &id);
|
|
3776
|
+
return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id));
|
|
3777
|
+
}
|
|
3778
|
+
|
|
3779
|
+
void
|
|
3780
|
+
mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid)
|
|
3781
|
+
{
|
|
3782
|
+
mrb_sym added;
|
|
3783
|
+
mrb_value recv = mrb_obj_value(c);
|
|
3784
|
+
|
|
3785
|
+
if (c->tt == MRB_TT_SCLASS) {
|
|
3786
|
+
added = MRB_SYM(singleton_method_added);
|
|
3787
|
+
recv = mrb_iv_get(mrb, recv, MRB_SYM(__attached__));
|
|
3788
|
+
}
|
|
3789
|
+
else {
|
|
3790
|
+
added = MRB_SYM(method_added);
|
|
3791
|
+
}
|
|
3792
|
+
if (!mrb_func_basic_p(mrb, recv, added, mrb_do_nothing)) {
|
|
3793
|
+
mrb_value sym = mrb_symbol_value(mid);
|
|
3794
|
+
mrb_funcall_argv(mrb, recv, added, 1, &sym);
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
|
|
3798
|
+
mrb_value
|
|
3799
|
+
define_method_m(mrb_state *mrb, struct RClass *c, int vis)
|
|
3800
|
+
{
|
|
3801
|
+
mrb_sym mid;
|
|
3802
|
+
mrb_value proc = mrb_undef_value();
|
|
3803
|
+
mrb_value blk;
|
|
3804
|
+
|
|
3805
|
+
mrb_get_args(mrb, "n|o&", &mid, &proc, &blk);
|
|
3806
|
+
switch (mrb_type(proc)) {
|
|
3807
|
+
case MRB_TT_PROC:
|
|
3808
|
+
blk = proc;
|
|
3809
|
+
break;
|
|
3810
|
+
case MRB_TT_UNDEF:
|
|
3811
|
+
/* ignored */
|
|
3812
|
+
break;
|
|
3813
|
+
default:
|
|
3814
|
+
mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %T (expected Proc)", proc);
|
|
3815
|
+
break;
|
|
3816
|
+
}
|
|
3817
|
+
if (mrb_nil_p(blk)) {
|
|
3818
|
+
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
|
|
3819
|
+
}
|
|
3820
|
+
struct RProc *p = MRB_OBJ_ALLOC(mrb, MRB_TT_PROC, mrb->proc_class);
|
|
3821
|
+
mrb_proc_copy(mrb, p, mrb_proc_ptr(blk));
|
|
3822
|
+
p->flags |= MRB_PROC_STRICT;
|
|
3823
|
+
|
|
3824
|
+
mrb_method_t m;
|
|
3825
|
+
MRB_METHOD_FROM_PROC(m, p);
|
|
3826
|
+
MRB_METHOD_SET_VISIBILITY(m, vis);
|
|
3827
|
+
mrb_define_method_raw(mrb, c, mid, m);
|
|
3828
|
+
mrb_method_added(mrb, c, mid);
|
|
3829
|
+
return mrb_symbol_value(mid);
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
mrb_value
|
|
3833
|
+
mrb_mod_define_method_m(mrb_state *mrb, struct RClass *c)
|
|
3834
|
+
{
|
|
3835
|
+
return define_method_m(mrb, c, MRB_METHOD_PUBLIC_FL);
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
static mrb_value
|
|
3839
|
+
mod_define_method(mrb_state *mrb, mrb_value self)
|
|
3840
|
+
{
|
|
3841
|
+
return mrb_mod_define_method_m(mrb, mrb_class_ptr(self));
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3844
|
+
static mrb_value
|
|
3845
|
+
top_define_method(mrb_state *mrb, mrb_value self)
|
|
3846
|
+
{
|
|
3847
|
+
return define_method_m(mrb, mrb->object_class, MRB_METHOD_PRIVATE_FL);
|
|
3848
|
+
}
|
|
3849
|
+
|
|
3850
|
+
static mrb_value
|
|
3851
|
+
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
|
|
3852
|
+
{
|
|
3853
|
+
mrb_value obj = mrb_get_arg1(mrb);
|
|
3854
|
+
mrb_bool eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));
|
|
3855
|
+
|
|
3856
|
+
return mrb_bool_value(eqq);
|
|
3857
|
+
}
|
|
3858
|
+
|
|
3859
|
+
static mrb_value
|
|
3860
|
+
mrb_mod_dup(mrb_state *mrb, mrb_value self)
|
|
3861
|
+
{
|
|
3862
|
+
mrb_value mod = mrb_obj_clone(mrb, self);
|
|
3863
|
+
mrb_obj_ptr(mod)->frozen = 0;
|
|
3864
|
+
return mod;
|
|
3865
|
+
}
|
|
3866
|
+
|
|
3867
|
+
static mrb_value
|
|
3868
|
+
mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
|
|
3869
|
+
{
|
|
3870
|
+
const mrb_value *argv;
|
|
3871
|
+
mrb_int argc;
|
|
3872
|
+
|
|
3873
|
+
mrb_check_type(mrb, mod, MRB_TT_MODULE);
|
|
3874
|
+
|
|
3875
|
+
mrb_get_args(mrb, "*", &argv, &argc);
|
|
3876
|
+
if (argc == 0) {
|
|
3877
|
+
/* set MODFUNC SCOPE if implemented */
|
|
3878
|
+
return mod;
|
|
3879
|
+
}
|
|
3880
|
+
|
|
3881
|
+
/* set PRIVATE method visibility if implemented */
|
|
3882
|
+
/* mrb_mod_dummy_visibility(mrb, mod); */
|
|
3883
|
+
|
|
3884
|
+
struct RClass *rclass = mrb_class_ptr(mod);
|
|
3885
|
+
int ai = mrb_gc_arena_save(mrb);
|
|
3886
|
+
for (int i=0; i<argc; i++) {
|
|
3887
|
+
mrb_check_type(mrb, argv[i], MRB_TT_SYMBOL);
|
|
3888
|
+
|
|
3889
|
+
mrb_sym mid = mrb_symbol(argv[i]);
|
|
3890
|
+
mrb_method_t m = mrb_method_search(mrb, rclass, mid);
|
|
3891
|
+
|
|
3892
|
+
prepare_singleton_class(mrb, (struct RBasic*)rclass);
|
|
3893
|
+
MRB_METHOD_SET_VISIBILITY(m, MRB_METHOD_PUBLIC_FL);
|
|
3894
|
+
mrb_define_method_raw(mrb, rclass->c, mid, m);
|
|
3895
|
+
mrb_gc_arena_restore(mrb, ai);
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
return mod;
|
|
3899
|
+
}
|
|
3900
|
+
|
|
3901
|
+
static struct RClass*
|
|
3902
|
+
mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
|
|
3903
|
+
{
|
|
3904
|
+
struct RClass *klass = mrb_basic_ptr(obj)->c;
|
|
3905
|
+
|
|
3906
|
+
if (klass->tt != MRB_TT_SCLASS)
|
|
3907
|
+
return klass;
|
|
3908
|
+
else {
|
|
3909
|
+
/* copy singleton(unnamed) class */
|
|
3910
|
+
struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class);
|
|
3911
|
+
|
|
3912
|
+
switch (mrb_type(obj)) {
|
|
3913
|
+
case MRB_TT_CLASS:
|
|
3914
|
+
case MRB_TT_SCLASS:
|
|
3915
|
+
break;
|
|
3916
|
+
default:
|
|
3917
|
+
clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
|
|
3918
|
+
break;
|
|
3919
|
+
}
|
|
3920
|
+
clone->super = klass->super;
|
|
3921
|
+
if (klass->iv) {
|
|
3922
|
+
mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
|
|
3923
|
+
mrb_obj_iv_set(mrb, (struct RObject*)clone, MRB_SYM(__attached__), obj);
|
|
3924
|
+
}
|
|
3925
|
+
if (klass->mt) {
|
|
3926
|
+
clone->mt = mt_copy(mrb, klass->mt);
|
|
3927
|
+
}
|
|
3928
|
+
else {
|
|
3929
|
+
clone->mt = mt_new(mrb);
|
|
3930
|
+
}
|
|
3931
|
+
clone->tt = MRB_TT_SCLASS;
|
|
3932
|
+
return clone;
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
|
|
3936
|
+
static void
|
|
3937
|
+
copy_class(mrb_state *mrb, mrb_value dst, mrb_value src)
|
|
3938
|
+
{
|
|
3939
|
+
struct RClass *dc = mrb_class_ptr(dst);
|
|
3940
|
+
struct RClass *sc = mrb_class_ptr(src);
|
|
3941
|
+
/* if the origin is not the same as the class, then the origin and
|
|
3942
|
+
the current class need to be copied */
|
|
3943
|
+
if (sc->flags & MRB_FL_CLASS_IS_PREPENDED) {
|
|
3944
|
+
struct RClass *c0 = sc->super;
|
|
3945
|
+
struct RClass *c1 = dc;
|
|
3946
|
+
|
|
3947
|
+
/* copy prepended iclasses */
|
|
3948
|
+
while (!(c0->flags & MRB_FL_CLASS_IS_ORIGIN)) {
|
|
3949
|
+
c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
|
|
3950
|
+
c1 = c1->super;
|
|
3951
|
+
c0 = c0->super;
|
|
3952
|
+
}
|
|
3953
|
+
c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
|
|
3954
|
+
c1->super->flags |= MRB_FL_CLASS_IS_ORIGIN;
|
|
3955
|
+
}
|
|
3956
|
+
if (sc->mt) {
|
|
3957
|
+
if (sc->tt == MRB_TT_ICLASS && !(sc->flags & MRB_FL_CLASS_IS_ORIGIN)) {
|
|
3958
|
+
dc->mt = sc->mt;
|
|
3959
|
+
}
|
|
3960
|
+
else {
|
|
3961
|
+
dc->mt = mt_copy(mrb, sc->mt);
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
dc->super = sc->super;
|
|
3965
|
+
dc->flags = sc->flags;
|
|
3966
|
+
dc->frozen = 0;
|
|
3967
|
+
}
|
|
3968
|
+
|
|
3969
|
+
/* 15.3.1.3.16 */
|
|
3970
|
+
mrb_value mrb_obj_init_copy(mrb_state *mrb, mrb_value self);
|
|
3971
|
+
|
|
3972
|
+
static void
|
|
3973
|
+
init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
|
|
3974
|
+
{
|
|
3975
|
+
mrb_assert((mrb_type(dest) == mrb_type(obj)));
|
|
3976
|
+
switch (mrb_unboxed_type(obj)) {
|
|
3977
|
+
case MRB_TT_ICLASS:
|
|
3978
|
+
copy_class(mrb, dest, obj);
|
|
3979
|
+
return;
|
|
3980
|
+
case MRB_TT_CLASS:
|
|
3981
|
+
case MRB_TT_MODULE:
|
|
3982
|
+
copy_class(mrb, dest, obj);
|
|
3983
|
+
mrb_iv_copy(mrb, dest, obj);
|
|
3984
|
+
mrb_iv_remove(mrb, dest, MRB_SYM(__classname__));
|
|
3985
|
+
break;
|
|
3986
|
+
case MRB_TT_OBJECT:
|
|
3987
|
+
case MRB_TT_SCLASS:
|
|
3988
|
+
case MRB_TT_HASH:
|
|
3989
|
+
case MRB_TT_CDATA:
|
|
3990
|
+
case MRB_TT_EXCEPTION:
|
|
3991
|
+
mrb_iv_copy(mrb, dest, obj);
|
|
3992
|
+
break;
|
|
3993
|
+
case MRB_TT_ISTRUCT:
|
|
3994
|
+
mrb_istruct_copy(dest, obj);
|
|
3995
|
+
break;
|
|
3996
|
+
#if !defined(MRB_NO_FLOAT) && defined(MRB_WORD_BOXING)
|
|
3997
|
+
case MRB_TT_FLOAT:
|
|
3998
|
+
{
|
|
3999
|
+
struct RFloat *f = (struct RFloat*)mrb_obj_ptr(dest);
|
|
4000
|
+
f->f = mrb_float(obj);
|
|
4001
|
+
}
|
|
4002
|
+
break;
|
|
4003
|
+
#endif
|
|
4004
|
+
#ifdef MRB_USE_BIGINT
|
|
4005
|
+
case MRB_TT_BIGINT:
|
|
4006
|
+
mrb_bint_copy(mrb, dest, obj);
|
|
4007
|
+
break;
|
|
4008
|
+
#endif
|
|
4009
|
+
#ifdef MRB_USE_RATIONAL
|
|
4010
|
+
case MRB_TT_RATIONAL:
|
|
4011
|
+
mrb_rational_copy(mrb, dest, obj);
|
|
4012
|
+
break;
|
|
4013
|
+
#endif
|
|
4014
|
+
#ifdef MRB_USE_COMPLEX
|
|
4015
|
+
case MRB_TT_COMPLEX:
|
|
4016
|
+
mrb_complex_copy(mrb, dest, obj);
|
|
4017
|
+
break;
|
|
4018
|
+
#endif
|
|
4019
|
+
|
|
4020
|
+
default:
|
|
4021
|
+
break;
|
|
4022
|
+
}
|
|
4023
|
+
if (!mrb_func_basic_p(mrb, dest, MRB_SYM(initialize_copy), mrb_obj_init_copy)) {
|
|
4024
|
+
mrb_funcall_argv(mrb, dest, MRB_SYM(initialize_copy), 1, &obj);
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
4027
|
+
|
|
4028
|
+
/* 15.3.1.3.8 */
|
|
4029
|
+
/*
|
|
4030
|
+
* call-seq:
|
|
4031
|
+
* obj.clone -> an_object
|
|
4032
|
+
*
|
|
4033
|
+
* Produces a shallow copy of *obj*---the instance variables of
|
|
4034
|
+
* *obj* are copied, but not the objects they reference. Copies
|
|
4035
|
+
* the frozen state of *obj*. See also the discussion
|
|
4036
|
+
* under `Object#dup`.
|
|
4037
|
+
*
|
|
4038
|
+
* class Klass
|
|
4039
|
+
* attr_accessor :str
|
|
4040
|
+
* end
|
|
4041
|
+
* s1 = Klass.new #=> #<Klass:0x401b3a38>
|
|
4042
|
+
* s1.str = "Hello" #=> "Hello"
|
|
4043
|
+
* s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
|
|
4044
|
+
* s2.str[1,4] = "i" #=> "i"
|
|
4045
|
+
* s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
|
|
4046
|
+
* s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
|
|
4047
|
+
*
|
|
4048
|
+
* This method may have class-specific behavior. If so, that
|
|
4049
|
+
* behavior will be documented under the #`initialize_copy` method of
|
|
4050
|
+
* the class.
|
|
4051
|
+
*
|
|
4052
|
+
* Some Class(True False Nil Symbol Integer Float) Object cannot clone.
|
|
4053
|
+
*/
|
|
4054
|
+
/*
|
|
4055
|
+
* Creates a shallow copy of the given object `self`.
|
|
4056
|
+
*
|
|
4057
|
+
* This function performs a shallow copy, meaning instance variables are copied,
|
|
4058
|
+
* but the objects they refer to are not duplicated. The frozen state of the
|
|
4059
|
+
* original object is also copied to the clone. If the object has a singleton
|
|
4060
|
+
* class, that singleton class is also cloned and associated with the new object.
|
|
4061
|
+
* After the new object is created and its basic state is copied, its
|
|
4062
|
+
* `initialize_copy` method is called with the original object as an argument,
|
|
4063
|
+
* allowing for class-specific adjustments to the cloning process.
|
|
4064
|
+
*
|
|
4065
|
+
* @param mrb The mruby state.
|
|
4066
|
+
* @param self The `mrb_value` object to clone.
|
|
4067
|
+
* @return A new `mrb_value` which is a clone of `self`.
|
|
4068
|
+
* @raise TypeError if `self` is an immediate value (e.g., Fixnum, Symbol in some
|
|
4069
|
+
* configurations) or if `self` is a singleton class itself, as these
|
|
4070
|
+
* cannot be cloned.
|
|
4071
|
+
* @sideeffect
|
|
4072
|
+
* 1. Allocates a new object on the mruby heap.
|
|
4073
|
+
* 2. Copies instance variables from `self` to the new object.
|
|
4074
|
+
* 3. If `self` has a singleton class, it is cloned and assigned to the new object.
|
|
4075
|
+
* This involves further allocations and setup for the new singleton class.
|
|
4076
|
+
* 4. The `frozen` state of `self` is propagated to the clone.
|
|
4077
|
+
* 5. Calls the `initialize_copy` method on the newly created clone, passing `self`
|
|
4078
|
+
* as an argument. This method can have arbitrary side effects.
|
|
4079
|
+
*/
|
|
4080
|
+
MRB_API mrb_value
|
|
4081
|
+
mrb_obj_clone(mrb_state *mrb, mrb_value self)
|
|
4082
|
+
{
|
|
4083
|
+
if (mrb_immediate_p(self)) {
|
|
4084
|
+
return self;
|
|
4085
|
+
}
|
|
4086
|
+
if (mrb_sclass_p(self)) {
|
|
4087
|
+
mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
|
|
4088
|
+
}
|
|
4089
|
+
struct RObject *p = (struct RObject*)mrb_obj_alloc(mrb, mrb_unboxed_type(self), mrb_obj_class(mrb, self));
|
|
4090
|
+
p->c = mrb_singleton_class_clone(mrb, self);
|
|
4091
|
+
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c);
|
|
4092
|
+
|
|
4093
|
+
mrb_value clone = mrb_obj_value(p);
|
|
4094
|
+
init_copy(mrb, clone, self);
|
|
4095
|
+
p->frozen = mrb_obj_ptr(self)->frozen;
|
|
4096
|
+
|
|
4097
|
+
return clone;
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
/* 15.3.1.3.9 */
|
|
4101
|
+
/*
|
|
4102
|
+
* call-seq:
|
|
4103
|
+
* obj.dup -> an_object
|
|
4104
|
+
*
|
|
4105
|
+
* Produces a shallow copy of *obj*---the instance variables of
|
|
4106
|
+
* *obj* are copied, but not the objects they reference.
|
|
4107
|
+
* `dup` copies the frozen state of *obj*. See also
|
|
4108
|
+
* the discussion under `Object#clone`. In general,
|
|
4109
|
+
* `clone` and `dup` may have different semantics
|
|
4110
|
+
* in descendant classes. While `clone` is used to duplicate
|
|
4111
|
+
* an object, including its internal state, `dup` typically
|
|
4112
|
+
* uses the class of the descendant object to create the new instance.
|
|
4113
|
+
*
|
|
4114
|
+
* This method may have class-specific behavior. If so, that
|
|
4115
|
+
* behavior will be documented under the #`initialize_copy` method of
|
|
4116
|
+
* the class.
|
|
4117
|
+
*/
|
|
4118
|
+
|
|
4119
|
+
/*
|
|
4120
|
+
* Creates a shallow copy of the given object `obj`.
|
|
4121
|
+
*
|
|
4122
|
+
* This function performs a shallow copy, meaning instance variables are copied,
|
|
4123
|
+
* but the objects they refer to are not duplicated. Unlike `mrb_obj_clone`,
|
|
4124
|
+
* `mrb_obj_dup` does *not* copy the frozen state of the original object; the
|
|
4125
|
+
* duplicated object is always unfrozen. Also, it does not copy the singleton class.
|
|
4126
|
+
* After the new object is created and its basic state is copied, its
|
|
4127
|
+
* `initialize_copy` method is called with the original object as an argument.
|
|
4128
|
+
*
|
|
4129
|
+
* @param mrb The mruby state.
|
|
4130
|
+
* @param obj The `mrb_value` object to duplicate.
|
|
4131
|
+
* @return A new `mrb_value` which is a duplicate of `obj`.
|
|
4132
|
+
* @raise TypeError if `obj` is an immediate value (e.g., Fixnum, Symbol in some
|
|
4133
|
+
* configurations) or if `obj` is a singleton class itself, as these
|
|
4134
|
+
* cannot be duplicated.
|
|
4135
|
+
* @sideeffect
|
|
4136
|
+
* 1. Allocates a new object on the mruby heap with the same class as `obj`.
|
|
4137
|
+
* 2. Copies instance variables from `obj` to the new object.
|
|
4138
|
+
* 3. The new object is *not* frozen, regardless of `obj`'s frozen state.
|
|
4139
|
+
* 4. The singleton class of `obj` (if any) is *not* copied.
|
|
4140
|
+
* 5. Calls the `initialize_copy` method on the newly created duplicate, passing `obj`
|
|
4141
|
+
* as an argument. This method can have arbitrary side effects.
|
|
4142
|
+
*/
|
|
4143
|
+
MRB_API mrb_value
|
|
4144
|
+
mrb_obj_dup(mrb_state *mrb, mrb_value obj)
|
|
4145
|
+
{
|
|
4146
|
+
if (mrb_immediate_p(obj)) {
|
|
4147
|
+
return obj;
|
|
4148
|
+
}
|
|
4149
|
+
if (mrb_sclass_p(obj)) {
|
|
4150
|
+
mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4153
|
+
struct RBasic *p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
|
|
4154
|
+
mrb_value dup = mrb_obj_value(p);
|
|
4155
|
+
init_copy(mrb, dup, obj);
|
|
4156
|
+
|
|
4157
|
+
return dup;
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4160
|
+
/* implementation of __id__ */
|
|
4161
|
+
mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self);
|
|
4162
|
+
|
|
4163
|
+
mrb_noreturn void
|
|
4164
|
+
mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
|
|
4165
|
+
{
|
|
4166
|
+
mrb_no_method_error(mrb, name, args, "undefined method '%n' for %T", name, self);
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
/* 15.3.1.3.30 */
|
|
4170
|
+
/*
|
|
4171
|
+
* call-seq:
|
|
4172
|
+
* obj.method_missing(symbol [, *args] ) -> result
|
|
4173
|
+
*
|
|
4174
|
+
* Invoked by Ruby when *obj* is sent a message it cannot handle.
|
|
4175
|
+
* *symbol* is the symbol for the method called, and *args*
|
|
4176
|
+
* are any arguments that were passed to it. By default, the interpreter
|
|
4177
|
+
* raises an error when this method is called. However, it is possible
|
|
4178
|
+
* to override the method to provide more dynamic behavior.
|
|
4179
|
+
* If it is decided that a particular method should not be handled, then
|
|
4180
|
+
* *super* should be called, so that ancestors can pick up the
|
|
4181
|
+
* missing method.
|
|
4182
|
+
* The example below creates
|
|
4183
|
+
* a class `Roman`, which responds to methods with names
|
|
4184
|
+
* consisting of roman numerals, returning the corresponding integer
|
|
4185
|
+
* values.
|
|
4186
|
+
*
|
|
4187
|
+
* class Roman
|
|
4188
|
+
* def romanToInt(str)
|
|
4189
|
+
* # ...
|
|
4190
|
+
* end
|
|
4191
|
+
* def method_missing(sym)
|
|
4192
|
+
* str = sym.to_s
|
|
4193
|
+
* romanToInt(str)
|
|
4194
|
+
* end
|
|
4195
|
+
* end
|
|
4196
|
+
*
|
|
4197
|
+
* r = Roman.new
|
|
4198
|
+
* r.iv #=> 4
|
|
4199
|
+
* r.xxiii #=> 23
|
|
4200
|
+
* r.mm #=> 2000
|
|
4201
|
+
*/
|
|
4202
|
+
mrb_value
|
|
4203
|
+
mrb_obj_missing(mrb_state *mrb, mrb_value mod)
|
|
4204
|
+
{
|
|
4205
|
+
mrb_sym name;
|
|
4206
|
+
const mrb_value *a;
|
|
4207
|
+
mrb_int alen;
|
|
4208
|
+
|
|
4209
|
+
mrb->c->ci->mid = 0;
|
|
4210
|
+
mrb_get_args(mrb, "n*!", &name, &a, &alen);
|
|
4211
|
+
mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a));
|
|
4212
|
+
/* not reached */
|
|
4213
|
+
return mrb_nil_value();
|
|
4214
|
+
}
|
|
4215
|
+
|
|
4216
|
+
static mrb_value
|
|
4217
|
+
inspect_main(mrb_state *mrb, mrb_value mod)
|
|
4218
|
+
{
|
|
4219
|
+
return mrb_str_new_lit(mrb, "main");
|
|
4220
|
+
}
|
|
4221
|
+
|
|
4222
|
+
static const mrb_code new_iseq[] = {
|
|
4223
|
+
OP_ENTER, 0x0, 0x10, 0x3, // 000 OP_ENTER 0:0:1:0:0:1:1
|
|
4224
|
+
OP_SSEND, 4, 0, 0, // 004 OP_SSEND R4 :allocate n=0
|
|
4225
|
+
OP_MOVE, 0, 4, // 008 OP_MOVE R0 R4
|
|
4226
|
+
OP_MOVE, 4, 3, // 011 OP_MOVE R4 R3 ; &
|
|
4227
|
+
OP_MOVE, 3, 2, // 014 OP_MOVE R3 R2 ; **
|
|
4228
|
+
OP_MOVE, 2, 1, // 017 OP_MOVE R2 R1 ; *
|
|
4229
|
+
OP_SSENDB, 1, 1, 255, // 020 OP_SSENDB R1 :initialize n=*|nk=*
|
|
4230
|
+
OP_RETURN, 0 // 024 OP_RETURN R0
|
|
4231
|
+
};
|
|
4232
|
+
|
|
4233
|
+
MRB_PRESYM_DEFINE_VAR_AND_INITER(new_syms, 2, MRB_SYM(allocate), MRB_SYM(initialize))
|
|
4234
|
+
|
|
4235
|
+
static const mrb_irep new_irep = {
|
|
4236
|
+
4, 6, 0, MRB_IREP_STATIC,
|
|
4237
|
+
new_iseq, NULL, new_syms, NULL, NULL, NULL,
|
|
4238
|
+
sizeof(new_iseq), 0, 2, 0, 0,
|
|
4239
|
+
};
|
|
4240
|
+
|
|
4241
|
+
mrb_alignas(8)
|
|
4242
|
+
static const struct RProc new_proc = {
|
|
4243
|
+
NULL, MRB_TT_PROC, MRB_GC_RED, MRB_OBJ_IS_FROZEN, MRB_PROC_SCOPE | MRB_PROC_STRICT,
|
|
4244
|
+
{ &new_irep }, NULL, { NULL }
|
|
4245
|
+
};
|
|
4246
|
+
|
|
4247
|
+
static void
|
|
4248
|
+
init_class_new(mrb_state *mrb, struct RClass *cls)
|
|
4249
|
+
{
|
|
4250
|
+
mrb_method_t m;
|
|
4251
|
+
|
|
4252
|
+
MRB_PRESYM_INIT_SYMBOLS(mrb, new_syms);
|
|
4253
|
+
MRB_METHOD_FROM_PROC(m, &new_proc);
|
|
4254
|
+
mrb_define_method_raw(mrb, cls, MRB_SYM(new), m);
|
|
4255
|
+
}
|
|
4256
|
+
|
|
4257
|
+
static const mrb_code neq_iseq[] = {
|
|
4258
|
+
OP_ENTER, 0x4, 0, 0, // 000 OP_ENTER 1:0:0:0:0:0:0
|
|
4259
|
+
OP_EQ, 0, // 004 OP_EQ R0 (R1)
|
|
4260
|
+
OP_JMPNOT, 0, 0, 5, // 006 OP_JMPNOT R0 015
|
|
4261
|
+
OP_LOADFALSE, 0, // 010 OP_LOADFALSE R0 (false)
|
|
4262
|
+
OP_JMP, 0, 2, // 012 OP_JMP 017
|
|
4263
|
+
OP_LOADTRUE, 0, // 015 OP_LOADTRUE R0 (true)
|
|
4264
|
+
OP_RETURN, 0 // 017 OP_RETURN R0
|
|
4265
|
+
};
|
|
4266
|
+
|
|
4267
|
+
static const mrb_irep neq_irep = {
|
|
4268
|
+
4, 6, 0, MRB_IREP_STATIC,
|
|
4269
|
+
neq_iseq, NULL, NULL, NULL, NULL, NULL,
|
|
4270
|
+
sizeof(neq_iseq), 0, 2, 0, 0,
|
|
4271
|
+
};
|
|
4272
|
+
|
|
4273
|
+
mrb_alignas(8)
|
|
4274
|
+
static const struct RProc neq_proc = {
|
|
4275
|
+
NULL, MRB_TT_PROC, MRB_GC_RED, MRB_OBJ_IS_FROZEN, MRB_PROC_SCOPE | MRB_PROC_STRICT,
|
|
4276
|
+
{ &neq_irep }, NULL, { NULL }
|
|
4277
|
+
};
|
|
4278
|
+
|
|
4279
|
+
/* ---------------------------*/
|
|
4280
|
+
static const mrb_mt_entry bob_rom_entries[] = {
|
|
4281
|
+
MRB_MT_ENTRY(mrb_obj_equal_m, MRB_OPSYM(eq), MRB_ARGS_REQ(1)), /* 15.3.1.3.1 */
|
|
4282
|
+
MRB_MT_ENTRY(mrb_bob_not, MRB_OPSYM(not), MRB_ARGS_NONE()),
|
|
4283
|
+
MRB_MT_ENTRY(mrb_obj_id_m, MRB_SYM(__id__), MRB_ARGS_NONE()), /* 15.3.1.3.4 */
|
|
4284
|
+
MRB_MT_ENTRY(mrb_f_send, MRB_SYM(__send__), MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()), /* 15.3.1.3.5 */
|
|
4285
|
+
MRB_MT_ENTRY(mrb_obj_equal_m, MRB_SYM_Q(equal), MRB_ARGS_REQ(1)), /* 15.3.1.3.11 */
|
|
4286
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(initialize), MRB_ARGS_NONE() | MRB_MT_PRIVATE),
|
|
4287
|
+
MRB_MT_ENTRY(mrb_obj_instance_eval, MRB_SYM(instance_eval), MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()), /* 15.3.1.3.18 */
|
|
4288
|
+
MRB_MT_ENTRY(mrb_obj_missing, MRB_SYM(method_missing), MRB_ARGS_ANY() | MRB_MT_PRIVATE), /* 15.3.1.3.30 */
|
|
4289
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(singleton_method_added), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4290
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(singleton_method_removed), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4291
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(singleton_method_undefined), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4292
|
+
};
|
|
4293
|
+
|
|
4294
|
+
static const mrb_mt_entry cls_rom_entries[] = {
|
|
4295
|
+
MRB_MT_ENTRY(mrb_instance_alloc, MRB_SYM(allocate), MRB_ARGS_NONE()),
|
|
4296
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(inherited), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4297
|
+
MRB_MT_ENTRY(mrb_class_initialize, MRB_SYM(initialize), MRB_ARGS_OPT(1) | MRB_MT_PRIVATE), /* 15.2.3.3.1 */
|
|
4298
|
+
MRB_MT_ENTRY(mrb_class_superclass, MRB_SYM(superclass), MRB_ARGS_NONE()), /* 15.2.3.3.4 */
|
|
4299
|
+
};
|
|
4300
|
+
|
|
4301
|
+
static const mrb_mt_entry mod_rom_entries[] = {
|
|
4302
|
+
MRB_MT_ENTRY(mrb_mod_eqq, MRB_OPSYM(eqq), MRB_ARGS_REQ(1)), /* 15.2.2.4.7 */
|
|
4303
|
+
MRB_MT_ENTRY(mrb_mod_alias, MRB_SYM(alias_method), MRB_ARGS_ANY()), /* 15.2.2.4.8 */
|
|
4304
|
+
MRB_MT_ENTRY(mrb_mod_ancestors, MRB_SYM(ancestors), MRB_ARGS_NONE()), /* 15.2.2.4.9 */
|
|
4305
|
+
MRB_MT_ENTRY(mrb_mod_attr_accessor, MRB_SYM(attr_accessor), MRB_ARGS_ANY()), /* 15.2.2.4.12 */
|
|
4306
|
+
MRB_MT_ENTRY(mrb_mod_attr_reader, MRB_SYM(attr_reader), MRB_ARGS_ANY()), /* 15.2.2.4.13 */
|
|
4307
|
+
MRB_MT_ENTRY(mrb_mod_attr_writer, MRB_SYM(attr_writer), MRB_ARGS_ANY()), /* 15.2.2.4.14 */
|
|
4308
|
+
MRB_MT_ENTRY(mrb_mod_module_eval, MRB_SYM(class_eval), MRB_ARGS_ANY()), /* 15.2.2.4.15 */
|
|
4309
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(const_added), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4310
|
+
MRB_MT_ENTRY(mrb_mod_const_defined, MRB_SYM_Q(const_defined), MRB_ARGS_ARG(1,1)), /* 15.2.2.4.20 */
|
|
4311
|
+
MRB_MT_ENTRY(mrb_mod_const_get, MRB_SYM(const_get), MRB_ARGS_REQ(1)), /* 15.2.2.4.21 */
|
|
4312
|
+
MRB_MT_ENTRY(mrb_mod_const_missing, MRB_SYM(const_missing), MRB_ARGS_REQ(1)),
|
|
4313
|
+
MRB_MT_ENTRY(mrb_mod_const_set, MRB_SYM(const_set), MRB_ARGS_REQ(2)), /* 15.2.2.4.23 */
|
|
4314
|
+
MRB_MT_ENTRY(mod_define_method, MRB_SYM(define_method), MRB_ARGS_ARG(1,1)),
|
|
4315
|
+
MRB_MT_ENTRY(mrb_mod_dup, MRB_SYM(dup), MRB_ARGS_NONE()),
|
|
4316
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(extended), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.2.4.26 */
|
|
4317
|
+
MRB_MT_ENTRY(mrb_mod_include, MRB_SYM(include), MRB_ARGS_ANY()), /* 15.2.2.4.27 */
|
|
4318
|
+
MRB_MT_ENTRY(mrb_mod_include_p, MRB_SYM_Q(include), MRB_ARGS_REQ(1)), /* 15.2.2.4.28 */
|
|
4319
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(included), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.2.4.29 */
|
|
4320
|
+
MRB_MT_ENTRY(mrb_mod_initialize, MRB_SYM(initialize), MRB_ARGS_NONE() | MRB_MT_PRIVATE), /* 15.2.2.4.31 */
|
|
4321
|
+
MRB_MT_ENTRY(mrb_mod_to_s, MRB_SYM(inspect), MRB_ARGS_NONE()),
|
|
4322
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(method_added), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4323
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(method_removed), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4324
|
+
MRB_MT_ENTRY(mrb_mod_method_defined, MRB_SYM_Q(method_defined), MRB_ARGS_REQ(1)), /* 15.2.2.4.34 */
|
|
4325
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(method_undefined), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4326
|
+
MRB_MT_ENTRY(mrb_mod_module_eval, MRB_SYM(module_eval), MRB_ARGS_ANY()), /* 15.2.2.4.35 */
|
|
4327
|
+
MRB_MT_ENTRY(mrb_mod_module_function, MRB_SYM(module_function), MRB_ARGS_ANY() | MRB_MT_PRIVATE),
|
|
4328
|
+
MRB_MT_ENTRY(mrb_mod_prepend, MRB_SYM(prepend), MRB_ARGS_ANY()),
|
|
4329
|
+
MRB_MT_ENTRY(mrb_do_nothing, MRB_SYM(prepended), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
|
|
4330
|
+
MRB_MT_ENTRY(mrb_mod_private, MRB_SYM(private), MRB_ARGS_ANY() | MRB_MT_PRIVATE), /* 15.2.2.4.36 */
|
|
4331
|
+
MRB_MT_ENTRY(mrb_mod_protected, MRB_SYM(protected), MRB_ARGS_ANY() | MRB_MT_PRIVATE), /* 15.2.2.4.37 */
|
|
4332
|
+
MRB_MT_ENTRY(mrb_mod_public, MRB_SYM(public), MRB_ARGS_ANY() | MRB_MT_PRIVATE), /* 15.2.2.4.38 */
|
|
4333
|
+
MRB_MT_ENTRY(mrb_mod_remove_const, MRB_SYM(remove_const), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.2.4.40 */
|
|
4334
|
+
MRB_MT_ENTRY(mrb_mod_to_s, MRB_SYM(to_s), MRB_ARGS_NONE()),
|
|
4335
|
+
MRB_MT_ENTRY(mrb_mod_undef, MRB_SYM(undef_method), MRB_ARGS_ANY()), /* 15.2.2.4.41 */
|
|
4336
|
+
};
|
|
4337
|
+
|
|
4338
|
+
void
|
|
4339
|
+
mrb_init_class(mrb_state *mrb)
|
|
4340
|
+
{
|
|
4341
|
+
struct RClass *bob; /* BasicObject */
|
|
4342
|
+
struct RClass *obj; /* Object */
|
|
4343
|
+
struct RClass *mod; /* Module */
|
|
4344
|
+
struct RClass *cls; /* Class */
|
|
4345
|
+
|
|
4346
|
+
/* boot class hierarchy */
|
|
4347
|
+
bob = boot_defclass(mrb, 0, MRB_TT_OBJECT);
|
|
4348
|
+
obj = boot_defclass(mrb, bob, MRB_TT_OBJECT); mrb->object_class = obj;
|
|
4349
|
+
mod = boot_defclass(mrb, obj, MRB_TT_MODULE); mrb->module_class = mod;/* obj -> mod */
|
|
4350
|
+
cls = boot_defclass(mrb, mod, MRB_TT_CLASS); mrb->class_class = cls; /* obj -> cls */
|
|
4351
|
+
|
|
4352
|
+
/* fix-up loose ends */
|
|
4353
|
+
bob->c = obj->c = mod->c = cls->c = cls;
|
|
4354
|
+
make_metaclass(mrb, bob);
|
|
4355
|
+
make_metaclass(mrb, obj);
|
|
4356
|
+
make_metaclass(mrb, mod);
|
|
4357
|
+
make_metaclass(mrb, cls);
|
|
4358
|
+
|
|
4359
|
+
/* name basic classes */
|
|
4360
|
+
mrb_define_const_id(mrb, bob, MRB_SYM(BasicObject), mrb_obj_value(bob));
|
|
4361
|
+
mrb_define_const_id(mrb, obj, MRB_SYM(Object), mrb_obj_value(obj));
|
|
4362
|
+
mrb_define_const_id(mrb, obj, MRB_SYM(Module), mrb_obj_value(mod));
|
|
4363
|
+
mrb_define_const_id(mrb, obj, MRB_SYM(Class), mrb_obj_value(cls));
|
|
4364
|
+
|
|
4365
|
+
/* name each classes */
|
|
4366
|
+
mrb_class_name_class(mrb, NULL, bob, MRB_SYM(BasicObject));
|
|
4367
|
+
mrb_class_name_class(mrb, NULL, obj, MRB_SYM(Object)); /* 15.2.1 */
|
|
4368
|
+
mrb_class_name_class(mrb, NULL, mod, MRB_SYM(Module)); /* 15.2.2 */
|
|
4369
|
+
mrb_class_name_class(mrb, NULL, cls, MRB_SYM(Class)); /* 15.2.3 */
|
|
4370
|
+
|
|
4371
|
+
MRB_MT_INIT_ROM(mrb, bob, bob_rom_entries);
|
|
4372
|
+
|
|
4373
|
+
mrb_method_t m;
|
|
4374
|
+
MRB_METHOD_FROM_PROC(m, &neq_proc);
|
|
4375
|
+
mrb_define_method_raw(mrb, bob, MRB_OPSYM(neq), m);
|
|
4376
|
+
|
|
4377
|
+
mrb_define_class_method_id(mrb, cls, MRB_SYM(new), mrb_class_new_class, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK());
|
|
4378
|
+
MRB_MT_INIT_ROM(mrb, cls, cls_rom_entries);
|
|
4379
|
+
|
|
4380
|
+
init_class_new(mrb, cls);
|
|
4381
|
+
|
|
4382
|
+
MRB_MT_INIT_ROM(mrb, mod, mod_rom_entries);
|
|
4383
|
+
mrb_define_alias_id(mrb, mod, MRB_SYM(attr), MRB_SYM(attr_reader)); /* 15.2.2.4.11 */
|
|
4384
|
+
|
|
4385
|
+
mrb_undef_method_id(mrb, cls, MRB_SYM(module_function));
|
|
4386
|
+
|
|
4387
|
+
mrb->top_self = MRB_OBJ_ALLOC(mrb, MRB_TT_OBJECT, mrb->object_class);
|
|
4388
|
+
mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(inspect), inspect_main, MRB_ARGS_NONE());
|
|
4389
|
+
mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(to_s), inspect_main, MRB_ARGS_NONE());
|
|
4390
|
+
mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(define_method), top_define_method, MRB_ARGS_ARG(1,1));
|
|
4391
|
+
mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(public), top_public, MRB_ARGS_ANY());
|
|
4392
|
+
mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(private), top_private, MRB_ARGS_ANY());
|
|
4393
|
+
mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(protected), top_protected, MRB_ARGS_ANY());
|
|
4394
|
+
}
|