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