Compare commits

...

360 Commits

Author SHA1 Message Date
google-labs-jules[bot] 71e8dbcd97 Refactor str_succ_bang for in-place modification
This commit refactors the str_succ_bang function in mrbgems/mruby-string-ext/src/string.c to perform string succession in-place.

The previous implementation used an intermediate temporary string, which incurred memory and performance overhead.
This change aims to reduce memory usage and improve performance by modifying the string buffer directly, using mrb_str_resize and memmove when prepending characters is necessary (e.g., '9' -> '10').

Formatting changes (newlines before 'else') have also been applied as per user request.
2025-06-23 09:23:54 +00:00
Yukihiro "Matz" Matsumoto 791b374155 khash.h: reduce KHASH_DEFAULT_SIZE from 32 to 8 2025-06-23 17:07:31 +09:00
Yukihiro "Matz" Matsumoto c152f3a79a mruby-set: add comprehensive tests for Set operations: +, -, & 2025-06-23 17:07:31 +09:00
Yukihiro "Matz" Matsumoto 18b45c7ab5 mruby-set: change string representation from #<Set: {1}> to Set[1] 2025-06-23 17:07:31 +09:00
Yukihiro "Matz" Matsumoto 561a3eac82 mruby-set: make eql? an alias of == method 2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto 20b32531ea mruby-set: Fix memory leak in Set#flatten! and simplify implementation
- Remove circular reference check in favor of max depth check only
- Fix memory leak by properly handling errors in set_flatten_bang
- Simplify code by reducing variables and unifying error handling
2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto 9d739cdad8 mruby-set: use set_is_set extensively 2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto f47609574a mruby-set: remove some AI generated work-log comments 2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto ea0ceff7fb mruby-set: implement Set#flatten and flatten! in C
The code is generated by Cursor.
2025-06-23 17:07:30 +09:00
Yukihiro "Matz" Matsumoto 73c61e4a60 mruby-set: optimize inspect/to_s to avoid intermediate array 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto e2982bdb57 mruby-set: optimize join method to avoid intermediate array 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto 0430f1e9b8 mruby-set: optimize eql? by checking fast path 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto d7a0d5687e mruby-set: optimize equal by checking fast path 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto 83fc43e71d mruby-set: improve Set#hash by using FNV-1 hashing 2025-06-23 17:07:29 +09:00
Yukihiro "Matz" Matsumoto 3a5d0a1840 mruby-set: simplify the code with KHASH_FOREACH macro 2025-06-23 17:07:28 +09:00
Yukihiro "Matz" Matsumoto eb1820d75e symbol.c: remove unused <mruby/khash.h> header 2025-06-23 17:07:28 +09:00
Yukihiro "Matz" Matsumoto e30ec3da42 mruby-metaprog: use KHASH_FOREACH macro 2025-06-23 17:07:28 +09:00
Yukihiro "Matz" Matsumoto bce8cee8f9 khash.h (KHASH_FOREACH): a new macro to iterate over khash table 2025-06-23 17:07:28 +09:00
Yukihiro "Matz" Matsumoto d41d477e22 mruby-set: add type checking helper functions
Add two helper functions to improve code clarity and maintainability:
- set_check_type: Checks if a value is a Set and raises an error if not
- set_is_set: Checks if a value is a Set and returns a boolean result

Update all relevant methods to use these helper functions, reducing
code duplication and centralizing type checking logic.
2025-06-23 17:07:27 +09:00
Yukihiro "Matz" Matsumoto deb5c47fc6 mruby-set: implement comparison methods in C for better performance
Reimplemented the following methods in C for improved efficiency:
- superset? and proper_superset? (>= and >)
- subset? and proper_subset? (<= and <)
- intersect? and disjoint?
- <=> comparison operator
2025-06-23 17:07:27 +09:00
Yukihiro "Matz" Matsumoto 60f06e7a0f mruby-set: Add comprehensive method documentation 2025-06-23 17:07:27 +09:00
Yukihiro "Matz" Matsumoto 091e48159a mruby-set: Use numbered parameters for block arguments 2025-06-23 17:07:27 +09:00
Yukihiro "Matz" Matsumoto 04b38c2c47 mruby-set: rename internal methods
Renaming all internal C methods from __set_* to a cleaner __* convention
(e.g., __set_merge is now __merge), and updating their call sites in the
Ruby code accordingly.
2025-06-23 17:07:26 +09:00
Yukihiro "Matz" Matsumoto e096eeed1a mruby-set: reimplement #initialize in Ruby again
And we have eliminated mrb_funcall* from set.c.
2025-06-23 17:07:26 +09:00
Yukihiro "Matz" Matsumoto 5e2a7568e2 mruby-set: move #replace to Ruby again
Since it does only clear() and merge(), there is little use of the C
implemented fast path. This change also reduce memory consumption.
2025-06-23 17:07:26 +09:00
Yukihiro "Matz" Matsumoto 100ba913f2 mruby-set: extensive refactor in set.c
We refactor out loop by set_khash_foreach() function, so that we don't
need to repeat for loop. it makes the code simpler. The code is written
by Atlassian Rovodev.
2025-06-23 17:07:26 +09:00
Yukihiro "Matz" Matsumoto f210772465 mruby-set: optimize Set operations to use mrb_get_arg1()
Replace mrb_get_args() with more efficient mrb_get_arg1() for
single-argument functions. The code is written by Atlassian Rovodev.
2025-06-23 17:07:26 +09:00
Yukihiro "Matz" Matsumoto c117674cfe mruby-set: refactor Set#replace
The code is written by Atlassian Rovodev.
2025-06-23 17:07:25 +09:00
Yukihiro "Matz" Matsumoto 8538c79f3f mruby-set: refactor Set#merge
The code is written by Atlassian Rovodev.
2025-06-23 17:07:25 +09:00
Yukihiro "Matz" Matsumoto 169654ad9b mruby-set: refactor Set#subtract
The code is written by Atlassian Rovodev.
2025-06-23 17:07:25 +09:00
Yukihiro "Matz" Matsumoto c188b9a1aa mruby-set: refactor Set#difference
The code is written by Atlassian Rovodev.
2025-06-23 17:07:25 +09:00
Yukihiro "Matz" Matsumoto 10ea05d3aa mruby-set: refactor Set#union (+, |)
The code is written by Atlassian Rovodev.
2025-06-23 17:07:24 +09:00
Yukihiro "Matz" Matsumoto d9f0c5a3a4 mruby-set: refactor Set#xor (^)
According to the similar strategy as Set#intersection.
The code is mostly written by Atlassian Rovodev.
2025-06-23 17:07:24 +09:00
Yukihiro "Matz" Matsumoto 56a41b844e mruby-set: refactor Set#intersection
Define generic operation method in Ruby, then prepare fast-path function
in C as a general structure. Some methods will follow this pattern.
The code is generated by Atlassian Rovodev.
2025-06-23 17:07:24 +09:00
Yukihiro "Matz" Matsumoto 4ae3068b2a mruby-set: replace mrb_funcall_id() by set_to_a() 2025-06-23 17:07:24 +09:00
Yukihiro "Matz" Matsumoto 73a1eb03e8 mruby-set: remove mrb_funcall_id() from set_join() 2025-06-23 17:07:24 +09:00
Yukihiro "Matz" Matsumoto abae5a5ff5 mruby-set: remove __equal_fallback that no longer used 2025-06-23 17:07:23 +09:00
Yukihiro "Matz" Matsumoto a2339a7fde mruby-set: refactor set_equal() function
Made not to use mrb_funcall() as well.
2025-06-23 17:07:23 +09:00
Yukihiro "Matz" Matsumoto 72b51c4e92 mruby-set: I prefer newline before else keyword 2025-06-23 17:07:23 +09:00
Yukihiro "Matz" Matsumoto 655981c6ed mruby-set: remove unused object allocation
AI added this allocation to avoid memory leaks, but actually this extra
allocation does nothing useful. We see more room for AI improvement.
2025-06-23 17:07:23 +09:00
Yukihiro "Matz" Matsumoto e4ed04ba8b mruby-set (set_init): adjust a local variable declaration 2025-06-23 17:07:23 +09:00
Yukihiro "Matz" Matsumoto 52285161e7 mruby-set: remove methods added by AI hallucination 2025-06-23 17:07:22 +09:00
Yukihiro "Matz" Matsumoto 1238fb2808 mruby-set (flatten_merge): remove unnecessary assignment 2025-06-23 17:07:22 +09:00
Yukihiro "Matz" Matsumoto f44a7bc5db mruby-set: remove statistic measurement code 2025-06-23 17:07:22 +09:00
Yukihiro "Matz" Matsumoto 7a1732d438 mruby-set: make #initialize_copy private 2025-06-23 17:07:22 +09:00
Yukihiro "Matz" Matsumoto 11106525c4 mruby-set (__get_hash): remove no longer used method 2025-06-23 17:07:22 +09:00
Yukihiro "Matz" Matsumoto 7ffe6a3a9a mruby-set: re-implement Set class in C
The code is mostly developed by Atlassian Rovodev.
2025-06-23 17:07:21 +09:00
Yukihiro "Matz" Matsumoto e87bd7fcc1 mruby-set: update README.md
The document is written by Google Jules.
2025-06-23 17:07:21 +09:00
Yukihiro "Matz" Matsumoto 695207be68 hash.c (mrb_obj_hash_code): expose hash function 2025-06-23 17:07:21 +09:00
Yukihiro "Matz" Matsumoto d73e337442 mruby-bigint: update README.md
The document is written by Google Jules.
2025-06-23 17:07:20 +09:00
Yukihiro "Matz" Matsumoto 4cd7f523fb Merge pull request #6555 from dearblue/mt_foreach 2025-06-21 06:33:35 +09:00
Yukihiro "Matz" Matsumoto e2e2b5d35b Merge pull request #6556 from dearblue/iv_foreach 2025-06-21 06:33:18 +09:00
dearblue 5931aeb825 mrb_mt_foreach() needs to update the pointer at each loop
When calling a user function, a pointer retrieved outside of a loop may be invalidated.
2025-06-19 22:35:09 +09:00
dearblue afd5805224 iv_foreach() needs to update the pointer at each loop
When calling a user function, a pointer retrieved outside of a loop may be invalidated.
2025-06-19 22:25:13 +09:00
Yukihiro "Matz" Matsumoto 2edfd96cbe mruby-rational: add README.md
The document is written by Google Jules.
2025-06-17 16:22:19 +09:00
Yukihiro "Matz" Matsumoto ef1cdbc0c7 mruby-complex: add README.md
The document is written by Google Jules.
2025-06-17 16:19:44 +09:00
Yukihiro "Matz" Matsumoto 67dbaf856f mruby-pack: add README.md
The document is written by Google Jules.
2025-06-16 12:45:18 +09:00
Yukihiro "Matz" Matsumoto 0fc6288ae2 mruby-binding: make Binding#initialize_copy private 2025-06-16 12:44:06 +09:00
Yukihiro "Matz" Matsumoto 085adaf408 mruby-date: make Data#initialize_copy private 2025-06-16 12:43:34 +09:00
Yukihiro "Matz" Matsumoto 783bc526e4 mruby-enumerator: make Enumerator#initialize_copy private 2025-06-16 12:42:56 +09:00
Yukihiro "Matz" Matsumoto 35fafe57fb mruby-io: make IO#initialize_copy private 2025-06-16 12:42:22 +09:00
Yukihiro "Matz" Matsumoto 10c40c4e87 mruby-set: make Set#initialize_copy private 2025-06-16 12:41:54 +09:00
Yukihiro "Matz" Matsumoto 0a306b81ed mruby-struct: make Struct#initialize_copy private 2025-06-16 12:41:19 +09:00
Yukihiro "Matz" Matsumoto d015d91c12 mruby-time: make Time#initialize_copy private 2025-06-16 12:40:29 +09:00
Yukihiro "Matz" Matsumoto 262d3715f5 proc.c: make Proc#initialize_copy private 2025-06-15 14:14:24 +09:00
Yukihiro "Matz" Matsumoto 8cb427b75c hash.c: make Hash#initialize_copy private 2025-06-15 14:13:56 +09:00
Yukihiro "Matz" Matsumoto a25a896caf range.c: make Range#initialize_copy private 2025-06-15 14:12:58 +09:00
Yukihiro "Matz" Matsumoto 65369ca1e6 array.c: make Array#initialize_copy private 2025-06-15 14:12:12 +09:00
Yukihiro "Matz" Matsumoto ff2464e879 string.c: make String#initialize_copy private 2025-06-15 14:11:54 +09:00
Yukihiro "Matz" Matsumoto f7813268d6 mruby-socket: inline #_new_with_prelude that is only called once. 2025-06-14 13:39:12 +09:00
Yukihiro "Matz" Matsumoto ebd9f29b38 The method #initialize_copy should be private, no direct call
Fixed test/t/array.rb and test/t/string.rb in standard tests.
And mrbgems/mruby-struct/test/struct.rb as well.
2025-06-14 13:38:22 +09:00
Yukihiro "Matz" Matsumoto bf0f37833d mruby-socket: fixed raising RuntimeError from #accept; #6554
In mruby, bare `raise` in rescue clause does not re-raise the last
exception. You should explicitly specify the exception.
2025-06-14 01:56:43 +09:00
Yukihiro "Matz" Matsumoto 12c124e1d4 mruby-time: add README.md
The document is written by Google Jules.
2025-06-14 01:06:55 +09:00
Yukihiro "Matz" Matsumoto ac8d5c6ae6 mruby-sprintf: add README.md
The document is written by Google Jules.
2025-06-14 01:04:23 +09:00
Yukihiro "Matz" Matsumoto 1b189bc1a2 mruby-random: add README.md
The document is written by Google Jules.
2025-06-14 01:02:52 +09:00
Yukihiro "Matz" Matsumoto 8ef1d1e104 mruby-enum-lazy: add README.md
The document is written by Google Jules.
2025-06-13 04:45:48 +09:00
Yukihiro "Matz" Matsumoto 74f46a05fd mruby-enum-chain: add README.md
The document is written by Google Jules.
2025-06-13 04:42:17 +09:00
Yukihiro "Matz" Matsumoto 6b64447f0e mruby-enumerator: add README.md
The document is written by Google Jules.
2025-06-13 04:40:29 +09:00
Yukihiro "Matz" Matsumoto 04b769b5ca mruby-os-memsize: add README.md
The document is written by Google Jules.
2025-06-12 21:29:20 +09:00
Yukihiro "Matz" Matsumoto 91ec6ea9cc mruby-objectspace: add REAME.md
The document is written by Google Jules.
2025-06-12 21:28:42 +09:00
Yukihiro "Matz" Matsumoto 0b52b33597 mruby-proc-binding: add README.md
The document is written by Google Jules.
2025-06-11 18:38:14 +09:00
Yukihiro "Matz" Matsumoto 18f65c6652 mruby-method: update README.md
Updated document is written by Google Jules.
2025-06-11 18:35:59 +09:00
Yukihiro "Matz" Matsumoto 84c308aedc mruby-metaprog: add README.md
The document is written by Google Jules.
2025-06-11 18:33:35 +09:00
Yukihiro "Matz" Matsumoto 0a45941337 mruby-eval: add README.md
The document is written by Google Jules.
2025-06-11 18:31:52 +09:00
Yukihiro "Matz" Matsumoto b5197c22f6 mruby-socket: should not directly call private #initialize; fix #6554 2025-06-10 14:28:26 +09:00
Yukihiro "Matz" Matsumoto 2f00046758 mruby-toplevel-ext: add README.md
The document is written by Google Jules.
2025-06-10 11:28:18 +09:00
Yukihiro "Matz" Matsumoto 3a27a868a1 mruby-symbol-ext: add README.md
The document is written by Google Jules.
2025-06-10 11:25:45 +09:00
Yukihiro "Matz" Matsumoto 4e711fe0ef mruby-string-ext: add README.md
The document is written by Google Jules.
2025-06-10 11:23:50 +09:00
Yukihiro "Matz" Matsumoto 396a85de9a mruby-range-ext: add README.md
The document is written by Google Jules.
2025-06-10 11:09:16 +09:00
Yukihiro "Matz" Matsumoto 59902a94ab mruby-proc-ext: add README.md
The document is written by Google Jules.
2025-06-10 11:07:16 +09:00
Yukihiro "Matz" Matsumoto 3814cbc539 mruby-object-ext: add README.md
The document is written by Google Jules.
2025-06-10 11:03:19 +09:00
Yukihiro "Matz" Matsumoto 5e5b4445ff mruby-numeric-ext: add README.md
The document is written by Google Jules.
2025-06-10 10:58:22 +09:00
Yukihiro "Matz" Matsumoto 97ad019707 mruby-kernel-ext: add README.md
The document is written by Google Jules.
2025-06-10 10:56:01 +09:00
Yukihiro "Matz" Matsumoto 8fbe5523cf mruby-hash-ext: add README.md
The document is written by Google Jules.
2025-06-10 10:53:57 +09:00
Yukihiro "Matz" Matsumoto 470c1dc184 mruby-errno: add README.md
The document is written by Google Jules.
2025-06-09 17:14:02 +09:00
Yukihiro "Matz" Matsumoto 813dc8eae5 mruby-error: add README.md
The document is written by Google Jules.
2025-06-09 17:13:20 +09:00
Yukihiro "Matz" Matsumoto 5cdd394c6d mruby-encoding: add README.md
The document is written by Google Jules.
2025-06-09 17:11:46 +09:00
Yukihiro "Matz" Matsumoto 6509f52642 mruby-struct: add README.md
The document is written by Google Jules.
2025-06-09 11:01:48 +09:00
Yukihiro "Matz" Matsumoto acf3656e49 mruby-data: add README.md
The document is written by Google Jules.
2025-06-09 11:01:05 +09:00
Yukihiro "Matz" Matsumoto 1beecb9670 mruby-cmath: add README.md
The document is written by Google Jules.
2025-06-08 17:04:05 +09:00
Yukihiro "Matz" Matsumoto d7f7ea0d82 mruby-math: add README.md
The document is written by Google Jules.
2025-06-08 17:02:55 +09:00
Yukihiro "Matz" Matsumoto 6bcee69c9c mruby-catch: add README.md
The document is written by Google Jules.
2025-06-08 17:00:07 +09:00
Yukihiro "Matz" Matsumoto 5731fbf17c mruby-binding: add README.md
The document is written by Google Jules.
2025-06-08 16:59:25 +09:00
Yukihiro "Matz" Matsumoto f835b86d10 mruby-enum-ext: add README.md
The document is written by Google Jules.
2025-06-07 11:53:04 +09:00
Yukihiro "Matz" Matsumoto 50945bec68 mruby-compar-ext: add README.md
The document is written by Google Jules.
2025-06-07 11:50:53 +09:00
Yukihiro "Matz" Matsumoto 5cc5a8a9c3 mruby-class-ext: add README.md
The document is written by Google Jules.
2025-06-07 11:48:40 +09:00
Yukihiro "Matz" Matsumoto c7ffb0cc55 mruby-array-ext: add README.md
The document is written by Google Jules.
2025-06-07 11:46:11 +09:00
Yukihiro "Matz" Matsumoto 35d073a986 vm.c: fix unintended argument renaming by Google Jules; #6533 2025-06-06 11:53:14 +09:00
Yukihiro "Matz" Matsumoto 2b75da7335 Merge pull request #6553 from mruby/add-vm-comments 2025-06-06 08:15:41 +09:00
google-labs-jules[bot] da9365f98e Add descriptive comments for MRB_API functions in src/vm.c
This commit adds Doxygen-style comments to several MRB_API functions
in src/vm.c to improve code readability and documentation.

The following functions were commented:
- mrb_stack_extend
- mrb_protect_error
- mrb_funcall
- mrb_funcall_id
- mrb_funcall_with_block
- mrb_funcall_argv
- mrb_yield_with_class
- mrb_yield_argv
- mrb_yield
- mrb_vm_run
- mrb_vm_exec
- mrb_top_run

Additionally, the parameter name 'self' in mrb_yield_with_class was
renamed to 'self_obj' for better clarity and consistency with the new comment.
2025-06-05 23:14:43 +00:00
Yukihiro "Matz" Matsumoto e55b3f0c55 Merge pull request #6552 from mruby/fix-comments-variable-c 2025-06-06 08:14:17 +09:00
google-labs-jules[bot] b4826fdbcf Fix: Correct placement of comments in src/variable.c
This commit corrects the placement of C-style block comments
for MRB_API functions in src/variable.c. Comments are now
placed directly before each function definition as per standard
documentation practices.
2025-06-05 23:13:42 +00:00
Yukihiro "Matz" Matsumoto 2f19fe1e36 Merge pull request #6551 from mruby/add-comments-state 2025-06-06 08:13:11 +09:00
google-labs-jules[bot] 19ddbdcf4b Add descriptive comments for MRB_API functions in src/state.c
This commit adds descriptive comments to the following MRB_API functions in src/state.c, clarifying their purpose and functionality:

- mrb_open_core
- mrb_open
- mrb_free_context
- mrb_close
- mrb_add_irep
- mrb_top_self
- mrb_state_atexit
2025-06-05 23:12:50 +00:00
Yukihiro "Matz" Matsumoto bdd379bc8c Merge pull request #6550 from mruby/add-comments-to-proc-c 2025-06-06 08:12:32 +09:00
google-labs-jules[bot] ddbbf3bd82 Add descriptive comments for MRB_API functions in src/proc.c
This commit adds Doxygen-style comments to the following MRB_API functions in src/proc.c:
- mrb_proc_new_cfunc
- mrb_proc_new_cfunc_with_env
- mrb_closure_new_cfunc
- mrb_proc_cfunc_env_get

The comments describe the purpose, parameters, and return value of each function.
2025-06-05 23:12:02 +00:00
Yukihiro "Matz" Matsumoto 64d390b9e0 numeric.c : add descriptive comments for public functions
- mrb_int_overflow
- mrb_int_zerodiv
- mrb_int_pow
- mrb_div_int
- mrb_div_int_value
- mrb_float_to_str
- mrb_check_num_exact
- mrb_int_mul
- mrb_num_shift
- mrb_float_to_integer
- mrb_int_add
- mrb_int_sub
- mrb_int_to_cstr
- mrb_integer_to_str
- mrb_cmp

The comments were written by Google Jules.
2025-06-06 08:11:37 +09:00
Yukihiro "Matz" Matsumoto d3f339062b Merge pull request #6549 from mruby/add-kernel-comments 2025-06-05 10:36:52 +09:00
google-labs-jules[bot] 1e3295d93e Add descriptive comments to kernel functions
This commit adds descriptive C-style comments to the following functions
in `src/kernel.c`:

- `mrb_func_basic_p`: Explains that the function checks if an object's method is implemented by a specific C function.
- `mrb_obj_freeze`: Explains that the function freezes an object, preventing further modifications.
- `mrb_obj_is_instance_of`: Explains that the function checks if an object is an instance of a given class.
2025-06-05 01:35:27 +00:00
Yukihiro "Matz" Matsumoto 24a84a5a37 Merge pull request #6548 from mruby/add-comments-etc 2025-06-05 10:34:17 +09:00
google-labs-jules[bot] 52d56fe443 Add descriptive comments to MRB_API functions in src/etc.c
This commit adds Doxygen-style comments to several MRB_API functions
in the `src/etc.c` file. These comments explain the purpose,
parameters, and return values of these functions, improving code
readability and maintainability.

The following functions were commented:
- mrb_data_object_alloc
- mrb_data_check_type
- mrb_data_check_get_ptr
- mrb_data_get_ptr
- mrb_obj_to_sym
- mrb_obj_id
- mrb_word_boxing_float_value
- mrb_word_boxing_value_float
- mrb_word_boxing_cptr_value
- mrb_boxing_int_value
2025-06-05 01:33:38 +00:00
Yukihiro "Matz" Matsumoto 576a104a77 Merge pull request #6546 from mruby/dependabot/github_actions/ls-lint/action-2.3.1 2025-06-05 10:18:26 +09:00
dependabot[bot] ad015f14a8 build(deps): bump ls-lint/action from 2.3.0 to 2.3.1
Bumps [ls-lint/action](https://github.com/ls-lint/action) from 2.3.0 to 2.3.1.
- [Commits](https://github.com/ls-lint/action/compare/v2.3.0...v2.3.1)

---
updated-dependencies:
- dependency-name: ls-lint/action
  dependency-version: 2.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-04 14:33:09 +00:00
Yukihiro "Matz" Matsumoto 1ff94c5e00 AUTHORS: update entries [ci skip] 2025-06-04 13:20:08 +09:00
Yukihiro "Matz" Matsumoto a3e72804cd range.c: add descriptive comments to MRB_API functions in src/range.c
This commit adds descriptive comments to the following functions:

- mrb_range_ptr
- mrb_range_new
- mrb_range_beg_len

The comments were written by Google Jules.
2025-06-04 11:03:35 +09:00
Yukihiro "Matz" Matsumoto 99d9568aeb Merge pull request #6544 from zenspider/zenspider/frozen_strings 2025-06-04 11:03:26 +09:00
Yukihiro "Matz" Matsumoto 851f9f61a9 Merge pull request #6545 from mruby/add-comments-class-c 2025-06-04 11:00:55 +09:00
google-labs-jules[bot] e68eafd511 Add descriptive comments for MRB_API functions in src/class.c
This commit adds C-style block comments to all MRB_API functions
defined in the src/class.c file. The comments explain the purpose
of each function, its parameters, and its return value, aiming to
improve code readability and maintainability.
2025-06-04 01:59:44 +00:00
Ryan Davis 59f08ff148 Fix build strings that must be mutable. Tested with RUBYOPT=--enable-frozen-string-literal make 2025-06-03 18:18:29 -07:00
Yukihiro "Matz" Matsumoto 8e0081923f Merge pull request #6543 from mruby/add-comments-dump-c-partial 2025-06-03 09:01:56 +09:00
google-labs-jules[bot] c837d386de Add descriptive comments to several functions in src/dump.c
This commit adds Doxygen-style comments to the following functions
in src/dump.c, ensuring "@brief" is not used:

Non-static functions (comments reviewed/updated):
- mrb_dump_irep
- mrb_dump_irep_binary
- mrb_dump_irep_cfunc

Static functions (new comments added):
- write_irep_header
- write_iseq_block
- dump_float (if compiled)
- get_pool_block_size
- write_pool_block
- get_syms_block_size
- write_syms_block
- get_irep_record_size

This work is part of a larger effort to document all non-trivial
functions in this file as per your feedback. The remaining functions
will be documented in subsequent commits.
2025-06-03 00:01:24 +00:00
Yukihiro "Matz" Matsumoto c3d2b903c6 error.c: add descriptive comments
The comments are written by Google Jules.
2025-06-03 08:53:06 +09:00
Yukihiro "Matz" Matsumoto 83b21e8fd6 Merge pull request #6542 from mruby/add-symbol-comments 2025-06-03 08:43:23 +09:00
google-labs-jules[bot] e8458f9c22 Add descriptive comments to MRB_API functions in src/symbol.c
This commit adds descriptive comments to all functions marked with MRB_API
in the `src/symbol.c` file. The comments explain the purpose, parameters,
and return values of these functions, improving code readability and
maintainability.

The following functions were commented:
- mrb_intern
- mrb_intern_static
- mrb_intern_cstr
- mrb_intern_str
- mrb_intern_check
- mrb_check_intern
- mrb_intern_check_cstr
- mrb_check_intern_cstr
- mrb_intern_check_str
- mrb_check_intern_str
- mrb_sym_name_len
- mrb_sym_str
- mrb_sym_name
- mrb_sym_dump
2025-06-02 23:42:40 +00:00
Yukihiro "Matz" Matsumoto d2728fb0ae mruby-time (mrb_to_time_t): separate into smaller functions
The code was written by Google Jules.
2025-06-02 16:05:44 +09:00
Yukihiro "Matz" Matsumoto 70956e9683 mruby-time: add descriptive comments
The comments were written by Google Jules.
2025-06-02 16:04:54 +09:00
Yukihiro "Matz" Matsumoto 91c59ced99 mruby-time: replace magic numbers to C macros
The code is written by Google Jules.
2025-06-02 15:55:44 +09:00
Yukihiro "Matz" Matsumoto 46b8e80d9e Merge pull request #6541 from mruby/add-api-comments-array 2025-06-02 08:48:57 +09:00
google-labs-jules[bot] 7f3329e393 Add descriptive comments for MRB_API functions in src/array.c
This change adds C-style multiline comments to all functions
marked with MRB_API in the src/array.c file.

The comments explain each function's purpose, its parameters,
and what it returns, where applicable. This improves the
readability and maintainability of the C API for mruby arrays.

The `@brief` markup was intentionally avoided as per your
requirements.
2025-06-01 23:48:11 +00:00
Yukihiro "Matz" Matsumoto 9c5d1cdaa9 Merge branch 'jules_wip_7626599795303680331' 2025-06-01 17:58:39 +09:00
google-labs-jules[bot] 493cc64902 hash.c: add descriptive comments to C-facing MRB_API hash functions
This commit adds C-style descriptive comments to MRB_API functions
in `src/hash.c` that are intended for use as part of mruby's C API.
The comments are targeted at C developers using these functions directly.

Comments were added or updated for the following functions:
- mrb_hash_new: Added comment.
- mrb_hash_new_capa: Updated existing comment to be more C API user-centric.
- mrb_hash_dup: Added comment.
- mrb_hash_get: Added comment.
- mrb_hash_fetch: Added comment.
- mrb_hash_set: Added comment.
- mrb_hash_delete_key: Added comment.
- mrb_hash_size: Added comment.
- mrb_hash_merge: Added comment.
- mrb_hash_foreach: Comment updated in a previous phase of work.

This work aligns with the guideline to comment C-facing MRB_API functions,
while avoiding adding new C-API comments to those MRB_API functions
that solely implement Ruby methods and already have extensive Ruby
method documentation (call-seq) in the source. The @brief markup
was avoided as per the original issue request.
2025-06-01 17:57:30 +09:00
Yukihiro "Matz" Matsumoto 273e7325c9 Merge pull request #6538 from mruby/dependabot/bundler/rake-13.3.0 2025-05-31 22:48:52 +09:00
Yukihiro "Matz" Matsumoto ec68497a39 Merge pull request #6540 from mruby/add-comments-object-c 2025-05-31 22:48:02 +09:00
Yukihiro "Matz" Matsumoto 05c7aa2fe2 Merge pull request #6539 from mruby/add-string-comments 2025-05-31 22:47:45 +09:00
google-labs-jules[bot] f4b56a5e56 Add descriptive comments to MRB_API functions in object.c
This commit adds and updates C-style block comments for all functions marked with MRB_API in src/object.c.

The comments explain the purpose, parameters, and return values of these functions, adhering to the project's documentation style and avoiding the use of '@brief' markup.

Existing comments were also reviewed and updated for clarity and consistency.
2025-05-31 13:45:31 +00:00
google-labs-jules[bot] 5924a23b8d Here's the rewritten message:
Add descriptive comments for MRB_API functions in src/string.c

This commit adds descriptive comments to various MRB_API functions
within the src/string.c file. These comments aim to improve code
readability and maintainability by explaining the purpose,
parameters, and return values of these functions.
2025-05-31 13:44:19 +00:00
dependabot[bot] bbb5d28530 build(deps): bump rake from 13.2.1 to 13.3.0
Bumps [rake](https://github.com/ruby/rake) from 13.2.1 to 13.3.0.
- [Release notes](https://github.com/ruby/rake/releases)
- [Changelog](https://github.com/ruby/rake/blob/master/History.rdoc)
- [Commits](https://github.com/ruby/rake/compare/v13.2.1...v13.3.0)

---
updated-dependencies:
- dependency-name: rake
  dependency-version: 13.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-30 14:40:20 +00:00
Yukihiro "Matz" Matsumoto df62559ddb Merge pull request #6537 from mruby/add-cdump-comments 2025-05-30 07:24:00 +09:00
Yukihiro "Matz" Matsumoto b925d6fee4 Merge pull request #6536 from mruby/add-debug-comments 2025-05-30 07:23:45 +09:00
google-labs-jules[bot] bee56a8634 The comments in cdump.c have been updated to remove the @brief tag from the Doxygen-style comment for the mrb_dump_irep_cstruct function. This change was made based on your feedback.
The rest of the comment, which details the function's purpose, parameters, return values, and conditional compilation, remains unchanged.
2025-05-29 22:22:07 +00:00
Yukihiro "Matz" Matsumoto 0011ee2267 Merge pull request #6535 from mruby/add-mempool-comments 2025-05-29 10:06:32 +09:00
Yukihiro "Matz" Matsumoto 70614ba82a Merge pull request #6534 from mruby/add-readfloat-comment 2025-05-29 09:25:39 +09:00
google-labs-jules[bot] a668834b2d Add descriptive comments to public functions in src/debug.c
This change adds Doxygen-style comments to the public API functions
in `src/debug.c`, including mrb_packed_int_len, mrb_packed_int_encode,
and mrb_packed_int_decode. The comments explain the purpose of each function,
its parameters, and its return value. This improves the readability
and maintainability of the code.
2025-05-28 22:06:18 +00:00
google-labs-jules[bot] e0d1f99744 I've added descriptive comments for functions/macros in src/mempool.c.
This commit adds Doxygen-style comments to the public functions,
internal static functions, and structs within the `src/mempool.c` file.
These comments clarify the purpose, parameters, and return values (where applicable)
of these code elements, improving code readability and maintainability.

The following elements were commented:
- struct mempool_page
- struct mempool
- ALIGN_PADDING macro
- mempool_open()
- mempool_close()
- page_alloc()
- mempool_alloc()
- mempool_realloc()
2025-05-28 22:02:53 +00:00
google-labs-jules[bot] 224d0c8933 Add descriptive comment to mrb_read_float function
This commit adds a descriptive comment at the beginning of the `mrb_read_float` function in `src/readfloat.c`.

The comment explains the function's purpose, its parameters (`str`, `endp`, `fp`), and its return value (`TRUE` or `FALSE`). This improves code readability and understanding.
2025-05-28 22:01:17 +00:00
Yukihiro "Matz" Matsumoto e5905fe1dc Merge pull request #6533 from katafrakt/fix-extended-callback 2025-05-28 11:13:38 +09:00
Yukihiro "Matz" Matsumoto eb5fbfbb40 class.c: Remove MRB_INLINE_METHOD_CACHE support from mt_tbl
The sorted array binary search implementation no longer uses the inline
cache array, so remove all MRB_INLINE_METHOD_CACHE definitions and
related code.
2025-05-28 08:33:21 +09:00
Yukihiro "Matz" Matsumoto e8ebeb151d class.c: Switch mt_tbl to sorted array binary search for method lookups
By replacing the open‐addressing hash with a sorted array and binary
search, we eliminate tombstone management and improve cache locality of
method entries. This preserves the original contiguous values+keys
layout and peak memory usage, while simplifying growth logic and
delivering lookup performance gains.
2025-05-28 07:54:42 +09:00
Paweł Świątkowski bdcd496bc2 Fix calling extended callback
The callback of extending module should be called, not of a singleton
class of an extended object.
2025-05-27 23:03:10 +02:00
Yukihiro "Matz" Matsumoto bec5dbc4e9 variable.c (iv_copy): just memcpy sorted array; no iv_put 2025-05-27 10:58:41 +09:00
Yukihiro "Matz" Matsumoto 63a09ee336 variable.c (iv_rehash): just memcpy sorted array; no need to call iv_put 2025-05-27 10:53:58 +09:00
Yukihiro "Matz" Matsumoto 9cee6ead4c variable.c: use binary search for iv_tbl lookups
Preserve the original iv_tbl heap layout and allocation pattern, but
switch iv_put to maintain sorted keys and iv_get/iv_del to perform
binary search. This eliminates extra probing overhead, improves
read-heavy lookup performance for small tables, and incurs zero
additional allocations.
2025-05-27 10:33:09 +09:00
Yukihiro "Matz" Matsumoto ca6dc4ec2d variable.c (iv_size): refactor the function
Along with removing an obsolete comment line.
2025-05-27 10:16:12 +09:00
Yukihiro "Matz" Matsumoto 7c02e17e25 variable.c (mrb_mod_cv_get): initialize local variable
To silence compiler warning.
2025-05-26 22:59:04 +09:00
Yukihiro "Matz" Matsumoto 11bf789730 array.c: remove unnecessary blank line 2025-05-26 14:32:19 +09:00
Yukihiro "Matz" Matsumoto 9537d9b75a Merge pull request #6532 from mruby/improve-mt-hash-load-factor 2025-05-25 20:57:36 +09:00
google-labs-jules[bot] e82f49adf7 I've reverted method table optimizations to prioritize memory savings for you.
My previous attempts to improve method table (mt_tbl) performance by introducing a load factor and adjusting the initial allocation size unfortunately led to undesirable increases in memory consumption.

Given that memory usage is a primary concern, I've reverted the following changes:
- Removed the load factor based rehashing logic.
- Removed the related definitions for the load factor.
- Ensured the initial allocation size is 8.

This restores the method table to its original behavior, where it rehashes only when the table is completely full or during initial allocation. This should bring memory usage back to its baseline level prior to these optimization attempts.
2025-05-25 11:40:43 +00:00
Yukihiro "Matz" Matsumoto ed8ec097a2 Merge pull request #6531 from mruby/improve-mt-hash-load-factor 2025-05-25 20:12:46 +09:00
google-labs-jules[bot] 8a91c91a69 Improve method table performance by rehashing at 75% load factor.
The method table (mt_tbl) in src/class.c previously only rehashed when it became completely full. With linear probing, this could lead to significant performance degradation for lookups and insertions as the table approached full capacity.

This change introduces a load factor (MT_LOAD_FACTOR_NUM/MT_LOAD_FACTOR_DEN, set to 3/4 or 0.75). The mt_put function now checks if adding a new element would cause the table's size to meet or exceed this load factor relative to its allocated capacity. If so, it triggers a rehash before inserting the new element.

This helps maintain more empty slots in the hash table, improving the average-case performance of linear probing and reducing the likelihood of worst-case scenarios. The existing initial allocation size and doubling strategy for rehashing are retained.
2025-05-24 22:50:29 +00:00
Yukihiro "Matz" Matsumoto 0c51a72bfe string.c (popcount): support when sizeof(int) == 4
This function is used when the compiler does not support builtin
popcount operation (namely VC++).
2025-05-23 23:10:45 +09:00
Yukihiro "Matz" Matsumoto ca526044d3 vm.c (stack_init): clear initial stack 2025-05-23 23:09:53 +09:00
Yukihiro "Matz" Matsumoto 86ef7a912d mruby-rational (int_lshift): check before actual left bit shift 2025-05-21 13:25:08 +09:00
Yukihiro "Matz" Matsumoto f4b01ed19e mruby-rational (int_lshift): exponential may be bigger than int bits 2025-05-21 10:40:02 +09:00
Yukihiro "Matz" Matsumoto 1fa9eaa2b5 mruby-eval (binding_eval_error_check): re-raise Exception in parsing 2025-05-21 10:25:35 +09:00
Yukihiro "Matz" Matsumoto 77d08772a5 error.c (mrb_vformat): prevent SEGV from %s with NULL 2025-05-21 09:52:10 +09:00
Yukihiro "Matz" Matsumoto 1726b61481 mruby-compiler (gen_move): avoid unnecessary goto's 2025-05-20 18:31:51 +09:00
Yukihiro "Matz" Matsumoto d329d9af79 mruby-compiler (gen_move): avoid optimization of ADDI/SUBI
ADDI/SUBI may fall back to method call that may clear block argument
place holder, which may be a live register. So we cannot directly call
ADDI/SUBI over local variables.
2025-05-20 18:31:21 +09:00
Yukihiro "Matz" Matsumoto d08276a052 codedump.c: remove unnecessary tab character from OP_MOVE 2025-05-19 23:36:16 +09:00
Yukihiro "Matz" Matsumoto 82d03b32f2 codedump.c: skip string body if it's empty 2025-05-19 23:34:02 +09:00
Yukihiro "Matz" Matsumoto f9414456a5 codedump.c: output format for OP_ARRAY has changed 2025-05-19 23:09:03 +09:00
Yukihiro "Matz" Matsumoto 1d426c50bf range.c (range_num_to_a): C++ compiler eagerly warns goto statement 2025-05-19 19:41:01 +09:00
Yukihiro "Matz" Matsumoto 94d9f6cfc7 range.c (range_num_to_a): support big integer beg/end in ranges 2025-05-19 17:36:54 +09:00
Yukihiro "Matz" Matsumoto ff4109735f range.c (range_num_to_a): improved float support 2025-05-19 17:36:45 +09:00
Yukihiro "Matz" Matsumoto 18c43c2a5a mruby-io: provide Kernel#p in this gem
To prevent ordering instability when output from mruby-io and Kernel#p
mixed.
2025-05-19 13:31:01 +09:00
Yukihiro "Matz" Matsumoto 65247613b9 Merge pull request #6530 from dearblue/visibility 2025-05-19 08:11:18 +09:00
Yukihiro "Matz" Matsumoto 31ebcb349e mruby-compiler: add y.tab.c in the repository again; close #6515
Since we have introduced lrama, everyone can generate same `y.tab.c`
on any platform, without installing Bison. That was the reason we have
removed `y.tab.c` from the repository. But this change cause #6515 and
bothered out-of-tree builds. So we (reluctantly) added `y.tab.c` again.
2025-05-19 08:00:37 +09:00
Yukihiro "Matz" Matsumoto c356e8f2ff .gitignore: no longer ignore y.tab.c; ref #6515 2025-05-19 08:00:36 +09:00
Yukihiro "Matz" Matsumoto 96cbde7988 mruby-compiler: remove mrb_free dependency from codegen.c 2025-05-19 08:00:36 +09:00
Yukihiro "Matz" Matsumoto bb712f9467 mruby-compiler: remove mrb_calloc dependency from parse.y 2025-05-19 08:00:36 +09:00
Yukihiro "Matz" Matsumoto 9fc58852e3 mruby-compiler: removed mrb_state dependency from two functions
- mrb_ccontext_partial_hook
- mrb_ccontext_cleanup_local_variables
2025-05-19 08:00:36 +09:00
Yukihiro "Matz" Matsumoto fa19d7d3b5 stdlib.gembox: add mruby-catch to the gembox 2025-05-19 08:00:36 +09:00
dearblue 36df859333 Revert "class.c (find_visibility_scope): when callinfo returns, *ep == NULL; #6512"
This reverts commit 3879b95a62.

This is because the code first reported in #6494 no longer works.
2025-05-18 18:52:32 +09:00
dearblue 4417321d1c Add more test code for method visibility
This test corresponds to the first issue of #6494.
Complement to #6512.
2025-05-18 18:50:02 +09:00
Yukihiro "Matz" Matsumoto b952ca30cd Merge pull request #6529 from mruby/dependabot/github_actions/super-linter/super-linter-7.4.0 2025-05-15 05:46:57 +09:00
dependabot[bot] ef840eced0 build(deps): bump super-linter/super-linter from 7.3.0 to 7.4.0
Bumps [super-linter/super-linter](https://github.com/super-linter/super-linter) from 7.3.0 to 7.4.0.
- [Release notes](https://github.com/super-linter/super-linter/releases)
- [Changelog](https://github.com/super-linter/super-linter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/super-linter/super-linter/compare/v7.3.0...v7.4.0)

---
updated-dependencies:
- dependency-name: super-linter/super-linter
  dependency-version: 7.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-14 14:19:47 +00:00
Yukihiro "Matz" Matsumoto 923b1c9e37 stdlib.gembox: add mruby-enum-chain gem 2025-05-14 15:58:24 +09:00
Yukihiro "Matz" Matsumoto 9e6ddbb2ad metaprog.gembox: add two binding gems
- mruby-binding
- mruby-proc-binding
2025-05-14 15:58:24 +09:00
Yukihiro "Matz" Matsumoto d414e3f912 math.gembox: exclude mruby-cmath from math gembox 2025-05-14 15:58:23 +09:00
Yukihiro "Matz" Matsumoto 34bd571a65 Merge pull request #6528 from jbampton/fix-grammar-spelling 2025-05-14 15:58:05 +09:00
Yukihiro "Matz" Matsumoto 1fcaa3995e Merge pull request #6418 from jbampton/add-ls-lint 2025-05-14 15:55:33 +09:00
John Bampton 781edbd446 misc: fix spelling 2025-05-14 02:01:02 +10:00
John Bampton 4f2f2cfd20 Add ls-lint with GitHub Actions
Rename files in the `mrbgems` directory
2025-05-14 01:14:02 +10:00
Yukihiro "Matz" Matsumoto 93a7e5ec26 Merge pull request #6526 from vickash/luckfox-pico 2025-05-13 16:46:23 +09:00
Yukihiro "Matz" Matsumoto 75466f9aab mruby-compiler: use mrb_basic_alloc_func() directly from compiler
As a side effect, memory allocation failure may cause segmentation
fault. Maybe we have to add error detection later.
2025-05-13 13:20:06 +09:00
Yukihiro "Matz" Matsumoto 9ef2f551b7 mruby-compiler: use new mempool API 2025-05-13 08:13:48 +09:00
Yukihiro "Matz" Matsumoto dbc9d12254 mempool.c (mempool_open): avoid using old API in mempool.c 2025-05-12 13:04:22 +09:00
Yukihiro "Matz" Matsumoto ebca0cbf6a Merge pull request #6525 from hasse09052/skip-empty-mirb-history 2025-05-12 12:59:28 +09:00
Yukihiro "Matz" Matsumoto c2d5a402ba compile.h: change struct mrb_mempool to mrb_mempool
So that compatibility layer can be used without macro definition.
2025-05-12 12:30:15 +09:00
vickash 6700c327ac Luckfox Pico config: Use realpath, comment flags and cmath exclusion 2025-05-11 23:25:32 -04:00
vickash f98a05c738 Add build config for Luckfox Pico embedded SBC 2025-05-11 22:35:05 -04:00
Yukihiro "Matz" Matsumoto 6566099dbb mempool.c: remove mrb_state dependency from mempool library
mempool.h provide compatibility layer so that existing programs does not
need to update (but update recommended anyway, since compatibility layer
takes mrb_state that is not used at all).
2025-05-12 08:26:18 +09:00
Yukihiro "Matz" Matsumoto 6766fcb905 class.c (mt_rehash): Fix mrb_calloc argument order
Since mrb_calloc() (along with mrb_calloc) takes two arguments: nmemb
which is number of array elements, and size which is size of the array.
Of course, revsersing does not change the behavior, but we'd like to
respect the original design intention of calloc(3).
2025-05-11 20:11:56 +09:00
Yukihiro "Matz" Matsumoto 4704a7700a Merge pull request #6521 from jbampton/add-codespell-config 2025-05-11 20:09:25 +09:00
hasse 6df8096af2 mruby-bin-mirb: skip adding empty input to mirb history 2025-05-11 02:44:04 +09:00
Yukihiro "Matz" Matsumoto c6e3ae7e74 doc/guides/memory.md: update the document
- new API
- detailed hook description
- migration path from old API
2025-05-10 09:34:20 +09:00
Yukihiro "Matz" Matsumoto 7e4810658e allocf.c: update and enhance documentation in the comment 2025-05-10 09:07:35 +09:00
Yukihiro "Matz" Matsumoto 5522c94bb3 mruby.h: remove mrb_allocf type
As a result, we removed (already obsoleted) `mrb_open_allocf()', and
made `mrb_open_core()` take no argument. [incompatible changes]
2025-05-10 08:59:18 +09:00
Yukihiro "Matz" Matsumoto 5c71681d82 allocf.c (mrb_basic_alloc_func): remove ud argument 2025-05-10 08:59:18 +09:00
Yukihiro "Matz" Matsumoto c3cc559dfc allocf.c: rename mrb_default_alloc to mrb_basic_alloc_func
Along with removing mrb_state first argument from the function. From
mruby 3.2, this function is *not* the default function, but the entry
point that can be redefined for the application. The function in
`src/allocf.c` is the default *implementation* (using malloc / realloc /
free) of the function.
2025-05-09 21:50:18 +09:00
John Bampton f515669ce3 Add codespell config file .codespellrc
Add `.codespellrc` to the GitHub labeler

Can now run codespell from the command line standalone and it will use
our standard config file. Running codespell with pre-commit will also use this config.

Useful when regenerating the ignored words file on the command line.

https://github.com/codespell-project/codespell?tab=readme-ov-file#using-a-config-file

https://github.com/codespell-project/codespell?tab=readme-ov-file#pre-commit-hook
2025-05-09 20:54:27 +10:00
Yukihiro "Matz" Matsumoto 0bdd529430 mruby.h: remove allocf and allocf_ud from mrb_state
This is preparation for memory allocation restructuring.
2025-05-09 18:13:28 +09:00
Yukihiro "Matz" Matsumoto 3d2f848e64 mruby-random: Random#rand(nil) should raise TypeError 2025-05-08 17:37:05 +09:00
Yukihiro "Matz" Matsumoto 88e86ee62e mruby-random: update error messages to be compatible with CRuby; #6523 2025-05-08 16:42:33 +09:00
Yukihiro "Matz" Matsumoto 21d6bfb6dd test/kernel.rb: disable some Kernel#p tests; ref #6524 2025-05-08 16:21:01 +09:00
Yukihiro "Matz" Matsumoto 37b84f40e0 Merge pull request #6523 from leviongit/rand-range 2025-05-08 16:06:02 +09:00
Yukihiro "Matz" Matsumoto 5b10fdf684 Merge pull request #6524 from hasumikin/fix/Kernel#p 2025-05-08 16:01:35 +09:00
Yukihiro "Matz" Matsumoto 147af9d669 Merge pull request #6522 from jbampton/label-more-files 2025-05-08 15:59:47 +09:00
Yukihiro "Matz" Matsumoto 3879b95a62 class.c (find_visibility_scope): when callinfo returns, *ep == NULL; #6512 2025-05-08 12:02:32 +09:00
Yukihiro "Matz" Matsumoto 2b0d866da1 class.c (find_visibility_scope): rename the function; ref #6512
Since the function returns either callinfo or env, thus the name does
not describe the current behavior. In addition, we did some refactoring
on the function.
2025-05-08 12:02:00 +09:00
Yukihiro "Matz" Matsumoto 50c8e180d8 class.c (find_visibility_ci): refactor to reduce complexity; ref #6512 2025-05-08 07:57:35 +09:00
Yukihiro "Matz" Matsumoto dbc4768758 mruby/internal.h: rename visibility separation macros; ref #6512 2025-05-08 07:32:36 +09:00
Yukihiro "Matz" Matsumoto c9a36e5d39 mruby/value.h: rename flag check macros; ref #6512 2025-05-08 07:27:30 +09:00
Yukihiro "Matz" Matsumoto 41e91a2ca8 vm.c (mrb_exec_irep): remove recently added separate_module argument
The argument was added in #6512
2025-05-08 07:27:23 +09:00
Yukihiro "Matz" Matsumoto ef0cbc2981 mruby-eval (exec_irep): cache mrb->c->ci to a local variable 2025-05-07 23:30:41 +09:00
Yukihiro "Matz" Matsumoto 567617ceb5 Merge branch 'dearblue-visibility' 2025-05-07 15:37:37 +09:00
Yukihiro "Matz" Matsumoto aec8d0c58b Merge branch 'visibility' of github.com:dearblue/mruby into dearblue-visibility 2025-05-07 15:37:08 +09:00
Yukihiro "Matz" Matsumoto 81f5f5b8d4 mruby-bin-debugger: should not use Exception#inspect to print errors
Use mrb_exc_get_output() instead.
2025-05-07 12:34:13 +09:00
Yukihiro "Matz" Matsumoto c36d9b7732 mruby-bin-mirb: should not use Exception#inspect to print errors
Use mrb_exc_get_output() instead.
2025-05-07 12:32:12 +09:00
Yukihiro "Matz" Matsumoto 6eb969ff04 backtrace.c (print_backtrace): use mrb_exc_get_output()
To keep the old error print even after Exception#inspect format changed.
2025-05-07 12:22:11 +09:00
Yukihiro "Matz" Matsumoto 33d9ad6c44 error.c (mrb_exc_get_output): a new function for old inspect format 2025-05-07 12:19:05 +09:00
Yukihiro "Matz" Matsumoto 85d048c1fb mruby-error: update tests for new Exception#inspect format 2025-05-07 12:19:05 +09:00
Yukihiro "Matz" Matsumoto a87b4b6bc3 test/exception.rb: update for new Exception#inspect 2025-05-07 12:19:05 +09:00
Yukihiro "Matz" Matsumoto 333c364d5f error.c (mrb_exc_inspect): Update format to match CRuby 2025-05-07 12:19:04 +09:00
Yukihiro "Matz" Matsumoto b5ad35d8ef proc.h (MRB_SET_VISIBILITY_FLAGS): rename macro 2025-05-07 12:19:04 +09:00
Yukihiro "Matz" Matsumoto 0da5e0e190 AUTHORS: update entries [ci skip] 2025-05-07 12:19:04 +09:00
Yukihiro "Matz" Matsumoto abfef2c38d Merge pull request #6520 from jbampton/update-pre-commit 2025-05-04 23:19:54 +09:00
leviongit 7be940942c random.c : treat ranges where r.begin > r.end the same way cruby does 2025-05-04 04:10:39 +02:00
leviongit 98906d5ac9 random.c : fix Random#rand not returning value 2025-05-04 03:48:22 +02:00
HASUMI Hitoshi fdfd67ff40 Fix Kernel#p when no argument
## Expected
```ruby
p
=> nil
```

## Actual
```ruby
p
=> []
```
2025-05-04 10:17:37 +09:00
leviongit 202c213fe1 random.c : add some tests 2025-05-04 02:44:19 +02:00
leviongit 4390aeb78d random.c : add rand(Range) 2025-05-04 02:44:19 +02:00
Yukihiro "Matz" Matsumoto 0723e10dcd Merge pull request #6519 from jbampton/update-prettier-ignore 2025-05-03 14:42:24 +09:00
John Bampton 757c0472d0 gha: label more files 2025-05-03 04:47:04 +10:00
John Bampton ddae958405 pre-commit: autoupdate and update node LTS version
https://nodejs.org/en

https://pre-commit.com/#pre-commit-autoupdate
2025-05-03 02:00:44 +10:00
John Bampton 7a3eebc1d5 Add tools/lrama to .prettierignore
Prettier uses an ignore file to exclude files from formatting when
running with pre-commit and also when running standalone from the command line.

This is detailed on the CLI docs page:

https://prettier.io/docs/cli
2025-05-03 01:42:36 +10:00
Yukihiro "Matz" Matsumoto 30d1db4528 10error.rb: move 2 more classes to error.c
- FloatDomainError
- RegexpError
2025-05-02 08:50:20 +09:00
Yukihiro "Matz" Matsumoto 0fb280adbf 10error.rb: move some error class definitions to error.c
- Exception
- ArgumentError
- LocalJumpError
- RangeErrpr
- TypeError
- IndexError
- KeyError
- NotImplementError
- FrozenError
- ZeroDivisionError
2025-05-01 15:10:55 +09:00
Yukihiro "Matz" Matsumoto 1bc16676a1 class.c: implement BasicObject#!= in C file
The method is defined in inline bytecode. As a side-effect, `00class.rb`
was removed.
2025-05-01 10:23:03 +09:00
Yukihiro "Matz" Matsumoto 683ecc09b5 codedump.c: do not print extra ';' if operands are not local vars 2025-04-30 07:54:40 +09:00
Yukihiro "Matz" Matsumoto 789d350da9 codedump.c: put parenthesis around virtual operand
Some operands are virtual (e.g. `a` and `a+1`). It is easier to count
instructions if you can distinguish virtual and real operands.
2025-04-29 07:49:59 +09:00
Yukihiro "Matz" Matsumoto 08f74dd2be class.c: move alias attr attr_reader from 00class.rb 2025-04-28 14:20:07 +09:00
Yukihiro "Matz" Matsumoto 1b39c7d7da mruby-compiler (codegen): private backquote should be called; fix #6516 2025-04-28 10:40:05 +09:00
Yukihiro "Matz" Matsumoto e9d20a1590 doc/limitations.md: document double dispatch removal
We have removed `append_features`/`prepend_features`/`extend_object`.
It is incompatible with CRuby, but simpler.
2025-04-28 10:30:01 +09:00
Yukihiro "Matz" Matsumoto 6c72f8b378 class.c (extend_object): remove method; implement Kernel#extend in C 2025-04-28 10:30:00 +09:00
Yukihiro "Matz" Matsumoto 6c25b5896a class.c (prepend_features): remove the method
Just like `#append_features`, we remove `#prepend_features` and
implemented `#prepend` directly in C.
2025-04-28 10:30:00 +09:00
Yukihiro "Matz" Matsumoto 9387cd382e class.c (append_features): remove the method
The technique is called "double dispatch" (that was popular in
Smalltalk), but it does not work well with mruby. It's slower and
consumes more memory. Even thought `#append_features` defined in ISO
standard (15.2.2.4.11), we decided to remove it. Strictly speaking, it
is mruby limitation. And it should be documented clearly.
2025-04-28 10:30:00 +09:00
Yukihiro "Matz" Matsumoto 5fe406d59c vm.c (send_method): should not use C++ keyword public 2025-04-28 10:30:00 +09:00
Yukihiro "Matz" Matsumoto a6ef3a45d1 vm.c (mrb_f_public_send): define #public_send method
The method itself is available when mruby-metaprog is loaded.
2025-04-25 17:39:12 +09:00
Yukihiro "Matz" Matsumoto dd96afd5a8 variable.c (mrb_const_set): call const_added hook 2025-04-25 16:25:36 +09:00
Yukihiro "Matz" Matsumoto e5478c2b40 class.c (setup_class): simplified using mrb_const_set() 2025-04-25 16:23:02 +09:00
Yukihiro "Matz" Matsumoto 8f120971b5 variable.c: merge mrb_vm_const_set to mrb_const_set
Inline vm part to the VM itself.
2025-04-25 16:12:06 +09:00
Yukihiro "Matz" Matsumoto 03719490eb class.c: define const_added method (with empty body) 2025-04-25 15:56:57 +09:00
Yukihiro "Matz" Matsumoto 6e1538ce3a Merge pull request #6518 from HirohitoHigashi/master 2025-04-25 15:51:36 +09:00
Yukihiro "Matz" Matsumoto 279855985f Merge pull request #6517 from jbampton/remove-unneeded-semicolon 2025-04-25 15:46:14 +09:00
HirohitoHigashi 586ff7a694 Change mrbc_args.flags bit width from 2 to 3. 2025-04-25 12:05:01 +09:00
John Bampton fe201dc72f core/codegen.c: remove unneeded duplicate semicolon 2025-04-25 05:10:24 +10:00
Yukihiro "Matz" Matsumoto 9c6349c769 Merge pull request #6513 from mruby/stable 2025-04-21 13:57:27 +09:00
Hiroshi Mimaki d4097716b3 NEWS: remove wrong spelling from the pull-request description 2025-04-21 10:24:03 +09:00
mimaki 99f5668243 Merge branch 'master' into stable 2025-04-20 13:25:22 +09:00
mimaki a309524d0b Update version and release date. (mruby 3.4.0 (2025-04-20)) 2025-04-20 13:08:22 +09:00
Yukihiro "Matz" Matsumoto baea6e284e mruby-bigint (mpz_bits): use lzb() 2025-04-17 08:11:27 +09:00
Yukihiro "Matz" Matsumoto 061521ead5 mruby-bigint (mpz_bits): renamed from mpz_bit_length() 2025-04-17 08:10:34 +09:00
Yukihiro "Matz" Matsumoto 16198dc985 mruby-numeric-ext (int_sqrt): translate Japanese comment (oops) 2025-04-17 01:43:03 +09:00
Yukihiro "Matz" Matsumoto e42523fcf4 mruby-numeric-ext: add test for Integer.sqrt() 2025-04-16 23:30:23 +09:00
Yukihiro "Matz" Matsumoto ddfe65763e mruby-numeric-ext (int_sqrt): support bigint 2025-04-16 23:08:23 +09:00
Yukihiro "Matz" Matsumoto dee661913f mruby-numeric-ext (int_sqrt): Integer.sqrt implemented
This is the first version. It should support bigint eventually.
2025-04-16 22:37:06 +09:00
Yukihiro "Matz" Matsumoto 9a0f96e617 pre-commit autoupdate 2025-04-16 22:34:27 +09:00
Yukihiro "Matz" Matsumoto 8b213c4fbf string.c (sub_replace): check if found argument is within proper range
Since it is an internal method, we didn't check the argument range, but
if it's called directly, out-of-range argument could cause SEGV.
2025-04-15 07:11:09 +09:00
Yukihiro "Matz" Matsumoto 9cc6d39956 test/module.rb: add test for #6506 2025-04-14 22:09:35 +09:00
Yukihiro "Matz" Matsumoto 1969100fb4 variable.c (mrb_vm_get_const): seek singleton class superclass; fix #6506
Also ensure we don't revive #2515, #3003, #3598
2025-04-14 22:09:35 +09:00
Yukihiro "Matz" Matsumoto 953ebdf334 variable.c (mrb_vm_const_get): refactoring for singleton classes 2025-04-14 22:09:35 +09:00
Yukihiro "Matz" Matsumoto 95f9de4877 mruby-metaprog (mrb_mod_s_constants): Module.constants implemented
The method returns the list of all constants accessible from the point
of call.
2025-04-14 22:09:35 +09:00
Yukihiro "Matz" Matsumoto e08452585e variable.c (mrb_mod_cv_get): c must not be NULL as an argument 2025-04-14 22:09:34 +09:00
Yukihiro "Matz" Matsumoto 90d77e71f5 variable.c (mrb_mod_cv_set): small refactoring
The argument c should not be NULL.
2025-04-14 22:09:34 +09:00
Yukihiro "Matz" Matsumoto 118e13d85c variable.c: a new function mrb_mod_const_at()
And mrb_mod_constants() use the new function now.
2025-04-14 22:09:34 +09:00
Yukihiro "Matz" Matsumoto cda551ce25 mruby-metaprog (mrb_mod_s_constants): call Module#constants if possible
When the optional argument is given or the receiver is not `Module`.
2025-04-14 22:09:34 +09:00
Yukihiro "Matz" Matsumoto 82522a2e71 mruby-bigint (mrb_bint_to_s): add check for MRB_32BIT and MRB_INT64 2025-04-14 22:09:33 +09:00
Yukihiro "Matz" Matsumoto 29964b3ba7 mruby-io (mrb_file_size): add check for MRB_32BIT and MRB_INT64 2025-04-14 22:09:33 +09:00
Yukihiro "Matz" Matsumoto 0d5fecf833 variable.c (mrb_const_get): adjust local variable scope 2025-04-14 22:09:33 +09:00
dearblue 3fd5e1c250 Fixed visibility at method definition
There was a problem with visibility state from proc that straddles a fiber or is independent.

Therefore, it has been changed to give priority to env objects, if any.
Also, added "separate module" flag to block traversal to a higher level env object.

Note that the "separate module" flag is now set when calling blocks with the `mrb_yield_with_class()` function.

fixed https://github.com/mruby/mruby/issues/6494
2025-04-11 21:36:26 +09:00
Yukihiro "Matz" Matsumoto 52de3b7e10 Merge pull request #6511 from dearblue/precommit
Exclude the external project "lrama" from pre-commit
2025-04-08 23:44:31 +09:00
dearblue 40095bf755 Exclude the external project "lrama" from pre-commit 2025-04-08 22:11:32 +09:00
Yukihiro "Matz" Matsumoto 46aa35a117 Merge pull request #6510 from dearblue/visibility
Fixed class method visibility via `module_function`
2025-04-08 17:18:19 +09:00
dearblue 84e1b0045c Fixed class method visibility via module_function
The following code should work

```ruby
module M
  def me
    p self
  end

  module_function :me
end

M.me
```
2025-04-07 21:40:56 +09:00
Yukihiro "Matz" Matsumoto 1fdd961041 mruby-compiler (scope_new): need to initialize nregs; fix #6509
`nregs` should not be smaller than `nlocals`.
2025-04-07 11:35:19 +09:00
Yukihiro "Matz" Matsumoto 8c2ea232ea Revert "mruby-enum-ext (cycle): need to splat block parameters; #6508"
This reverts commit 6c4b799b42.
2025-04-07 08:23:52 +09:00
Yukihiro "Matz" Matsumoto 6c4b799b42 mruby-enum-ext (cycle): need to splat block parameters; #6508 2025-04-06 22:05:57 +09:00
Yukihiro "Matz" Matsumoto 96855d31b5 mruby-enum-ext (sum): need to honor index; fix #6508 2025-04-06 22:04:56 +09:00
Yukihiro "Matz" Matsumoto dd68681002 mruby-enum-ext: tally should respect multi-values; fix #6507 2025-04-05 22:12:51 +09:00
Yukihiro "Matz" Matsumoto cb8cd9388c mruby-enum-ext: filter_map should not ignore index; fix #6504 2025-04-05 21:44:49 +09:00
Yukihiro "Matz" Matsumoto 9750513c25 mruby-bigint (mpz_get_str): add type cast to stop warning 2025-04-04 23:55:44 +09:00
Yukihiro "Matz" Matsumoto bf36ba9d10 Merge pull request #6505 from jbampton/fix-spelling
mrbgems: fix spelling
2025-04-04 17:33:32 +09:00
John Bampton b1d910f6f4 mrbgems: fix spelling 2025-04-04 15:05:13 +10:00
Yukihiro "Matz" Matsumoto 76f7678db2 AUTHORS: update entries [ci skip] 2025-04-04 07:56:52 +09:00
Yukihiro "Matz" Matsumoto 07d7aa6fdb mruby-pack: fix int and mrb_int mixture 2025-04-02 16:45:11 +09:00
Yukihiro "Matz" Matsumoto b88680ee9e mruby-pack (pack_unpack): use mrb_bool instead of int 2025-04-02 16:44:06 +09:00
Yukihiro "Matz" Matsumoto 3684a27209 tools/lrama: update to lrama 0.7.0; close #6384 2025-04-02 00:16:23 +09:00
Yukihiro "Matz" Matsumoto 5c2c77c71c mruby-string (str_succ_bang): fixed sample string; close #6500
To avoid spellcheck failure in pre-commit.
2025-04-01 11:00:25 +09:00
Yukihiro "Matz" Matsumoto 4af6fe87c4 doc/mruby3.4.md: remove wrong spelling from the pull-request description 2025-03-31 21:42:01 +09:00
Yukihiro "Matz" Matsumoto 9405702e02 Merge pull request #6503 from jbampton/misc-typo-fixes
misc: fix typos
2025-03-31 16:16:55 +09:00
Yukihiro "Matz" Matsumoto 206eccb828 boxing_word.h: allow 4 byte alignment of object pointers
Only if MRB_WORDBOX_NO_FLOAT_TRUNCATE or MRB_NO_FLOAT is defined.
2025-03-30 23:23:02 +09:00
John Bampton b56f984c25 misc: fix typos 2025-03-30 14:04:34 +10:00
Yukihiro "Matz" Matsumoto 39fbc96eaf Merge pull request #6502 from jbampton/patch-2
pre-commit: update prettier to the latest version
2025-03-29 19:02:42 +09:00
John Bampton 14f2e6db5a pre-commit: update prettier to the latest version
https://www.npmjs.com/package/prettier
2025-03-29 16:31:58 +10:00
Yukihiro "Matz" Matsumoto a317b744f4 Merge pull request #6501 from jbampton/patch-2
Update pre-commit Node.js version to `v22.14.0 LTS`
2025-03-29 14:09:15 +09:00
John Bampton 14de644234 Update pre-commit Node.js version to v22.14.0 LTS 2025-03-29 07:32:47 +10:00
Yukihiro "Matz" Matsumoto 6a3e5b87f8 Merge pull request #6497 from jbampton/patch-2
gha: update `build.yml` try `windows-2025` image
2025-03-28 12:40:40 +09:00
Yukihiro "Matz" Matsumoto a9353c4f73 Merge pull request #6498 from jbampton/pre-commit-clean-up
Clean up and standardize the pre-commit config
2025-03-28 09:02:57 +09:00
Yukihiro "Matz" Matsumoto 2ce0606f14 guides/symbol.md: 'punctuation' is uncountable; close #6488
Issue #6488 is addressed by fixing spelling.
2025-03-28 08:22:53 +09:00
John Bampton c1a0a6193b pre-commit autoupdate 2025-03-28 08:04:21 +10:00
John Bampton 1ae4f94844 Clean up and standardize the pre-commit config 2025-03-28 07:39:59 +10:00
Yukihiro "Matz" Matsumoto 7538ee8f5d gperf: remove obsolete command line options -p and -g 2025-03-28 06:16:00 +09:00
John Bampton 68a0ecc782 gha: update build.yml try windows-2025 image
https://github.com/actions/runner-images?tab=readme-ov-file#available-images

https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md
2025-03-28 04:24:32 +10:00
Yukihiro "Matz" Matsumoto 0090e2cd01 github/workflows/coverage.yml: measure coverage on push only 2025-03-26 16:22:37 +09:00
Yukihiro "Matz" Matsumoto 7351f1127b vm.c: ci_bidx() returns mrb_int, that may be different in size from int 2025-03-26 16:19:26 +09:00
Yukihiro "Matz" Matsumoto d908daa8b9 mruby-rational (rational_hash): hash value is uint32_t 2025-03-25 08:10:49 +09:00
Yukihiro "Matz" Matsumoto b446b0d547 mruby-compiler: add type cast to silence warning 2025-03-25 08:10:04 +09:00
Yukihiro "Matz" Matsumoto a574034cb2 hash.c (hash_set_default_proc): mrb_proc_arity() returns mrb_int 2025-03-25 08:09:21 +09:00
Yukihiro "Matz" Matsumoto 4ca61298ac mruby-sprintf: add type cast to silence warning 2025-03-25 08:08:26 +09:00
Yukihiro "Matz" Matsumoto 7e18b1dadb mruby-fiber/fibertest.c: use ptrdiff_t for pointer difference 2025-03-24 22:31:27 +09:00
Yukihiro "Matz" Matsumoto b8351d6191 mruby-io/file.c: use ptrdiff_t for pointer difference 2025-03-24 22:30:53 +09:00
Yukihiro "Matz" Matsumoto dd2950211c mruby-io/mruby_io_test.c: use -1 for length (means strlen(s)) 2025-03-24 15:19:54 +09:00
Yukihiro "Matz" Matsumoto 4aae7be949 mruby-io (path_gethome): move local variable declarations 2025-03-24 14:03:13 +09:00
Yukihiro "Matz" Matsumoto a33426da15 mruby-io (mrb_file_s_chmod): check string type before casting 2025-03-23 20:04:25 +09:00
Yukihiro "Matz" Matsumoto 11f6251d23 mruby-io (mrb_file_basename): fixed a silly mistake 2025-03-22 13:01:38 +09:00
Yukihiro "Matz" Matsumoto cde0b7edeb Merge pull request #6495 from dearblue/cleanup
Remove `MRB_ENDIAN_LOHI()` that is no longer in use
2025-03-22 11:15:36 +09:00
Yukihiro "Matz" Matsumoto aa06aff50d mruby-io/file.c: use mrb_sys_fail instead of mrb_raise (w/ errno info) 2025-03-22 11:02:05 +09:00
dearblue 4e7399d4f4 Remove MRB_ENDIAN_LOHI() that is no longer in use 2025-03-21 21:56:42 +09:00
Yukihiro "Matz" Matsumoto f3b79fcc23 mruby-io (mrb_file_s_readlink): increase buffer size linearly 2025-03-21 19:34:05 +09:00
Yukihiro "Matz" Matsumoto ca693dec30 mruby-io (mrb_file_s_readlink): when rc == bufsize, rc never be -1 2025-03-21 19:31:12 +09:00
Yukihiro "Matz" Matsumoto 9e315af2a5 mruby-io (mrb_file_basename): fixed wrong strncmp usage 2025-03-21 10:37:05 +09:00
Yukihiro "Matz" Matsumoto 90d4805f5b mruby-io (mrb_file_realpath): use mrb_str_cat instead of mrb_str_append 2025-03-20 22:04:49 +09:00
Yukihiro "Matz" Matsumoto 5bc391e170 mruby-io (mrb_file_basename): use mrb_str_cat() instead of snprintf(3) 2025-03-20 22:03:30 +09:00
Yukihiro "Matz" Matsumoto ed00879923 Merge pull request #6493 from hasumikin/patch-1
Fix TYPO in memory.md
2025-03-20 14:42:56 +09:00
Yukihiro "Matz" Matsumoto dbafada7be mruby-io (mrb_file_basename): use "z" specifier for mrb_get_args() 2025-03-20 13:39:38 +09:00
HASUMI Hitoshi 1ec84a2874 Fix TYPO in memory.md
No `alloc.c` in the source tree. It'd be `allocf.c`
2025-03-20 10:15:20 +09:00
Yukihiro "Matz" Matsumoto 226acdc540 hash.c (mrb_hash_set_default_proc): avoid repeated calls for mrb_nil_p() 2025-03-19 14:57:02 +09:00
Yukihiro "Matz" Matsumoto a55e3685a9 string.c: rename local variable indx to idx
`indx` seems not to be a common abbreviation.
2025-03-18 10:40:30 +09:00
Yukihiro "Matz" Matsumoto c0024e1077 Merge pull request #6492 from jethrodaniel/fix-typo
fix a typo, update specs
2025-03-18 10:40:00 +09:00
Mark Delk 6396aac434 fix a typo, update specs 2025-03-17 10:47:33 -05:00
236 changed files with 30200 additions and 3236 deletions
+3
View File
@@ -0,0 +1,3 @@
[codespell]
ignore-words = .github/linters/codespell.txt
skip = ./build,./doc/api,./doc/capi
+3
View File
@@ -19,8 +19,11 @@ build:
- lib/**/*
- minirake
- tasks/**/*
- .codespellrc
- .dockerignore
- .pre-commit-config.yaml
- .prettierignore
- .prettierrc
- .travis.yml
- .yardopts
core:
+12
View File
@@ -0,0 +1,12 @@
ls:
.c: snake_case
.cpp: snake_case
.h: snake_case
.json: snake_case
.rb: snake_case
.yaml: regex:\.?[a-z]+(-[a-z]+)*
.yml: regex:\.?[a-z]+(-[a-z]+)*
ignore:
- build_config
- mrbgems/mruby-compiler/core/y.tab.c
+2 -1
View File
@@ -22,7 +22,8 @@ jobs:
- {os: ubuntu-22.04, cc: clang, cxx: clang++}
- {os: macos-15, cc: clang, cxx: clang++}
- {os: macos-14, cc: clang, cxx: clang++}
- {os: windows-latest, cc: gcc, cxx: g++, altname: "mingw-gcc"}
- {os: windows-2025, cc: gcc, cxx: g++, altname: "mingw-gcc"}
- {os: windows-2022, cc: gcc, cxx: g++, altname: "mingw-gcc"}
env:
MRUBY_CONFIG: ci/gcc-clang
CC: ${{ matrix.cc }}
+1 -1
View File
@@ -1,6 +1,6 @@
name: Coverage
on: [push, pull_request]
on: [push]
jobs:
coverage:
+8
View File
@@ -25,3 +25,11 @@ jobs:
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: Run pre-commit
run: pre-commit run --all-files
ls-lint:
name: Run ls-lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ls-lint/action@v2.3.1
with:
config: .github/linters/.ls-lint.yml
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
# Full git history is needed to get a proper list of changed files within `super-linter`
fetch-depth: 0
- name: Lint Code Base
uses: super-linter/super-linter/slim@v7.3.0
uses: super-linter/super-linter/slim@v7.4.0
env:
# VALIDATE_BASH_EXEC: true
VALIDATE_DOCKERFILE_HADOLINT: true
-1
View File
@@ -37,4 +37,3 @@ node_modules
perf.data*
tags
!Gemfile.lock
y.tab.c
+23 -15
View File
@@ -4,15 +4,19 @@ default_stages: [pre-commit, pre-push]
default_language_version:
# force all unspecified Python hooks to run python3
python: python3
node: 22.2.0
# force all unspecified Node hooks to run Node.js v22.15.0 LTS
node: 22.15.0
minimum_pre_commit_version: "3.2.0"
exclude: "^tools/lrama/"
repos:
- repo: meta
hooks:
- id: identity
name: run identity check
name: run identity
description: check your identity
- id: check-hooks-apply
name: check hooks apply to the repository
name: run check-hooks-apply
description: check hooks apply to the repository
- repo: local
hooks:
- id: prettier
@@ -21,17 +25,19 @@ repos:
entry: prettier --write .
files: \.(json|md|ya?ml)$
language: node
additional_dependencies: ["prettier@3.3.3"]
additional_dependencies: ["prettier@3.5.3"]
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.0
rev: v8.25.1
hooks:
- id: gitleaks
name: detect hardcoded secrets
name: run gitleaks
description: detect hardcoded secrets with gitleaks
- repo: https://github.com/shssoichiro/oxipng
rev: v9.1.4
rev: v9.1.5
hooks:
- id: oxipng
name: run oxipng
description: use lossless compression to optimize PNG files
args: ["-o", "4", "--strip", "safe", "--alpha"]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
@@ -64,10 +70,12 @@ repos:
rev: v1.5.5
hooks:
- id: forbid-tabs
name: no-tabs checker
name: run no-tabs checker
description: check the codebase for tabs
exclude: Makefile$
- id: remove-tabs
name: tabs remover
name: run tabs remover
description: find and convert tabs to spaces
args: [--whitespaces-count, "2"]
exclude: Makefile$
- repo: https://github.com/rhysd/actionlint
@@ -81,8 +89,7 @@ repos:
hooks:
- id: codespell
name: run codespell
description: Check spelling with codespell
args: [--ignore-words=.github/linters/codespell.txt]
description: check spelling with codespell
- repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0
hooks:
@@ -95,7 +102,7 @@ repos:
hooks:
- id: markdownlint
name: run markdownlint
description: Checks the style of Markdown files
description: checks the style of Markdown files
args: [--config=.github/linters/.markdown-lint.yml]
types: [markdown]
files: \.md$
@@ -104,7 +111,7 @@ repos:
hooks:
- id: markdown-link-check
name: run markdown-link-check
description: Checks hyperlinks in Markdown files
description: checks hyperlinks in Markdown files
args: [--config=.github/linters/mlc_config.json, -q]
types: [markdown]
files: \.md$
@@ -113,12 +120,13 @@ repos:
hooks:
- id: shellcheck
name: run shellcheck
description: check shell scripts with a static analysis tool
- repo: https://github.com/adrienverge/yamllint
rev: v1.36.0
rev: v1.37.0
hooks:
- id: yamllint
name: run yamllint
description: Check YAML files with yamllint
description: check YAML files with yamllint
args: [--strict, -c=.github/linters/.yaml-lint.yml]
types: [yaml]
files: \.ya?ml$
+1
View File
@@ -2,3 +2,4 @@
build
coverage
doc/internal/opcode.md
tools/lrama
+15 -10
View File
@@ -1,17 +1,17 @@
# Authors of mruby (mruby developers)
## The List of Contributors sorted by number of commits (as of 2025-03-01 8ba2ed6)
## The List of Contributors sorted by number of commits (as of 2025-06-03 a3e7280)
6083 Yukihiro "Matz" Matsumoto (@matz)*
673 dearblue (@dearblue)*
6258 Yukihiro "Matz" Matsumoto (@matz)*
681 dearblue (@dearblue)*
587 KOBAYASHI Shuji (@shuujii)
353 Daniel Bovensiepen (@bovi)*
345 Takeshi Watanabe (@take-cheeze)*
333 Masaki Muranaka (@monaka)
234 Jun Hiroe (@suzukaze)
233 John Bampton (@jbampton)
228 Tomoyuki Sahara (@tsahara)*
220 Cremno (@cremno)*
219 John Bampton (@jbampton)
209 Yuki Kurihara (@ksss)+
144 Yasuhiro Matsumoto (@mattn)*
113 Carson McDonald (@carsonmcdonald)
@@ -19,9 +19,9 @@
83 Akira Yumiyama (@akiray03)*
83 skandhas (@skandhas)
80 Masamitsu MURASE (@masamitsu-murase)
73 Hiroshi Mimaki (@mimaki)*
71 Tatsuhiko Kubo (@cubicdaiya)*
71 Yuichiro MASUI (@masuidrive)
69 Hiroshi Mimaki (@mimaki)*
62 Yuichiro Kaneko (@yui-knk)+
59 Kurebayashi, Takahiro (@crimsonwoods)*
56 h2so5 (@h2so5)
@@ -49,6 +49,7 @@
18 Corey Powell (@IceDragon200)
18 Hidetaka Takano (@TJ-Hidetaka-Takano)
18 Jon Maken (@jonforums)+
18 leviongit (@leviongit)
18 mirichi (@mirichi)
17 Mitchell Blank Jr (@mitchblank)*
16 bggd (@bggd)
@@ -58,9 +59,9 @@
14 Kazuki Tsujimoto (@k-tsj)
14 Tadashi FUKUZAWA (@FUKUZAWA-Tadashi)+
14 fn ⌃ ⌥ (@FnControlOption)
14 leviongit (@leviongit)
13 Jose Narvaez (@goyox86)
13 Patrick Hogan (@pbhogan)
13 google-labs-jules[bot] (@google-jules)
12 Akira Kuroda (@akuroda)
12 Kouki Ooyatsu (kaishuu0123)*
12 NAKAMURA Usaku (@unak)*
@@ -89,10 +90,12 @@
7 Simon Génier (@simon-shopify)
7 Terence Lee (@hone)
7 roco (@rystyle)*
7 vickash (@vickash)
6 Akito Mochizuki (@ak-mochi)
6 Beoran (@beoran)
6 David Siaw (@davidsiaw)*
6 Frederick John Milens III (@fjmilens3)
6 HASUMI Hitoshi (@hasumikin)
6 Hiro Asari (@BanzaiMan)
6 INOUE Yasuyuki (@yasuyuki)
6 Junji Sawada (@junjis0203)
@@ -113,11 +116,9 @@
5 Yurie Yamane (@yurie)+
5 dreamedge (@dreamedge)
5 nkshigeru (@nkshigeru)
5 vickash (@vickash)
5 xuejianqing (@joans321)
4 Dante Catalfamo (@dantecatalfamo)
4 Goro Kikuchi (@gorogit)
4 HASUMI Hitoshi (@hasumikin)
4 Herwin Weststrate (@herwinw)
4 Horimoto Yasuhiro (@komainu8)
4 Jon Moss (@maclover7)
@@ -126,6 +127,7 @@
4 Lanza (@LanzaSchneider)
4 Li Yazhou (@flaneur2020)
4 Marcus Stollsteimer (@stomar)
4 Mark Delk (@jethrodaniel)
4 NARUSE, Yui (@nurse)
4 Ravil Bayramgalin (@brainopia)*+
4 Satoshi Odawara (@SatoshiOdawara)
@@ -139,11 +141,11 @@
3 Daniel K. Sierpiński (@513ry)+
3 David Turnbull (@AE9RB)
3 Franck Verrot (@franckverrot)
3 Hirohito Higashi (@HirohitoHigashi)
3 J. Mutua (@katmutua)+
3 Jan Berdajs (@mrbrdo)
3 Jonas Minnberg (@sasq64)
3 Joseph McCullough (@joequery)
3 Mark Delk (@jethrodaniel)
3 Mark McCurry (@fundamental)
3 Nobuhiro Iwamatsu (@iwamatsu)
3 Per Lundberg (@perlun)*
@@ -171,7 +173,6 @@
2 Francois Chagnon (@EiNSTeiN-)*
2 Gilad Zohari (@gzohari)
2 Go Saito (@govm)
2 Hirohito Higashi (@HirohitoHigashi)
2 Hiroyuki Iwatsuki (@iwadon)
2 Huei-Horng Yo (@hiroshiyui)
2 Jonas Kulla (@Ancurio)
@@ -209,6 +210,7 @@
1 Atsushi Morimoto (@mynz)
1 Ben A Morgan (@BenMorganIO)
1 Benoit Daloze (@eregon)
1 Bradley Whited (@esotericpig)
1 Colin MacKenzie IV (@sinisterchipmunk)
1 Daehyub Kim (@lateau)
1 Daniel Varga (@vargad)
@@ -265,10 +267,12 @@
1 Patrick Ellis (@pje)
1 Patrick Pokatilo (@SHyx0rmZ)
1 Pavel Evstigneev (@Paxa)+
1 Paweł Świątkowski (@katafrakt)
1 Pete Kinnecom (@petekinnecom)
1 Prayag Verma (@pra85)
1 Ranmocy (@ranmocy)
1 Robert McNally (@wolfmcnally)
1 Ryan Davis (@zenspider)
1 Ryan Scott Lewis (@RyanScottLewis)
1 Ryo Okubo (@syucream)
1 SAkira a.k.a. Akira Suzuki (@sakisakira)
@@ -303,6 +307,7 @@
1 arton (@arton)
1 duangsuse (@duangsuse)
1 fl0l0u (@fl0l0u)
1 hasse (@hasse09052)
1 hhc0null (@hhc0null)
1 iTitou (@titouanc)
1 javier ramírez (@javier)
+1 -1
View File
@@ -12,7 +12,7 @@ things in mind before submitting your pull request:
- Create a branch which is dedicated to your change
- Test your changes before creating a pull request (`rake test`)
- If possible write a test case which confirms your change
- Don't mix several features or bug-fixes in one pull request
- Don't mix several features or bugfixes in one pull request
- Create a meaningful commit message
- Explain your change (i.e. with a link to the issue you are fixing)
- Use mrbgem to provide non ISO features (classes, modules and methods) unless
+1 -1
View File
@@ -48,7 +48,7 @@ PROJECT_NAME = mruby
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 3.3.0
PROJECT_NUMBER = 3.4.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+1 -1
View File
@@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
coderay (1.1.3)
rake (13.2.1)
rake (13.3.0)
yard (0.9.37)
yard-coderay (0.1.0)
coderay
+236 -171
View File
@@ -1,189 +1,254 @@
NEWS
----
# User visible changes in `mruby3.3` from `mruby3.2`
# User visible changes in `mruby3.4` from `mruby3.3`
"**_NOTE_**:" are changes to be aware of.
# The language
- aliases work properly with `super` ([2ad3f0e](https://github.com/mruby/mruby/commit/2ad3f0e))
- `callee` method work differently with aliases in mruby ([f2dc76e](https://github.com/mruby/mruby/commit/f2dc76e))
- define `Kernel#respond_to_missing?` method ([347586e](https://github.com/mruby/mruby/commit/347586e))
- `_inspect` method (`inspect` with recursive check) is removed
([e2bbf75](https://github.com/mruby/mruby/commit/e2bbf75), [5cb0c74](https://github.com/mruby/mruby/commit/5cb0c74), [113565a](https://github.com/mruby/mruby/commit/113565a),
[0713f2a](https://github.com/mruby/mruby/commit/0713f2a), [6ae6b63](https://github.com/mruby/mruby/commit/6ae6b63), [fc9fffc](https://github.com/mruby/mruby/commit/fc9fffc))
- `__printstr__` method is removed; use `print` instead
([acecee0](https://github.com/mruby/mruby/commit/acecee0), [192e6e3](https://github.com/mruby/mruby/commit/192e6e3))
- New method `String#bytesplice` ([5274647](https://github.com/mruby/mruby/commit/5274647), [a2e2e83](https://github.com/mruby/mruby/commit/a2e2e83))
- Allow `return` in blocks to cross C boundaries ([#6125](https://github.com/mruby/mruby/pull/6125))
# Configuration
- mruby can be built using Docker now. Try `docker-compose build` for example. ([#5961](https://github.com/mruby/mruby/pull/5961))
- New Platform: DJGPP (MS-DOS) ([#6022](https://github.com/mruby/mruby/pull/6022))
- New Platform: Nintendo Wii ([#6086](https://github.com/mruby/mruby/pull/6086))
- Improved Platform: Android ([#6013](https://github.com/mruby/mruby/pull/6013))
- Improved Platform: Dreamcast ([#6130](https://github.com/mruby/mruby/pull/6130))
- Allow tests to be disabled for specific gems; warn about disabled tests ([#6012](https://github.com/mruby/mruby/pull/6012))
- Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH` ([#5902](https://github.com/mruby/mruby/pull/5902))
# mruby memory API
- `mrb_default_allocf` can be overridden by the application ([34c5d96](https://github.com/mruby/mruby/commit/34c5d96))
- `mrb_open_allocf` will be deprecated ([cfee5c2](https://github.com/mruby/mruby/commit/cfee5c2))
- mruby now supports `private` and `protected` visibility ([b0db0bd](https://github.com/mruby/mruby/commit/b0db0bd))
- Maximum length of inlined symbols reduced from 5 to 4 characters to provide space for visibility flags ([6442a01](https://github.com/mruby/mruby/commit/6442a01))
- Many methods are made private according to CRuby visibility ([4a0e806](https://github.com/mruby/mruby/commit/4a0e806))
- Generate OP_SSEND for `self.method` type calls ([111fe4b](https://github.com/mruby/mruby/commit/111fe4b))
- `initialize` method will be always private ([eb8b412](https://github.com/mruby/mruby/commit/eb8b412))
- Add new hooks `method_removed`, `method_undefined` ([9c74f6e](https://github.com/mruby/mruby/commit/9c74f6e))
- Add new hooks `singleton_method_removed`, `singleton_method_undefined` ([0863c08](https://github.com/mruby/mruby/commit/0863c08))
- Updated `OP_DEF` output from codedump ([3a3e877](https://github.com/mruby/mruby/commit/3a3e877))
- Better handling of binary strings, e.g. String#b ([b0127f0](https://github.com/mruby/mruby/commit/b0127f0))
- Hash `to_s` format has changed ([baeeb5e](https://github.com/mruby/mruby/commit/baeeb5e))
- Some encoding related method such as `#force_encoding` ([e47b4ca](https://github.com/mruby/mruby/commit/e47b4ca)), `#b` ([b0127f0](https://github.com/mruby/mruby/commit/b0127f0))
- Constant folding for `String#+` ([6687bdd](https://github.com/mruby/mruby/commit/6687bdd))
- Remove Float bit-operation ([db8368f](https://github.com/mruby/mruby/commit/db8368f))
- use SWAR technique for strlen performance ([cbb31e6](https://github.com/mruby/mruby/commit/cbb31e6))
- use merge sort for `Array#sort` ([5bd63d6](https://github.com/mruby/mruby/commit/5bd63d6))
# Changes in C API
- add new error handling API functions ([8c8bbd9](https://github.com/mruby/mruby/commit/8c8bbd9))
- Add `mrb_vm_ci_env_clear()` function with `MRB_API` ([#5945](https://github.com/mruby/mruby/pull/5945))
- a new function `mrb_check_frozen_value()` ([ccdf75c](https://github.com/mruby/mruby/commit/ccdf75c))
- avoid formatting in `mrb_bug()` ([82a48bd](https://github.com/mruby/mruby/commit/82a48bd)) <br>
**_NOTE_**: If you are using it, you must give a simple string or replace it with a call to `mrb_raise()` series.
- stop using `mrbc_` prefix for compiler context ([c5e3cbe](https://github.com/mruby/mruby/commit/c5e3cbe)) <br>
The same names are provided as before, but we recommend replacing them.
- Allow `Class#allocate` to be prohibited
([#5979](https://github.com/mruby/mruby/pull/5979), [#6122](https://github.com/mruby/mruby/pull/6122), [#6123](https://github.com/mruby/mruby/pull/6123)) <br>
To disable `#allocate`, use `MRB_UNDEF_ALLOCATOR()`.
This is also automatically applied when the subclass is created, but to explicitly allow it, use `MRB_DEFINE_ALLOCATOR()`.
- pool.c renamed to mempool.c (and mrb_pool to mrb_mempool) ([49525fa](https://github.com/mruby/mruby/commit/49525fa))
- mrb_pool_value renamed to mrb_irep_pool to reduce confusion ([62ef5db](https://github.com/mruby/mruby/commit/62ef5db))
- rename BOXNIX_SET_VALUE to BOXNO_SET_VALUE ([#6397](https://github.com/mruby/mruby/pull/6397))
- `MRB_FROZEN_P()` is replaced by `mrb_frozen_p()` ([c11d18e](https://github.com/mruby/mruby/commit/c11d18e))
- rename `color` to `gc_color` ([0e79f6b](https://github.com/mruby/mruby/commit/0e79f6b), [1e36d76](https://github.com/mruby/mruby/commit/1e36d76))
- add `obj->frozen` instead of flags `MRB_SET_FROZEN_FLAG`/`MRB_UNSET_FROZEN_FLAG` ([8276143](https://github.com/mruby/mruby/commit/8276143))
# Build & Configuration
- New Build Target: `test:run:serial`, `test:run:serial:lib`, `test:run:serial:bin` ([#6423](https://github.com/mruby/mruby/pull/6423))
- New Platform: PlayStation Portable ([#6022](https://github.com/mruby/mruby/pull/6465))
- New Platform: emscripten ([#6487](https://github.com/mruby/mruby/pull/6487))
- New Config: no-float (with MRB_NO_FLOAT) ([32200f1](https://github.com/mruby/mruby/commit/32200f1))
# Changes in mrbgems
- **default.gembox**: Add mruby debugger mrdb (`mruby-bin-debugger`) ([#5966](https://github.com/mruby/mruby/pull/5966))
- **mruby-bin-config**: new options `--cxx`, `--cxxflags`, `--as`, `--asflags`, `--objc`, `--objcflags` ([#6054](https://github.com/mruby/mruby/pull/6054))
- **mruby-binding**: renamed from `mruby-binding-core` of mruby3.2 ([11af5db](https://github.com/mruby/mruby/commit/11af5db)) <br>
**_NOTE_**: If using `mruby-binding-core` of mruby 3.2, replace it with `mruby-binding`.
- **mruby-binding**: implemented `Binding#initialize_copy` method ([#5517](https://github.com/mruby/mruby/pull/5517))
- **mruby-binding**: `Kernel#binding` responds only to calls from Ruby ([#5981](https://github.com/mruby/mruby/pull/5981))
- **mruby-compar-ext**: Comparable#clamp to accept nil as arguments ([836bebc](https://github.com/mruby/mruby/commit/836bebc))
- **mruby-compiler**: add print name for identifier tokens ([d7b2e3a](https://github.com/mruby/mruby/commit/d7b2e3a))
- **mruby-data**: allow empty Data ([927a9df](https://github.com/mruby/mruby/commit/927a9df))
- **mruby-enumerator**: remove internal attribute methods `obj`, `args`, `kwd`, `meth`, `fib`. ([735fa24](https://github.com/mruby/mruby/commit/735fa24))
- **mruby-enumerator**: add Enumerator#size ([861f8bd](https://github.com/mruby/mruby/commit/861f8bd))
- **mruby-eval**: merged `mruby-binding` of mruby3.2 ([501b22a](https://github.com/mruby/mruby/commit/501b22a), [#5989](https://github.com/mruby/mruby/pull/5989)) <br>
**_NOTE_**: If using `mruby-binding` of mruby 3.2, replace it with `mruby-eval`.
- **mruby-fiber**: Add a new `mrb_fiber_new()` with `MRB_API` ([#6097](https://github.com/mruby/mruby/pull/6097))
- **mruby-fiber**: Allows calling `Fiber#resume` from C ([#6106](https://github.com/mruby/mruby/pull/6106))
- **mruby-fiber**: `Fiber#to_s` format changed ([#6105](https://github.com/mruby/mruby/pull/6105))
- **mruby-io**: add File#atime and File#ctime ([321cfe9](https://github.com/mruby/mruby/commit/321cfe9))
- **mruby-io**: Add "x" mode option for `IO.open` ([#6081](https://github.com/mruby/mruby/pull/6081))
- **mruby-io**: File.new should not take blocks ([53de964](https://github.com/mruby/mruby/commit/53de964))
- **mruby-method**: `Method#to_s` format changed ([f5bc82f](https://github.com/mruby/mruby/commit/f5bc82f), [02f189c](https://github.com/mruby/mruby/commit/02f189c))
- **mruby-numeric-ext**: `int.pow(n,m)` to take bigint as exponential ([d482eab](https://github.com/mruby/mruby/commit/d482eab))
- **mruby-pack**: support new directives `j`, `J`, `b`, `B`, `#`
([2a1e3a5](https://github.com/mruby/mruby/commit/2a1e3a5), [e7021f1](https://github.com/mruby/mruby/commit/e7021f1), [e17f325](https://github.com/mruby/mruby/commit/e17f325))
- **mruby-range-ext**: new method `Range#overlap?` ([384d0e2](https://github.com/mruby/mruby/commit/384d0e2))
- **mruby-string-ext**: Add `String#valid_encoding?` method ([eabe2d9](https://github.com/mruby/mruby/commit/eabe2d9))
- **mruby-struct**: allow empty Struct when a name is not given ([c212ede](https://github.com/mruby/mruby/commit/c212ede))
- **mruby-time**: should allow year before 1900 ([e5de08b](https://github.com/mruby/mruby/commit/e5de08b))
- **mruby-time**: support bigint to time_t if necessary ([7096d27](https://github.com/mruby/mruby/commit/7096d27))
- **mruby-time**: need to handle negative time_t ([b064d7e](https://github.com/mruby/mruby/commit/b064d7e))
- **mruby-print**: removed; if you do not use `mruby-io`, mruby use `#print` etc. in the core ([8c8bbd9](https://github.com/mruby/mruby/commit/8c8bbd9))
- **mruby-enum-lazy**: Add Enumerable::Lazy#grep_v to mruby-enum-lazy ([#6171](https://github.com/mruby/mruby/pull/6171))
- **mruby-io**: Add `level` argument to `File.dirname` ([#6463](https://github.com/mruby/mruby/pull/6463))
- **mruby-io**: File.absolute_path? ([#6482](https://github.com/mruby/mruby/pull/6482))
- **mruby-io**: File.absolute_path ([96113a2](https://github.com/mruby/mruby/commit/96113a2))
- **mruby-toplevel-ext**: top-level public/private/protected moved to the core ([2a876d2](https://github.com/mruby/mruby/commit/2a876d2))
- **mruby-metaprog**: method list methods now works according to the visibility ([9229da1](https://github.com/mruby/mruby/commit/9229da1))
- **mruby-metaprog**: `public_instance_methods`, `private_instance_methods`, `protected_instance_methods` ([9e3e7b2](https://github.com/mruby/mruby/commit/9e3e7b2))
- **mruby-encoding**: MRB_UTF8_STRING turned on automatically with this gem ([74bdae9](https://github.com/mruby/mruby/commit/74bdae9))
# Changes in build system
# Fixed GitHub Issues
- Extended `rake install` task ([#5928](https://github.com/mruby/mruby/pull/5928)) <br>
**_NOTE_**: Due to this impact, executable files in the `mruby/bin/` directory by default are now symbolic links (batch files on Windows).
If previously relied on those executables, should be replaced with direct references to the entity created under the build directory (e.g. `mruby/build/host/bin/`).
- Encode and decode escape characters for presym ([#6011](https://github.com/mruby/mruby/pull/6011))
- Rakefile: remove default build target directories in `deep_clean` ([#6032](https://github.com/mruby/mruby/pull/6032), [1e38569](https://github.com/mruby/mruby/commit/1e38569))
- [#6173](https://github.com/mruby/mruby/issues/6173) Fails to build with tcc(Tiny C Compiler)
- [#6156](https://github.com/mruby/mruby/issues/6156) '/LIBPATH' issue
- [#6183](https://github.com/mruby/mruby/issues/6183) ".e".to_f returns NAN
- [#6182](https://github.com/mruby/mruby/issues/6182) mrb_read_float() converts "0.3" with a small error compared to strtod()
- [#6210](https://github.com/mruby/mruby/issues/6210) Unary minus seems broken
- [#6255](https://github.com/mruby/mruby/issues/6255) Wrong number of characters in broken UTF-8 string
- [#4038](https://github.com/mruby/mruby/issues/4038) Heap buffer overflow in OP_ENTER
- [#6262](https://github.com/mruby/mruby/issues/6262) Unable to define == for objects when using Array#delete
- [#6267](https://github.com/mruby/mruby/issues/6267) When MRB_UTF8_STRING is enabled, giving byte characters for String#index and String#split gives wrong results
- [#6277](https://github.com/mruby/mruby/issues/6277) MSVC: can't use malloc() in string.c with WIN32_LEAN_AND_MEAN
- [#6240](https://github.com/mruby/mruby/issues/6240) Differentiate between lib and lib64 in the build settings.
- [#6304](https://github.com/mruby/mruby/issues/6304) Calling method_missing with only Kwargs passes arguments incorrectly
- [#6317](https://github.com/mruby/mruby/issues/6317) mrb_gc_register() may cause GC and collect the object being protected
- [#6307](https://github.com/mruby/mruby/issues/6307) Planned change patch for mrb_vm_exec()
- [#6298](https://github.com/mruby/mruby/issues/6298) foo :bar {} is legal in mruby?
- [#6326](https://github.com/mruby/mruby/issues/6326) Detect “Use-after-free” with address sanitizer
- [#5358](https://github.com/mruby/mruby/issues/5358) static warning from getpwnam
- [#6339](https://github.com/mruby/mruby/issues/6339) mrb_ary_delete() may refer to an invalid address (use-after-free)
- [#6346](https://github.com/mruby/mruby/issues/6346) Block kwargs are passed as last positional arg when using yield
- [#6365](https://github.com/mruby/mruby/issues/6365) powl() not available when compiling for Dreamcast
- [#6369](https://github.com/mruby/mruby/issues/6369) 100x Performance Regression from 3.1
- [#6270](https://github.com/mruby/mruby/issues/6270) NODE_ZSUPER from deeply nested blocks will result in a truncated digits for block index in OP_ARGARY
- [#6297](https://github.com/mruby/mruby/issues/6297) Assigning to a block variable changes the actual block (thus affecting block_given? and yield)
- [#6389](https://github.com/mruby/mruby/issues/6389) instance_exec named block args don't work properly
- [#6388](https://github.com/mruby/mruby/issues/6388) Recent commit broke my windows build
- [#6411](https://github.com/mruby/mruby/issues/6411) Wrong function unwinding when using return in a block
- [#6439](https://github.com/mruby/mruby/issues/6439) OP_JMPUW does not call the ensure block when it jumps to the beginning of the begin block
- [#6441](https://github.com/mruby/mruby/issues/6441) break inside while loop will execute the ensure block outside of the while loop
- [#6453](https://github.com/mruby/mruby/issues/6453) Bigint: incorrect behavior of ^ operator
- [#6452](https://github.com/mruby/mruby/issues/6452) Bigint: weird mod behavior
- [#6451](https://github.com/mruby/mruby/issues/6451) Bigint: incorrect division behavior
- [#6456](https://github.com/mruby/mruby/issues/6456) bigint: bug with division of a small number by a bigint
- [#6466](https://github.com/mruby/mruby/issues/6466) mruby-bin-mruby using Kernel#p and Kernel#print in bintest fails test
- [#6467](https://github.com/mruby/mruby/issues/6467) Heap-Use-After-Free due to Recursive group_by Calls
- [#6471](https://github.com/mruby/mruby/issues/6471) Discrepancy in codegen for binary operations between master branch and 3.3.0
- [#6477](https://github.com/mruby/mruby/issues/6477) heap-buffer-overflow in mrb_vm_exec
- [#6485](https://github.com/mruby/mruby/issues/6485) Hash#rehash does not check if the hash is frozen
- [#6483](https://github.com/mruby/mruby/issues/6483) Hash#default_proc= accepts arbitrary objects that are not callable
- [#6491](https://github.com/mruby/mruby/issues/6491) Destroy existing string literals when composing string literals
# Other breaking changes
# Merged Pull Requests (User Visible Ones)
- `mrb_f_raise()` is now an internal function
([#5923](https://github.com/mruby/mruby/pull/5923), [#6070](https://github.com/mruby/mruby/pull/6070))
- `mrb_make_exception()` is now an internal function with different parameters
([431f83e](https://github.com/mruby/mruby/commit/431f83e), [78137f3](https://github.com/mruby/mruby/commit/78137f3))
- The `File#path` method no longer uses the `#to_path` method for implicit conversion
([d86c4a7](https://github.com/mruby/mruby/commit/d86c4a7))
- stop mrb isolation for each test file ([a20fbe5](https://github.com/mruby/mruby/commit/a20fbe5))
- RBreak remembers the CI location ([#6103](https://github.com/mruby/mruby/pull/6103))
# Bugs Fixed
- [#5724](https://github.com/mruby/mruby/issues/5724) Rational#\*\* is missing
- [#5725](https://github.com/mruby/mruby/issues/5725) weird const_missing exceptions in mrblib code
- [#5789](https://github.com/mruby/mruby/issues/5789) No memory release of backtrace information due to stack error
- [#5932](https://github.com/mruby/mruby/issues/5932) How to create a block using the C API? mrb_yield keeps crashing!
- [#5943](https://github.com/mruby/mruby/issues/5943) TCPSocket#write is failed
- [#5944](https://github.com/mruby/mruby/issues/5944) Behavior of calling method with a hash variable
- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
- [#5949](https://github.com/mruby/mruby/issues/5949) Caller appears to report wrong line when block passed and brackets omitted
- [0906cd7](https://github.com/mruby/mruby/commit/0906cd7) numeric.c: fix rounding function issues with big numbers
- [#5974](https://github.com/mruby/mruby/issues/5974) Invalid escape sequences in gem_init.c on windows
- [#5975](https://github.com/mruby/mruby/issues/5975) Equals comparison fails on extreme ends of 64-bit integers
- [#5985](https://github.com/mruby/mruby/issues/5985) Sign extension with OP_LOADI32 in get_int_operand()
- [#5986](https://github.com/mruby/mruby/issues/5986) Fix bugs in String#bytesplice
- [#5987](https://github.com/mruby/mruby/issues/5987) ~(-1 << 64) is incorrect
- [#5991](https://github.com/mruby/mruby/issues/5991) 'gets' method not working in mruby-3.2.0
- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
- [#5995](https://github.com/mruby/mruby/issues/5995) One seemingly unnecessary parameter is passed in the block parameters
- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
- [b47c8b7](https://github.com/mruby/mruby/commit/b47c8b7) gc.c (clear_all_old): fix a generational GC bug
- [#6029](https://github.com/mruby/mruby/issues/6029) mruby build fails under mrbgems directory
- [a264965](https://github.com/mruby/mruby/commit/a264965) mruby-os-memsize/memsize.c: fix irep size calculation
- [3310e10](https://github.com/mruby/mruby/commit/3310e10) mruby-test/mrbgem.rake: fix mrb_state handling bug
- [#6041](https://github.com/mruby/mruby/issues/6041) GC Performance may have degraded
- [#6044](https://github.com/mruby/mruby/issues/6044) Generated presym/table.h contains invalid characters
- [#6051](https://github.com/mruby/mruby/issues/6051) Null pointer dereference in mrb_addrinfo_unix_path
- [#6052](https://github.com/mruby/mruby/issues/6052) Null pointer dereference while handling the Proc class
- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
- [#6060](https://github.com/mruby/mruby/issues/6060) SEGFAULT Issue Related to Fiber Usage in ngx_mruby Development
- [#6061](https://github.com/mruby/mruby/issues/6061) Performance issue in String#codepoints
- [#6064](https://github.com/mruby/mruby/issues/6064) MRUBY_PACKAGE_DIR does not always have a value.
- [#6065](https://github.com/mruby/mruby/issues/6065) Null pointer dereference while handling the Proc class
- [#6066](https://github.com/mruby/mruby/issues/6066) Null pointer dereference involving Struct.new()
- [#6067](https://github.com/mruby/mruby/issues/6067) Null pointer dereference in mrb_string_value_cstr
- [#6068](https://github.com/mruby/mruby/issues/6068) Stack overflow in mrb_vm_exec
- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
- [#6084](https://github.com/mruby/mruby/issues/6084) Incorrect symbolic sinks in binary built on Linux
- [#6087](https://github.com/mruby/mruby/issues/6087) 'Remote branch HEAD not found in upstream origin' error on build
- [#6089](https://github.com/mruby/mruby/issues/6089) binding.eval() handles def expressions differently from CRuby
- [#6098](https://github.com/mruby/mruby/issues/6098) Fails to call superclass of wrapped method
- [#6099](https://github.com/mruby/mruby/issues/6099) `ensure` section is not executed if the function exits via a return in a proc
- [#6108](https://github.com/mruby/mruby/issues/6108) VM crashes with break
- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
- [#6134](https://github.com/mruby/mruby/issues/6134) String#unpack1 returns an array instead of a single string
- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
# Pull Requests (User Visible Ones)
- [#5517](https://github.com/mruby/mruby/pull/5517) Fixed local variables not separated between copied binding objects
- [#5902](https://github.com/mruby/mruby/pull/5902) Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH`
- [#5923](https://github.com/mruby/mruby/pull/5923) Demotion `mrb_f_raise()` from `MRB_API`
- [#5928](https://github.com/mruby/mruby/pull/5928) Improved `rake install`
- [#5945](https://github.com/mruby/mruby/pull/5945) Avoid exposure for `REnv` objects
- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
- [#5966](https://github.com/mruby/mruby/pull/5966) Update default.gembox add mruby debugger mrdb
- [#5979](https://github.com/mruby/mruby/pull/5979) Allow Class#allocate to be prohibited
- [#5981](https://github.com/mruby/mruby/pull/5981) `Kernel#binding` responds only to calls from Ruby
- [#5989](https://github.com/mruby/mruby/pull/5989) Integrate mruby-binding-eval into mruby-eval
- [#5961](https://github.com/mruby/mruby/pull/5961) Add Docker to build and run all mruby tests. Run pre-commit and generate YARD docs with Docker
- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
- [#6009](https://github.com/mruby/mruby/pull/6009) Avoid adding <MRUBY_ROOT>/bintest which does not exist
- [#6011](https://github.com/mruby/mruby/pull/6011) Encode and decode escape characters for presym
- [#6012](https://github.com/mruby/mruby/pull/6012) Allow tests to be disabled for specific gems; warn about disabled tests
- [#6013](https://github.com/mruby/mruby/pull/6013) Fix Android toolchain
- [#6022](https://github.com/mruby/mruby/pull/6022) Build configuration for MS-DOS and DJGPP
- [#6032](https://github.com/mruby/mruby/pull/6032) Rake: update task clean to remove bin and build folders
- [#6045](https://github.com/mruby/mruby/pull/6045) Fixes escape sequence bug and enhancements in Presym scanning
- [#6054](https://github.com/mruby/mruby/pull/6054) Extends `bin/mruby-config`
- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
- [#6070](https://github.com/mruby/mruby/pull/6070) Demotion mrb_f_raise() in kernel.c from MRB_API too
- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
- [#6081](https://github.com/mruby/mruby/pull/6081) Add "x" mode option for IO.open
- [#6086](https://github.com/mruby/mruby/pull/6086) Add build config for Nintendo Wii
- [#6097](https://github.com/mruby/mruby/pull/6097) Add a new mrb_fiber_new() with MRB_API
- [#6103](https://github.com/mruby/mruby/pull/6103) RBreak remembers the CI location
- [#6105](https://github.com/mruby/mruby/pull/6105) Implement `Fiber#to_s` method
- [#6106](https://github.com/mruby/mruby/pull/6106) Ease fiber limitations
- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
- [#6122](https://github.com/mruby/mruby/pull/6122) Prohibit `Class#allocate` in a different way
- [#6123](https://github.com/mruby/mruby/pull/6123) Inherit `MRB_FL_UNDEF_ALLOCATE` in subclasses
- [#6125](https://github.com/mruby/mruby/pull/6125) Allow `OP_RETURN_BLK` to cross C boundaries
- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
- [#6130](https://github.com/mruby/mruby/pull/6130) `dreamcast_shelf build config`: complete overhaul
- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
- [#6171](https://github.com/mruby/mruby/pull/6171) Add Enumerable::Lazy#grep_v to mruby-enum-lazy
- [#6174](https://github.com/mruby/mruby/pull/6174) Fix MRUBY_PACKAGE_DIR in mruby-config.bat
- [#6175](https://github.com/mruby/mruby/pull/6175) Corrected strange conditional in mrb_vm_run()
- [#6176](https://github.com/mruby/mruby/pull/6176) Stop assuming alias proc in CI_PROC_SET()
- [#6177](https://github.com/mruby/mruby/pull/6177) gha: add macOS 14 to the build
- [#6184](https://github.com/mruby/mruby/pull/6184) Remove the L_STOP label
- [#6185](https://github.com/mruby/mruby/pull/6185) Added mrb_callinfo::u.keep_context for clarity
- [#6186](https://github.com/mruby/mruby/pull/6186) Omit NULL check of e->cxt in OP_RETURN_BLK
- [#6191](https://github.com/mruby/mruby/pull/6191) Speed up symbol equality comparison
- [#6192](https://github.com/mruby/mruby/pull/6192) Fix `OP_STOP` with exception
- [#6193](https://github.com/mruby/mruby/pull/6193) Fix wrong assertion in `OP_SENDB`.
- [#6194](https://github.com/mruby/mruby/pull/6194) Simplify the calculation of the number of closures in `MRB_TT_FIBER`
- [#6197](https://github.com/mruby/mruby/pull/6197) Fix int_xor to call flo_xor.
- [#6201](https://github.com/mruby/mruby/pull/6201) tasks/doc.rake: standardize the `rake doc` error messages
- [#6202](https://github.com/mruby/mruby/pull/6202) Remove the `.yardoc` folder with `rake doc:clean:api`
- [#6204](https://github.com/mruby/mruby/pull/6204) Clean up the `.editorconfig` file
- [#6209](https://github.com/mruby/mruby/pull/6209) Minor `.gitignore` clean up
- [#6211](https://github.com/mruby/mruby/pull/6211) Minor `.gitignore` clean up; order entries
- [#6216](https://github.com/mruby/mruby/pull/6216) Shared empty `iv_tbl` of module
- [#6217](https://github.com/mruby/mruby/pull/6217) Strict declaration for `mrb_istruct_size()`
- [#6219](https://github.com/mruby/mruby/pull/6219) Avoid assigning a fixed value in the loop
- [#6220](https://github.com/mruby/mruby/pull/6220) Reorganize `mrb_cache_entry` and `mrb_method_t` types
- [#6221](https://github.com/mruby/mruby/pull/6221) Arranging `each_backtrace()`
- [#6222](https://github.com/mruby/mruby/pull/6222) Need to synchronize `dbg->regs` after VM call in `mrdb`
- [#6224](https://github.com/mruby/mruby/pull/6224) `mrb_env_unshare()` to break the link to fiber
- [#6225](https://github.com/mruby/mruby/pull/6225) Revert "Adjust environment when `mrb_exec_irep` happened."
- [#6227](https://github.com/mruby/mruby/pull/6227) fix: `Array#shuffle(!)` result distribution
- [#6228](https://github.com/mruby/mruby/pull/6228) Revert "`env` referred from top-level callinfo should not be unshared; fix #4019"
- [#6230](https://github.com/mruby/mruby/pull/6230) Fix status of fiber after switched by exception raised
- [#6231](https://github.com/mruby/mruby/pull/6231) Add a way to let other gems handle closing of fds in mruby-io
- [#6232](https://github.com/mruby/mruby/pull/6232) Fold the code for freeing `env`
- [#6233](https://github.com/mruby/mruby/pull/6233) Free stack memory at end of fiber
- [#6235](https://github.com/mruby/mruby/pull/6235) fix `Array#delete` always firing the block when deleting `nil`
- [#6236](https://github.com/mruby/mruby/pull/6236) unify the code for filter methods (and speed up `#reject!`)
- [#6237](https://github.com/mruby/mruby/pull/6237) Stricter env objects to attach to ci
- [#6238](https://github.com/mruby/mruby/pull/6238) Minimize zero initialization of the stack
- [#6243](https://github.com/mruby/mruby/pull/6243) Fixed base64 decoding in `mruby-pack`
- [#6244](https://github.com/mruby/mruby/pull/6244) Revise scope of role of `mrb_vm_run()`
- [#6246](https://github.com/mruby/mruby/pull/6246) Fix typo in `test/t/hash.rb`
- [#6249](https://github.com/mruby/mruby/pull/6249) Fix spelling in `src/vm.c`
- [#6250](https://github.com/mruby/mruby/pull/6250) Fix spelling
- [#6251](https://github.com/mruby/mruby/pull/6251) Clean up root move `CODEOWNERS` to `.github` directory
- [#6253](https://github.com/mruby/mruby/pull/6253) Allow recycling fibers by GC if not referenced directly
- [#6256](https://github.com/mruby/mruby/pull/6256) Update documentation for `mrb_top_run()`
- [#6257](https://github.com/mruby/mruby/pull/6257) fix some mrbconf.md typos
- [#6260](https://github.com/mruby/mruby/pull/6260) Remove `exc_caught` from `mrb_vm_exec()`
- [#6261](https://github.com/mruby/mruby/pull/6261) fix: `to_a` integer ranges with `begin > end` failing
- [#6263](https://github.com/mruby/mruby/pull/6263) fix: `Array#delete` mistakenly calling block even if not passed
- [#6264](https://github.com/mruby/mruby/pull/6264) Must pass keyword arguments for `Kernel#to_enum`
- [#6265](https://github.com/mruby/mruby/pull/6265) Fixes `Dir.children` and `Dir.each_child`
- [#6266](https://github.com/mruby/mruby/pull/6266) Passes the nonexistent key as a block argument in `Array#delete`
- [#6273](https://github.com/mruby/mruby/pull/6273) Improvements to `mrb_protect_atexit()`
- [#6275](https://github.com/mruby/mruby/pull/6275) Fixed `Binding#eval` that failed to assign to the same variable
- [#6276](https://github.com/mruby/mruby/pull/6276) Always run `atexit` on the top-level call frame
- [#6279](https://github.com/mruby/mruby/pull/6279) Include headers for malloc() explicitly; fix #6277
- [#6280](https://github.com/mruby/mruby/pull/6280) Remove `MRB_ENV_CLOSED` flag
- [#6281](https://github.com/mruby/mruby/pull/6281) Fixes local variables in `mruby-binding`.
- [#6283](https://github.com/mruby/mruby/pull/6283) Simplify `uvenv()`
- [#6288](https://github.com/mruby/mruby/pull/6288) Detach `env` of ci explicitly on atexit
- [#6289](https://github.com/mruby/mruby/pull/6289) Simplify `OP_RETURN_BLK` and `OP_BREAK`
- [#6290](https://github.com/mruby/mruby/pull/6290) Allow to change the output directory name of the `libmruby` file
- [#6293](https://github.com/mruby/mruby/pull/6293) Changed the instruction table in `opcode.md`
- [#6294](https://github.com/mruby/mruby/pull/6294) Optimise `mrb_iv_get`
- [#6302](https://github.com/mruby/mruby/pull/6302) Minor cleanup in mrb_str_init
- [#6303](https://github.com/mruby/mruby/pull/6303) mrb_str_aset_m() should return replace instead of str
- [#6305](https://github.com/mruby/mruby/pull/6305) Protect keyword arguments in `prepare_missing()`
- [#6308](https://github.com/mruby/mruby/pull/6308) Assume that `MRB_CATCH()` has `mrb->exc` set
- [#6310](https://github.com/mruby/mruby/pull/6310) Doubling the call stack when extending it
- [#6311](https://github.com/mruby/mruby/pull/6311) Added fast-path for positional arguments less than 15 in `OP_SEND`
- [#6312](https://github.com/mruby/mruby/pull/6312) Omit error checking at `OP_RETURN`, `OP_RETURN_BLK` and `OP_BREAK`
- [#6313](https://github.com/mruby/mruby/pull/6313) Fix wrong column number in opcode.md
- [#6314](https://github.com/mruby/mruby/pull/6314) Optimize even?/odd? for big integers
- [#6318](https://github.com/mruby/mruby/pull/6318) Shrink variables in `mrb_vm_exec()`
- [#6320](https://github.com/mruby/mruby/pull/6320) Shrinking the code in `OP_BREAK` and `OP_RETURN_BLK`
- [#6321](https://github.com/mruby/mruby/pull/6321) Avoid warnings in `lib/**/*.rb`
- [#6322](https://github.com/mruby/mruby/pull/6322) Fix mrb_ro_data_p on Intel Mac
- [#6324](https://github.com/mruby/mruby/pull/6324) Remove `localjump_error()`
- [#6327](https://github.com/mruby/mruby/pull/6327) fix ncurses linking issues
- [#6328](https://github.com/mruby/mruby/pull/6328) Fix use-after-free in `obj_free()` for env objects
- [#6329](https://github.com/mruby/mruby/pull/6329) Fix use-after-free in `mrb_obj_alloc()`
- [#6330](https://github.com/mruby/mruby/pull/6330) Add a precondition to call `mrb_env_unshare()`.
- [#6331](https://github.com/mruby/mruby/pull/6331) Restore the GC arena with tests
- [#6332](https://github.com/mruby/mruby/pull/6332) Must not depend on the “host” build to generate `mruby-compiler/core/y.tab.c`
- [#6333](https://github.com/mruby/mruby/pull/6333) Reduce the number of branch instructions in the `heap_p()`
- [#6335](https://github.com/mruby/mruby/pull/6335) Add `return_ci` in `CHECKPOINT_MAIN()` of `OP_RETURN`
- [#6338](https://github.com/mruby/mruby/pull/6338) Need to place static proc objects into 8-byte alignments
- [#6340](https://github.com/mruby/mruby/pull/6340) Fix use-after-free for `Array#<=>`
- [#6341](https://github.com/mruby/mruby/pull/6341) Need to restore the GC arena after some function calls
- [#6344](https://github.com/mruby/mruby/pull/6344) prefer using `mrb_yield` to call block arguments
- [#6347](https://github.com/mruby/mruby/pull/6347) codegen.c,parse.y: remove flattening of `yield` arguments; fix #6346
- [#6348](https://github.com/mruby/mruby/pull/6348) Cancel the warning disablement
- [#6349](https://github.com/mruby/mruby/pull/6349) Perform GC before deleting directories
- [#6350](https://github.com/mruby/mruby/pull/6350) Fixed character encoding conversion function mismatch
- [#6351](https://github.com/mruby/mruby/pull/6351) Remove unnecessary `mrb_gc_arena_restore()`
- [#6353](https://github.com/mruby/mruby/pull/6353) Fix use-after-free in `mrb_ary_delete()`
- [#6356](https://github.com/mruby/mruby/pull/6356) Making splat argument objects invisible from Ruby side
- [#6373](https://github.com/mruby/mruby/pull/6373) Add build config for Milk-V Duo (RISC-V Linux) board
- [#6382](https://github.com/mruby/mruby/pull/6382) Make array objects invisible in `mrb_gc_register()`
- [#6385](https://github.com/mruby/mruby/pull/6385) Small improvements for `mrb_gc_register()`
- [#6386](https://github.com/mruby/mruby/pull/6386) Avoid calling `mrb_gv_set()` from `mrb_gc_unregister()`
- [#6387](https://github.com/mruby/mruby/pull/6387) Small improvements for `mrb_gc_unregister()`
- [#6390](https://github.com/mruby/mruby/pull/6390) Fix use-after-free by `mrb_gc_unregistor()`
- [#6391](https://github.com/mruby/mruby/pull/6391) Fixed argument forwarding in `instance_exec`
- [#6392](https://github.com/mruby/mruby/pull/6392) Fix argument forwarding in `mrb_exec_irep()`
- [#6393](https://github.com/mruby/mruby/pull/6393) Follow-up to #6391
- [#6395](https://github.com/mruby/mruby/pull/6395) Storing method-id inside Symbol#to_proc
- [#6396](https://github.com/mruby/mruby/pull/6396) Milk-V Build Config: update GPIO gem URL
- [#6397](https://github.com/mruby/mruby/pull/6397) boxing_no.h: rename BOXNIX_SET_VALUE -> BOXNO_SET_VALUE
- [#6399](https://github.com/mruby/mruby/pull/6399) Add macOS 15 to the build
- [#6405](https://github.com/mruby/mruby/pull/6405) `io_read`: use `%i` instead of `%d` in call to `mrb_raisef`
- [#6407](https://github.com/mruby/mruby/pull/6407) Allow to exclude specific files in `rake install`
- [#6408](https://github.com/mruby/mruby/pull/6408) Improve compliance with C++ standards
- [#6410](https://github.com/mruby/mruby/pull/6410) Put `#include <stdlib.h>` in `parse.y`
- [#6412](https://github.com/mruby/mruby/pull/6412) Distinguish the call frame of the generator with `OP_RETURN_BLK`
- [#6413](https://github.com/mruby/mruby/pull/6413) Add links to documentation in `README.md`
- [#6415](https://github.com/mruby/mruby/pull/6415) Fix numbered parameters when used as a singleton
- [#6416](https://github.com/mruby/mruby/pull/6416) Optimize the "new" method's iseq
- [#6419](https://github.com/mruby/mruby/pull/6419) Follow Ruby's behavior for numbered parameters in -> {}
- [#6420](https://github.com/mruby/mruby/pull/6420) Update `labeler.yml`: add label for the `tools` directory
- [#6422](https://github.com/mruby/mruby/pull/6422) Add annotations for function names defined in the preprocessor
- [#6423](https://github.com/mruby/mruby/pull/6423) Adding a serialized test task
- [#6427](https://github.com/mruby/mruby/pull/6427) Need to update `ci` variable after re-entry to VM
- [#6428](https://github.com/mruby/mruby/pull/6428) Change the limits of OP_ADDI and OP_SUBI from 0-127 to 0-255.
- [#6429](https://github.com/mruby/mruby/pull/6429) Fix numbered parameters when used as hash keys
- [#6432](https://github.com/mruby/mruby/pull/6432) Moving code in macro arguments out of macros
- [#6434](https://github.com/mruby/mruby/pull/6434) Added document "Layout of the mruby filesystem"
- [#6436](https://github.com/mruby/mruby/pull/6436) Make `rake doc:update-index` prettier friendly
- [#6437](https://github.com/mruby/mruby/pull/6437) Add more details to the pre-commit config
- [#6438](https://github.com/mruby/mruby/pull/6438) Remove unused `MRuby::Build#list_install_excludes` method
- [#6440](https://github.com/mruby/mruby/pull/6440) Fix `redo` keyword
- [#6442](https://github.com/mruby/mruby/pull/6442) Fixed wrong range condition in `OP_JMPUW`
- [#6443](https://github.com/mruby/mruby/pull/6443) Fix NODE_NEGATE for bigints
- [#6444](https://github.com/mruby/mruby/pull/6444) Add test cases for bigints
- [#6446](https://github.com/mruby/mruby/pull/6446) Omit the `_WIN64` definition check
- [#6447](https://github.com/mruby/mruby/pull/6447) Fixed `File.expand_path`
- [#6448](https://github.com/mruby/mruby/pull/6448) Suppress presym in `mruby/ext/io.h` file
- [#6449](https://github.com/mruby/mruby/pull/6449) Using presym in the `mruby-io/src/file_test.c` file
- [#6450](https://github.com/mruby/mruby/pull/6450) Change `MRB_WITH_IO_PREAD_PWRITE` configuration name
- [#6454](https://github.com/mruby/mruby/pull/6454) mruby-bigint: handle rhs bigint in int_mod and int_divmod functions
- [#6455](https://github.com/mruby/mruby/pull/6455) mruby-bigint: fix rounding behavior in mpz_mdiv and mpz_mdivmod functions
- [#6457](https://github.com/mruby/mruby/pull/6457) bigint: fix bug with division of a small number by a bigint
- [#6459](https://github.com/mruby/mruby/pull/6459) `FileTest` is a module
- [#6461](https://github.com/mruby/mruby/pull/6461) To create a release package file in draft
- [#6462](https://github.com/mruby/mruby/pull/6462) Properly cast the return value of `memchr()`
- [#6463](https://github.com/mruby/mruby/pull/6463) Add `level` argument to `File.dirname`
- [#6465](https://github.com/mruby/mruby/pull/6465) Add initial PlayStation portable crossbuild support
- [#6468](https://github.com/mruby/mruby/pull/6468) Fixed missing changes to `IB_FIND_BY_KEY()` parameter names
- [#6469](https://github.com/mruby/mruby/pull/6469) Add more `const` qualifier for `RProc`
- [#6472](https://github.com/mruby/mruby/pull/6472) Moved tests for `Integer#quo`
- [#6473](https://github.com/mruby/mruby/pull/6473) Hide `mpz_and()` symbol
- [#6473](https://github.com/mruby/mruby/pull/6473) Hide mpz_and() symbol
- [#6474](https://github.com/mruby/mruby/pull/6474) Avoid array object creation with “unknown keyword” error
- [#6475](https://github.com/mruby/mruby/pull/6475) Don't include deleted mruby-print
- [#6478](https://github.com/mruby/mruby/pull/6478) Fixed buffer overrun in function `chars2bytes()`
- [#6479](https://github.com/mruby/mruby/pull/6479) Reimplementation of `File.expand_path` method
- [#6482](https://github.com/mruby/mruby/pull/6482) Add `File.absolute_path?` method
- [#6487](https://github.com/mruby/mruby/pull/6487) Add Emscripten toolchain & build_config
+1 -3
View File
@@ -30,12 +30,10 @@ of the Ministry of Economy, Trade and Industry of Japan.
## How to get mruby
To get mruby, you can download the stable version 3.3.0 from the official mruby
To get mruby, you can download the stable version 3.4.0 from the official mruby
GitHub repository or clone the trunk of the mruby source tree with the "git
clone" command. You can also install and compile mruby using [ruby-install](https://github.com/postmodern/ruby-install), [ruby-build](https://github.com/rbenv/ruby-build) or [rvm](https://github.com/rvm/rvm).
The release candidate version 3.4.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/3.4.0-rc2.zip](https://github.com/mruby/mruby/archive/3.4.0-rc2.zip)
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
The trunk of the mruby source tree can be checked out with the
+1 -1
View File
@@ -60,7 +60,7 @@ MRuby::Build.new do |conf|
# gperf settings
# conf.gperf do |gperf|
# gperf.command = 'gperf'
# gperf.compile_options = %q[-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
# gperf.compile_options = %q[-L ANSI-C -C -j1 -i 1 -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
# end
# file extensions
+106
View File
@@ -0,0 +1,106 @@
# Cross Compiling configuration for Luckfox Pico embedded SBC.
#
# To build on Ubuntu x86_64: rake MRUBY_CONFIG=build_config/luckfox_pico.rb
# Uses Buildroot SDK for this board. Binaries run on the corresponding Linux image.
# Requires: https://github.com/LuckfoxTECH/luckfox-pico
#
# NOTE: default config includes all standard mrbgems, EXCEPT: mruby-cmath
#
MRuby::CrossBuild.new("luckfox_pico") do |conf|
# Clone the luckfox-pico repo above next to (same directory level) as mruby.
SDK_BASE = File.realpath(File.expand_path("../../../", File.expand_path(__FILE__)) + "/luckfox-pico")
TOOLCHAIN_BASE = "#{SDK_BASE}/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf"
SYSROOT = "#{TOOLCHAIN_BASE}/arm-rockchip830-linux-uclibcgnueabihf/sysroot"
toolchain :gcc
# C compiler settings
conf.cc do |cc|
cc.command = "#{TOOLCHAIN_BASE}/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc"
cc.include_paths << "#{TOOLCHAIN_BASE}/lib/gcc/arm-rockchip830-linux-uclibcgnueabihf/8.3.0/include"
cc.include_paths << "#{TOOLCHAIN_BASE}/lib/gcc/arm-rockchip830-linux-uclibcgnueabihf/8.3.0/include-fixed"
cc.include_paths << "#{TOOLCHAIN_BASE}/arm-rockchip830-linux-uclibcgnueabihf/include/c++/8.3.0/arm-rockchip830-linux-uclibcgnueabihf"
cc.include_paths << "#{SYSROOT}/usr/include"
# Flags taken from the SDK's Makefile
cc.flags << ["-march=armv7-a", "-mfpu=neon", "-mfloat-abi=hard"]
cc.flags << ["-D_LARGEFILE_SOURCE", "-D_LARGEFILE64_SOURCE", "-D_FILE_OFFSET_BITS=64", "-ffunction-sections", "-fdata-sections"]
cc.flags << ["-O2", "-fPIC"]
cc.flags << ["-Wl,--copy-dt-needed-entries", "-Wl,-lc,-lgcc_s"]
end
# Linker settings
conf.linker do |linker|
linker.command = cc.command
linker.library_paths << "#{TOOLCHAIN_BASE}/arm-rockchip830-linux-uclibcgnueabihf/lib"
linker.flags = cc.flags
end
# Archiver settings
conf.archiver do |archiver|
archiver.command = "#{TOOLCHAIN_BASE}/bin/arm-rockchip830-linux-uclibcgnueabihf-ar"
end
# Do not build executable test
conf.build_mrbtest_lib_only
# Disable C++ exception
conf.disable_cxx_exception
# All standard gems.
conf.gem 'mrbgems/mruby-array-ext/'
conf.gem 'mrbgems/mruby-bigint/'
conf.gem 'mrbgems/mruby-bin-config/'
conf.gem 'mrbgems/mruby-bin-debugger/'
conf.gem 'mrbgems/mruby-bin-mirb/'
conf.gem 'mrbgems/mruby-bin-mrbc/'
conf.gem 'mrbgems/mruby-bin-mruby/'
conf.gem 'mrbgems/mruby-bin-strip/'
conf.gem 'mrbgems/mruby-binding/'
conf.gem 'mrbgems/mruby-catch/'
conf.gem 'mrbgems/mruby-class-ext/'
# SDK doesn't include complex math for uClibc
# conf.gem 'mrbgems/mruby-cmath/'
conf.gem 'mrbgems/mruby-compar-ext/'
conf.gem 'mrbgems/mruby-compiler/'
conf.gem 'mrbgems/mruby-complex/'
conf.gem 'mrbgems/mruby-data/'
conf.gem 'mrbgems/mruby-dir/'
conf.gem 'mrbgems/mruby-enum-chain/'
conf.gem 'mrbgems/mruby-enum-ext/'
conf.gem 'mrbgems/mruby-enum-lazy/'
conf.gem 'mrbgems/mruby-enumerator/'
conf.gem 'mrbgems/mruby-errno/'
conf.gem 'mrbgems/mruby-error/'
conf.gem 'mrbgems/mruby-eval/'
conf.gem 'mrbgems/mruby-exit/'
conf.gem 'mrbgems/mruby-fiber/'
conf.gem 'mrbgems/mruby-hash-ext/'
conf.gem 'mrbgems/mruby-io/'
conf.gem 'mrbgems/mruby-kernel-ext/'
conf.gem 'mrbgems/mruby-math/'
conf.gem 'mrbgems/mruby-metaprog/'
conf.gem 'mrbgems/mruby-method/'
conf.gem 'mrbgems/mruby-numeric-ext/'
conf.gem 'mrbgems/mruby-object-ext/'
conf.gem 'mrbgems/mruby-objectspace/'
conf.gem 'mrbgems/mruby-os-memsize/'
conf.gem 'mrbgems/mruby-pack/'
conf.gem 'mrbgems/mruby-proc-binding/'
conf.gem 'mrbgems/mruby-proc-ext/'
conf.gem 'mrbgems/mruby-random/'
conf.gem 'mrbgems/mruby-range-ext/'
conf.gem 'mrbgems/mruby-rational/'
conf.gem 'mrbgems/mruby-set/'
conf.gem 'mrbgems/mruby-sleep/'
conf.gem 'mrbgems/mruby-socket/'
conf.gem 'mrbgems/mruby-sprintf/'
conf.gem 'mrbgems/mruby-string-ext/'
conf.gem 'mrbgems/mruby-struct/'
conf.gem 'mrbgems/mruby-symbol-ext/'
# conf.gem 'mrbgems/mruby-test-inline-struct/'
# conf.gem 'mrbgems/mruby-test/'
conf.gem 'mrbgems/mruby-time/'
conf.gem 'mrbgems/mruby-toplevel-ext/'
end
+1 -1
View File
@@ -176,7 +176,7 @@ If you need an include path of header file use `search_header_path`:
fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h'
```
If you need a full file name of header file use `search_header`:
If you need a full filename of header file use `search_header`:
```ruby
# Searches `iconv.h`.
+6 -6
View File
@@ -40,7 +40,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
mruby 3.3.0 (2024-02-14)
mruby 3.4.0 (2025-04-20)
```
## 2.2 Basic Operation
@@ -52,7 +52,7 @@ To invoke the mruby debugger, just type `mrdb`.
To specify the script file:
```bash
$ mrdb [option] file name
$ mrdb [option] filename
```
For example: Debugging sample.rb
@@ -121,7 +121,7 @@ Be aware that the breakpoint command will not check the validity of the class na
You can get the current breakpoint information by the following options.
breakpoint breakpoint number : file name. line number
breakpoint breakpoint number : filename. line number
breakpoint breakpoint number : [class name,] method name
@@ -267,7 +267,7 @@ Example:
```
(sample.rb:1) info breakpoints
Num Type Enb What
1 breakpoint y at sample.rb:3 -> file name,line number
1 breakpoint y at sample.rb:3 -> filename,line number
2 breakpoint n in Sample_class:sample_class_method -> [class:]method name
3 breakpoint y in sample_global_method
```
@@ -301,11 +301,11 @@ When you do not specify both the `first` and `last` options, you will receive th
Example:
```
Specifying file name and first row number
Specifying filename and first row number
sample.rb:1) list sample2.rb:5
```
Specifying the file name and the first and last row number:
Specifying the filename and the first and last row number:
```
(sample.rb:1) list sample2.rb:6,7
+108 -11
View File
@@ -2,22 +2,119 @@
# Memory Allocation
There are three methods to customize memory allocation in mruby.
In mruby, you can customize how memory is allocated in two ways:
1. Provide your own `realloc()`/`free()`
2. Redefine `mrb_default_allocf()`
3. Specify a function with `mrb_open_allocf()`
1. **Provide your own `malloc()`/`realloc()`/`free()`**
2. **Override `mrb_basic_alloc_func()`**
## Provide your own `realloc()`/`free()`
---
On some platforms, especially on microcontrollers, the standard library may not provide `malloc()`, `realloc()`, and `free()`. In such cases, it may be necessary to define memory allocation functions for the specific platform. mruby uses `realloc()` and `free()` from the standard C library for memory management. By defining these two functions of your own, you can make mruby work. However, note the following two points:
## 1. Provide your own `malloc()`/`realloc()`/`free()`
First, `realloc(NULL, size)` behaves the same as malloc(size). Second, `free(NULL)` exits without doing anything.
On platforms without a full C standard library —such as many microcontrollers— you may need to supply your own implementations of `malloc()`, `realloc()`, and `free()`. mrubys allocator calls directly into these functions, so replacing them lets you control **every** allocation and deallocation performed by your entire program, including any thirdparty libraries you link against.
## Redefine `mrb_default_allocf()`
Keep in mind:
The only function in mruby that uses the standard C library's memory allocation functions is `mrb_default_allocf()`, defined in `alloc.c`. By defining this function within your application, you can customize the memory management of your application.
- Calling `realloc(NULL, size)` must behave like `malloc(size)`.
- Calling `free(NULL)` must be a noop.
## Specify a function with `mrb_open_allocf()`
Simply define these three functions in your code (or link against a library that provides them), and mruby — along with all other code in your process — will use your versions automatically.
If you want to perform different memory management for each `mrb_state` within your application, you can use the `mrb_open_allocf()` function to create the `mrb_state` structure. This allows you to specify a memory allocation function (which is compatible with `mrb_default_allocf`) for each `mrb_state`. Although this scheme is not recommended. It may become obsolete in the future, since I have never seen per mrb_state memory management use-case.
## 2. Override `mrb_basic_alloc_func()`
Inside mruby, all of its own memory allocations go through a single function called mrb_basic_alloc_func() (formerly mrb_default_allocf()). By defining this function in your application before linking, you can intercept and handle **only** the memory operations initiated by mruby itself without affecting other libraries or parts of your program.
```c
// Example signature:
// void* mrb_basic_alloc_func(void* ptr, size_t size);
```
Implement mrb_basic_alloc_func() in your code, and mruby will invoke it for every internal allocation, reallocation, and free request.
### Expected behavior
- `mrb_basic_alloc_func(NULL, size)` should allocate `size` bytes, just like `malloc(size)`.
- `mrb_basic_alloc_func(ptr, size)` should resize the existing block at `ptr` to `size` bytes, just like `realloc(ptr, size)`.
- `mrb_basic_alloc_func(ptr, 0)` should free the block at `ptr`, just like `free(ptr)`.
---
## Summary of effects:
- **Custom `malloc`/`realloc`/`free`**: replaces allocation behavior globally (mruby + all other code and thirdparty libraries).
- **Custom `mrb_basic_alloc_func()`**: replaces allocation behavior only for mrubys internal use, leaving other libraries allocations untouched.
## Migration note
If you are moving from the old API:
1. **Removal of `mrb_open_allocf()`**
- \_Old:
```c
mrb_state *mrb = mrb_open_allocf(my_allocf, ud);
```
- \_New:
```c
// No allocf parameter; set up your hook via mrb_basic_alloc_func definition.
mrb_state *mrb = mrb_open_core();
```
2. **`mrb_open_core()` takes no arguments**
- Simply drop any allocf or user-data arguments, and redefine `mrb_basic_alloc_func` as you need.
3. **No more `mrb_allocf` type**
- Definitions using the `mrb_allocf` typedef can be removed; implement `mrb_basic_alloc_func()` with the signature below:
```c
void* mrb_basic_alloc_func(void *ptr, size_t size);
```
4. **`mrb_basic_alloc_func` signature change**
- _Old:_
```c
void* mrb_default_allocf(mrb_state *mrb, void *ptr, size_t size, void *ud);
```
- _New:_
```c
void* mrb_basic_alloc_func(void *ptr, size_t size);
```
---
### Code examples
- **Old style**:
```c
static void*
my_allocf(mrb_state *mrb, void *ud, void *ptr, size_t size)
{
// ...custom logic...
}
mrb_state *mrb = mrb_open_allocf(my_allocf, some_ud);
```
- **New style**:
```c
// Define your hook before creating the state:
void*
mrb_basic_alloc_func(void *ptr, size_t size)
{
// ...custom logic...
}
mrb_state *mrb = mrb_open_core();
```
+2 -2
View File
@@ -368,7 +368,7 @@ mruby can be extended with pure Ruby. It is possible to override existing
classes or add new ones in this way. Put all Ruby files into the `mrblib`
directory.
### Pre-Conditions
### Preconditions
none
@@ -400,7 +400,7 @@ mruby codes under `mrblib` directory would be executed after gem init C
function is called. Make sure _mruby script_ depends on _C code_ and
_C code_ doesn't depend on _mruby script_.
### Pre-Conditions
### Preconditions
See C and Ruby example.
+1 -1
View File
@@ -71,7 +71,7 @@ header.
For `MRB_OPSYM()`, specify the names corresponding to operators (see
`MRuby::Presym::OPERATORS` in `lib/mruby/presym.rb` for the names that
can be specified for it). Other than that, describe only word characters
excluding leading and ending punctuations.
excluding leading and ending punctuation.
These macros are converted to static symbol IDs at compile time, unless
preallocate symbols are disabled by `conf.disable_presym`. In that case,
+27
View File
@@ -186,3 +186,30 @@ def g(a: 1, b: a)
end
g(a:1)
```
## No Double Dispatch in Module Loading
To make implementation simpler, mruby does not use double dispatching in module loading (`include`/`prepend`/`extend`).
Those method internally called corresponding actual load methods (`append_features`/`prepend_features`/`extend_object`).
But they are rarely overloaded, consumes more memory, and make loading little bit slower. As a Ruby implementation for the smaller device,
we decided mruby simpler.
```ruby
module M
def self.append_features(mod)
p :append
end
end
class C
include M
end
```
#### Ruby [ruby 3.5.0dev (2025-04-21 85bab61565))]
Prints `:append`.
#### mruby [3.5.0 (2025-04-28)]
Nothing printed (since `include` does not call `append_features` internally).
+1 -1
View File
@@ -197,7 +197,7 @@ For better and faster hash values.
---
# Major bug fixes
# Major bugfixes
- Fix infinite recursive call bugs in integer division [98799aa6](https://github.com/mruby/mruby/commit/98799aa6)
- Fix to raise TypeError with super inside instance_eval / class_eval [#5476](https://github.com/mruby/mruby/pull/5476)
+4 -4
View File
@@ -4,7 +4,7 @@
# The language
- mruby now supports `private` and `protected` visibitily ([b0db0bd](https://github.com/mruby/mruby/commit/b0db0bd))
- mruby now supports `private` and `protected` visibility ([b0db0bd](https://github.com/mruby/mruby/commit/b0db0bd))
- Maximum length of inlined symbols reduced from 5 to 4 characters to provide space for visibility flags ([6442a01](https://github.com/mruby/mruby/commit/6442a01))
- Many methods are made private according to CRuby visibility ([4a0e806](https://github.com/mruby/mruby/commit/4a0e806))
- Generate OP_SSEND for `self.method` type calls ([111fe4b](https://github.com/mruby/mruby/commit/111fe4b))
@@ -32,7 +32,7 @@
# Build & Configuration
- New Build Target: `test:run:serial`, `test:run:serial:lib`, `test:run:serial:bin` ([#6423](https://github.com/mruby/mruby/pull/6423))
- New Platform: Playstation Portable ([#6022](https://github.com/mruby/mruby/pull/6465))
- New Platform: PlayStation Portable ([#6022](https://github.com/mruby/mruby/pull/6465))
- New Platform: emscripten ([#6487](https://github.com/mruby/mruby/pull/6487))
- New Config: no-float (with MRB_NO_FLOAT) ([32200f1](https://github.com/mruby/mruby/commit/32200f1))
@@ -131,7 +131,7 @@
- [#6243](https://github.com/mruby/mruby/pull/6243) Fixed base64 decoding in `mruby-pack`
- [#6244](https://github.com/mruby/mruby/pull/6244) Revise scope of role of `mrb_vm_run()`
- [#6246](https://github.com/mruby/mruby/pull/6246) Fix typo in `test/t/hash.rb`
- [#6249](https://github.com/mruby/mruby/pull/6249) Fix grammar in `src/vm.c`; `catched` -> `caught`
- [#6249](https://github.com/mruby/mruby/pull/6249) Fix spelling in `src/vm.c`
- [#6250](https://github.com/mruby/mruby/pull/6250) Fix spelling
- [#6251](https://github.com/mruby/mruby/pull/6251) Clean up root move `CODEOWNERS` to `.github` directory
- [#6253](https://github.com/mruby/mruby/pull/6253) Allow recycling fibers by GC if not referenced directly
@@ -237,7 +237,7 @@
- [#6461](https://github.com/mruby/mruby/pull/6461) To create a release package file in draft
- [#6462](https://github.com/mruby/mruby/pull/6462) Properly cast the return value of `memchr()`
- [#6463](https://github.com/mruby/mruby/pull/6463) Add `level` argument to `File.dirname`
- [#6465](https://github.com/mruby/mruby/pull/6465) Add initial playstation portable crossbuild support
- [#6465](https://github.com/mruby/mruby/pull/6465) Add initial PlayStation portable crossbuild support
- [#6468](https://github.com/mruby/mruby/pull/6468) Fixed missing changes to `IB_FIND_BY_KEY()` parameter names
- [#6469](https://github.com/mruby/mruby/pull/6469) Add more `const` qualifier for `RProc`
- [#6472](https://github.com/mruby/mruby/pull/6472) Moved tests for `Integer#quo`
-6
View File
@@ -42,12 +42,6 @@
#error Cannot define MRB_USE_FLOAT32 and MRB_NO_FLOAT at the same time
#endif
/* add -DMRB_NO_METHOD_CACHE to disable method cache to save memory */
//#define MRB_NO_METHOD_CACHE
/* size of the method cache (need to be the power of 2) */
//#define MRB_METHOD_CACHE_SIZE (1<<8)
//#define MRB_USE_INLINE_METHOD_CACHE
/* define on big endian machines; used by MRB_NAN_BOXING, etc. */
#ifndef MRB_ENDIAN_BIG
# if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
+6 -33
View File
@@ -157,17 +157,6 @@ typedef uint32_t mrb_aspec;
typedef struct mrb_irep mrb_irep;
struct mrb_state;
/**
* Function pointer type of custom allocator used in @see mrb_open_allocf.
*
* The function pointing it must behave similarly as realloc except:
* - If ptr is NULL it must allocate new space.
* - If size is zero, ptr must be freed.
*
* See @see mrb_default_allocf for the default implementation.
*/
typedef void* (*mrb_allocf) (struct mrb_state *mrb, void *ptr, size_t size, void *ud);
#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE
#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
#endif
@@ -176,7 +165,8 @@ typedef struct {
uint8_t n:4; /* (15=*) c=n|nk<<4 */
uint8_t nk:4; /* (15=*) */
uint8_t cci; /* called from C function */
uint8_t vis; /* visibility in the current scope */
uint8_t vis; /* 5(ZERO):1(separate module):2(method visibility) */
/* under 3-bit flags are copied to env, and after that, env takes precedence */
mrb_sym mid;
const struct RProc *proc;
struct RProc *blk;
@@ -255,9 +245,6 @@ typedef void (*mrb_atexit_func)(struct mrb_state*);
typedef struct mrb_state {
struct mrb_jmpbuf *jmp;
mrb_allocf allocf; /* memory allocation function */
void *allocf_ud; /* auxiliary data of allocf */
struct mrb_context *c;
struct mrb_context *root_c;
struct iv_tbl *globals; /* global variable table */
@@ -1239,32 +1226,19 @@ MRB_API char* mrb_locale_from_utf8(const char *p, int len);
*/
MRB_API mrb_state* mrb_open(void);
/**
* Create new mrb_state with custom allocators.
*
* @param f
* Reference to the allocation function.
* @param ud
* User data will be passed to custom allocator f.
* If user data isn't required just pass NULL.
* @return
* Pointer to the newly created mrb_state.
*/
MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud);
/**
* Create new mrb_state with just the mruby core
*
* @param f
* Reference to the allocation function.
* Use mrb_default_allocf for the default
* Use mrb_basic_alloc_func for the default
* @param ud
* User data will be passed to custom allocator f.
* If user data isn't required just pass NULL.
* @return
* Pointer to the newly created mrb_state.
*/
MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud);
MRB_API mrb_state* mrb_open_core(void);
/**
* Closes and frees a mrb_state.
@@ -1275,11 +1249,10 @@ MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud);
MRB_API void mrb_close(mrb_state *mrb);
/**
* The default allocation function.
* The memory allocation function. You can redefine this function for your own allocator.
*
* @see mrb_allocf
*/
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
MRB_API void* mrb_basic_alloc_func(void*, size_t);
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
+9 -2
View File
@@ -50,8 +50,9 @@ enum mrb_special_consts {
#define WORDBOX_FIXNUM_FLAG (1 << (WORDBOX_FIXNUM_BIT_POS - 1))
#define WORDBOX_FIXNUM_MASK ((1 << WORDBOX_FIXNUM_BIT_POS) - 1)
#if defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE)
#if defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) || defined(MRB_NO_FLOAT)
/* floats are allocated in heaps */
#define WORDBOX_IMMEDIATE_MASK 0x03
#define WORDBOX_SYMBOL_BIT_POS 2
#define WORDBOX_SYMBOL_SHIFT WORDBOX_SYMBOL_BIT_POS
#define WORDBOX_SYMBOL_FLAG (1 << (WORDBOX_SYMBOL_BIT_POS - 1))
@@ -68,7 +69,9 @@ enum mrb_special_consts {
#define WORDBOX_SYMBOL_MASK 0x1f
#endif
#ifndef WORDBOX_IMMEDIATE_MASK
#define WORDBOX_IMMEDIATE_MASK 0x07
#endif
#define WORDBOX_SET_SHIFT_VALUE(o,n,v) \
((o).w = (((uintptr_t)(v)) << WORDBOX_##n##_SHIFT) | WORDBOX_##n##_FLAG)
@@ -107,7 +110,7 @@ enum mrb_special_consts {
* undef : ...0001 0100
* fixnum: ...IIII III1
* symbol: ...SSSS SS10
* object: ...PPPP P000 (any bits are 1)
* object: ...PPPP PP00 (any bits are 1)
*/
typedef struct mrb_value {
uintptr_t w;
@@ -145,7 +148,11 @@ MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
#endif
MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int);
#if WORDBOX_IMMEDIATE_MASK == 0x3
#define mrb_immediate_p(o) ((o).w & WORDBOX_IMMEDIATE_MASK || (o).w <= MRB_Qundef)
#else
#define mrb_immediate_p(o) ((o).w & WORDBOX_IMMEDIATE_MASK || (o).w == MRB_Qnil)
#endif
#define mrb_ptr(o) mrb_val_union(o).p
#define mrb_cptr(o) mrb_val_union(o).vp->p
+3 -3
View File
@@ -41,8 +41,8 @@ typedef struct mrb_ccontext {
MRB_API mrb_ccontext* mrb_ccontext_new(mrb_state *mrb);
MRB_API void mrb_ccontext_free(mrb_state *mrb, mrb_ccontext *cxt);
MRB_API const char *mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s);
MRB_API void mrb_ccontext_partial_hook(mrb_state *mrb, mrb_ccontext *c, int (*partial_hook)(struct mrb_parser_state*), void*data);
MRB_API void mrb_ccontext_cleanup_local_variables(mrb_state *mrb, mrb_ccontext *c);
MRB_API void mrb_ccontext_partial_hook(mrb_ccontext *c, int (*partial_hook)(struct mrb_parser_state*), void*data);
MRB_API void mrb_ccontext_cleanup_local_variables(mrb_ccontext *c);
/* compatibility macros */
#define mrbc_context mrb_ccontext
@@ -123,7 +123,7 @@ struct mrb_parser_heredoc_info {
/* parser structure */
struct mrb_parser_state {
mrb_state *mrb;
struct mrb_mempool *pool;
mempool *pool;
mrb_ast_node *cells;
const char *s, *send;
#ifndef MRB_NO_STDIO
+12 -3
View File
@@ -28,6 +28,7 @@ mrb_method_t mrb_vm_find_method(mrb_state *mrb, struct RClass *c, struct RClass
mrb_value mrb_mod_const_missing(mrb_state *mrb, mrb_value mod);
mrb_value mrb_const_missing(mrb_state *mrb, mrb_value mod, mrb_sym sym);
size_t mrb_class_mt_memsize(mrb_state*, struct RClass*);
mrb_value mrb_obj_extend(mrb_state*, mrb_value obj);
#endif
mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value);
@@ -60,6 +61,7 @@ void mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg);
mrb_value mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc);
mrb_value mrb_f_raise(mrb_state*, mrb_value);
mrb_value mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg);
mrb_value mrb_exc_get_output(mrb_state *mrb, struct RObject *exc);
struct RBacktrace {
MRB_OBJECT_HEADER;
@@ -82,6 +84,7 @@ size_t mrb_hash_memsize(mrb_value obj);
size_t mrb_gc_mark_hash(mrb_state*, struct RHash*);
void mrb_gc_free_hash(mrb_state*, struct RHash*);
mrb_value mrb_hash_first_key(mrb_state*, mrb_value);
uint32_t mrb_obj_hash_code(mrb_state *mrb, mrb_value key);
/* irep */
struct mrb_insn_data mrb_decode_insn(const mrb_code *pc);
@@ -171,16 +174,16 @@ void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value);
mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym);
void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value);
mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value);
size_t mrb_obj_iv_tbl_memsize(mrb_value);
mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*);
void mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod);
mrb_value mrb_mod_const_at(mrb_state *mrb, struct RClass *c, mrb_value ary);
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym);
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass *c, mrb_sym sym);
mrb_bool mrb_ident_p(const char *s, mrb_int len);
mrb_value mrb_exc_const_get(mrb_state *mrb, mrb_sym sym);
@@ -191,6 +194,10 @@ size_t mrb_gc_mark_iv(mrb_state*, struct RObject*);
void mrb_gc_free_iv(mrb_state*, struct RObject*);
/* VM */
#define MRB_CI_VISIBILITY(ci) MRB_FLAGS_GET((ci)->vis, 0, 2)
#define MRB_CI_SET_VISIBILITY(ci, visi) MRB_FLAGS_SET((ci)->vis, 0, 2, visi)
#define MRB_CI_VISIBILITY_BREAK_P(ci) MRB_FLAG_CHECK((ci)->vis, 2)
#define MRB_CI_SET_VISIBILITY_BREAK(ci) MRB_FLAG_ON((ci)->vis, 2)
mrb_int mrb_ci_bidx(mrb_callinfo *ci);
mrb_int mrb_ci_nregs(mrb_callinfo *ci);
mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p);
@@ -198,6 +205,7 @@ mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value);
mrb_value mrb_object_exec(mrb_state *mrb, mrb_value self, struct RClass *target_class);
mrb_value mrb_mod_module_eval(mrb_state*, mrb_value);
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
mrb_value mrb_f_public_send(mrb_state *mrb, mrb_value self);
#ifdef MRB_USE_BIGINT
mrb_value mrb_bint_new_int(mrb_state *mrb, mrb_int x);
@@ -247,6 +255,7 @@ void mrb_gc_free_bint(mrb_state *mrb, struct RBasic *x);
void mrb_bint_copy(mrb_state *mrb, mrb_value x, mrb_value y);
size_t mrb_bint_memsize(mrb_value x);
mrb_value mrb_bint_hash(mrb_state *mrb, mrb_value x);
mrb_value mrb_bint_sqrt(mrb_state *mrb, mrb_value x);
#endif
#endif /* MRUBY_INTERNAL_H */
+21 -1
View File
@@ -21,7 +21,7 @@ typedef uint32_t khint_t;
typedef khint_t khiter_t;
#ifndef KHASH_DEFAULT_SIZE
# define KHASH_DEFAULT_SIZE 32
# define KHASH_DEFAULT_SIZE 8
#endif
#define KHASH_MIN_SIZE 8
@@ -281,4 +281,24 @@ typedef const char *kh_cstr_t;
MRB_END_DECL
/**
* Macro for iterating over all elements in a khash.
*
* Usage:
* KHASH_FOREACH(mrb, kh, k) {
* // k is the khiter_t iterator
* // Access the key with kh_key(kh, k)
* // Access the value with kh_val(kh, k) if applicable
* // Your code here
* }
*
* @param mrb The mrb_state
* @param kh The khash to iterate over
* @param k The name to use for the khiter_t iterator variable
*/
#define KHASH_FOREACH(mrb, kh, k) \
if (kh) \
for (khiter_t k = kh_begin(kh); k != kh_end(kh); k++) \
if (kh_exist(kh, k))
#endif /* MRUBY_KHASH_H */
+12 -6
View File
@@ -5,9 +5,15 @@
*/
/* memory pool implementation */
typedef struct mrb_mempool mrb_mempool;
MRB_API struct mrb_mempool* mrb_mempool_open(mrb_state*);
MRB_API void mrb_mempool_close(struct mrb_mempool*);
MRB_API void* mrb_mempool_alloc(struct mrb_mempool*, size_t);
MRB_API void* mrb_mempool_realloc(struct mrb_mempool*, void*, size_t oldlen, size_t newlen);
MRB_API mrb_bool mrb_mempool_can_realloc(struct mrb_mempool*, void*, size_t);
typedef struct mempool mempool;
MRB_API struct mempool* mempool_open(void);
MRB_API void mempool_close(struct mempool*);
MRB_API void* mempool_alloc(struct mempool*, size_t);
MRB_API void* mempool_realloc(struct mempool*, void*, size_t oldlen, size_t newlen);
/* compatibility layer */
typedef struct mempool mrb_mempool;
#define mrb_mempool_open(m) mempool_open()
#define mrb_mempool_close(m) mempool_close(m)
#define mrb_mempool_alloc(m, size) mempool_alloc((m),(size))
#define mrb_mempool_realloc(m, ptr, oldlen, newlen) mempool_realloc((m),(ptr),(oldlen),(newlen))
+1 -1
View File
@@ -30,7 +30,7 @@
* For `MRB_OPSYM`, specify the names corresponding to operators (see
* `MRuby::Presym::OPERATORS` in `lib/mruby/presym.rb` for the names that
* can be specified for it). Other than that, describe only word characters
* excluding leading and ending punctuations.
* excluding leading and ending punctuation.
*
* These macros are expanded to `mrb_intern_lit` if presym is disabled,
* therefore the mruby state variable is required. The above macros can be
+7 -3
View File
@@ -30,13 +30,17 @@ struct REnv {
mrb_sym mid;
};
/* flags (21bits): 5(ZERO):8(cioff/bidx):8(stack_len) */
/* flags (20bits): 1(ZERO):1(separate module):2(visibility):8(cioff/bidx):8(stack_len) */
#define MRB_ENV_SET_LEN(e,len) ((e)->flags = (((e)->flags & ~0xff)|((unsigned int)(len) & 0xff)))
#define MRB_ENV_LEN(e) ((mrb_int)((e)->flags & 0xff))
#define MRB_ENV_CLOSE(e) ((e)->cxt = NULL)
#define MRB_ENV_ONSTACK_P(e) ((e)->cxt != NULL)
#define MRB_ENV_BIDX(e) (((e)->flags >> 8) & 0xff)
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<8))
#define MRB_ENV_SET_VISIBILITY(e, vis) MRB_FLAGS_SET((e)->flags, 16, 2, vis)
#define MRB_ENV_VISIBILITY(e) MRB_FLAGS_GET((e)->flags, 16, 2)
#define MRB_ENV_VISIBILITY_BREAK_P(e) MRB_FLAG_CHECK((e)->flags, 18)
#define MRB_ENV_COPY_FLAGS_FROM_CI(e, ci) MRB_FLAGS_SET((e)->flags, 16, 3, (ci)->vis)
/*
* Returns TRUE on success.
@@ -127,8 +131,8 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
#define MRB_METHOD_PROC(m) ((m).as.proc)
#define MRB_METHOD_UNDEF_P(m) ((m).as.proc==NULL)
#define MRB_METHOD_VISIBILITY(m) ((m).flags & MRB_METHOD_VISIBILITY_MASK)
#define MRB_SET_VISIBILITY(f,v) ((f)=(((f)&~MRB_METHOD_VISIBILITY_MASK)|(v)))
#define MRB_METHOD_SET_VISIBILITY(m,v) MRB_SET_VISIBILITY((m).flags,(v))
#define MRB_SET_VISIBILITY_FLAGS(f,v) ((f)=(((f)&~MRB_METHOD_VISIBILITY_MASK)|(v)))
#define MRB_METHOD_SET_VISIBILITY(m,v) MRB_SET_VISIBILITY_FLAGS((m).flags,(v))
#define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m) || (MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE))
/* use MRB_METHOD_CFUNC(m) only when MRB_METHOD_CFUNC_P(m) is true */
+8 -5
View File
@@ -94,11 +94,14 @@ struct mrb_state;
# define MRB_PRIx PRIx32
#endif
#ifdef MRB_ENDIAN_BIG
# define MRB_ENDIAN_LOHI(a,b) a b
#else
# define MRB_ENDIAN_LOHI(a,b) b a
#endif
#define MRB_FLAGS_MASK(shift, width) (~(~0U << (width)) << (shift))
#define MRB_FLAGS_GET(b, s, w) (((b) >> (s)) & MRB_FLAGS_MASK(0, w))
#define MRB_FLAGS_SET(b, s, w, n) ((b) = MRB_FLAGS_ZERO(b, s, w) | MRB_FLAGS_MAKE(s, w, n))
#define MRB_FLAGS_ZERO(b, s, w) ((b) & ~MRB_FLAGS_MASK(s, w))
#define MRB_FLAGS_MAKE(s, w, n) (((n) & MRB_FLAGS_MASK(0, w)) << (s))
#define MRB_FLAG_ON(b, s) ((b) |= MRB_FLAGS_MASK(s, 1))
#define MRB_FLAG_OFF(b, s) ((b) &= ~MRB_FLAGS_MASK(s, 1))
#define MRB_FLAG_CHECK(b, s) (!!((b) & MRB_FLAGS_MASK(s, 1)))
MRB_API mrb_bool mrb_read_int(const char *p, const char *e, char **endp, mrb_int *np);
/* obsolete; do not use mrb_int_read() */
+3 -3
View File
@@ -57,7 +57,7 @@ MRB_BEGIN_DECL
/*
* Patch level string. (optional)
*/
#define MRUBY_PATCHLEVEL_STR "RC2"
#define MRUBY_PATCHLEVEL_STR ""
#ifndef MRUBY_PATCHLEVEL_STR
# if MRUBY_PATCHLEVEL < 0
@@ -85,12 +85,12 @@ MRB_BEGIN_DECL
/*
* Release month.
*/
#define MRUBY_RELEASE_MONTH 3
#define MRUBY_RELEASE_MONTH 4
/*
* Release day.
*/
#define MRUBY_RELEASE_DAY 17
#define MRUBY_RELEASE_DAY 20
/*
* Release date as a string.
+1 -1
View File
@@ -266,7 +266,7 @@ module MRuby
def initialize(build)
super
@command = 'gperf'
@compile_options = %q[-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
@compile_options = %q[-L ANSI-C -C -j1 -i 1 -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
end
def run(outfile, infile)
-2
View File
@@ -7,8 +7,6 @@ MRuby::GemBox.new do |conf|
# Use Rational/Complex numbers
conf.gem :core => "mruby-rational"
conf.gem :core => "mruby-complex"
# Use Complex math functions in CMath module
conf.gem :core => "mruby-cmath"
# Use Multi-precision Integer
conf.gem :core => "mruby-bigint"
end
+6
View File
@@ -10,6 +10,12 @@ MRuby::GemBox.new do |conf|
# Use eval()
conf.gem :core => "mruby-eval"
# Use binding()
conf.gem :core => "mruby-binding"
# Use Proc#binding()
conf.gem :core => "mruby-proc-binding"
# Use mruby-compiler to build other mrbgems
conf.gem :core => "mruby-compiler"
end
+87
View File
@@ -0,0 +1,87 @@
# mruby-array-ext
This mrbgem extends the `Array` class in mruby, providing a rich set of additional methods for array manipulation. These extensions enhance mruby's built-in array capabilities, offering functionalities commonly found in standard Ruby.
## Functionality
The `mruby-array-ext` gem adds the following methods to the `Array` class:
### Set Operations
- `uniq`: Returns a new array by removing duplicate values.
- `uniq!`: Removes duplicate elements from self. Returns `nil` if no changes are made.
- `-` (difference): Returns a new array that is a copy of the original array, removing any items that also appear in another array.
- `|` (union): Returns a new array by joining this array with another array, removing duplicates.
- `&` (intersection): Returns a new array containing elements common to two arrays, with no duplicates.
- `difference`: Returns a new array that is a copy of the original array, removing all occurrences of any item that also appear in the specified other arrays.
- `union`: Returns a new array by joining this array with other arrays, removing duplicates.
- `intersection`: Returns a new array containing elements common to this array and specified other arrays, removing duplicates.
- `intersect?`: Returns `true` if the array and another array have at least one element in common.
### Element Manipulation and Access
- `flatten`: Returns a new array that is a one-dimensional flattening of self.
- `flatten!`: Flattens self in place. Returns `nil` if no modifications were made.
- `fetch`: Tries to return the element at a given position. Throws an `IndexError` if the index is out of bounds, unless a default value or block is provided.
- `fill`: Sets selected elements of self to a given object or the result of a block.
- `compact`: Returns a copy of self with all `nil` elements removed.
- `compact!`: Removes `nil` elements from self. Returns `nil` if no changes were made.
- `rotate(count=1)`: Returns a new array by rotating self so that the element at `count` is the first element.
- `rotate!(count=1)`: Rotates self in place.
- `insert(index, obj...)`: Inserts the given values before the element with the given index.
- `slice!(index)` / `slice!(start, length)` / `slice!(range)`: Deletes element(s) given by an index or range and returns the deleted object(s).
- `at(index)`: Returns the element at `index`. Returns `nil` if the index is out of range.
- `dig(idx, ...)`: Extracts a nested value specified by a sequence of indices.
- `fetch_values(idx, ...)`: Returns an array containing the values associated with the given indexes. Raises `IndexError` if an index is not found, unless a block is provided.
- `values_at(selector, ...)`: Returns an array containing the elements corresponding to the given selector(s).
### Searching and Comparison
- `assoc(obj)`: Searches through an array of arrays, comparing `obj` with the first element of each contained array. Returns the first matching contained array or `nil`.
- `rassoc(obj)`: Searches through an array of arrays, comparing `obj` with the second element of each contained array. Returns the first matching contained array or `nil`.
- `bsearch { |x| block }`: Finds a value from the array which meets the given condition using binary search.
- `bsearch_index { |x| block }`: Finds the index of a value from the array which meets the given condition using binary search.
### Iterators and Combinatorics
- `reverse_each`: Calls the given block for each element in reverse order.
- `permutation(n=self.size)`: Yields all permutations of length `n` of the elements of the array.
- `combination(n)`: Yields all combinations of length `n` of elements from the array.
- `product(*arys)`: Returns an array of all combinations of elements from self and the given arrays.
- `repeated_combination(n)`: Yields all repeated combinations of length `n`.
- `repeated_permutation(n)`: Yields all repeated permutations of length `n`.
### Conversions and Other Utilities
- `to_h`: Returns the result of interpreting the array as an array of `[key, value]` pairs.
- `transpose`: Assumes that self is an array of arrays and transposes the rows and columns.
### Filtering
- `delete_if { |item| block }`: Deletes every element of self for which the block evaluates to `true`.
- `reject! { |item| block }`: Equivalent to `delete_if`, but returns `nil` if no changes were made.
- `keep_if { |item| block }`: Deletes every element of self for which the given block evaluates to `false`.
- `select! { |item| block }`: Deletes elements for which the block returns a `false` value. Returns `self` if changes were made, otherwise `nil`.
### Aliases
- `append` (alias for `push`)
- `prepend` (alias for `unshift`)
- `filter!` (alias for `select!`)
## Usage
To use this gem, add it to your `build_config.rb` or `mrbgem.rake` file. For detailed examples of each method, please refer to the comments in the source code (`mrblib/array.rb` and `src/array.c`).
Example:
```ruby
a = [1, 2, 2, 3, nil, 4]
p a.compact #=> [1, 2, 2, 3, 4]
p a.uniq #=> [1, 2, 3, nil, 4]
b = ["a", "b", "c"]
p b.rotate #=> ["b", "c", "a"]
```
This gem is part of the mruby project.
+1 -1
View File
@@ -50,7 +50,7 @@ I hereby place this file and all of FGMP in the public domain.
Thanks to Paul Rouse <par@r-cube.demon.co.uk> for changes to get fgmp
to work on a 286 MS-DOS compiler, the functions mpz_sqrt and
mpz_sqrtrem, plus other general bug fixes.
mpz_sqrtrem, plus other general bugfixes.
Thanks also to Erick Gallesio <eg@kaolin.unice.fr> for a fix
to mpz_init_set_str
+38 -1
View File
@@ -1,7 +1,44 @@
# Multi-precision Integer extension for mruby
# mruby-bigint
mruby-bigint is an mrbgem that provides multi-precision integer (BigInt) support for mruby. It allows you to work with integers that are larger than the standard Integer type can handle.
This extension uses fgmp, which is a public domain implementation of a subset of the GNU gmp library by Mark Henderson <markh@wimsey.bc.ca>.
But it's heavily modified to fit with mruby. You can get the original source code from <https://github.com/deischi/fgmp.git>.
You can read the original README for fgmp in [README-fgmp.md](README-fgmp.md).
If you want to create your own Multi-precision Integer GEM, see [examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md](../../examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md).
## Features
- Basic arithmetic operations: `+`, `-`, `*`, `/`, `%`
- Power operation: `**`
- Modular exponentiation
- Bitwise operations: `&`, `|`, `^`, `<<`, `>>`
- Comparison: `<=>`
- Conversion to and from strings: `to_s`, `String#to_i` (with base)
- Square root
- Greatest Common Divisor (GCD) (available if `MRB_USE_RATIONAL` is defined)
## Usage
Here are some simple examples of how to use mruby-bigint:
```ruby
# Creating BigInts
a = BigInt(12345678901234567890)
b = "98765432109876543210".to_i(10) # Specify base 10 for string conversion
# Arithmetic operations
c = a + b
puts c.to_s # Output: 111111111011111111100
d = a * 2
puts d.to_s # Output: 24691357802469135780
# Comparison
puts a <=> b # Output: -1
```
## fgmp Dependency
mruby-bigint depends on fgmp. For more information about fgmp, please see [README-fgmp.md](README-fgmp.md).
+74 -2
View File
@@ -882,7 +882,7 @@ mpz_get_str(mrb_state *mrb, char *s, mrb_int sz, mrb_int base, mpz_t *x)
if ((base & (base - 1)) == 0) { // base is a power of 2
int shift = 0;
while ((1 << shift) < base) shift++;
mp_limb mask = base - 1;
mp_limb mask = (mp_limb)base - 1;
mp_dbl_limb value = 0;
int bits = 0;
@@ -1246,6 +1246,61 @@ mpz_gcd(mrb_state *mrb, mpz_t *gg, mpz_t *aa, mpz_t *bb)
}
#endif
static size_t
mpz_bits(const mpz_t *x)
{
if (x->sz == 0 || x->sn == 0) return 0;
size_t limb_bits = sizeof(mp_limb) * 8;
// Get the most significant limb
size_t i = x->sz - 1;
mp_limb high = x->p[i];
// Number of bits = total full limbs + significant bits in top limb
return i * limb_bits + (limb_bits - lzb(high));
}
static void
mpz_sqrt(mrb_state *mrb, mpz_t *z, mpz_t *x)
{
mrb_assert(x->sn >= 0);
if (x->sz == 0) {
// sqrt(0) = 0
z->sn = 0;
z->sz = 0;
return;
}
// Estimate initial value: 1 << (bit_length(x) / 2)
size_t xbits = mpz_bits(x);
size_t sbit = (xbits + 1) / 2;
mpz_t s, t;
mpz_init_set_int(mrb, &s, 1);
mpz_mul_2exp(mrb, &s, &s, sbit);
mpz_init(mrb, &t);
// Iteratively refine s using Newton-Raphson method:
// s = (s + x / s) / 2
for (;;) {
mpz_mdiv(mrb, &t, x, &s); // t = x / s
mpz_add(mrb, &t, &t, &s); // t = s + x/s
mpz_div_2exp(mrb, &t, &t, 1); // t = (s + x/s) / 2
if (mpz_cmp(mrb, &t, &s) >= 0) {
// Converged: t >= s
break;
}
mpz_set(mrb, &s, &t);
}
mpz_move(mrb, z, &s);
mpz_clear(mrb, &t);
}
/* --- mruby functions --- */
/* initialize mpz_t from RBigint (not need to clear) */
static void
@@ -1861,7 +1916,7 @@ mrb_bint_to_s(mrb_state *mrb, mrb_value x, mrb_int base)
return mrb_str_new_lit(mrb, "0");
}
size_t len = mpz_sizeinbase(&a, (int)base);
if (MRB_INT_MAX-2 < len) {
if (sizeof(size_t) >= sizeof(mrb_int) && MRB_INT_MAX-2 < len) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string from Integer");
}
mrb_value str = mrb_str_new(mrb, NULL, len+2);
@@ -2014,6 +2069,23 @@ mrb_bint_memsize(mrb_value x)
return z.sz * sizeof(mp_limb);
}
mrb_value
mrb_bint_sqrt(mrb_state *mrb, mrb_value x)
{
mpz_t a;
bint_as_mpz(RBIGINT(x), &a);
if (a.sn < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "square root of negative number");
}
mpz_t z;
mpz_init(mrb, &z);
mpz_sqrt(mrb, &z, &a);
return bint_norm(mrb, bint_new(mrb, &z));
}
mrb_value
mrb_bint_hash(mrb_state *mrb, mrb_value x)
{
+1 -1
View File
@@ -19,7 +19,7 @@
* I'm already aware that fgmp is considerably slower than gmp
*
* CREDITS:
* Paul Rouse <par@r-cube.demon.co.uk> - generic bug fixes, mpz_sqrt and
* Paul Rouse <par@r-cube.demon.co.uk> - generic bugfixes, mpz_sqrt and
* mpz_sqrtrem, and modifications to get fgmp to compile on a system
* with int and long of different sizes (specifically MS-DOS,286 compiler)
* Also see the file "notes" included with the fgmp distribution, for
@@ -11,6 +11,7 @@
#include <mruby/error.h>
#include <mruby/numeric.h>
#include <mruby/string.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
#include "apiprint.h"
@@ -70,12 +71,15 @@ mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t
v = mrb_funcall_argv(mrb, recv, MRB_SYM(instance_eval), 1, &ruby_code);
}
if (exc) {
*exc = mrb_obj_is_kind_of(mrb, v, E_EXCEPTION);
mrb_bool is_exc = mrb_obj_is_kind_of(mrb, v, E_EXCEPTION);
if (is_exc) {
s = mrb_exc_get_output(mrb, mrb_obj_ptr(v));
}
else {
s = mrb_inspect(mrb, v);
}
s = mrb_inspect(mrb, v);
if (exc) *exc = is_exc;
/* enable code_fetch_hook */
mrb->code_fetch_hook = tmp;
+28 -12
View File
@@ -112,19 +112,17 @@ get_history_path(mrb_state *mrb)
#endif
static void
p(mrb_state *mrb, mrb_value obj, int prompt)
p(mrb_state *mrb, mrb_value obj)
{
mrb_value val;
char* msg;
val = mrb_funcall_argv(mrb, obj, MRB_SYM(inspect), 0, NULL);
if (prompt) {
if (!mrb->exc) {
fputs(" => ", stdout);
}
else {
val = mrb_funcall_id(mrb, mrb_obj_value(mrb->exc), MRB_SYM(inspect), 0);
}
if (!mrb->exc) {
fputs(" => ", stdout);
}
else {
val = mrb_exc_get_output(mrb, mrb->exc);
}
if (!mrb_string_p(val)) {
val = mrb_obj_as_string(mrb, obj);
@@ -135,6 +133,22 @@ p(mrb_state *mrb, mrb_value obj, int prompt)
putc('\n', stdout);
}
static void
p_error(mrb_state *mrb, struct RObject* exc)
{
mrb_value val;
char* msg;
val = mrb_exc_get_output(mrb, exc);
if (!mrb_string_p(val)) {
val = mrb_obj_as_string(mrb, val);
}
msg = mrb_locale_from_utf8(RSTRING_PTR(val), (int)RSTRING_LEN(val));
fwrite(msg, strlen(msg), 1, stdout);
mrb_locale_free(msg);
putc('\n', stdout);
}
/* Guess if the user might want to enter more
* or if they wants an evaluation of their code now */
static mrb_bool
@@ -517,7 +531,7 @@ main(int argc, char **argv)
mrb_load_file_cxt(mrb, lfp, cxt);
fclose(lfp);
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
mrb_ccontext_cleanup_local_variables(mrb, cxt);
mrb_ccontext_cleanup_local_variables(cxt);
}
#ifndef MRB_NO_MIRB_UNDERSCORE
@@ -593,7 +607,9 @@ main(int argc, char **argv)
}
strcpy(last_code_line, line);
strcat(last_code_line, "\n");
MIRB_ADD_HISTORY(line);
if (strlen(line) > 0) {
MIRB_ADD_HISTORY(line);
}
MIRB_LINE_FREE(line);
#endif
@@ -672,7 +688,7 @@ main(int argc, char **argv)
/* did an exception occur? */
if (mrb->exc) {
MRB_EXC_CHECK_EXIT(mrb, mrb->exc);
p(mrb, mrb_obj_value(mrb->exc), 0);
p_error(mrb, mrb->exc);
mrb->exc = 0;
}
else {
@@ -680,7 +696,7 @@ main(int argc, char **argv)
if (!mrb_respond_to(mrb, result, MRB_SYM(inspect))){
result = mrb_any_to_s(mrb, result);
}
p(mrb, result, 1);
p(mrb, result);
#ifndef MRB_NO_MIRB_UNDERSCORE
*(mrb->c->ci->stack + 1) = result;
#endif
+3 -3
View File
@@ -26,7 +26,7 @@ struct mrbc_args {
mrb_bool verbose : 1;
mrb_bool no_ext_ops : 1;
mrb_bool no_optimize : 1;
uint8_t flags : 2;
uint8_t flags : 3;
};
static void
@@ -245,7 +245,7 @@ load_file(mrb_state *mrb, struct mrbc_args *args)
args->idx++;
if (args->idx < args->argc) {
need_close = FALSE;
mrb_ccontext_partial_hook(mrb, c, partial_hook, (void*)args);
mrb_ccontext_partial_hook(c, partial_hook, (void*)args);
}
result = mrb_load_file_cxt(mrb, infile, c);
@@ -286,7 +286,7 @@ dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, const struct RProc *pr
int
main(int argc, char **argv)
{
mrb_state *mrb = mrb_open_core(NULL, NULL);
mrb_state *mrb = mrb_open_core();
int n, result;
struct mrbc_args args;
FILE *wfp;
+2 -2
View File
@@ -339,10 +339,10 @@ main(int argc, char **argv)
}
fclose(lfp);
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
mrb_ccontext_cleanup_local_variables(mrb, c);
mrb_ccontext_cleanup_local_variables(c);
}
/* set program file name */
/* set program filename */
mrb_ccontext_filename(mrb, c, cmdline);
/* Load program */
@@ -126,7 +126,7 @@ main(int argc, char **argv)
print_usage(argv[0]);
return EXIT_FAILURE;
}
mrb = mrb_open_core(mrb_default_allocf, NULL);
mrb = mrb_open_core();
if (mrb == NULL) {
fputs("Invalid mrb_state, exiting mruby-strip\n", stderr);
return EXIT_FAILURE;
+256
View File
@@ -0,0 +1,256 @@
# mruby-binding
The `mruby-binding` mrbgem provides the `Binding` class for mruby. This class allows you to encapsulate the execution context (variables, methods, and `self`) at a particular point in your code, making it available for later use. It is similar in purpose to the `Binding` class in standard Ruby.
## Obtaining a Binding Object
You can obtain a `Binding` object using the `Kernel#binding` method:
### `Kernel#binding` -> Binding
Returns a `Binding` object that encapsulates the execution context (including local variables, `self`, and any active block) at the point of the call.
Example:
```ruby
def get_binding(param)
local_var = 42
binding # This will capture param, local_var, and self
end
b = get_binding("hello")
# b now holds the context from inside get_binding
```
**Note:** `Kernel#binding` cannot be called from a C function or a Proc defined in C. Attempting to do so will raise a `RuntimeError`.
## `Binding` Class Methods
A `Binding` object has the following methods:
### `local_variables` -> Array of Symbol
Returns an array of symbols representing the names of the local variables defined in the binding's context.
Example:
```ruby
def my_method
a = 10
b = 20
binding.local_variables # => [:a, :b]
end
```
### `local_variable_get(symbol)` -> Object
Retrieves the value of the local variable named by `symbol`. Raises a `NameError` if the variable is not defined in the binding's context.
Example:
```ruby
def my_method
a = 10
b = binding
b.local_variable_get(:a) # => 10
end
```
### `local_variable_set(symbol, value)` -> Object
Sets the local variable named by `symbol` to `value`. If the variable is not already defined, it will be defined in the binding's scope. Returns the `value` that was set.
Example:
```ruby
def my_method
a = 10
b = binding
b.local_variable_set(:a, 20) # a is now 20
b.local_variable_set(:c, 30) # c is now defined as 30 in this scope
a # => 20
c # => 30
end
```
### `local_variable_defined?(symbol)` -> Boolean
Returns `true` if the local variable named by `symbol` is defined in the binding's context, `false` otherwise.
Example:
```ruby
def my_method
a = 10
b = binding
b.local_variable_defined?(:a) # => true
b.local_variable_defined?(:c) # => false
end
```
### `receiver` -> Object
Returns the receiver object (`self`) of the binding.
Example:
```ruby
class MyClass
def get_binding
@x = "instance var"
binding
end
end
obj = MyClass.new
b = obj.get_binding
b.receiver # => obj (the instance of MyClass)
b.receiver.instance_variable_get(:@x) # => "instance var" (Not directly using eval)
```
### `source_location` -> [String, Integer] | nil
Returns a two-element array containing the filename and line number where the binding was created. Returns `nil` if the source location cannot be determined (e.g., for bindings created from C).
Example:
```ruby
# In a file named 'test.rb'
b = binding # Assuming this is line 2
b.source_location # => ["test.rb", 2] (approximately)
```
### `dup` / `clone` -> Binding
Creates a shallow copy of the binding. Modifications to local variables in one binding object can affect the other if the variables themselves are mutable objects, but setting a variable in one binding will not create it in the other after duplication. The internal state concerning local variable storage is also duplicated.
(The C code refers to `binding_initialize_copy`, which is what `dup` and `clone` would use.)
```ruby
def my_method
x = 1
original_binding = binding
original_binding.local_variable_set(:y, 2)
copied_binding = original_binding.dup
original_binding.local_variable_set(:x, 10)
original_binding.local_variable_set(:y, 20)
original_binding.local_variable_set(:z, 30) # New variable in original
puts copied_binding.local_variable_get(:x) # => 1 (Original value before duplication for variables existing at duplication time)
# Correction: The tests show that changes to existing variables are reflected.
# Let's re-verify test behavior for `dup`.
# Re-checking test `Binding#dup`:
# x = 5
# bind1 = binding
# bind1.local_variable_set(:y, 10)
# bind2 = bind1.dup
# assert_equal 5, bind2.local_variable_get(:x)
# assert_equal 10, bind2.local_variable_get(:y)
# x = 50 # x is changed in the original scope AFTER duplication
# assert_equal 50, bind1.local_variable_get(:x)
# assert_equal 50, bind2.local_variable_get(:x) # bind2 sees the change to x!
# bind1.local_variable_set(:y, 20) # y is changed in bind1 AFTER duplication
# assert_equal 20, bind1.local_variable_get(:y)
# assert_equal 20, bind2.local_variable_get(:y) # bind2 sees the change to y!
# bind1.local_variable_set(:z, 30) # z is added to bind1
# assert_raise(NameError) { bind2.local_variable_get(:z) } # bind2 does not see new z
# bind2.local_variable_set(:z, 40) # z is added to bind2
# assert_equal 30, bind1.local_variable_get(:z)
# assert_equal 40, bind2.local_variable_get(:z)
# Corrected explanation for dup/clone:
# Creates a copy of the binding. Both the original and copied bindings share the same
# underlying environment for local variables that existed at the time of duplication.
# This means:
# - If a variable that existed when `dup` was called is modified (either in the original
# scope or via `local_variable_set` on either binding), the change is visible in both bindings.
# - If a *new* local variable is added to one binding using `local_variable_set` *after*
# duplication, it is not visible in the other binding.
end
```
**Note on `eval`:** While the `Binding` object is often used with `eval` in standard Ruby to execute code within the binding's context, `mruby-binding` itself does not provide an `eval` method directly on the `Binding` object. You would typically use `Binding` with mruby's core `eval` method if you need to evaluate a string of code within a captured context. The `mruby-binding` gem provides the necessary infrastructure (like `mrb_binding_extract_proc` and `mrb_binding_extract_env` in C) that can be utilized by an `eval` implementation.
```ruby
# Conceptual example (actual eval might vary based on mruby core)
def my_method
a = 10
b = binding
# eval("puts a", b) # => would print 10
# eval("a = 20", b) # a in my_method's scope would become 20
end
```
## Usage Example
Here's a more complete example demonstrating some of the `Binding` object's capabilities:
```ruby
class Greeter
def initialize(name)
@name = name
end
def get_binding_for_greeting(additional_message)
greeting_type = "Hello"
# Capture the binding here
binding
end
end
# Create an instance and get a binding
greeter_instance = Greeter.new("World")
captured_binding = greeter_instance.get_binding_for_greeting("Have a nice day!")
# Access the receiver (self)
puts "Receiver: #{captured_binding.receiver}"
# => Receiver: #<Greeter:0x...> (actual object id will vary)
puts "Receiver's name: #{captured_binding.receiver.instance_variable_get(:@name)}"
# => Receiver's name: World
# List local variables in the binding
puts "Local variables: #{captured_binding.local_variables.inspect}"
# => Local variables: [:additional_message, :greeting_type] (order may vary)
# Get local variable values
puts "Greeting type: #{captured_binding.local_variable_get(:greeting_type)}"
# => Greeting type: Hello
puts "Additional message: #{captured_binding.local_variable_get(:additional_message)}"
# => Additional message: Have a nice day!
# Set a local variable within the binding's context
captured_binding.local_variable_set(:greeting_type, "Hi")
puts "New greeting type: #{captured_binding.local_variable_get(:greeting_type)}"
# => New greeting type: Hi
# Check if a variable is defined
puts "Is 'greeting_type' defined? #{captured_binding.local_variable_defined?(:greeting_type)}"
# => Is 'greeting_type' defined? true
puts "Is 'non_existent_var' defined? #{captured_binding.local_variable_defined?(:non_existent_var)}"
# => Is 'non_existent_var' defined? false
# Source location (will vary based on where the code is run)
location = captured_binding.source_location
if location
puts "Binding created at: #{location[0]}:#{location[1]}"
else
puts "Source location not available for this binding."
end
```
This example illustrates how a `Binding` object captures the state of local variables and `self` from the scope where it was created, and how these can be inspected and manipulated.
## Limitations and mruby-specific Considerations
- **Nesting Depth for Local Variables:** mruby has an internal limit on how deeply nested Procs (blocks) can be while still allowing the `Binding` object to access and manage their local variables. This limit is defined by the `BINDING_UPPER_MAX` constant (defaulting to 20, with a minimum of 10 and a maximum of 100, configurable at compile time via `MRB_BINDING_UPPER_MAX`). If you exceed this nesting depth, attempting to create or manipulate a binding that needs to access variables across too many Proc scopes might result in a `RuntimeError` ("too many upper procs for local variables").
- **`eval` Method:** As noted earlier, this gem provides the `Binding` object itself, not a `Binding#eval` method. You would use `Kernel.eval(string, binding)` if you need to evaluate code within the context of a binding, relying on mruby's core `eval` capabilities.
- **C Function Callers:** `Kernel#binding` cannot create a `Binding` object if the direct caller is a C function. It must be called from Ruby code.
```
```
+1 -1
View File
@@ -402,7 +402,7 @@ mrb_mruby_binding_gem_init(mrb_state *mrb)
mrb_define_private_method_id(mrb, mrb->kernel_module, MRB_SYM(binding), mrb_f_binding, MRB_ARGS_NONE());
mrb_define_method_id(mrb, binding, MRB_SYM(initialize_copy), binding_initialize_copy, MRB_ARGS_REQ(1));
mrb_define_private_method_id(mrb, binding, MRB_SYM(initialize_copy), binding_initialize_copy, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, binding, MRB_SYM_Q(local_variable_defined), binding_local_variable_defined_p, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, binding, MRB_SYM(local_variable_get), binding_local_variable_get, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, binding, MRB_SYM(local_variable_set), binding_local_variable_set, MRB_ARGS_REQ(2));
+94
View File
@@ -0,0 +1,94 @@
# mruby-catch
This mrbgem provides `catch` and `throw` functionality similar to what is available in standard Ruby. It allows for non-local exits from blocks of code.
## `catch`
The `catch` method is used to establish a block that can be exited prematurely using `throw`.
```ruby
catch(tag) do |current_tag|
# ... code ...
if some_condition
throw(tag, return_value)
end
# ... more code ...
end
```
- **With a tag:** When `catch` is called with a `tag` (any Ruby object), it executes the block. If `throw` is called with the same `tag` from within this block (or any method called from within it), the `catch` block immediately exits and returns the value provided to `throw`.
- **Block completion:** If the block executes to completion without `throw` being called with a matching tag, the `catch` block returns the result of the last expression evaluated in the block.
- **No tag:** If `catch` is called without a tag, a new unique `Object` is created and used as the tag. This tag is passed as an argument to the block.
```ruby
catch do |generated_tag|
# generated_tag is a new Object
throw(generated_tag, "hello")
end # => "hello"
```
## `throw`
The `throw` method is used to initiate a non-local exit to a corresponding `catch` block.
```ruby
throw(tag)
throw(tag, value)
```
- **With a tag and value:** `throw(tag, value)` jumps to the innermost active `catch` block that is waiting for `tag`. The `catch` block then returns `value`.
- **With only a tag:** `throw(tag)` is equivalent to `throw(tag, nil)`.
- **Uncaught throw:** If `throw` is called with a `tag` for which there is no matching `catch` block in the current call stack, an `UncaughtThrowError` is raised.
## `UncaughtThrowError`
This is a custom error class that inherits from `ArgumentError`. It is raised when `throw` is called for a tag that is not currently being caught.
It has two attributes:
- `tag`: The tag that was thrown.
- `value`: The value that was thrown with the tag.
## Example
```ruby
def check_value(val)
puts "Checking: #{val}"
if val < 0
throw(:negative_value, val)
elsif val == 0
throw(:zero_value) # value will be nil
end
puts "#{val} is positive"
val * 2
end
result = catch(:negative_value) do
puts catch(:zero_value) do
puts check_value(10)
puts check_value(-5) # This will throw to :negative_value
puts check_value(0) # This would throw to :zero_value, but it's not reached
end
puts "This line is skipped if :zero_value is thrown."
end
puts "Result: #{result}"
# Output:
# Checking: 10
# 10 is positive
# 20
# Checking: -5
# Result: -5
puts "--- Next example --- "
result2 = catch do |tag_a|
catch do |tag_b|
puts "In tag_b block"
throw(tag_a, "Exited from A via B")
puts "This is not printed"
end
puts "This is not printed either"
end
puts result2 # => Exited from A via B
```
+81
View File
@@ -0,0 +1,81 @@
# mruby-class-ext
This mrbgem extends the `Module` and `Class` classes in mruby, providing additional methods for reflection and class manipulation.
## Module Methods
### `mod < other`
Returns `true` if `mod` is a subclass of `other`. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "A < B".)
### `mod <= other`
Returns `true` if `mod` is a subclass of `other` or is the same as `other`. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "A < B".)
### `mod > other`
Returns `true` if `mod` is an ancestor of `other`. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "B > A".)
### `mod >= other`
Returns `true` if `mod` is an ancestor of `other`, or the two modules are the same. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "B > A".)
### `module <=> other_module`
Comparison---Returns -1, 0, +1 or `nil` depending on whether `module` includes `other_module`, they are the same, or if `module` is included by `other_module`.
Returns `nil` if `module` has no relationship with `other_module`, if `other_module` is not a module, or if the two values are incomparable.
### `name`
Returns the name of the module.
### `singleton_class?`
Returns `true` if the module is a singleton class.
### `module_exec(arg...) {|var...| block } -> obj`
### `class_exec(arg...) {|var...| block } -> obj`
Evaluates the given block in the context of the class/module. The method defined in the block will belong to the receiver. Any arguments passed to the method will be passed to the block. This can be used if the block needs to access instance variables.
```ruby
class Thing
end
Thing.class_exec{
def hello() "Hello there!" end
}
puts Thing.new.hello()
```
## Class Methods
### `subclasses -> array`
Returns an array of classes where the receiver is the direct superclass of the class, excluding singleton classes. The order of the returned array is not defined.
```ruby
class A; end
class B < A; end
class C < B; end
class D < A; end
A.subclasses #=> [D, B]
B.subclasses #=> [C]
C.subclasses #=> []
```
### `attached_object -> object`
Returns the object for which the receiver is the singleton class. Raises a `TypeError` if the class is not a singleton class.
```ruby
class Foo; end
Foo.singleton_class.attached_object #=> Foo
Foo.attached_object #=> TypeError: not a singleton class
Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370>
TrueClass.attached_object #=> TypeError: not a singleton class
NilClass.attached_object #=> TypeError: not a singleton class
```
+45
View File
@@ -0,0 +1,45 @@
# mruby-cmath
This mrbgem provides complex number support for mruby, offering mathematical functions that can handle complex numbers, similar to Ruby's standard `cmath` library.
## Requirements
This gem utilizes C99 `_Complex` features. Therefore, you will need a C compiler that supports C99 or a later version to build and use this gem.
## Provided Functions
The `CMath` module includes the following mathematical functions:
- `exp(z)`: Computes the exponential of `z`.
- `log(z)`: Computes the natural logarithm of `z`.
- `log(z, b)`: Computes the logarithm of `z` with base `b`.
- `log2(z)`: Computes the base-2 logarithm of `z`.
- `log10(z)`: Computes the base-10 logarithm of `z`.
- `sqrt(z)`: Computes the square root of `z`.
- `sin(z)`: Computes the sine of `z`.
- `cos(z)`: Computes the cosine of `z`.
- `tan(z)`: Computes the tangent of `z`.
- `asin(z)`: Computes the arc sine of `z`.
- `acos(z)`: Computes the arc cosine of `z`.
- `atan(z)`: Computes the arc tangent of `z`.
- `sinh(z)`: Computes the hyperbolic sine of `z`.
- `cosh(z)`: Computes the hyperbolic cosine of `z`.
- `tanh(z)`: Computes the hyperbolic tangent of `z`.
- `asinh(z)`: Computes the inverse hyperbolic sine of `z`.
- `acosh(z)`: Computes the inverse hyperbolic cosine of `z`.
- `atanh(z)`: Computes the inverse hyperbolic tangent of `z`.
## Usage Example
Here's a simple example of how to use `CMath` to calculate the square root of a negative number:
```ruby
# Assuming mruby is built with mruby-cmath
# Calculate the square root of -4
result = CMath.sqrt(-4)
# result will be a Complex number (0+2i)
puts result.real # Output: 0.0
puts result.imaginary # Output: 2.0
```
+65
View File
@@ -0,0 +1,65 @@
# mruby-compar-ext
Comparable module extension.
This mrbgem adds the `clamp` method to the `Comparable` module.
## `Comparable#clamp`
The `clamp` method restricts a value to a given range.
**Syntax:**
```ruby
obj.clamp(min, max) -> obj
obj.clamp(range) -> obj
```
**Description:**
- In the `(min, max)` form, it returns:
- `min` if `obj <=> min` is less than zero.
- `max` if `obj <=> max` is greater than zero.
- `obj` otherwise.
- In the `(range)` form, it returns:
- `range.begin` if `obj <=> range.begin` is less than zero.
- `range.end` if `obj <=> range.end` is greater than zero (and `range.end` is not `nil` and the range is inclusive).
- `obj` otherwise.
- If `range.begin` is `nil`, it is considered smaller than `obj`.
- If `range.end` is `nil`, it is considered greater than `obj`.
**Examples:**
```ruby
# Using min and max arguments
12.clamp(0, 100) #=> 12
523.clamp(0, 100) #=> 100
-3.123.clamp(0, 100) #=> 0
'd'.clamp('a', 'f') #=> 'd'
'z'.clamp('a', 'f') #=> 'f'
# Using a Range argument
12.clamp(0..100) #=> 12
523.clamp(0..100) #=> 100
-3.123.clamp(0..100) #=> 0
'd'.clamp('a'..'f') #=> 'd'
'z'.clamp('a'..'f') #=> 'f'
# Using ranges with nil begin or end
-20.clamp(0..) #=> 0
523.clamp(..100) #=> 100
```
**Error Handling:**
- Raises an `ArgumentError` if an exclusive range (e.g., `0...100`) is provided as the `range` argument when `range.end` is not `nil`.
- Raises an `ArgumentError` if `min` and `max` arguments cannot be compared (e.g., a `String` and an `Integer`).
- Raises an `ArgumentError` if the `min` argument is greater than the `max` argument.
```ruby
100.clamp(0...100) # ArgumentError: cannot clamp with an exclusive range
10.clamp("a", "z") # ArgumentError: comparison of String with String failed (depending on mruby version, may also be other errors if types are incompatible)
100.clamp(10, 0) # ArgumentError: min argument must be smaller than max argument
```
+62 -71
View File
@@ -20,6 +20,10 @@
#include <string.h>
#include <mruby/internal.h>
#define mrbc_malloc(s) mrb_basic_alloc_func(NULL,(s))
#define mrbc_realloc(p,s) mrb_basic_alloc_func((p),(s))
#define mrbc_free(p) mrb_basic_alloc_func((p),0)
#ifndef MRB_CODEGEN_LEVEL_MAX
#define MRB_CODEGEN_LEVEL_MAX 256
#endif
@@ -48,7 +52,7 @@ struct loopinfo {
typedef struct scope {
mrb_state *mrb;
mrb_mempool *mpool;
mempool *mpool;
struct scope *prev;
@@ -124,27 +128,27 @@ codegen_error(codegen_scope *s, const char *message)
while (s->prev) {
codegen_scope *tmp = s->prev;
if (s->irep) {
mrb_free(s->mrb, s->iseq);
mrbc_free(s->iseq);
for (int i=0; i<s->irep->plen; i++) {
mrb_irep_pool *p = &s->pool[i];
if ((p->tt & 0x3) == IREP_TT_STR || p->tt == IREP_TT_BIGINT) {
mrb_free(s->mrb, (void*)p->u.str);
mrbc_free((void*)p->u.str);
}
}
mrb_free(s->mrb, s->pool);
mrb_free(s->mrb, s->syms);
mrb_free(s->mrb, s->catch_table);
mrbc_free(s->pool);
mrbc_free(s->syms);
mrbc_free(s->catch_table);
if (s->reps) {
/* copied from mrb_irep_free() in state.c */
for (int i=0; i<s->irep->rlen; i++) {
if (s->reps[i])
mrb_irep_decref(s->mrb, (mrb_irep*)s->reps[i]);
}
mrb_free(s->mrb, s->reps);
mrbc_free(s->reps);
}
mrb_free(s->mrb, s->lines);
mrbc_free(s->lines);
}
mrb_mempool_close(s->mpool);
mempool_close(s->mpool);
s = tmp;
}
MRB_THROW(s->mrb->jmp);
@@ -153,21 +157,12 @@ codegen_error(codegen_scope *s, const char *message)
static void*
codegen_palloc(codegen_scope *s, size_t len)
{
void *p = mrb_mempool_alloc(s->mpool, len);
void *p = mempool_alloc(s->mpool, len);
if (!p) codegen_error(s, "pool memory allocation");
return p;
}
static void*
codegen_realloc(codegen_scope *s, void *p, size_t len)
{
p = mrb_realloc_simple(s->mrb, p, len);
if (!p && len > 0) codegen_error(s, "mrb_realloc");
return p;
}
static void
check_no_ext_ops(codegen_scope *s, uint16_t a, uint16_t b)
{
@@ -195,9 +190,9 @@ emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
else {
s->icapa *= 2;
}
s->iseq = (mrb_code*)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
s->iseq = (mrb_code*)mrbc_realloc(s->iseq, sizeof(mrb_code)*s->icapa);
if (s->lines) {
s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
s->lines = (uint16_t*)mrbc_realloc(s->lines, sizeof(uint16_t)*s->icapa);
}
}
if (s->lines) {
@@ -588,9 +583,8 @@ static void gen_int(codegen_scope *s, uint16_t dst, mrb_int i);
static void
gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
{
if (nopeep || no_peephole(s)) goto normal;
else if (dst == src) return;
else {
if (dst == src) return;
if (!(nopeep || no_peephole(s))) {
struct mrb_insn_data data = mrb_last_insn(s);
switch (data.insn) {
@@ -599,7 +593,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
if (data.a == src) {
if (data.b == dst) /* skip swapping MOVE */
return;
if (data.a < s->nlocals) goto normal;
if (data.a < s->nlocals) break;
rewind_pc(s);
s->lastpc = addr_pc(s, mrb_prev_pc(s, data.addr));
gen_move(s, dst, data.b, FALSE);
@@ -611,34 +605,34 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
gen_move(s, dst, src, FALSE);
return;
}
goto normal;
break;
case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
case OP_LOADI__1:
case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
if (data.a != src || data.a < s->nlocals) goto normal;
if (data.a != src || data.a < s->nlocals) break;
rewind_pc(s);
genop_1(s, data.insn, dst);
return;
case OP_HASH:
if (data.b != 0) goto normal;
if (data.b != 0) break;
/* fall through */
case OP_LOADI8: case OP_LOADINEG:
case OP_LOADL: case OP_LOADSYM:
case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
case OP_GETCONST: case OP_STRING:
case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
if (data.a != src || data.a < s->nlocals) goto normal;
if (data.a != src || data.a < s->nlocals) break;
rewind_pc(s);
genop_2(s, data.insn, dst, data.b);
return;
case OP_LOADI16:
if (data.a != src || data.a < s->nlocals) goto normal;
if (data.a != src || data.a < s->nlocals) break;
rewind_pc(s);
genop_2S(s, data.insn, dst, data.b);
return;
case OP_LOADI32:
if (data.a != src || data.a < s->nlocals) goto normal;
if (data.a != src || data.a < s->nlocals) break;
else {
uint32_t i = (uint32_t)data.b<<16|data.c;
rewind_pc(s);
@@ -646,7 +640,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
}
return;
case OP_ARRAY:
if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
if (data.a != src || data.a < s->nlocals || data.a < dst) break;
rewind_pc(s);
if (data.b == 0 || dst == data.a)
genop_2(s, OP_ARRAY, dst, 0);
@@ -654,22 +648,21 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
genop_3(s, OP_ARRAY2, dst, data.a, data.b);
return;
case OP_ARRAY2:
if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
if (data.a != src || data.a < s->nlocals || data.a < dst) break;
rewind_pc(s);
genop_3(s, OP_ARRAY2, dst, data.b, data.c);
return;
case OP_AREF:
case OP_GETUPVAR:
if (data.a != src || data.a < s->nlocals) goto normal;
if (data.a != src || data.a < s->nlocals) break;
rewind_pc(s);
genop_3(s, data.insn, dst, data.b, data.c);
return;
case OP_ADDI: case OP_SUBI:
if (addr_pc(s, data.addr) == s->lastlabel || data.a != src || data.a < s->nlocals) goto normal;
if (addr_pc(s, data.addr) == s->lastlabel || data.a != src || data.a < s->nlocals) break;
else {
struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
if (data0.insn != OP_MOVE || data0.a != data.a || data0.b != dst) goto normal;
s->pc = addr_pc(s, data0.addr);
if (data0.insn != OP_MOVE || data0.a != data.a || data0.b != dst) break;
if (addr_pc(s, data0.addr) != s->lastlabel) {
/* constant folding */
data0 = mrb_decode_insn(mrb_prev_pc(s, data0.addr));
@@ -684,13 +677,12 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
}
}
}
genop_2(s, data.insn, dst, data.b);
return;
break;
default:
break;
}
}
normal:
genop_2(s, OP_MOVE, dst, src);
return;
}
@@ -805,13 +797,13 @@ realloc_pool_str(codegen_scope *s, mrb_irep_pool *p, mrb_int len)
{
char *str;
if ((p->tt & 3) == IREP_TT_SSTR) {
str = (char*)codegen_realloc(s, NULL, len+1);
str = (char*)mrbc_malloc(len+1);
}
else {
str = (char*)p->u.str;
str = (char*)codegen_realloc(s, str, len+1);
str = (char*)mrbc_realloc(str, len+1);
}
p->tt = len<<2 | IREP_TT_STR;
p->tt = (uint32_t)(len<<2 | IREP_TT_STR);
str[len] = '\0';
p->u.str = (const char*)str;
}
@@ -820,7 +812,7 @@ static void
free_pool_str(codegen_scope *s, mrb_irep_pool *p)
{
if ((p->tt & 3) != IREP_TT_SSTR) {
codegen_realloc(s, (char*)p->u.str, 0);
mrbc_free((char*)p->u.str);
}
p->u.str = NULL;
s->irep->plen--;
@@ -860,7 +852,7 @@ merge_op_string(codegen_scope *s, uint16_t dst, uint16_t b1, uint16_t b2, const
mrb_irep_pool *p2 = &s->pool[b2];
mrb_int len1 = p1->tt>>2;
mrb_int len2 = p2->tt>>2;
int off = find_pool_str(s, p1->u.str, len1, p2->u.str, len2);;
int off = find_pool_str(s, p1->u.str, len1, p2->u.str, len2);
if (off < 0) {
switch (used) {
@@ -1095,7 +1087,7 @@ lit_pool_extend(codegen_scope *s)
{
if (s->irep->plen == s->pcapa) {
s->pcapa *= 2;
s->pool = (mrb_irep_pool*)codegen_realloc(s, s->pool, sizeof(mrb_irep_pool)*s->pcapa);
s->pool = (mrb_irep_pool*)mrbc_realloc(s->pool, sizeof(mrb_irep_pool)*s->pcapa);
}
return &s->pool[s->irep->plen++];
@@ -1125,7 +1117,7 @@ new_litbint(codegen_scope *s, const char *p, int base)
char *buf;
pv->tt = IREP_TT_BIGINT;
buf = (char*)codegen_realloc(s, NULL, plen+3);
buf = (char*)mrbc_malloc(plen+3);
buf[0] = (char)plen;
buf[1] = base;
memcpy(buf+2, p, plen);
@@ -1172,7 +1164,7 @@ new_lit_str2(codegen_scope *s, const char *str1, mrb_int len1, const char *str2,
else {
char *p;
pool->tt = (uint32_t)(len<<2) | IREP_TT_STR;
p = (char*)codegen_realloc(s, NULL, len+1);
p = (char*)mrbc_malloc(len+1);
memcpy(p, str1, len1);
if (str2) memcpy(p+len1, str2, len2);
p[len] = '\0';
@@ -1266,7 +1258,7 @@ new_sym(codegen_scope *s, mrb_sym sym)
if (s->scapa > 0xffff) {
codegen_error(s, "too many symbols");
}
s->syms = (mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->scapa);
s->syms = (mrb_sym*)mrbc_realloc(s->syms, sizeof(mrb_sym)*s->scapa);
}
s->syms[s->irep->slen] = sym;
return s->irep->slen++;
@@ -3629,13 +3621,12 @@ codegen(codegen_scope *s, node *tree, int val)
int off = new_lit_str(s, p, len);
int sym;
genop_1(s, OP_LOADSELF, cursp());
push();
genop_2(s, OP_STRING, cursp(), off);
push(); push();
pop_n(3);
sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */
genop_3(s, OP_SEND, cursp(), sym, 1);
genop_3(s, OP_SSEND, cursp(), sym, 1);
if (val) push();
}
break;
@@ -3969,7 +3960,7 @@ scope_add_irep(codegen_scope *s)
s->irep = irep = mrb_add_irep(s->mrb);
if (prev->irep->rlen == prev->rcapa) {
prev->rcapa *= 2;
prev->reps = (mrb_irep**)codegen_realloc(s, prev->reps, sizeof(mrb_irep*)*prev->rcapa);
prev->reps = (mrb_irep**)mrbc_realloc(prev->reps, sizeof(mrb_irep*)*prev->rcapa);
}
prev->reps[prev->irep->rlen] = irep;
prev->irep->rlen++;
@@ -3980,8 +3971,8 @@ static codegen_scope*
scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv)
{
static const codegen_scope codegen_scope_zero = { 0 };
mrb_mempool *pool = mrb_mempool_open(mrb);
codegen_scope *s = (codegen_scope*)mrb_mempool_alloc(pool, sizeof(codegen_scope));
mempool *pool = mempool_open();
codegen_scope *s = (codegen_scope*)mempool_alloc(pool, sizeof(codegen_scope));
if (!s) {
if (prev)
@@ -3999,26 +3990,26 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv)
scope_add_irep(s);
s->rcapa = 8;
s->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*s->rcapa);
s->reps = (mrb_irep**)mrbc_malloc(sizeof(mrb_irep*)*s->rcapa);
s->icapa = 1024;
s->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*s->icapa);
s->iseq = (mrb_code*)mrbc_malloc(sizeof(mrb_code)*s->icapa);
s->pcapa = 32;
s->pool = (mrb_irep_pool*)mrb_malloc(mrb, sizeof(mrb_irep_pool)*s->pcapa);
s->pool = (mrb_irep_pool*)mrbc_malloc(sizeof(mrb_irep_pool)*s->pcapa);
s->scapa = 256;
s->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*s->scapa);
s->syms = (mrb_sym*)mrbc_malloc(sizeof(mrb_sym)*s->scapa);
s->lv = nlv;
s->sp += node_len(nlv)+1; /* add self */
s->nlocals = s->sp;
s->nlocals = s->nregs = s->sp;
if (nlv) {
mrb_sym *lv;
node *n = nlv;
size_t i = 0;
s->irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*(s->nlocals-1));
s->irep->lv = lv = (mrb_sym*)mrbc_malloc(sizeof(mrb_sym)*(s->nlocals-1));
for (i=0, n=nlv; n; i++,n=n->cdr) {
lv[i] = lv_name(n);
}
@@ -4028,7 +4019,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv)
s->filename_sym = prev->filename_sym;
if (s->filename_sym) {
s->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*s->icapa);
s->lines = (uint16_t*)mrbc_malloc(sizeof(short)*s->icapa);
}
s->lineno = prev->lineno;
@@ -4060,7 +4051,7 @@ scope_finish(codegen_scope *s)
irep->flags = 0;
if (s->iseq) {
size_t catchsize = sizeof(struct mrb_irep_catch_handler) * irep->clen;
irep->iseq = (const mrb_code*)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc + catchsize);
irep->iseq = (const mrb_code*)mrbc_realloc(s->iseq, sizeof(mrb_code)*s->pc + catchsize);
irep->ilen = s->pc;
if (irep->clen > 0) {
memcpy((void*)(irep->iseq + irep->ilen), s->catch_table, catchsize);
@@ -4069,11 +4060,11 @@ scope_finish(codegen_scope *s)
else {
irep->clen = 0;
}
mrb_free(s->mrb, s->catch_table);
mrbc_free(s->catch_table);
s->catch_table = NULL;
irep->pool = (const mrb_irep_pool*)codegen_realloc(s, s->pool, sizeof(mrb_irep_pool)*irep->plen);
irep->syms = (const mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*irep->slen);
irep->reps = (const mrb_irep**)codegen_realloc(s, s->reps, sizeof(mrb_irep*)*irep->rlen);
irep->pool = (const mrb_irep_pool*)mrbc_realloc(s->pool, sizeof(mrb_irep_pool)*irep->plen);
irep->syms = (const mrb_sym*)mrbc_realloc(s->syms, sizeof(mrb_sym)*irep->slen);
irep->reps = (const mrb_irep**)mrbc_realloc(s->reps, sizeof(mrb_irep*)*irep->rlen);
if (s->filename_sym) {
mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
@@ -4081,13 +4072,13 @@ scope_finish(codegen_scope *s)
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
filename, s->lines, s->debug_start_pos, s->pc);
}
mrb_free(s->mrb, s->lines);
mrbc_free(s->lines);
irep->nlocals = s->nlocals;
irep->nregs = s->nregs;
mrb_gc_arena_restore(mrb, s->ai);
mrb_mempool_close(s->mpool);
mempool_close(s->mpool);
}
static struct loopinfo*
@@ -4178,7 +4169,7 @@ static int
catch_handler_new(codegen_scope *s)
{
size_t newsize = sizeof(struct mrb_irep_catch_handler) * (s->irep->clen + 1);
s->catch_table = (struct mrb_irep_catch_handler*)codegen_realloc(s, (void*)s->catch_table, newsize);
s->catch_table = (struct mrb_irep_catch_handler*)mrbc_realloc((void*)s->catch_table, newsize);
return s->irep->clen++;
}
@@ -4216,7 +4207,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
codegen(scope, p->tree, val);
proc = mrb_proc_new(mrb, scope->irep);
mrb_irep_decref(mrb, scope->irep);
mrb_mempool_close(scope->mpool);
mempool_close(scope->mpool);
proc->c = NULL;
if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
proc->upper = NULL;
@@ -4226,7 +4217,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
}
MRB_CATCH(mrb->jmp) {
mrb_irep_decref(mrb, scope->irep);
mrb_mempool_close(scope->mpool);
mempool_close(scope->mpool);
mrb->jmp = prev_jmp;
return NULL;
}
+28 -21
View File
@@ -27,6 +27,10 @@
#define YYLEX_PARAM p
#define mrbc_malloc(s) mrb_basic_alloc_func(NULL,(s))
#define mrbc_realloc(p,s) mrb_basic_alloc_func((p),(s))
#define mrbc_free(p) mrb_basic_alloc_func((p),0)
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
typedef struct mrb_parser_heredoc_info parser_heredoc_info;
@@ -111,7 +115,7 @@ cons_free_gen(parser_state *p, node *cons)
static void*
parser_palloc(parser_state *p, size_t size)
{
void *m = mrb_mempool_alloc(p->pool, size);
void *m = mempool_alloc(p->pool, size);
if (!m) {
MRB_THROW(p->mrb->jmp);
@@ -1079,7 +1083,7 @@ static node*
composite_string_node(parser_state *p, node *a, node *b)
{
size_t newlen = (size_t)a->cdr + (size_t)b->cdr;
char *str = (char*)mrb_mempool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
char *str = (char*)mempool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
memcpy(str + (size_t)a->cdr, b->car, (size_t)b->cdr);
str[newlen] = '\0';
a->car = (node*)str;
@@ -1540,7 +1544,7 @@ prohibit_literals(parser_state *p, node *n)
modifier_while "'while' modifier"
modifier_until "'until' modifier"
modifier_rescue "'rescue' modifier"
keyword_alias "'alis'"
keyword_alias "'alias'"
keyword_BEGIN "'BEGIN'"
keyword_END "'END'"
keyword__LINE__ "'__LINE__'"
@@ -4489,7 +4493,7 @@ static int
newtok(parser_state *p)
{
if (p->tokbuf != p->buf) {
mrb_free(p->mrb, p->tokbuf);
mrbc_free(p->tokbuf);
p->tokbuf = p->buf;
p->tsiz = MRB_PARSER_TOKBUF_SIZE;
}
@@ -4542,11 +4546,11 @@ tokadd(parser_state *p, int32_t c)
}
p->tsiz *= 2;
if (p->tokbuf == p->buf) {
p->tokbuf = (char*)mrb_malloc(p->mrb, p->tsiz);
p->tokbuf = (char*)mrbc_malloc(p->tsiz);
memcpy(p->tokbuf, p->buf, MRB_PARSER_TOKBUF_SIZE);
}
else {
p->tokbuf = (char*)mrb_realloc(p->mrb, p->tokbuf, p->tsiz);
p->tokbuf = (char*)mrbc_realloc(p->tokbuf, p->tsiz);
}
}
for (i = 0; i < len; i++) {
@@ -6633,7 +6637,7 @@ parser_update_cxt(parser_state *p, mrb_ccontext *cxt)
i++;
n = n->cdr;
}
cxt->syms = (mrb_sym*)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
cxt->syms = (mrb_sym*)mrbc_realloc(cxt->syms, i*sizeof(mrb_sym));
cxt->slen = i;
for (i=0, n=n0; n; i++,n=n->cdr) {
cxt->syms[i] = sym(n->car);
@@ -6684,13 +6688,13 @@ mrb_parser_parse(parser_state *p, mrb_ccontext *c)
MRB_API parser_state*
mrb_parser_new(mrb_state *mrb)
{
mrb_mempool *pool;
mempool *pool;
parser_state *p;
static const parser_state parser_state_zero = { 0 };
pool = mrb_mempool_open(mrb);
pool = mempool_open();
if (!pool) return NULL;
p = (parser_state*)mrb_mempool_alloc(pool, sizeof(parser_state));
p = (parser_state*)mempool_alloc(pool, sizeof(parser_state));
if (!p) return NULL;
*p = parser_state_zero;
@@ -6726,23 +6730,26 @@ mrb_parser_new(mrb_state *mrb)
MRB_API void
mrb_parser_free(parser_state *p) {
if (p->tokbuf != p->buf) {
mrb_free(p->mrb, p->tokbuf);
mrbc_free(p->tokbuf);
}
mrb_mempool_close(p->pool);
mempool_close(p->pool);
}
MRB_API mrb_ccontext*
mrb_ccontext_new(mrb_state *mrb)
{
return (mrb_ccontext*)mrb_calloc(mrb, 1, sizeof(mrb_ccontext));
static const mrb_ccontext cc_zero = { 0 };
mrb_ccontext *cc = (mrb_ccontext*)mrbc_malloc(sizeof(mrb_ccontext));
*cc = cc_zero;
return cc;
}
MRB_API void
mrb_ccontext_free(mrb_state *mrb, mrb_ccontext *cxt)
{
mrb_free(mrb, cxt->filename);
mrb_free(mrb, cxt->syms);
mrb_free(mrb, cxt);
mrbc_free(cxt->filename);
mrbc_free(cxt->syms);
mrbc_free(cxt);
}
MRB_API const char*
@@ -6750,12 +6757,12 @@ mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s)
{
if (s) {
size_t len = strlen(s);
char *p = (char*)mrb_malloc_simple(mrb, len + 1);
char *p = (char*)mrbc_malloc(len + 1);
if (p == NULL) return NULL;
memcpy(p, s, len + 1);
if (c->filename) {
mrb_free(mrb, c->filename);
mrbc_free(c->filename);
}
c->filename = p;
}
@@ -6763,17 +6770,17 @@ mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s)
}
MRB_API void
mrb_ccontext_partial_hook(mrb_state *mrb, mrb_ccontext *c, int (*func)(struct mrb_parser_state*), void *data)
mrb_ccontext_partial_hook(mrb_ccontext *c, int (*func)(struct mrb_parser_state*), void *data)
{
c->partial_hook = func;
c->partial_data = data;
}
MRB_API void
mrb_ccontext_cleanup_local_variables(mrb_state *mrb, mrb_ccontext *c)
mrb_ccontext_cleanup_local_variables(mrb_ccontext *c)
{
if (c->syms) {
mrb_free(mrb, c->syms);
mrbc_free(c->syms);
c->syms = NULL;
c->slen = 0;
}
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
# mruby-complex
mruby-complex is an mrbgem that provides a `Complex` class for mruby, allowing for the representation and manipulation of complex numbers. It is designed to be compatible with the Complex class in standard Ruby.
## Functionality
The `Complex` class provided by this mrbgem supports:
- Creation of complex numbers from real and imaginary parts, or using the `i` suffix for numbers.
- Basic arithmetic operations: addition (`+`), subtraction (`-`), multiplication (`*`), division (`/`).
- Methods to access the real and imaginary parts (`real`, `imaginary` or `imag`).
- Calculation of absolute value (`abs`, `magnitude`), argument/angle (`arg`, `angle`, `phase`), and square of the absolute value (`abs2`).
- Complex conjugate (`conjugate`, `conj`).
- Conversion to polar coordinates (`polar`).
- Conversion to other numeric types where appropriate (`to_f`, `to_i`, `to_r`, `to_c`).
- Inspection and string representation (`inspect`, `to_s`).
## Usage Examples
Here are some basic examples of how to use the `Complex` class:
```ruby
# Creating complex numbers
c1 = Complex(1, 2) # => (1+2i)
c2 = 3 + 4i # => (3+4i)
c3 = Complex.polar(5, Math::PI/2) # => (0.0+5.0i) (approximately)
# Arithmetic operations
puts c1 + c2 # => (4+6i)
puts c1 - c2 # => (-2-2i)
puts c1 * c2 # => (-5+10i)
puts c1 / c2 # => (0.44+0.08i)
# Accessing parts
puts c1.real # => 1
puts c1.imaginary # => 2
# Other methods
puts c2.abs # => 5.0
puts c2.arg # => 0.9272952180016122 (radians)
puts c2.conjugate # => (3-4i)
puts c1.polar # => [2.23606797749979, 1.1071487177940904]
# Numerics can be converted to Complex
puts 5.to_c # => (5+0i)
puts 2.3.to_c # => (2.3+0i)
# The `i` method on numerics creates a complex number with zero real part
puts 5i # => (0+5i)
puts 2.3i # => (0+2.3i)
```
## Note
This mrbgem aims to provide functionality similar to the `Complex` class found in the standard Ruby library. Refer to the Ruby documentation for `Complex` for more detailed information on the behavior of various methods.
+126
View File
@@ -0,0 +1,126 @@
# mruby-data
The `mruby-data` mrbgem provides a way to define simple classes in mruby that act as data structures, similar to Ruby's `Struct` class. It allows you to bundle a number of attributes together and access them using accessor methods.
## Purpose
`mruby-data` is useful when you need to create lightweight objects that primarily serve to hold and provide access to a set of data attributes without the need to write a full class definition manually.
## Functionality
### Defining a Data Class
You can define a new data class using the `Data.define` class method. It accepts one or more symbols as arguments, which will become the attribute names for the instances of the generated class.
```ruby
# Defines a new class 'Point' with attributes :x and :y
Point = Data.define(:x, :y)
# Defines a new class 'Customer' with attributes :name, :address, and :zip
Customer = Data.define(:name, :address, :zip)
```
### Creating Instances
Once a data class is defined, you can create instances of it using the `new` method, providing values for each attribute in the order they were defined.
```ruby
# Create an instance of Point
point1 = Point.new(10, 20)
# Create an instance of Customer
customer1 = Customer.new("John Doe", "123 Main St", 12345)
```
Alternatively, you can pass keyword arguments (available if mruby is compiled with `MRB_KW_ARGS`):
```ruby
customer2 = Customer.new(name: "Jane Doe", address: "456 Oak Ave", zip: 67890)
```
### Accessing Attributes
Instances of data classes have accessor methods for each defined attribute.
```ruby
puts point1.x # Output: 10
puts point1.y # Output: 20
puts customer1.name # Output: "John Doe"
```
### Instance Methods
Instances of classes created by `Data.define` have several useful methods:
- **`members`**: Returns an array of symbols representing the names of the attributes.
```ruby
p customer1.members # Output: [:name, :address, :zip]
```
- **`== (other)`**: Returns `true` if `other` is an instance of the same data class and all attribute values are equal.
```ruby
point2 = Point.new(10, 20)
point3 = Point.new(0, 0)
puts point1 == point2 # Output: true
puts point1 == point3 # Output: false
```
- **`eql?(other)`**: Similar to `==`, checks if `other` is an instance of the same data class and all attribute values are `eql?`.
- **`to_h`**: Converts the data instance into a hash where keys are the attribute symbols and values are their corresponding values.
```ruby
p customer1.to_h
# Output: {:name=>"John Doe", :address=>"123 Main St", :zip=>12345}
```
- **`to_s` / `inspect`**: Returns a string representation of the data instance.
```ruby
puts customer1 # Output: #<data Customer name="John Doe", address="123 Main St", zip=12345>
p customer1 # Output: #<data Customer name="John Doe", address="123 Main St", zip=12345>
```
## Freezing
By default, instances of data classes are frozen after initialization, meaning their attributes cannot be modified after creation.
```ruby
point = Point.new(1, 2)
# The following would raise an error as the object is frozen:
# point.x = 100
```
## Example Usage
```ruby
# Define a class for 2D vectors
Vector2D = Data.define(:x, :y)
# Create some vector instances
v1 = Vector2D.new(3, 4)
v2 = Vector2D.new(1, 5)
# Access attributes
puts "Vector v1: (#{v1.x}, #{v1.y})"
puts "Vector v2: (#{v2.x}, #{v2.y})"
# Use instance methods
puts "v1 members: #{v1.members}"
puts "v1 as hash: #{v1.to_h}"
# Comparison
v3 = Vector2D.new(3, 4)
puts "v1 == v2: #{v1 == v2}" # false
puts "v1 == v3: #{v1 == v3}" # true
```
This mrbgem simplifies the creation of simple value objects in mruby.
```
```
+1 -1
View File
@@ -493,7 +493,7 @@ mrb_mruby_data_gem_init(mrb_state* mrb)
mrb_define_method_id(mrb, d, MRB_OPSYM(eq), mrb_data_equal, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, d, MRB_SYM(members), mrb_data_members, MRB_ARGS_NONE());
mrb_define_method_id(mrb, d, MRB_SYM(initialize), mrb_data_initialize, MRB_ARGS_ANY());
mrb_define_method_id(mrb, d, MRB_SYM(initialize_copy), mrb_data_init_copy, MRB_ARGS_ANY());
mrb_define_private_method_id(mrb, d, MRB_SYM(initialize_copy), mrb_data_init_copy, MRB_ARGS_ANY());
mrb_define_method_id(mrb, d, MRB_SYM_Q(eql), mrb_data_eql, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, d, MRB_SYM(to_h), mrb_data_to_h, MRB_ARGS_NONE());
+96
View File
@@ -0,0 +1,96 @@
# mruby-encoding
This mrbgem provides a lightweight, "poorman's" encoding functionality for mruby. It is designed to offer basic encoding support, primarily focused on UTF-8 and ASCII-8BIT.
## Summary
- **License:** MIT
- **Author:** mruby developers
- **Supported Encodings:**
- `Encoding::UTF_8`
- `Encoding::ASCII_8BIT` (aliased as `Encoding::BINARY`)
## Functionality
This gem introduces an `Encoding` module and extends the `String` and `Integer` classes with encoding-related methods.
### `Encoding` Module
A module (not a class, unlike standard Ruby) that holds encoding constants.
- `Encoding::UTF_8`: Represents the UTF-8 encoding.
- `Encoding::ASCII_8BIT`: Represents the ASCII-8BIT encoding.
- `Encoding::BINARY`: An alias for `Encoding::ASCII_8BIT`.
### `String` Methods
- `string.valid_encoding? -> true or false`
- Returns `true` if the string is correctly encoded (particularly useful for UTF-8 strings). For `ASCII-8BIT` strings, it generally returns `true`.
- `string.encoding -> EncodingConstant`
- Returns the encoding of the string. This will be `Encoding::UTF_8` or `Encoding::BINARY`.
- `string.force_encoding(encoding_name) -> string`
- Changes the string's reported encoding to the specified `encoding_name` (e.g., "UTF-8", "ASCII-8BIT", "BINARY").
- The actual byte sequence of the string is not changed.
- Raises an `ArgumentError` if an unsupported encoding name is provided.
### `Integer` Method
- `integer.chr(encoding_name = Encoding::BINARY) -> String`
- Returns a single-character string represented by the integer.
- If `encoding_name` is "UTF-8", the integer is treated as a Unicode codepoint.
- If `encoding_name` is "ASCII-8BIT" or "BINARY" (the default), the integer is treated as a byte value (0-255).
- Raises a `RangeError` if the integer is out of the valid range for the specified encoding.
- Raises an `ArgumentError` for unknown encoding names.
## Usage Example
```ruby
# main.rb
if __ENCODING__ == "UTF-8"
s = "helloあ"
puts s.encoding #=> Encoding::UTF_8
puts s.valid_encoding? #=> true
s2 = "\xff".force_encoding("UTF-8")
puts s2.valid_encoding? #=> false
s3 = "world"
s3.force_encoding("BINARY")
puts s3.encoding #=> Encoding::BINARY
puts s3.valid_encoding? #=> true (ASCII-8BIT strings are generally considered valid)
puts 65.chr #=> "A" (defaults to ASCII-8BIT)
puts 230.chr("UTF-8") #=> "æ" (if U+00E6 is æ)
# For mruby, this might be different based on actual UTF-8 char mapping
# For example, 12354.chr("UTF-8") might be "あ"
else
s = "hello"
puts s.encoding #=> Encoding::BINARY (or ASCII-8BIT)
# Attempting to force to UTF-8 in a non-UTF-8 mruby build might be limited
# or behave as ASCII-8BIT depending on mruby's core string handling.
end
# Force encoding
my_string = "\xE3\x81\x82" # UTF-8 bytes for "あ"
puts my_string.encoding # Might be BINARY by default if not created as UTF-8 literal
my_string.force_encoding("UTF-8")
puts my_string.encoding #=> Encoding::UTF_8
puts my_string #=> あ
invalid_utf8 = "\xff\xfe"
invalid_utf8.force_encoding("UTF-8")
puts invalid_utf8.valid_encoding? #=> false
# Integer#chr
puts 65.chr # => "A"
puts 65.chr("BINARY") # => "A"
# When mruby is compiled with MRB_UTF8_STRING
if Object.const_defined?(:MRB_UTF8_STRING)
puts 12354.chr("UTF-8") # => "あ"
# puts 0x110000.chr("UTF-8") #=> RangeError
end
```
+80
View File
@@ -0,0 +1,80 @@
# mruby-enum-chain
## Description
This mrbgem provides the `Enumerator::Chain` class, which allows you to chain multiple enumerable objects together, treating them as a single, continuous enumerable.
This is useful when you have multiple collections (e.g., arrays, ranges, or other enumerators) and you want to iterate over all of them sequentially without first concatenating them into a single, larger collection.
## How to Use
There are three main ways to create an `Enumerator::Chain` instance:
### 1. Using `Enumerable#chain`
You can call the `chain` method on any object that includes the `Enumerable` module.
```ruby
a = [1, 2, 3]
b = (4..6)
c = {foo: 7, bar: 8}.each_key # Enumerator for keys
chained_enum = a.chain(b, c)
chained_enum.to_a # => [1, 2, 3, 4, 5, 6, :foo, :bar]
```
### 2. Using `Enumerator#+`
You can use the `+` operator on an `Enumerator` instance to chain it with another enumerable object.
```ruby
enum1 = [1, 2].each
enum2 = %w(a b).each
chained_enum = enum1 + enum2
chained_enum.to_a # => [1, 2, "a", "b"]
# You can chain multiple times
enum3 = (10..11).each
chained_enum_2 = enum1 + enum2 + enum3
chained_enum_2.to_a # => [1, 2, "a", "b", 10, 11]
```
### 3. Using `Enumerator::Chain.new`
You can directly instantiate `Enumerator::Chain` by passing enumerable objects to its constructor.
```ruby
arr = [10, 20]
rng = (30..31)
chained_enum = Enumerator::Chain.new(arr, rng)
chained_enum.to_a # => [10, 20, 30, 31]
```
## Key Features
- **`each(&block)`**: Iterates through each element of the chained enumerables in the order they were added. Returns an enumerator if no block is given.
- **`size`**: Returns the total number of elements in all chained enumerables. If any of the chained enumerables do not respond to `size` (e.g., an infinite enumerator or one with an unknown size), this method will return `nil`.
```ruby
([1, 2].chain([3, 4])).size # => 4
([1, 2].chain( (1..Float::INFINITY) )).size # => nil
```
- **`rewind`**: Rewinds all of the chained enumerables that respond to the `rewind` method. This resets the iteration state to the beginning.
```ruby
e = [1,2].chain(3..4)
e.next # => 1
e.next # => 2
e.next # => 3
e.rewind
e.next # => 1
```
- **`+(other)`**: Creates a new `Enumerator::Chain` by appending another enumerable to the current chain.
## License
MIT License
+487
View File
@@ -0,0 +1,487 @@
# mruby-enum-ext
This mrbgem extends the `Enumerable` module in mruby with additional useful methods.
## Added Methods
Below is a list of methods added to the `Enumerable` module, along with a brief description and example for each.
---
### `drop(n)`
Drops the first `n` elements from an enumerable and returns the rest of the elements in an array.
_Example:_
```ruby
a = [1, 2, 3, 4, 5, 0]
a.drop(3) #=> [4, 5, 0]
```
---
### `drop_while { |obj| block }`
Drops elements up to, but not including, the first element for which the block returns `nil` or `false`. Returns an array containing the remaining elements. If no block is given, an enumerator is returned.
_Example:_
```ruby
a = [1, 2, 3, 4, 5, 0]
a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
```
---
### `take(n)`
Returns the first `n` elements from an enumerable as an array.
_Example:_
```ruby
a = [1, 2, 3, 4, 5, 0]
a.take(3) #=> [1, 2, 3]
```
---
### `take_while { |obj| block }`
Passes elements to the block until the block returns `nil` or `false`, then stops iterating and returns an array of all prior elements. If no block is given, an enumerator is returned.
_Example:_
```ruby
a = [1, 2, 3, 4, 5, 0]
a.take_while {|i| i < 3 } #=> [1, 2]
```
---
### `each_cons(n) { |a| block }`
Iterates the given block for each array of consecutive `n` elements. If no block is given, an enumerator is returned.
_Example:_
```ruby
(1..10).each_cons(3) {|a| p a}
# outputs below
# [1, 2, 3]
# [2, 3, 4]
# [3, 4, 5]
# [4, 5, 6]
# [5, 6, 7]
# [6, 7, 8]
# [7, 8, 9]
# [8, 9, 10]
```
---
### `each_slice(n) { |a| block }`
Iterates the given block for each slice of `n` elements. If no block is given, an enumerator is returned.
_Example:_
```ruby
(1..10).each_slice(3) {|a| p a}
# outputs below
# [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]
# [10]
```
---
### `group_by { |obj| block }`
Groups the collection by the result of the block. Returns a hash where keys are the evaluated result from the block and values are arrays of elements corresponding to the key. If no block is given, an enumerator is returned.
_Example:_
```ruby
(1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
```
---
### `sort_by { |obj| block }`
Sorts the enumerable using a set of keys generated by mapping the values in the enumerable through the given block. Returns an array. If no block is given, an enumerator is returned. (Note: `Array#sort_by` and `Array#sort_by!` are also implemented for optimized in-place sorting for arrays).
_Example:_
```ruby
%w(apple pear fig).sort_by { |word| word.length }
#=> ["fig", "pear", "apple"]
```
_(Example adapted, original was for `Array#sort_by`)_
---
### `first` / `first(n)`
Returns the first element, or the first `n` elements, of the enumerable. If the enumerable is empty, `first` returns `nil`, and `first(n)` returns an empty array.
_Examples:_
```ruby
a = [1, 2, 3, 4, 5]
a.first #=> 1
a.first(3) #=> [1, 2, 3]
[].first #=> nil
[].first(3) #=> []
```
---
### `count` / `count(item)` / `count { |obj| block }`
Returns the number of items in the enumerable.
- If an argument `item` is given, counts items equal to `item`.
- If a block is given, counts elements yielding a true value.
- If no argument or block is given, counts all items.
_Examples:_
```ruby
[1, 2, 3, 2].count #=> 4
[1, 2, 3, 2].count(2) #=> 2
[1, 2, 3, 4].count { |x| x%2 == 0 } #=> 2
```
---
### `flat_map { |obj| block }` (alias: `collect_concat`)
Returns a new array with the concatenated results of running the block once for every element. If no block is given, an enumerator is returned.
_Example:_
```ruby
[1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
[[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
```
---
### `max_by { |obj| block }`
Returns the object in the enumerable that gives the maximum value from the given block. If no block is given, an enumerator is returned.
_Example:_
```ruby
%w[albatross dog horse].max_by {|x| x.length } #=> "albatross"
```
---
### `min_by { |obj| block }`
Returns the object in the enumerable that gives the minimum value from the given block. If no block is given, an enumerator is returned.
_Example:_
```ruby
%w[albatross dog horse].min_by {|x| x.length } #=> "dog"
```
---
### `minmax` / `minmax { |a, b| block }`
Returns a two-element array containing the minimum and maximum values. The first form assumes objects implement `Comparable`; the second uses the block to return `a <=> b`.
_Examples:_
```ruby
a = %w(albatross dog horse)
a.minmax #=> ["albatross", "horse"]
a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
```
---
### `minmax_by { |obj| block }`
Returns a two-element array containing the objects that correspond to the minimum and maximum values from the given block. If no block is given, an enumerator is returned.
_Example:_
```ruby
%w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"]
```
---
### `none?` / `none? { |obj| block }` / `none?(pattern)`
- With a block: Returns `true` if the block never returns `true` for any element.
- With a pattern: Returns `true` if `pattern === element` is never true for any element.
- With no argument or block: Returns `true` if none of the collection members are truthy.
_Examples:_
```ruby
%w(ant bear cat).none? { |word| word.length == 5 } #=> true
%w(ant bear cat).none? { |word| word.length >= 4 } #=> false
%w{ant bear cat}.none?(/d/) #=> true
[1, 3.14, 42].none?(Float) #=> false
[].none? #=> true
[nil, false].none? #=> true
```
---
### `one?` / `one? { |obj| block }` / `one?(pattern)`
- With a block: Returns `true` if the block returns `true` exactly once.
- With a pattern: Returns `true` if `pattern === element` is true for exactly one element.
- With no argument or block: Returns `true` if exactly one of the collection members is truthy.
_Examples:_
```ruby
%w(ant bear cat).one? { |word| word.length == 4 } #=> true
%w(ant bear cat).one? { |word| word.length > 4 } #=> false
%w{ant bear cat}.one?(/t/) #=> false # (Note: original example might be specific to mruby version, "ant" and "cat" contain "t")
[nil, true, false].one? #=> true
[nil, true, 99].one?(Integer) #=> true
```
---
### `all?` / `all? { |obj| block }` / `all?(pattern)`
- With a block: Returns `true` if the block never returns `false` or `nil` for any element.
- With a pattern: Returns `true` if `pattern === element` is true for every element.
- With no argument or block: Returns `true` if all collection members are truthy.
_Examples:_
```ruby
%w[ant bear cat].all? { |word| word.length >= 3 } #=> true
%w[ant bear cat].all? { |word| word.length >= 4 } #=> false
[1, 2i, 3.14].all?(Numeric) #=> true
[nil, true, 99].all? #=> false
```
---
### `any?` / `any? { |obj| block }` / `any?(pattern)`
- With a block: Returns `true` if the block ever returns a truthy value for an element.
- With a pattern: Returns `true` if `pattern === element` is true for any element.
- With no argument or block: Returns `true` if at least one collection member is truthy.
_Examples:_
```ruby
%w[ant bear cat].any? { |word| word.length >= 3 } #=> true
%w[ant bear cat].any?(/d/) #=> false
[nil, true, 99].any?(Integer) #=> true
[nil, true, 99].any? #=> true
[].any? #=> false
```
---
### `each_with_object(obj) { |(*args), memo_obj| ... }`
Iterates the given block for each element with an arbitrary object `obj` given, and returns the initially given `obj`. If no block is given, an enumerator is returned.
_Example:_
```ruby
(1..10).each_with_object([]) { |i, a| a << i*2 }
#=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
```
---
### `reverse_each { |item| block }`
Builds a temporary array and traverses that array in reverse order, executing the block for each item. If no block is given, an enumerator is returned.
_Example:_
```ruby
(1..3).reverse_each { |v| p v }
# produces:
# 3
# 2
# 1
```
---
### `cycle(n=nil) { |obj| block }`
Calls the block for each element repeatedly `n` times, or forever if `n` is `nil`. If `n` is non-positive or the collection is empty, does nothing. Returns `nil` if the loop finishes. If no block is given, an enumerator is returned.
_Examples:_
```ruby
a = ["a", "b", "c"]
# a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
```
---
### `find_index(value)` / `find_index { |obj| block }`
Compares each entry with `value` or passes to `block`. Returns the index for the first non-false evaluation. If no object matches, returns `nil`. If no argument or block is given, an enumerator is returned.
_Examples:_
```ruby
(1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
(1..100).find_index(50) #=> 49
```
---
### `zip(arg, ...) { |arr| block }`
Takes one element from the enumerable and merges corresponding elements from each `arg`. Generates a sequence of n-element arrays. The length will be `enum#size`. If any argument is shorter, `nil` values are supplied. If a block is given, it's invoked for each output array; otherwise, an array of arrays is returned.
_Examples:_
```ruby
a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]
a.zip(b) #=> [[4, 7], [5, 8], [6, 9]]
[1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
c = []
a.zip(b) { |x, y| c << x + y } #=> nil
c #=> [11, 13, 15]
```
---
### `to_h { |element| block }`
Returns a hash by interpreting the enumerable as a list of `[key, value]` pairs. If a block is given, it's used to transform elements before they are converted into pairs.
_Example:_
```ruby
%i[hello world].each_with_index.to_h
# => {:hello => 0, :world => 1}
# With a block (example assumes a suitable block)
# (0..3).to_h {|x| [x, x*x] } # => {0=>0, 1=>1, 2=>4, 3=>9} (Conceptual example)
```
_(The `to_h` method in the source is a bit complex with its block handling; the example is simplified.)_
---
### `uniq { |item| block }`
Returns a new array by removing duplicate values. If a block is given, it will use the return value of the block for uniqueness comparison.
_Examples:_
```ruby
[1, 2, 2, 3, 1].uniq #=> [1, 2, 3]
["a", "B", "c", "b"].uniq { |s| s.downcase } #=> ["a", "B", "c"]
```
---
### `filter_map { |obj| block }`
Returns a new array containing the truthy results of running the block for every element. If no block is given, an enumerator is returned.
_Example:_
```ruby
[-2, -1, 0, 1, 2].filter_map { |x| x*2 if x > 0 } #=> [2, 4]
```
---
### `grep_v(pattern) { |obj| block }`
Returns an array of elements that do NOT match the `pattern`. If a block is given, the elements of the result are passed to the block and the block's results are returned.
_Example:_
```ruby
a = ["apple", "banana", "orange", "grape"]
a.grep_v(/an/) #=> ["apple", "orange", "grape"]
a.grep_v(/an/) { |s| s.upcase } #=> ["APPLE", "ORANGE", "GRAPE"]
```
---
### `tally`
Tallies the collection. Returns a hash where keys are elements and values are their counts.
_Example:_
```ruby
["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
```
---
### `sum(initial=0) { |obj| block }`
Returns the sum of elements. If a block is given, each element is processed by the block before addition. `initial` is the starting value for the sum.
_Examples:_
```ruby
[1, 2, 3].sum #=> 6
[1, 2, 3].sum(10) #=> 16
[1, 2, 3].sum { |x| x * 2 } #=> 12
({a:1, b:2, c:3}).sum {|k,v| v} #=> 6 (Example from Ruby docs, assuming similar behavior)
```
---
### `each_entry(*args) { |obj| block }`
Calls block once for each element, passing that element as a parameter (converting multiple values from yield to an array). If no block is given, an enumerator is returned.
_Example:_
```ruby
class Foo
include Enumerable
def each
yield 1
yield 1, 2
yield
end
end
Foo.new.each_entry{ |o| p o }
# produces:
# 1
# [1, 2]
# nil
```
---
**Note on `Array#sort_by` and `Array#sort_by!`**
The gem also provides optimized `sort_by` and `sort_by!` methods directly on the `Array` class. `sort_by!` sorts the array in place.
```ruby
arr = ["apple", "pear", "fig"]
arr.sort_by! { |word| word.length }
p arr #=> ["fig", "pear", "apple"]
```
+8 -7
View File
@@ -820,8 +820,8 @@ module Enumerable
return to_enum(:filter_map) unless blk
ary = []
self.each do |x|
x = blk.call(x)
self.each do |*x|
x = blk.call(*x)
ary.push x if x
end
ary
@@ -851,7 +851,8 @@ module Enumerable
# ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
def tally
hash = {}
self.each do |x|
self.each do |*x|
x = x.__svalue
hash[x] = (hash[x]||0)+1
end
hash
@@ -870,12 +871,12 @@ module Enumerable
def sum(init=0,&block)
result=init
if block
self.each do |e|
result += block.call(e)
self.each do |*e|
result += block.call(*e)
end
else
self.each do |e|
result += e
self.each do |*e|
result += e.__svalue
end
end
result
+91
View File
@@ -0,0 +1,91 @@
# mruby-enum-lazy
## Overview
This mrbgem provides lazy evaluation for Enumerable objects in mruby. It introduces the `Enumerable#lazy` method, which returns an instance of `Enumerator::Lazy`. This allows for more efficient processing of collections, especially large or potentially infinite sequences, by evaluating elements only when they are needed.
## Functionality
When you call `.lazy` on an Enumerable object (like an Array or Range), you get back an `Enumerator::Lazy` object. This object behaves much like a regular Enumerator, but with a key difference: methods that transform the collection are deferred until the results are actually required.
The following methods are implemented to act lazily:
- `map` / `collect`
- `select` / `find_all`
- `reject`
- `grep`
- `grep_v`
- `drop`
- `drop_while`
- `take`
- `take_while`
- `flat_map` / `collect_concat`
- `zip`
- `uniq`
To trigger the evaluation of the lazy operations and retrieve all results (if finite), you can use methods like `force` or `to_a`.
### How it works
Operations on an `Enumerator::Lazy` object are chained together. The actual computation of each element is postponed until it's requested (e.g., by `force`, `to_a`, or iterating with `each`). This can lead to significant performance improvements by avoiding unnecessary computations and memory allocations, particularly when dealing with large data sets or when only a subset of results is needed.
## Usage Example
Here's a simple example demonstrating lazy evaluation:
```ruby
# Without lazy evaluation
# This would attempt to create an infinite array, which is not feasible.
# (1..Float::INFINITY).map { |x| x * x }.select { |x| x % 2 == 0 }.take(5).to_a
# With lazy evaluation
p (1..Float::INFINITY).lazy.map { |x| x * x }.select { |x| x % 2 == 0 }.take(5).force
# Output: [4, 16, 36, 64, 100]
# Another example:
a = [1, 2, 3, 4, 5]
lazy_sequence = a.lazy.map do |x|
puts "mapping #{x}"
x * 10
end.select do |x|
puts "selecting #{x}"
x > 20
end
puts "Applying force..."
result = lazy_sequence.force
# Output:
# mapping 1
# selecting 10
# mapping 2
# selecting 20
# mapping 3
# selecting 30
# mapping 4
# selecting 40
# mapping 5
# selecting 50
# Applying force...
p result # Output: [30, 40, 50]
```
## Dependencies
This gem depends on the following mruby core gems:
- `mruby-enumerator`
- `mruby-enum-ext`
## License
MIT License
## Author
mruby developers
## Acknowledgements
Based on <https://github.com/yhara/enumerable-lazy>
Inspired by <https://github.com/antimon2/enumerable_lz>
Reference: <http://jp.rubyist.net/magazine/?0034-Enumerable_lz> (ja)
+89
View File
@@ -0,0 +1,89 @@
# mruby-enumerator
The `mruby-enumerator` mrbgem provides the `Enumerator` class, which allows for both internal and external iteration in mruby.
## Purpose and Functionality
Enumerators are useful when you want to work with collections of data in a flexible way. They allow you to:
- **Iterate externally:** Fetch elements one by one using methods like `next`.
- **Chain operations:** Combine multiple iteration steps (e.g., mapping and then selecting) without creating intermediate arrays.
- **Create custom iterators:** Define your own iteration logic.
## Creating an Enumerator
You can create an `Enumerator` in several ways:
1. **Using `Kernel#to_enum` or `Kernel#enum_for`:** This is the most common way. You can turn any object that has an `each` method (or a similar iteration method) into an Enumerator.
```ruby
e = [1, 2, 3].to_enum # Creates an enumerator for the array
e = "hello".enum_for(:each_byte) # Creates an enumerator for iterating over bytes
```
2. **Using `Enumerator.new`:** You can create an Enumerator by providing a block that defines how values are yielded.
```ruby
fib = Enumerator.new do |yielder|
a = b = 1
loop do
yielder << a
a, b = b, a + b
end
end
fib.take(5) # => [1, 1, 2, 3, 5]
```
## Key Methods
The `Enumerator` class includes many helpful methods from the `Enumerable` module, as well as some of its own:
- **`next`**: Returns the next value from the enumerator. Raises `StopIteration` if the enumerator is at the end.
- **`peek`**: Returns the next value without advancing the iterator.
- **`rewind`**: Resets the enumerator to its beginning.
- **`with_index(offset = 0)`**: Iterates over elements, providing both the element and its index (with an optional offset). Returns a new Enumerator if no block is given.
```ruby
["a", "b"].each.with_index(1) do |char, index|
puts "#{index}: #{char}"
end
# Output:
# 1: a
# 2: b
```
- **`each_with_index`**: Similar to `with_index(0)`.
- **`with_object(obj)`**: Iterates over elements, passing an arbitrary object along with each element. Returns the given object. Returns a new Enumerator if no block is given.
```ruby
(1..3).each.with_object([]) do |i, arr|
arr << i * 2
end # => [2, 4, 6]
```
- **`each(*args)`**: Iterates over the enumerator. If arguments are provided, they are passed to the underlying iteration method.
- **`feed(value)`**: Sets a value to be returned by the `yield` inside the enumerator on its next call.
## Chaining Enumerators
One of the powerful features of Enumerators is the ability to chain operations:
```ruby
data = [1, 2, 3, 4, 5]
result = data.to_enum
.with_index # [[1, 0], [2, 1], [3, 2], [4, 3], [5, 4]]
.select { |num, idx| num.even? } # [[2, 1], [4, 3]]
.map { |num, idx| "#{idx}:#{num}" } # ["1:2", "3:4"]
p result # => ["1:2", "3:4"]
```
This avoids creating intermediate arrays for each step, making the code more efficient and readable for complex data transformations.
## Integration
This mrbgem integrates the `Enumerator` class into mruby, making it available for use in your mruby projects. It also extends `Kernel` with `to_enum` and `enum_for`, and `Enumerable` with methods like `zip`, `chunk`, and `chunk_while` that leverage `Enumerator`.
Refer to the source code and tests for more detailed examples and advanced usage.
@@ -132,7 +132,7 @@ class Enumerator
@stop_exc = false
end
def initialize_copy(obj)
private def initialize_copy(obj)
raise TypeError, "can't copy type #{obj.class}" unless obj.kind_of? Enumerator
raise TypeError, "can't copy execution context" if obj.instance_eval{@fib}
meth = args = kwd = fib = nil
+58
View File
@@ -2,6 +2,64 @@
Errno module for mruby
This mrbgem provides the `Errno` module, which allows mruby programs to access system error numbers and their corresponding error messages. This is particularly useful for handling errors returned by underlying system calls.
## Functionality
The `mruby-errno` gem defines the `Errno` module and the `SystemCallError` class.
### Accessing Error Constants
The `Errno` module provides constants for various system errors. Each error constant corresponds to a specific system error number.
Example:
```ruby
p Errno::EPERM::Errno # Output: 1 (or the system-specific value for EPERM)
p Errno::EPERM.new.message # Output: "Operation not permitted"
```
### Raising and Rescuing System Call Errors
The `SystemCallError` class is the base class for system call errors. You can raise instances of `SystemCallError` or its subclasses (like `Errno::EPERM`) and rescue them in your code.
Example:
```ruby
begin
raise Errno::EACCES, "my_method"
rescue SystemCallError => e
p e.class # Output: Errno::EACCES
p e.errno # Output: 13 (or the system-specific value for EACCES)
p e.message # Output: "Permission denied - my_method"
p e.to_s # Output: "Permission denied - my_method"
end
# You can also rescue specific Errno constants
begin
# Simulate a system call that might fail
# For example, trying to open a file without permissions
raise Errno::ENOENT, "missing_file.txt"
rescue Errno::ENOENT => e
puts "Caught an ENOENT error: #{e.message}"
# Output: Caught an ENOENT error: No such file or directory - missing_file.txt
end
```
### Errno::NOERROR
The `Errno::NOERROR` constant represents the absence of an error, typically with a value of 0.
Example:
```ruby
p Errno::NOERROR::Errno # Output: 0
```
## Defining Error Types
New error types and their corresponding numbers are defined in the `known_errors.def` file. The `gen.rb` script processes this file to generate the necessary C and Ruby code for the `Errno` module. This allows `mruby-errno` to be easily extended with new system error definitions.
## License
Copyright (c) 2013 Internet Initiative Japan Inc.
+5 -6
View File
@@ -24,7 +24,7 @@ assert('SystemCallError#errno') do
end
assert('SystemCallError#inspect') do
assert_equal("unknown error - a (SystemCallError)", SystemCallError.new("a").inspect)
assert_equal("#<SystemCallError: unknown error - a>", SystemCallError.new("a").inspect)
end
assert('Errno::NOERROR') do
@@ -50,9 +50,8 @@ assert('Errno::EPERM#message') do
end
assert('Errno::EPERM#inspect') do
msg = Errno::EPERM.new.message
assert_equal("#{msg} (Errno::EPERM)", Errno::EPERM.new.inspect)
msg = Errno::EPERM.new.message
assert_equal("#{msg} - a (Errno::EPERM)", Errno::EPERM.new("a").inspect)
e = Errno::EPERM.new
msg = e.message
assert_equal("#<Errno::EPERM: #{msg}>", e.inspect)
assert_equal("#<Errno::EPERM: #{msg} - a>", Errno::EPERM.new("a").inspect)
end
+103
View File
@@ -0,0 +1,103 @@
# mruby-error
The `mruby-error` mrbgem provides a set of C-level APIs for structured exception handling within mruby. These functions allow C extensions or embedded mruby code to implement error handling patterns similar to Ruby's `begin`, `rescue`, and `ensure` keywords. This is particularly useful when writing C code that needs to interact with mruby's exception system in a robust way.
## `mrb_protect`
The `mrb_protect` function is used to execute a C function (`body`) and capture any exceptions that might be raised during its execution. This allows you to run potentially unsafe operations and handle errors gracefully.
**C Signature:**
```c
mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);
```
**Parameters:**
- `mrb_state *mrb`: The current mruby state.
- `mrb_func_t body`: A function pointer to the C function to be executed. This function should have the signature `mrb_value (*body)(mrb_state *mrb, mrb_value data)`.
- `mrb_value data`: A `mrb_value` that will be passed as an argument to the `body` function.
- `mrb_bool *state`: A pointer to a boolean. After `mrb_protect` returns, this boolean will be:
- `FALSE` (0) if the `body` function executed without raising an exception.
- `TRUE` (1) if an exception was raised within the `body` function.
**Return Value:**
- If no exception occurs (`*state` is `FALSE`), `mrb_protect` returns the value returned by the `body` function.
- If an exception occurs (`*state` is `TRUE`), `mrb_protect` returns the exception object.
## `mrb_ensure`
The `mrb_ensure` function ensures that a specific C function (`ensure`) is executed, regardless of whether another C function (`body`) completes normally or raises an exception. This is analogous to Ruby's `ensure` clause.
**C Signature:**
```c
mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data);
```
**Parameters:**
- `mrb_state *mrb`: The current mruby state.
- `mrb_func_t body`: A function pointer to the main C function to be executed.
- `mrb_value b_data`: A `mrb_value` passed as data to the `body` function.
- `mrb_func_t ensure`: A function pointer to the C function that will always be executed after the `body` function.
- `mrb_value e_data`: A `mrb_value` passed as data to the `ensure` function.
**Behavior:**
The `body` function is executed first. After its completion (either normally or due to an exception), the `ensure` function is executed. If the `body` function raised an exception, that exception is re-thrown after the `ensure` function has finished. The return value of `mrb_ensure` is the result of the `body` function if no exception occurred.
## `mrb_rescue`
The `mrb_rescue` function executes a C function (`body`) and, if an exception that is a `StandardError` (or a subclass of `StandardError`) is raised, it executes a specified `rescue` C function. This is similar to a `rescue` clause in Ruby that doesn't specify a particular exception type (which defaults to `StandardError`).
**C Signature:**
```c
mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data);
```
**Parameters:**
- `mrb_state *mrb`: The current mruby state.
- `mrb_func_t body`: A function pointer to the main C function to be executed.
- `mrb_value b_data`: A `mrb_value` passed as data to the `body` function.
- `mrb_func_t rescue`: A function pointer to the C function that will be executed if a `StandardError` (or its subclass) is caught.
- `mrb_value r_data`: A `mrb_value` passed as data to the `rescue` function.
**Behavior:**
If the `body` function executes without raising an exception, its result is returned. If a `StandardError` (or one of its descendants) is raised, the `rescue` function is executed, and its result becomes the return value of `mrb_rescue`. If an exception occurs that is not a `StandardError` (or its subclass), it is not caught by this function and will propagate up the call stack. Similarly, if the `rescue` block itself raises an exception, that exception will propagate.
## `mrb_rescue_exceptions`
The `mrb_rescue_exceptions` function provides more fine-grained exception handling than `mrb_rescue`. It executes a C function (`body`) and, if an exception matching one of the specified classes is raised, it executes a `rescue` C function. This is analogous to Ruby's `rescue SpecificError1, SpecificError2 => e` syntax.
**C Signature:**
```c
mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data, mrb_int len, struct RClass **classes);
```
**Parameters:**
- `mrb_state *mrb`: The current mruby state.
- `mrb_func_t body`: A function pointer to the main C function to be executed.
- `mrb_value b_data`: A `mrb_value` passed as data to the `body` function.
- `mrb_func_t rescue`: A function pointer to the C function that will be executed if a matching exception is caught.
- `mrb_value r_data`: A `mrb_value` passed as data to the `rescue` function.
- `mrb_int len`: The number of exception classes provided in the `classes` array.
- `struct RClass **classes`: An array of pointers to mruby `RClass` objects representing the exception classes to be rescued.
**Behavior:**
If the `body` function executes without raising an exception, its result is returned. If an exception is raised that is an instance of one of the classes specified in the `classes` array (or a subclass of one of them), the `rescue` function is executed, and its result becomes the return value of `mrb_rescue_exceptions`. If an exception occurs that does not match any of the specified classes, it is not caught and will propagate. If the `rescue` block itself raises an exception, that exception will propagate.
## Usage Examples
The C functions provided by this mrbgem are typically used when writing mruby C extensions that need to interact with Ruby code or manage resources carefully in the presence of potential exceptions.
For concrete examples of how these functions are used, please refer to the test files within this mrbgem:
- `test/exception.c`: Shows how these C functions are called directly.
- `test/exception.rb`: Demonstrates the behavior of these C functions from the Ruby side, through the `ExceptionTest` module (defined in `test/exception.c`).
These tests illustrate how to set up callback functions and how the error handling mechanisms behave in practice.
+26
View File
@@ -0,0 +1,26 @@
# mruby-eval
This mrbgem provides methods for evaluating Ruby code from strings in mruby.
## Features
The `mruby-eval` gem implements the following methods:
- **`eval`**: Evaluates a string as Ruby code. This is a private method on `Kernel`.
- **`instance_eval`**: Evaluates a string or a block within the context of an object. This is a method on `BasicObject`.
- **`class_eval` / `module_eval`**: Evaluates a string or a block within the context of a class or module. This is a method on `Module`.
- **`Binding#eval`**: Evaluates a string within the context of a `Binding` object.
## Usage
For detailed usage and examples, please refer to the standard Ruby documentation for these methods. The mruby implementation aims to be compatible with the behavior of these methods in CRuby.
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
## License
mruby-eval is released under the MIT License. See the [LICENSE.txt](https://github.com/mruby/mruby/blob/master/LICENSE.txt) file in the main mruby repository for details.
+11 -3
View File
@@ -142,11 +142,15 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi
static mrb_value
exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
{
mrb_callinfo *ci = mrb->c->ci;
/* no argument passed from eval() */
mrb->c->ci->n = 0;
mrb->c->ci->nk = 0;
ci->n = 0;
ci->nk = 0;
/* clear visibility */
MRB_CI_SET_VISIBILITY_BREAK(ci);
/* clear block */
mrb->c->ci->stack[1] = mrb_nil_value();
ci->stack[1] = mrb_nil_value();
return mrb_exec_irep(mrb, self, proc);
}
@@ -158,6 +162,10 @@ binding_eval_error_check(mrb_state *mrb, struct mrb_parser_state *p, const char
}
if (0 < p->nerr) {
if (p->mrb->exc) {
mrb_exc_raise(mrb, mrb_obj_value(p->mrb->exc));
}
mrb_value str;
if (file) {
+23
View File
@@ -160,3 +160,26 @@ assert('Module#class_eval with string') do
b = c.class_eval("class A; def a; 55; end; end; class B; def b; A; end; end; B")
assert_equal 55, b.new.b.new.a
end
assert 'method visibility with eval' do
c = Class.new do
eval <<~CODE
private
def bad!
"BAD!"
end
CODE
def good!
"GOOD!"
end
end
assert_raise NoMethodError do
c.new.bad!
end
assert_equal "GOOD!" do
c.new.good!
end
end
+2 -2
View File
@@ -21,7 +21,7 @@ fiber_s_yield_by_c_method(mrb_state *mrb, mrb_value self)
static mrb_value
fiber_resume_by_c_func(mrb_state *mrb, mrb_value self)
{
int ci_index = mrb->c->ci - mrb->c->cibase;
ptrdiff_t ci_index = mrb->c->ci - mrb->c->cibase;
mrb_value ret = mrb_fiber_resume(mrb, self, 0, NULL);
if (ci_index != mrb->c->ci - mrb->c->cibase) {
mrb_raisef(mrb, E_EXCEPTION,
@@ -34,7 +34,7 @@ fiber_resume_by_c_func(mrb_state *mrb, mrb_value self)
static mrb_value
fiber_resume_by_c_method(mrb_state *mrb, mrb_value self)
{
int ci_index = mrb->c->ci - mrb->c->cibase;
ptrdiff_t ci_index = mrb->c->ci - mrb->c->cibase;
mrb_value ret = mrb_funcall_argv(mrb, self, mrb_intern_lit(mrb, "resume"), 0, NULL);
if (ci_index != mrb->c->ci - mrb->c->cibase) {
mrb_raisef(mrb, E_EXCEPTION,
+392
View File
@@ -0,0 +1,392 @@
# mruby-hash-ext
This mrbgem extends the core `Hash` class in mruby, providing a collection of additional methods to enhance its functionality. These extensions offer more ways to manipulate and interact with hashes, drawing inspiration from common Ruby hash methods.
## How to Use
To incorporate `mruby-hash-ext` into your mruby project, add it to your `build_config.rb` file. For example:
```ruby
MRuby::Build.new do |conf|
# ... other configurations ...
conf.gem :github => 'mruby/mruby-hash-ext'
# or if you have it locally:
# conf.gem "#{root}/mrbgems/mruby-hash-ext"
end
```
Then, rebuild your mruby project. The extended hash methods will then be available for use.
## Implemented Methods
This gem implements the following methods for the `Hash` class:
- `values_at(*keys)`: Returns an array containing the values associated with the given keys.
- `slice(*keys)`: Returns a hash containing only the given keys and their values.
- `except(*keys)`: Returns a hash excluding the given keys and their values.
- `Hash.[](*object)`: Creates a new hash populated with the given objects.
- `#merge!(other_hash..)`, `#update(other_hash..)`: Adds the contents of `other_hash` to `hsh`.
- `#compact!`: Removes all nil values from the hash.
- `#compact`: Returns a new hash with the nil values/key pairs removed.
- `#fetch(key [, default])`, `#fetch(key) {| key | block }`: Returns a value from the hash for the given key.
- `#delete_if {| key, value | block }`: Deletes every key-value pair from `hsh` for which `block` evaluates to `true`.
- `#flatten`: Returns a new array that is a one-dimensional flattening of this hash.
- `#invert`: Returns a new hash created by using `hsh`'s values as keys, and the keys as values.
- `#keep_if {| key, value | block }`: Deletes every key-value pair from `hsh` for which `block` evaluates to false.
- `#key(value)`: Returns the key of an occurrence of a given value.
- `#to_h`: Returns `self`. If called on a subclass of Hash, converts the receiver to a Hash object.
- `#< other_hash`: Returns `true` if `hsh` is a subset of `other_hash`.
- `#<= other_hash`: Returns `true` if `hsh` is a subset of `other_hash` or equal to `other_hash`.
- `#> other_hash`: Returns `true` if `other_hash` is a subset of `hsh`.
- `#>= other_hash`: Returns `true` if `other_hash` is a subset of `hsh` or equal to `hsh`.
- `#dig(key, ...)`: Extracts the nested value specified by the sequence of keys.
- `#transform_keys {|key| block }`: Returns a new hash with keys transformed by the block.
- `#transform_keys! {|key| block }`: Modifies the hash by transforming its keys using the block.
- `#transform_values {|value| block }`: Returns a new hash with values transformed by the block.
- `#transform_values! {|value| block }`: Modifies the hash by transforming its values using the block.
- `#to_proc`: Returns a proc that maps a key to its value in the hash.
- `#fetch_values(key, ...)`: Returns an array of values for the given keys, raising KeyError if any are not found.
- `#filter {| key, value | block }` (Alias for `select`): Returns a new hash containing entries for which the block returns true.
- `#filter! {| key, value | block }` (Alias for `select!`): Modifies the hash, keeping only entries for which the block returns true.
### `values_at(*keys) -> array`
Returns an array containing the values associated with the given keys. If a key is not found, `nil` is returned for that key's position in the array.
```ruby
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
h.values_at("cow", "cat") #=> ["bovine", "feline"]
h.values_at("dog", "mouse") #=> ["canine", nil]
h.values_at() #=> []
```
### `slice(*keys) -> new_hash`
Returns a new hash containing only the given keys and their associated values from the original hash. If a key is not found in the original hash, it's ignored.
```ruby
h = { a: 100, b: 200, c: 300 }
h.slice(:a) #=> {a: 100}
h.slice(:b, :c, :d) #=> {b: 200, c: 300} (ignores :d as it's not in h)
h.slice() #=> {}
```
### `except(*keys) -> new_hash`
Returns a new hash containing all key-value pairs from the original hash except for those specified by the given keys. If a key is not found in the original hash, it's ignored.
```ruby
h = { a: 100, b: 200, c: 300 }
h.except(:a) #=> {b: 200, c: 300}
h.except(:b, :c, :d) #=> {a: 100} (ignores :d as it's not in h)
h.except() #=> {a: 100, b: 200, c: 300}
```
### `Hash.[](*object)`
Creates a new hash populated with the given objects.
- **`Hash[key, value, ...]`**: Creates a new hash with key-value pairs.
- **`Hash[[ [key, value], ... ]]`**: Creates a new hash from an array of key-value pairs.
- **`Hash[object]`**: Creates a new hash from an object convertible to a hash.
```ruby
h1 = Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
h2 = Hash[[ ["a", 100], ["b", 200] ]] #=> {"a"=>100, "b"=>200}
h3 = Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
```
### `#merge!(other_hash..) -> hsh`
### `#merge!(other_hash..){|key, oldval, newval| block} -> hsh`
(Alias: `#update`)
Adds the contents of `other_hash` to `hsh`. If no block is specified, entries with duplicate keys are overwritten with the values from `other_hash`. Otherwise, the value of each duplicate key is determined by calling the block with the key, its value in `hsh`, and its value in `other_hash`.
```ruby
h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge!(h2) { |key, v1, v2| v1 }
#=> {"a"=>100, "b"=>200, "c"=>300}
```
### `#compact! -> hsh`
Removes all nil values from the hash. Returns the hash. Returns `nil` if the hash does not contain nil values.
```ruby
h = { a: 1, b: false, c: nil }
h.compact! #=> { a: 1, b: false }
```
### `#compact -> new_hsh`
Returns a new hash with the nil values/key pairs removed.
```ruby
h = { a: 1, b: false, c: nil }
h.compact #=> { a: 1, b: false }
h #=> { a: 1, b: false, c: nil }
```
### `#fetch(key [, default] ) -> obj`
### `#fetch(key) {| key | block } -> obj`
Returns a value from the hash for the given key.
If the key can't be found, there are several options:
- With no other arguments, it will raise a `KeyError` exception.
- If `default` is given, then that will be returned.
- If the optional code block is specified, then that will be run and its result returned.
```ruby
h = { "a" => 100, "b" => 200 }
h.fetch("a") #=> 100
h.fetch("z", "go fish") #=> "go fish"
h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
# h.fetch("z") # Raises KeyError: key not found: "z"
```
### `#delete_if {| key, value | block } -> hsh`
### `#delete_if -> an_enumerator`
Deletes every key-value pair from `hsh` for which `block` evaluates to `true`.
If no block is given, an enumerator is returned instead.
```ruby
h = { "a" => 100, "b" => 200, "c" => 300 }
h.delete_if {|key, value| key >= "b" } #=> {"a"=>100}
```
### `#flatten -> an_array`
### `#flatten(level) -> an_array`
Returns a new array that is a one-dimensional flattening of this hash. That is, for every key or value that is an array, extract its elements into the new array. Unlike `Array#flatten`, this method does not flatten recursively by default. The optional `level` argument determines the level of recursion to flatten.
```ruby
a = {1=> "one", 2 => [2,"two"], 3 => "three"}
a.flatten # => [1, "one", 2, [2, "two"], 3, "three"]
a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
```
### `#invert -> new_hash`
Returns a new hash created by using `hsh`'s values as keys, and the keys as values. If a value appears more than once, the last key encountered will be used due to hash key uniqueness.
```ruby
h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
```
### `#keep_if {| key, value | block } -> hsh`
### `#keep_if -> an_enumerator`
Deletes every key-value pair from `hsh` for which `block` evaluates to `false`.
If no block is given, an enumerator is returned instead.
```ruby
h = { "a" => 1, "b" => 2, "c" => 3, "d" => 4 }
h.keep_if {|key, value| value % 2 == 0 } #=> {"b"=>2, "d"=>4}
```
### `#key(value) -> key`
Returns the key of an occurrence of a given value. If the value is not found, returns `nil`.
```ruby
h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
h.key(200) #=> "b"
h.key(300) #=> "c" (returns the first key found for the value)
h.key(999) #=> nil
```
### `#to_h -> hsh or new_hash`
Returns `self`. If called on a subclass of Hash, converts the receiver to a Hash object. For a Hash instance, it simply returns `self`.
```ruby
h = { "a" => 1, "b" => 2 }
h.to_h #=> {"a"=>1, "b"=>2}
class MyHash < Hash; end
my_h = MyHash["c" => 3, "d" => 4]
my_h.to_h #=> {"c"=>3, "d"=>4} (returns a Hash object, not MyHash)
```
### `#< other_hash -> true or false`
Returns `true` if `hsh` is a proper subset of `other_hash` (i.e., `other_hash` contains all key/value pairs of `hsh`, and `other_hash` has at least one additional key/value pair).
```ruby
h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 < h2 #=> true
h2 < h1 #=> false
h1 < h1 #=> false
```
### `#<= other_hash -> true or false`
Returns `true` if `hsh` is a subset of `other_hash` or is equal to `other_hash` (i.e., `other_hash` contains all key/value pairs of `hsh`).
```ruby
h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 <= h2 #=> true
h2 <= h1 #=> false
h1 <= h1 #=> true
```
### `#> other_hash -> true or false`
Returns `true` if `other_hash` is a proper subset of `hsh` (i.e., `hsh` contains all key/value pairs of `other_hash`, and `hsh` has at least one additional key/value pair).
```ruby
h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 > h2 #=> false
h2 > h1 #=> true
h1 > h1 #=> false
```
### `#>= other_hash -> true or false`
Returns `true` if `other_hash` is a subset of `hsh` or is equal to `hsh` (i.e., `hsh` contains all key/value pairs of `other_hash`).
```ruby
h1 = {a:1, b:2}
h2 = {a:1, b:2, c:3}
h1 >= h2 #=> false
h2 >= h1 #=> true
h1 >= h1 #=> true
```
### `#dig(key,...) -> object`
Extracts the nested value specified by the sequence of `key` objects by calling `dig` at each step. Returns `nil` if any intermediate step is `nil`.
```ruby
h = { a: { b: { c: 1 } } }
h.dig(:a, :b, :c) #=> 1
h.dig(:a, :x, :c) #=> nil
g = { a: [1, 2, {b: 3}] }
g.dig(:a, 2, :b) #=> 3
g.dig(:a, 1, :b) #=> nil (element at index 1 is 2, which does not respond to #dig)
```
### `#transform_keys {|key| block } -> new_hash`
### `#transform_keys -> an_enumerator`
Returns a new hash, with the keys computed from running the block once for each key in the hash, and the values unchanged.
If no block is given, an enumerator is returned instead.
```ruby
h = { a: 1, b: 2, c: 3 }
h.transform_keys {|k| k.to_s.upcase } #=> {"A"=>1, "B"=>2, "C"=>3}
```
### `#transform_keys! {|key| block } -> hsh`
### `#transform_keys! -> an_enumerator`
Invokes the given block once for each key in `hsh`, replacing it with the new key returned by the block, and then returns `hsh`.
If no block is given, an enumerator is returned instead.
```ruby
h = { a: 1, b: 2, c: 3 }
h.transform_keys! {|k| k.to_s.upcase } #=> {"A"=>1, "B"=>2, "C"=>3}
h #=> {"A"=>1, "B"=>2, "C"=>3}
```
### `#transform_values {|value| block } -> new_hash`
### `#transform_values -> an_enumerator`
Returns a new hash with the results of running the block once for every value. This method does not change the keys.
If no block is given, an enumerator is returned instead.
```ruby
h = { a: 1, b: 2, c: 3 }
h.transform_values {|v| v * v } #=> {a: 1, b: 4, c: 9}
```
### `#transform_values! {|value| block } -> hsh`
### `#transform_values! -> an_enumerator`
Invokes the given block once for each value in the hash, replacing it with the new value returned by the block, and then returns `hsh`.
If no block is given, an enumerator is returned instead.
```ruby
h = { a: 1, b: 2, c: 3 }
h.transform_values! {|v| v * v } #=> {a: 1, b: 4, c: 9}
h #=> {a: 1, b: 4, c: 9}
```
### `#to_proc -> a_proc`
Returns a `Proc` object that maps a key to its corresponding value in the hash. This allows a hash to be used as a block argument.
```ruby
h = {a: 1, b: 2}
p = h.to_proc
p.call(:a) #=> 1
['a', 'b', 'c'].map(&h) #=> [1, 2, nil] (uses h[x] for each element)
```
### `#fetch_values(key, ...) -> array`
### `#fetch_values(key, ...) { |key| block } -> array`
Returns an array containing the values associated with the given keys. Raises `KeyError` if any of the keys can't be found, unless a block is provided to compute a default value.
```ruby
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
h.fetch_values("cow", "cat") #=> ["bovine", "feline"]
# h.fetch_values("cow", "bird") # raises KeyError: key not found: "bird"
h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
```
### `#filter {| key, value | block } -> new_hsh`
### `#filter -> an_enumerator`
(Alias for `select`)
Returns a new hash consisting of entries for which the block returns a true value.
If no block is given, an enumerator is returned instead.
```ruby
h = { "a" => 100, "b" => 200, "c" => 300 }
h.filter {|key, value| key < "b"} #=> {"a"=>100}
h.filter {|key, value| value < 200} #=> {"a"=>100}
```
### `#filter! {| key, value | block } -> hsh_or_nil`
### `#filter! -> an_enumerator`
(Alias for `select!`)
Equivalent to `Hash#keep_if`, but returns `nil` if no changes were made.
Deletes every key-value pair from `hsh` for which `block` evaluates to `false`.
If no block is given, an enumerator is returned instead.
```ruby
h = { "a" => 100, "b" => 200, "c" => 300 }
h.filter! {|key, value| key < "b"} #=> {"a"=>100}
h #=> {"a"=>100}
h.filter! {|key, value| key < "a"} #=> nil (no changes)
```
+11
View File
@@ -13,6 +13,17 @@ module Kernel
end
end
private def p(*a)
for e in a
$stdout.write e.inspect
$stdout.write "\n"
end
len = a.size
return nil if len == 0
return a[0] if len == 1
a
end
private def print(...)
$stdout.print(...)
end
+30 -31
View File
@@ -245,11 +245,9 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass)
#if defined(_WIN32)
char bname[_MAX_DIR];
char extname[_MAX_EXT];
char buffer[_MAX_DIR + _MAX_EXT];
mrb_value s;
char *path;
mrb_get_args(mrb, "S", &s);
char *path = mrb_str_to_cstr(mrb, s);
mrb_get_args(mrb, "z", &path);
size_t ridx = strlen(path);
if (ridx > 0) {
ridx--;
@@ -257,22 +255,22 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass)
path[ridx] = '\0';
ridx--;
}
if (strncmp(path, "/", 2) == 0) {
if (ridx == 0 && path[0] == '/') {
return mrb_str_new_cstr(mrb, path);
}
}
_splitpath((const char*)path, NULL, NULL, bname, extname);
snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname);
return mrb_str_new_cstr(mrb, buffer);
mrb_value buffer = mrb_str_new_cstr(mrb, bname);
mrb_str_cat_cstr(mrb, buffer, extname);
return buffer;
#else
mrb_value s;
mrb_get_args(mrb, "S", &s);
char *path = mrb_str_to_cstr(mrb, s);
char *bname;
char *path, *bname;
mrb_get_args(mrb, "z", &path);
if ((bname = basename(path)) == NULL) {
mrb_sys_fail(mrb, "basename");
}
if (strncmp(bname, "//", 3) == 0) bname[1] = '\0'; /* patch for Cygwin */
if (strcmp(bname, "//") == 0) bname[1] = '\0'; /* patch for Cygwin */
return mrb_str_new_cstr(mrb, bname);
#endif
}
@@ -281,10 +279,10 @@ static mrb_value
mrb_file_realpath(mrb_state *mrb, mrb_value klass)
{
mrb_value pathname, dir_string;
mrb_int argc = mrb_get_args(mrb, "S|S", &pathname, &dir_string);
if (argc == 2) {
if (mrb_get_args(mrb, "S|S", &pathname, &dir_string) == 2) {
mrb_value s = mrb_str_dup(mrb, dir_string);
s = mrb_str_append(mrb, s, mrb_str_new_cstr(mrb, FILE_SEPARATOR));
s = mrb_str_cat_cstr(mrb, s, FILE_SEPARATOR);
s = mrb_str_append(mrb, s, pathname);
pathname = s;
}
@@ -363,7 +361,7 @@ path_parse(mrb_state *mrb, mrb_value ary, const char *path, int ai)
SKIP_DIRSEP(path);
const char *path0 = path;
NEXT_DIRSEP(path);
int len = path - path0;
ptrdiff_t len = path - path0;
if (len == 0) {
break;
}
@@ -414,7 +412,7 @@ path_gethome(mrb_state *mrb, const char **pathp)
const char *username = ++*pathp;
NEXT_DIRSEP(*pathp);
int len = *pathp - username;
ptrdiff_t len = *pathp - username;
if (len == 0) {
home = getenv("HOME");
@@ -431,7 +429,7 @@ path_gethome(mrb_state *mrb, const char **pathp)
}
}
else {
const char *uname = RSTRING_CSTR(mrb, mrb_str_new(mrb, username, len));
const char *uname = RSTRING_CSTR(mrb, mrb_str_new(mrb, username, (mrb_int)len));
#if defined(_WIN32) || defined(MRB_IO_NO_PWNAM)
mrb_raisef(mrb, E_ARGUMENT_ERROR, "user %s doesn't exist", uname);
#else
@@ -458,7 +456,7 @@ path_expand(mrb_state *mrb, const char *path, const char *base, mrb_bool tilda)
{
mrb_value ary;
// split path conponents as array and normalization
// split path components as array and normalization
if (tilda && path[0] == '~') {
base = path_gethome(mrb, &path);
ary = path_split(mrb, path, base, NULL);
@@ -639,7 +637,7 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
}
/* FALLTHRU - should not happen */
default:
mrb_sys_fail(mrb, "flock failed");
mrb_sys_fail(mrb, "flock");
break;
}
}
@@ -653,10 +651,10 @@ mrb_file_size(mrb_state *mrb, mrb_value self)
mrb_stat st;
int fd = mrb_io_fileno(mrb, self);
if (mrb_fstat(fd, &st) == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "fstat failed");
mrb_sys_fail(mrb, "fstat");
}
if (st.st_size > MRB_INT_MAX) {
if (sizeof(st.st_size) >= sizeof(mrb_int) && st.st_size > MRB_INT_MAX) {
#ifdef MRB_NO_FLOAT
mrb_raise(mrb, E_RUNTIME_ERROR, "File#size too large for MRB_NO_FLOAT");
#else
@@ -702,7 +700,7 @@ mrb_file_truncate(mrb_state *mrb, mrb_value self)
int fd = mrb_io_fileno(mrb, self);
mrb_int length = mrb_as_int(mrb, lenv);
if (mrb_ftruncate(fd, length) != 0) {
mrb_raise(mrb, E_IO_ERROR, "ftruncate failed");
mrb_sys_fail(mrb, "ftruncate");
}
return mrb_fixnum_value(0);
@@ -740,6 +738,7 @@ mrb_file_s_chmod(mrb_state *mrb, mrb_value klass)
mrb_get_args(mrb, "i*", &mode, &filenames, &argc);
for (int i = 0; i < argc; i++) {
mrb_ensure_string_type(mrb, filenames[i]);
const char *utf8_path = RSTRING_CSTR(mrb, filenames[i]);
char *path = mrb_locale_from_utf8(utf8_path, -1);
if (CHMOD(path, mode) == -1) {
@@ -761,17 +760,16 @@ mrb_file_s_readlink(mrb_state *mrb, mrb_value klass)
return mrb_nil_value(); // unreachable
#else
const char *path;
char *buf, *tmp;
size_t bufsize = 100;
ssize_t rc;
mrb_value ret;
mrb_get_args(mrb, "z", &path);
tmp = mrb_locale_from_utf8(path, -1);
buf = (char*)mrb_malloc(mrb, bufsize);
while ((rc = readlink(tmp, buf, bufsize)) == (ssize_t)bufsize && rc != -1) {
bufsize *= 2;
char *tmp = mrb_locale_from_utf8(path, -1);
char *buf = (char*)mrb_malloc(mrb, bufsize);
ssize_t rc;
while ((rc = readlink(tmp, buf, bufsize)) == (ssize_t)bufsize) {
bufsize += 100;
buf = (char*)mrb_realloc(mrb, buf, bufsize);
}
mrb_locale_free(tmp);
@@ -780,7 +778,8 @@ mrb_file_s_readlink(mrb_state *mrb, mrb_value klass)
mrb_sys_fail(mrb, path);
}
tmp = mrb_utf8_from_locale(buf, -1);
ret = mrb_str_new(mrb, tmp, rc);
mrb_value ret = mrb_str_new(mrb, tmp, rc);
mrb_utf8_free(tmp);
mrb_free(mrb, buf);
+1 -1
View File
@@ -1923,7 +1923,7 @@ mrb_init_io(mrb_state *mrb)
#endif
mrb_define_method_id(mrb, io, MRB_SYM(initialize), io_init, MRB_ARGS_ARG(1,2));
mrb_define_method_id(mrb, io, MRB_SYM(initialize_copy), io_init_copy, MRB_ARGS_REQ(1));
mrb_define_private_method_id(mrb, io, MRB_SYM(initialize_copy), io_init_copy, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, io, MRB_SYM(isatty), io_isatty, MRB_ARGS_NONE());
mrb_define_method_id(mrb, io, MRB_SYM_Q(eof), io_eof, MRB_ARGS_NONE()); /* 15.2.20.5.6 */
mrb_define_method_id(mrb, io, MRB_SYM(getc), io_getc, MRB_ARGS_NONE()); /* 15.2.20.5.8 */
+1 -1
View File
@@ -276,7 +276,7 @@ mrb_mruby_io_gem_test(mrb_state* mrb)
}
#endif
if (env_home) {
char *utf8 = mrb_utf8_from_locale(env_home, strlen(env_home));
char *utf8 = mrb_utf8_from_locale(env_home, -1);
mrb_value path = mrb_str_new_cstr(mrb, utf8);
#ifdef _WIN32
char *pathp = RSTRING_PTR(path);
+165
View File
@@ -0,0 +1,165 @@
# mruby-kernel-ext
This mrbgem extends the `Kernel` module in mruby with additional useful methods.
## Methods
### `fail(*args)`
Raises a `RuntimeError`. This is an alias for `raise`.
Example:
```ruby
fail "Something went wrong"
# Raises RuntimeError: Something went wrong
```
### `caller(start=1, length=nil) -> array | nil`
### `caller(range) -> array | nil`
Returns the current execution stack (backtrace).
- If `start` is provided, it indicates the number of frames to skip.
- If `length` is provided, it limits the number of frames returned.
- If a `range` is provided, it specifies the portion of the stack to return.
Returns `nil` if `start` is greater than or equal to the number of frames in the stack.
Example:
```ruby
def foo
bar
end
def bar
puts caller(0) # Show all frames starting from the current one
puts caller(1) # Skip one frame
end
foo
```
### `__method__ -> symbol | nil`
Returns the name of the current method as a `Symbol`. If called outside of a method, it returns `nil`.
Example:
```ruby
class MyClass
def my_method
puts __method__
end
end
MyClass.new.my_method
# Output: :my_method
```
### `__callee__ -> symbol | nil`
Returns the called name of the current method as a `Symbol`. If called outside of a method, it returns `nil`. This can be different from `__method__` when using aliases.
Example:
```ruby
class MyClass
def original_method
puts __callee__
end
alias aliased_method original_method
end
obj = MyClass.new
obj.original_method # Output: :original_method
obj.aliased_method # Output: :aliased_method
```
### `Integer(arg, base=0) -> integer`
Converts `arg` to an `Integer`.
- Numeric types are converted directly (floating-point numbers are truncated).
- If `arg` is a `String`, `base` (0, or between 2 and 36) is used as the base for conversion.
- If `base` is omitted or zero, radix indicators (`0`, `0b`, `0x`) in the string are honored.
- Strings must strictly conform to numeric representation, unlike `String#to_i`.
- Passing `nil` raises a `TypeError`.
Examples:
```ruby
Integer(123.999) #=> 123
Integer("0x1a") #=> 26
Integer("0930", 10) #=> 930
Integer("111", 2) #=> 7
# Integer(nil) #=> TypeError
# Integer("invalid") #=> ArgumentError
```
### `Float(arg) -> float`
Converts `arg` to a `Float`.
- Numeric types are converted directly.
- Other types are converted using `arg.to_f`.
- Passing `nil` raises a `TypeError`.
Examples:
```ruby
Float(1) #=> 1.0
Float(123.456) #=> 123.456
Float("123.456") #=> 123.456
# Float(nil) #=> TypeError
# Float("invalid") #=> ArgumentError
```
### `String(arg) -> string`
Converts `arg` to a `String` using its `to_s` method.
Examples:
```ruby
String(self) #=> "main"
String(self.class) #=> "Object"
String(123456) #=> "123456"
String(:symbol) #=> "symbol"
```
### `Array(arg) -> array`
Converts `arg` to an `Array`.
- If `arg` responds to `to_a`, it calls `to_a` to convert.
- Otherwise, it returns a new array containing `arg` as its single element.
Examples:
```ruby
Array(1..5) #=> [1, 2, 3, 4, 5]
Array([1, 2, 3]) #=> [1, 2, 3]
Array("hello") #=> ["hello"] # If String does not have to_a
Array({ a: 1, b: 2 }) #=> [[:a, 1], [:b, 2]] # If Hash has to_a
```
### `Hash(arg) -> hash`
Converts `arg` to a `Hash`.
- If `arg` is already a `Hash`, it is returned.
- If `arg` is `nil` or an empty `Array`, an empty `Hash` is returned.
- Otherwise, it raises a `TypeError`.
Examples:
```ruby
Hash({ key: :value }) #=> { key: :value }
Hash(nil) #=> {}
Hash([]) #=> {}
# Hash([1, 2, 3]) #=> TypeError
```
+77
View File
@@ -0,0 +1,77 @@
# mruby-math
This mrbgem provides a comprehensive set of mathematical functions for mruby. It allows you to perform common mathematical operations within your mruby applications.
This gem is a standard component of mruby and provides functionalities similar to the `Math` module in standard Ruby.
## Available Functions
### Trigonometric Functions
- `Math.sin(x)`: Computes the sine of x (expressed in radians). Returns -1..1.
- `Math.cos(x)`: Computes the cosine of x (expressed in radians). Returns -1..1.
- `Math.tan(x)`: Returns the tangent of x (expressed in radians).
### Inverse Trigonometric Functions
- `Math.asin(x)`: Computes the arc sine of x. Returns computed value between `-(PI/2)` and `(PI/2)`.
- `Math.acos(x)`: Computes the arc cosine of x. Returns 0..PI.
- `Math.atan(x)`: Computes the arc tangent of x. Returns `-(PI/2) .. (PI/2)`.
- `Math.atan2(y, x)`: Computes the arc tangent given y and x. Returns -PI..PI.
### Hyperbolic Trigonometric Functions
- `Math.sinh(x)`: Computes the hyperbolic sine of x (expressed in radians).
- `Math.cosh(x)`: Computes the hyperbolic cosine of x (expressed in radians).
- `Math.tanh(x)`: Computes the hyperbolic tangent of x (expressed in radians).
### Inverse Hyperbolic Trigonometric Functions
- `Math.asinh(x)`: Computes the inverse hyperbolic sine of x.
- `Math.acosh(x)`: Computes the inverse hyperbolic cosine of x.
- `Math.atanh(x)`: Computes the inverse hyperbolic tangent of x.
### Exponential and Logarithmic Functions
- `Math.exp(x)`: Returns e\*\*x.
- `Math.log(numeric)` or `Math.log(num,base)`: Returns the natural logarithm of numeric. If additional second argument is given, it will be the base of logarithm.
- `Math.log2(numeric)`: Returns the base 2 logarithm of numeric.
- `Math.log10(numeric)`: Returns the base 10 logarithm of numeric.
### Other Functions
- `Math.sqrt(numeric)`: Returns the square root of numeric.
- `Math.cbrt(numeric)`: Returns the cube root of numeric.
- `Math.frexp(numeric)`: Returns a two-element array containing the normalized fraction (a Float) and exponent (a Integer) of numeric.
- `Math.ldexp(flt, int)`: Returns the value of flt\*(2\*\*int).
- `Math.hypot(x, y)`: Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle with sides x and y.
- `Math.erf(x)`: Calculates the error function of x.
- `Math.erfc(x)`: Calculates the complementary error function of x.
## Usage Examples
```ruby
# Basic trigonometric functions
puts Math.sin(Math::PI / 2) # Output: 1.0
puts Math.cos(0) # Output: 1.0
puts Math.tan(Math::PI / 4) # Output: 1.0 (approximately, due to float precision)
# Square root
puts Math.sqrt(16) # Output: 4.0
puts Math.sqrt(2) # Output: 1.4142135623730951
# Cube root
puts Math.cbrt(8) # Output: 2.0
puts Math.cbrt(27) # Output: 3.0
# Exponential and Logarithm
puts Math.exp(0) # Output: 1.0
puts Math.exp(1) # Output: 2.718281828459045 (Math::E)
puts Math.log(Math::E) # Output: 1.0
puts Math.log(100, 10) # Output: 2.0
puts Math.log2(16) # Output: 4.0
puts Math.log10(1000) # Output: 3.0
# Hypotenuse
puts Math.hypot(3, 4) # Output: 5.0
```
+123
View File
@@ -0,0 +1,123 @@
# mruby-metaprog
This mrbgem provides a collection of methods for metaprogramming in mruby. Metaprogramming is the ability of a program to inspect, modify, and create its own code at runtime.
## Functionality
The `mruby-metaprog` mrbgem offers methods for:
- **Instance Variable Manipulation:**
- `instance_variable_defined?(symbol)`: Checks if an instance variable is defined in an object.
- `instance_variable_get(symbol)`: Retrieves the value of an instance variable.
- `instance_variable_set(symbol, value)`: Sets the value of an instance variable.
- `instance_variables()`: Returns an array of instance variable names in an object.
- **Method Inspection:**
- `methods(regular=true)`: Returns a list of public and protected methods of an object.
- `private_methods(all=true)`: Returns a list of private methods accessible to an object.
- `protected_methods(all=true)`: Returns a list of protected methods accessible to an object.
- `public_methods(all=true)`: Returns a list of public methods accessible to an object.
- `singleton_methods(all=true)`: Returns an array of singleton method names for an object.
- **Singleton Method Definition:**
- `define_singleton_method(name, &block)`: Defines a singleton method for an object.
- **Class Variable Manipulation:**
- `class_variable_defined?(symbol)`: Checks if a class variable is defined in a module.
- `class_variable_get(symbol)`: Retrieves the value of a class variable.
- `class_variable_set(symbol, value)`: Sets the value of a class variable.
- `class_variables(inherit=true)`: Returns an array of class variable names in a module.
- `remove_class_variable(symbol)`: Removes a class variable from a module.
- **Module Inspection:**
- `included_modules()`: Returns a list of modules included in a module or class.
- `instance_methods(include_super=true)`: Returns an array of public and protected instance methods in a module or class.
- `public_instance_methods(include_super=true)`: Returns an array of public instance methods in a module or class.
- `private_instance_methods(include_super=true)`: Returns an array of private instance methods in a module or class.
- `protected_instance_methods(include_super=true)`: Returns an array of protected instance methods in a module or class.
- `undefined_instance_methods()`: Returns an array of undefined instance methods in a module/class.
- **Method Removal:**
- `remove_method(symbol)`: Removes a method from a class.
- **Constant Inspection:**
- `constants(inherit=true)`: Returns an array of constant names defined in a module.
- **Module Nesting:**
- `Module.nesting()`: Returns an array representing the current module nesting.
- **Message Sending:**
- `send(symbol, *args, &block)`: Invokes a method on an object.
- `public_send(symbol, *args, &block)`: Invokes a public method on an object.
- **Variable Inspection:**
- `global_variables()`: Returns an array of global variable names.
- `local_variables()`: Returns an array of local variable names in the current scope.
## Examples
### Working with Instance Variables
```ruby
class MyClass
def initialize(value)
@my_var = value
end
end
obj = MyClass.new(10)
p obj.instance_variable_defined?(:@my_var) #=> true
p obj.instance_variable_get(:@my_var) #=> 10
obj.instance_variable_set(:@another_var, "hello")
p obj.instance_variables #=> [:@my_var, :@another_var]
```
### Inspecting Methods
```ruby
class AnotherClass
def public_method; end
protected
def protected_method; end
private
def private_method; end
end
obj = AnotherClass.new
p obj.public_methods(false) #=> [:public_method]
p obj.protected_methods(false) #=> [:protected_method]
p obj.private_methods(false) #=> [:private_method]
def obj.singleton_method_example; end
p obj.singleton_methods #=> [:singleton_method_example]
```
### Defining Singleton Methods
```ruby
obj = Object.new
obj.define_singleton_method(:greet) do |name|
"Hello, #{name}!"
end
p obj.greet("World") #=> "Hello, World!"
```
### Working with Class Variables
```ruby
class ParentClass
@@parent_cvar = 100
end
class ChildClass < ParentClass
@@child_cvar = 200
def self.get_parent_cvar
class_variable_get(:@@parent_cvar)
end
end
p ChildClass.class_variable_defined?(:@@child_cvar) #=> true
p ChildClass.class_variable_get(:@@child_cvar) #=> 200
ChildClass.class_variable_set(:@@new_cvar, 300)
p ChildClass.class_variables.sort #=> [:@@child_cvar, :@@new_cvar, :@@parent_cvar] (order may vary)
p ChildClass.get_parent_cvar #=> 100
ChildClass.remove_class_variable(:@@new_cvar)
p ChildClass.class_variables.sort #=> [:@@child_cvar, :@@parent_cvar] (order may vary)
```
## License
This mrbgem is licensed under the [MIT License](LICENSE).
+29 -11
View File
@@ -182,11 +182,9 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *kl
}
ary = mrb_ary_new_capa(mrb, kh_size(set));
for (khint_t i=0; i<kh_end(set); i++) {
if (kh_exist(set, i)) {
if (kh_val(set, i)) {
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
}
KHASH_FOREACH(mrb, set, k) {
if (kh_val(set, k)) {
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, k)));
}
}
kh_destroy(st, mrb, set);
@@ -297,10 +295,8 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
}
ary = mrb_ary_new(mrb);
for (khint_t i=0;i<kh_end(set);i++) {
if (kh_exist(set, i)) {
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
}
KHASH_FOREACH(mrb, set, k) {
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, k)));
}
kh_destroy(st, mrb, set);
@@ -643,8 +639,29 @@ mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
static mrb_value
mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
{
mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented");
return mrb_nil_value(); /* not reached */
if (mrb_get_argc(mrb) > 0 || mrb_class_ptr(mod) != mrb->module_class) {
return mrb_mod_constants(mrb, mod);
}
const struct RProc *proc = mrb->c->ci[-1].proc;
struct RClass *c = MRB_PROC_TARGET_CLASS(proc);
mrb_value ary = mrb_ary_new(mrb);
if (!c) c = mrb->object_class;
mrb_mod_const_at(mrb, c, ary);
proc = proc->upper;
while (proc) {
struct RClass *c2 = MRB_PROC_TARGET_CLASS(proc);
if (!c2) c2 = mrb->object_class;
mrb_mod_const_at(mrb, c2, ary);
proc = proc->upper;
}
while (c) {
mrb_mod_const_at(mrb, c, ary);
c = c->super;
if (c == mrb->object_class) break;
}
return ary;
}
static mrb_value
@@ -691,6 +708,7 @@ mrb_mruby_metaprog_gem_init(mrb_state* mrb)
mrb_define_method_id(mrb, krn, MRB_SYM(singleton_methods), mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */
mrb_define_method_id(mrb, krn, MRB_SYM(define_singleton_method), mod_define_singleton_method, MRB_ARGS_REQ(1)|MRB_ARGS_BLOCK());
mrb_define_method_id(mrb, krn, MRB_SYM(send), mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.44 */
mrb_define_method_id(mrb, krn, MRB_SYM(public_send), mrb_f_public_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK());
mrb_define_method_id(mrb, mod, MRB_SYM(class_variables), mrb_mod_class_variables, MRB_ARGS_OPT(1)); /* 15.2.2.4.19 */
mrb_define_method_id(mrb, mod, MRB_SYM(remove_class_variable), mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
+29 -22
View File
@@ -1,6 +1,6 @@
# mruby-method
An implementation of class **Method** and **UnboundMethod** for mruby
The `mruby-method` mrbgem provides implementations for the `Method` and `UnboundMethod` classes. These classes allow for powerful introspection and manipulation of methods in mruby. This includes obtaining information like method name, owner, receiver, parameters, and source location, as well as features like creating method objects from existing methods, binding unbound methods to objects, and unbinding methods from their receivers.
```ruby
p Enumerable.instance_method(:find_all).source_location
@@ -22,36 +22,43 @@ end
## Kernel
- `Kernel#method`
- `Kernel#singleton_method`
- `Kernel#method(sym)`: Returns a Method object corresponding to the method identified by `sym` for the receiver.
- `Kernel#singleton_method(sym)`: Returns a Method object corresponding to the singleton method identified by `sym` for the receiver.
## Module
- `Module#instance_method`
- `Module#instance_method(sym)`: Returns an UnboundMethod object corresponding to the instance method identified by `sym` in the module/class.
## Method class
- `Method#name`
- `Method#call`
- `Method#super_method`
- `Method#arity`
- `Method#unbind`
- `Method#[]`
- `Method#owner`
- `Method#receiver`
- `Method#parameters`
- `Method#source_location`
- `Method#to_proc`
- `Method#name`: Returns the name of the method.
- `Method#owner`: Returns the class or module that defines the method.
- `Method#receiver`: Returns the object to which the method is bound.
- `Method#arity`: Returns an integer indicating the number of arguments accepted by the method. A negative number indicates optional arguments.
- `Method#parameters`: Returns an array of arrays, each describing a parameter (e.g., `[[:req, :foo]]`).
- `Method#source_location`: Returns a two-element array `[filename, line_number]` indicating where the method was defined in Ruby code, or `nil` if not available. (Requires debug mode).
- `Method#call(*args, **opts, &block)`: Invokes the method with the given arguments and block, returning the result.
- `Method#[](*args, **opts, &block)`: Alias for `call`. Invokes the method.
- `Method#super_method`: Returns a Method object representing the superclass's version of this method. Returns `nil` if no superclass method exists.
- `Method#unbind`: Returns an UnboundMethod object based on this method.
- `Method#to_proc`: Converts the Method object into a Proc object that can be called.
- `Method#<< (other_method_or_proc)`: Returns a new Proc that represents the composition of this method and another method or proc (`self(other(...))`).
- `Method#>> (other_method_or_proc)`: Returns a new Proc that represents the composition of another method or proc and this method (`other(self(...))`).
- `Method#== (other)` / `Method#eql?(other)`: Returns `true` if the method is the same as `other` (same receiver, owner, and proc/name).
- `Method#inspect`: Returns a string representation of the Method object, including its class, name, owner, and source location if available. (Alias for `to_s`).
## UnboundMethod class
- `UnboundMethod#name`
- `UnboundMethod#bind`
- `UnboundMethod#super_method`
- `UnboundMethod#arity`
- `UnboundMethod#owner`
- `UnboundMethod#parameters`
- `UnboundMethod#source_location`
- `UnboundMethod#name`: Returns the name of the method.
- `UnboundMethod#owner`: Returns the class or module that originally defined the method.
- `UnboundMethod#arity`: Returns an integer indicating the number of arguments accepted by the method. A negative number indicates optional arguments.
- `UnboundMethod#parameters`: Returns an array of arrays, each describing a parameter (e.g., `[[:req, :foo]]`).
- `UnboundMethod#source_location`: Returns a two-element array `[filename, line_number]` indicating where the method was defined in Ruby code, or `nil` if not available. (Requires debug mode).
- `UnboundMethod#bind(obj)`: Binds the UnboundMethod to `obj` and returns a Method object. Raises `TypeError` if `obj` is not an instance of the method's owner or its descendants.
- `UnboundMethod#bind_call(obj, *args, **opts, &block)`: Binds the UnboundMethod to `obj` and then calls it with the given arguments and block.
- `UnboundMethod#super_method`: Returns an UnboundMethod object representing the superclass's version of this method. Returns `nil` if no superclass method exists.
- `UnboundMethod#== (other)` / `UnboundMethod#eql?(other)`: Returns `true` if the unbound method is the same as `other` (same owner and proc/name).
- `UnboundMethod#inspect`: Returns a string representation of the UnboundMethod object, including its class, name, owner, and source location if available. (Alias for `to_s`).
# See also
+76
View File
@@ -0,0 +1,76 @@
# mruby-numeric-ext
## Purpose
This mrbgem extends the `Numeric` and `Integer` classes in mruby with additional methods for common numerical operations and checks.
## Functionality
This gem adds the following methods:
### Numeric Class
- `zero?`: Returns `true` if the number is zero, `false` otherwise.
- `nonzero?`: Returns the number itself if it's not zero, `nil` otherwise.
- `positive?`: Returns `true` if the number is greater than 0, `false` otherwise.
- `negative?`: Returns `true` if the number is less than 0, `false` otherwise.
- `integer?`: Returns `true` if the number is an `Integer` (this is overridden in the `Integer` class).
### Integer Class
- `allbits?(mask)`: Returns `true` if all bits of `self & mask` are 1.
- `anybits?(mask)`: Returns `true` if any bits of `self & mask` are 1.
- `nobits?(mask)`: Returns `true` if no bits of `self & mask` are 1.
- `ceildiv(other)`: Returns the result of `self` divided by `other`, rounded up to the nearest integer.
- `integer?`: Returns `true` (overrides `Numeric#integer?`).
- `remainder(numeric)`: Returns the remainder of `self` divided by `numeric`. Equivalent to `x - y * (x / y).truncate`.
- `pow(numeric)`: Returns `self` raised to the power of `numeric`.
- `pow(integer, integer)`: Returns modular exponentiation (`(self ** exponent) % modulus`).
- `digits(base=10)`: Returns an array of integers representing the base-radix digits of `self`. The first element is the least significant digit.
- `size`: Returns the number of bytes in the machine representation of the integer.
- `odd?`: Returns `true` if the integer is odd, `false` otherwise.
- `even?`: Returns `true` if the integer is even, `false` otherwise.
- `Integer.sqrt(integer)`: (Class method) Returns the integer square root of the given non-negative integer.
## How to use
To use this mrbgem, add it to your `build_config.rb`:
```ruby
MRuby::Build.new do |conf|
# ... (other configurations)
conf.gem :core => 'mruby-numeric-ext'
end
```
Then you can use the extended methods:
```ruby
p 5.positive? # => true
p (-3).negative? # => true
p 0.zero? # => true
p 5.nonzero? # => 5
p 0.nonzero? # => nil
p 7.allbits?(3) # => false (binary 111 & 011 is 011, not 011)
p 7.anybits?(3) # => true
p 7.nobits?(8) # => true (binary 111 & 1000 is 000)
p 10.ceildiv(3) # => 4
p (-10).ceildiv(3) # => -3
p 10.remainder(3) # => 1
p (-10).remainder(3) # => -1
p 2.pow(3) # => 8
p 2.pow(3, 5) # => 3 ( (2**3) % 5 )
p 12345.digits # => [5, 4, 3, 2, 1]
p 12345.digits(16) # => [9, 3, 0, 3]
p 42.size # => (depends on machine, e.g., 4 or 8)
p 5.odd? # => true
p 4.even? # => true
p Integer.sqrt(16) # => 4
p Integer.sqrt(17) # => 4
```
@@ -262,6 +262,46 @@ flo_remainder(mrb_state *mrb, mrb_value self)
}
#endif
static mrb_int
isqrt(mrb_int n)
{
mrb_assert(n >= 0);
if (n < 2) return n;
mrb_int x = n;
mrb_int y = (x + 1) / 2;
// Babylonian method (integer version)
while (y < x) {
x = y;
y = (x + n / x) / 2;
}
return x;
}
static mrb_value
int_sqrt(mrb_state *mrb, mrb_value self)
{
mrb_value arg = mrb_get_arg1(mrb);
if (mrb_integer_p(arg)) {
mrb_int n = mrb_integer(arg);
if (n < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "non-negative integer required");
}
return mrb_int_value(mrb, isqrt(n));
}
#ifdef MRB_USE_BIGINT
else if (mrb_bigint_p(arg)) {
return mrb_bint_sqrt(mrb, arg);
}
#endif
else {
mrb_raise(mrb, E_TYPE_ERROR, "expected Integer");
}
}
void
mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
{
@@ -275,6 +315,7 @@ mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
mrb_define_method_id(mrb, ic, MRB_SYM(size), int_size, MRB_ARGS_NONE());
mrb_define_method_id(mrb, ic, MRB_SYM_Q(odd), int_odd, MRB_ARGS_NONE());
mrb_define_method_id(mrb, ic, MRB_SYM_Q(even), int_even, MRB_ARGS_NONE());
mrb_define_class_method_id(mrb, ic, MRB_SYM(sqrt), int_sqrt, MRB_ARGS_REQ(1));
#ifndef MRB_NO_FLOAT
struct RClass *fc = mrb->float_class;
@@ -81,3 +81,9 @@ assert('Integer#digits') do
assert_equal([4, 6, 6, 0, 5], 12345.digits(7))
assert_equal([45, 23, 1], 12345.digits(100))
end
assert('Integer.sqrt') do
assert_equal(4, Integer.sqrt(16))
assert_equal(10, Integer.sqrt(100))
assert_equal(85, Integer.sqrt(7244))
end
+144
View File
@@ -0,0 +1,144 @@
# mruby-object-ext
This mrbgem provides several extension methods to core objects in mruby, enhancing their functionality and providing useful utilities for common programming patterns.
## Core Extension Methods
This gem extends core mruby objects with the following methods:
### `Kernel#yield_self` (aliased as `then`)
Yields the receiver (self) to the given block and returns the result of the block. This is useful for chaining operations in a readable way.
**Signature:**
```ruby
obj.yield_self {|current_obj| ... } > an_object
obj.then {|current_obj| ... } -> an_object
```
**Example:**
```ruby
result = "hello"
.yield_self {|s| s.upcase }
.then {|s| s + " WORLD" }
puts result #=> "HELLO WORLD"
# Another example with a different data type
(1..5)
.yield_self {|range| range.to_a }
.then {|arr| arr.select(&:even?) }
.then {|evens| evens.map {|n| n * n } }
.then {|squares| puts squares.inspect } #=> [4, 16]
```
### `Kernel#tap`
Yields the receiver (self) to the given block and then returns the receiver itself. This method is primarily used for "tapping into" a method chain to perform operations on intermediate results without affecting the final result of the chain.
**Signature:**
```ruby
obj.tap {|current_obj| ... } -> obj
```
**Example:**
```ruby
(1..10)
.to_a
.tap {|arr| puts "Array: #{arr.inspect}" }
.select(&:even?)
.tap {|evens| puts "Evens: #{evens.inspect}" }
.map {|n| n * n }
.tap {|squares| puts "Squares: #{squares.inspect}" }
# Output:
# Array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Evens: [2, 4, 6, 8, 10]
# Squares: [4, 16, 36, 64, 100]
```
### `Kernel#itself`
Returns the receiver (self). While simple, it can be useful in certain chaining or meta-programming scenarios.
**Signature:**
```ruby
obj.itself -> obj
```
**Example:**
```ruby
string = "my string"
puts string.itself.object_id == string.object_id #=> true
# Can be useful with methods expecting a callable
data = { a: 1, b: 2 }
transformed_data = data.transform_values(&:itself) # No change if values are already what you want
puts transformed_data #=> {:a=>1, :b=>2} (in mruby hash output format)
```
### `BasicObject#instance_exec`
Executes the given block within the context of the receiver (obj). This means that inside the block, `self` is set to `obj`, giving the code access to `obj`'s instance variables and private methods. Arguments passed to `instance_exec` are passed as block parameters.
**Signature:**
```ruby
obj.instance_exec(arg...) {|var...| block } -> result_of_block
```
**Example:**
```ruby
class MyClass
def initialize(value)
@secret = value
end
def reveal_secret(multiplier, &block)
# self here is MyClass instance
instance_exec(multiplier, &block)
end
end
instance = MyClass.new(10)
result = instance.reveal_secret(5) {|m| @secret * m }
puts result #=> 50
# Example without a class context
num = 42
num.instance_exec("Number is: ") {|prefix| puts prefix + self.to_s } #=> Number is: 42
```
## `NilClass` Extensions
This gem also adds convenient type conversion methods to `NilClass`:
- **`nil.to_a`**: Returns an empty Array (`[]`).
```ruby
p nil.to_a #=> []
```
- **`nil.to_f`**: Returns `0.0`.
```ruby
p nil.to_f #=> 0.0
```
- **`nil.to_h`**: Returns an empty Hash (`{}`).
```ruby
p nil.to_h #=> {}
```
- **`nil.to_i`**: Returns `0`.
```ruby
p nil.to_i #=> 0
```
+59
View File
@@ -0,0 +1,59 @@
# mruby-objectspace
This mrbgem provides the `ObjectSpace` module for mruby, allowing introspection of live objects within the mruby environment.
## Purpose
The `ObjectSpace` module offers methods to count and iterate over objects currently allocated by the mruby interpreter. This can be useful for debugging, memory profiling, or understanding the internal state of your mruby application.
## Functionality
### `ObjectSpace.count_objects([result_hash]) -> Hash`
Counts all objects currently alive in the mruby process, categorized by their types.
- **`result_hash` (optional `Hash`):** If provided, this hash will be cleared and populated with the results. This can be useful to avoid allocating a new hash during sensitive operations like memory profiling, potentially reducing probe effect.
- **Returns:** A `Hash` where keys are symbols representing object types (e.g., `:T_OBJECT`, `:T_CLASS`, `:T_STRING`) or, in some cases, internal type integers. The values are the counts of objects for each type. The hash also includes special keys:
- `:TOTAL`: The total number of objects (including free slots).
- `:FREE`: The number of free (unallocated) object slots.
**Example of the returned hash structure:**
```ruby
{
:TOTAL=>10000,
:FREE=>3011,
:T_OBJECT=>6,
:T_CLASS=>404,
:T_STRING=>500,
# ... other types
}
```
### `ObjectSpace.each_object([module]) {|obj| ... } -> Fixnum`
Iterates over each live object in the mruby process, calling the provided block once for each object.
- **`module` (optional `Module` or `Class`):** If this argument is provided, the block will only be called for objects that are instances of the given `module` or one of its subclasses.
- **Block (`{|obj| ... }`):** A block that will be executed with each object (`obj`) found.
- **Returns:** A `Fixnum` representing the total number of objects iterated over.
**Example Usage:**
```ruby
# Iterate over all objects
total_objects = ObjectSpace.each_object do |obj|
# Do something with obj
p obj
end
puts "Total objects found: #{total_objects}"
# Iterate only over Array objects
array_count = ObjectSpace.each_object(Array) do |arr|
p arr
end
puts "Found #{array_count} Arrays."
```
+75
View File
@@ -0,0 +1,75 @@
# mruby-os-memsize
## Description
The `mruby-os-memsize` mrbgem extends the `ObjectSpace` module in mruby, providing tools to inspect the approximate amount of heap memory allocated for objects. This can be useful for debugging memory usage and understanding the memory footprint of your mruby application.
## Usage / API
This gem adds two class methods to the `ObjectSpace` module:
### `ObjectSpace.memsize_of(obj) -> Numeric`
Returns the approximate amount of heap memory allocated for the given `obj` in bytes.
- The returned value is platform-dependent, as it's based on the `size_t` type of the underlying C implementation.
- Immediate values (e.g., integers, booleans, symbols) and some small, embedded objects (like short strings or small arrays that fit directly into an object pointer) will typically report a size of 0 or a very small, fixed size representing the object pointer itself.
- The accuracy of the reported size can vary depending on the object's type and internal structure.
**Example:**
```ruby
str = "This is a test string"
array = [1, 2, 3, 4, 5]
puts "Size of string: #{ObjectSpace.memsize_of(str)} bytes"
puts "Size of array: #{ObjectSpace.memsize_of(array)} bytes"
puts "Size of 123: #{ObjectSpace.memsize_of(123)}" # Likely 0
puts "Size of :symbol: #{ObjectSpace.memsize_of(:symbol)}" # Likely 0
class MyClass
def initialize
@data = "some internal data"
end
end
instance = MyClass.new
puts "Size of MyClass instance: #{ObjectSpace.memsize_of(instance)}"
```
### `ObjectSpace.memsize_of_all([klass]) -> Numeric`
Returns the total approximate heap memory allocated for all living objects in the mruby environment.
- If an optional `klass` argument (a Class object) is provided, it returns the total memory size only for instances of that specific class.
**Example:**
```ruby
# Get total memory size of all objects
total_memory = ObjectSpace.memsize_of_all
puts "Total heap memory used by all objects: #{total_memory} bytes"
# Get total memory size for all String objects
total_string_memory = ObjectSpace.memsize_of_all(String)
puts "Total heap memory used by Strings: #{total_string_memory} bytes"
class Person
def initialize(name)
@name = name
end
end
p1 = Person.new("Alice")
p2 = Person.new("Bob")
total_person_memory = ObjectSpace.memsize_of_all(Person)
puts "Total heap memory used by Person instances: #{total_person_memory} bytes"
```
## License
This mrbgem is released under the MIT License. (See `mrbgem.rake` for details within the mruby distribution).
## Author
mruby developers
+97 -39
View File
@@ -1,53 +1,111 @@
# mruby-pack (pack / unpack)
# mruby-pack
mruby-pack provides `Array#pack` and `String#unpack` for mruby.
The `mruby-pack` mrbgem enhances mruby by providing `Array#pack` and `String#unpack` methods. These methods facilitate the conversion between Ruby data types (specifically arrays and strings) and binary data representations, offering a powerful way to handle binary data.
## Installation
Add the line below into your build configuration:
```
conf.gem :core => 'mruby-pack'
```ruby
conf.gem :core => 'mruby-pack'
```
There is no dependency on other mrbgems.
## Supported template string
## `Array#pack`
- A : arbitrary binary string (space padded, count is width)
- a : arbitrary binary string (null padded, count is width)
- B : bit string (descending)
- b : bit string (ascending)
- C : 8-bit unsigned (unsigned char)
- c : 8-bit signed (signed char)
- D, d: 64-bit float, native format
- E : 64-bit float, little endian byte order
- e : 32-bit float, little endian byte order
- F, f: 32-bit float, native format
- G : 64-bit float, network (big-endian) byte order
- g : 32-bit float, network (big-endian) byte order
- H : hex string (high nibble first)
- h : hex string (low nibble first)
- I : unsigned integer, native endian (`unsigned int` in C)
- i : signed integer, native endian (`int` in C)
- J : unsigned integer, native endian (`uintptr_t` in C)
- j : signed integer, native endian (`intptr_t` in C)
- L : 32-bit unsigned, native endian (`uint32_t`)
- l : 32-bit signed, native endian (`int32_t`)
- m : base64 encoded string (see RFC 2045, count is width)
- N : 32-bit unsigned, network (big-endian) byte order
- n : 16-bit unsigned, network (big-endian) byte order
- Q : 64-bit unsigned, native endian (`uint64_t`)
- q : 64-bit signed, native endian (`int64_t`)
- S : 16-bit unsigned, native endian (`uint16_t`)
- s : 16-bit signed, native endian (`int16_t`)
- U : UTF-8 character
- V : 32-bit unsigned, VAX (little-endian) byte order
- v : 16-bit unsigned, VAX (little-endian) byte order
- x : null byte
- X : back up bytes
- Z : same as "a", except that null is added with \*
- @ : absolute position
The `Array#pack` method converts an array into a binary string. It takes a template string as an argument, which dictates how each element in the array should be converted and packed into the resulting binary string. The template string consists of directives, where each directive specifies the type and format of the data to be packed.
**Example:**
```ruby
arr = [65, 66, 67]
binary_string = arr.pack("ccc") # Packs three 8-bit signed integers
# binary_string will be "ABC"
arr2 = [72, 101, 108, 108, 111]
binary_string2 = arr2.pack("C*") # Packs all elements as 8-bit unsigned integers
# binary_string2 will be "Hello"
arr3 = [0x1234, 0x5678]
binary_string3 = arr3.pack("S>2") # Packs two 16-bit unsigned integers, big-endian
# binary_string3 will be "\x12\x34\x56\x78" (depending on native endianness if S is used without > or <)
# Using "n2" would be more explicit for network (big-endian) byte order:
# binary_string3 = arr3.pack("n2") # Packs two 16-bit unsigned, network (big-endian) byte order
# binary_string3 will be "\x12\x34\x56\x78"
```
## `String#unpack`
The `String#unpack` method performs the reverse operation of `Array#pack`. It takes a binary string and a template string as input. It extracts data from the binary string according to the directives in the template and converts it into an array of Ruby objects.
**Example:**
```ruby
binary_data = "test"
arr = binary_data.unpack("aaaa")
# arr will be ["t", "e", "s", "t"]
binary_data2 = "\x01\x02\x03"
arr2 = binary_data2.unpack("C3") # Unpacks three 8-bit unsigned integers
# arr2 will be [1, 2, 3]
binary_data3 = "Hello\x00World"
arr3 = binary_data3.unpack("Z*Z*") # Unpacks two null-terminated strings
# arr3 will be ["Hello", "World"]
```
## Supported Template Directives
The template string is a sequence of characters that specify the type and format of the data to be packed or unpacked. Each directive can be followed by a count (e.g., "C4" for four 8-bit unsigned integers) or `*` to consume all remaining items/bytes.
Here is a list of supported template characters and their meanings:
| Directive | Description |
| --------- | ------------------------------------------------------------------------------------------------------- |
| `A` | Arbitrary binary string (space padded, count is width) |
| `a` | Arbitrary binary string (null padded, count is width) |
| `B` | Bit string (descending bit order) |
| `b` | Bit string (ascending bit order) |
| `C` | 8-bit unsigned integer (unsigned char) |
| `c` | 8-bit signed integer (signed char) |
| `D`, `d` | Double-precision float, native format (64-bit) |
| `E` | Double-precision float, little-endian (64-bit) |
| `e` | Single-precision float, little-endian (32-bit) |
| `F`, `f` | Single-precision float, native format (32-bit) |
| `G` | Double-precision float, network (big-endian) byte order (64-bit) |
| `g` | Single-precision float, network (big-endian) byte order (32-bit) |
| `H` | Hex string (high nibble first) |
| `h` | Hex string (low nibble first) |
| `I` | Unsigned integer, native endian (`unsigned int` in C) |
| `i` | Signed integer, native endian (`int` in C) |
| `J` | Unsigned integer, native endian (`uintptr_t` in C) |
| `j` | Signed integer, native endian (`intptr_t` in C) |
| `L` | 32-bit unsigned integer, native endian (`uint32_t`) |
| `l` | 32-bit signed integer, native endian (`int32_t`) |
| `m` | Base64 encoded string (see RFC 2045, count is input bytes for pack, output chars for unpack) |
| `N` | 32-bit unsigned integer, network (big-endian) byte order |
| `n` | 16-bit unsigned integer, network (big-endian) byte order |
| `Q` | 64-bit unsigned integer, native endian (`uint64_t`) |
| `q` | 64-bit signed integer, native endian (`int64_t`) |
| `S` | 16-bit unsigned integer, native endian (`uint16_t`) (Use `S>` for big-endian, `S<` for little-endian) |
| `s` | 16-bit signed integer, native endian (`int16_t`) (Use `s>` for big-endian, `s<` for little-endian) |
| `U` | UTF-8 character |
| `V` | 32-bit unsigned integer, VAX (little-endian) byte order |
| `v` | 16-bit unsigned integer, VAX (little-endian) byte order |
| `x` | Null byte (skip forward one byte) |
| `X` | Back up one byte |
| `Z` | Null-terminated string (when unpacking, reads until NULL; when packing, appends a NULL if count is `*`) |
| `@` | Moves to absolute position (offset from the beginning of the string) |
**Modifiers:**
Some directives can be followed by modifiers that affect their behavior:
- `>`: Big-endian (for `S`, `s`, `L`, `l`, `Q`, `q`, etc., when native order is not desired).
- `<`: Little-endian (for `S`, `s`, `L`, `l`, `Q`, `q`, etc., when native order is not desired).
These modifiers are typically used with integer and float types to specify byte order explicitly. For network byte order (big-endian), directives like `n` (16-bit) and `N` (32-bit) are commonly used.
## License
+8 -9
View File
@@ -1188,7 +1188,7 @@ pack_nul(mrb_state *mrb, mrb_value dst, mrb_int didx, int count)
}
static void
check_x(mrb_state *mrb, int a, int count, char c)
check_x(mrb_state *mrb, mrb_int a, mrb_int count, char c)
{
if (a < count) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "%c outside of string", c);
@@ -1209,7 +1209,7 @@ has_tmpl(const struct tmpl *tmpl)
}
static enum pack_dir
read_tmpl(mrb_state *mrb, struct tmpl *tmpl, enum pack_type *typep, int *sizep, int *countp, unsigned int *flagsp)
read_tmpl(mrb_state *mrb, struct tmpl *tmpl, enum pack_type *typep, mrb_int *sizep, mrb_int *countp, unsigned int *flagsp)
{
mrb_int t, tlen;
int ch, size = 0;
@@ -1505,7 +1505,7 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
mrb_value o, result;
struct tmpl tmpl;
enum pack_type type;
int count, size;
mrb_int count, size;
unsigned int flags;
enum pack_dir dir;
@@ -1627,16 +1627,15 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
}
static mrb_value
pack_unpack(mrb_state *mrb, mrb_value str, int single)
pack_unpack(mrb_state *mrb, mrb_value str, mrb_bool single)
{
mrb_value result;
struct tmpl tmpl;
int count;
mrb_int count;
unsigned int flags;
enum pack_dir dir;
enum pack_type type;
int size;
int srcidx, srclen;
mrb_int size, srcidx, srclen;
const unsigned char *sptr;
prepare_tmpl(mrb, &tmpl);
@@ -1749,13 +1748,13 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
static mrb_value
mrb_pack_unpack(mrb_state *mrb, mrb_value str)
{
return pack_unpack(mrb, str, 0);
return pack_unpack(mrb, str, FALSE);
}
static mrb_value
mrb_pack_unpack1(mrb_state *mrb, mrb_value str)
{
return pack_unpack(mrb, str, 1);
return pack_unpack(mrb, str, TRUE);
}
void
+140
View File
@@ -0,0 +1,140 @@
# mruby-proc-binding
This mrbgem provides a `binding` method for `Proc` objects in mruby. This method returns a `Binding` object, which allows you to inspect and manipulate the lexical scope (local variables and `self`) of the `Proc` from which it was obtained.
## Usage Examples
Here's how you can use `mruby-proc-binding`:
### Getting a Binding
First, obtain a `Binding` object from a `Proc`:
```ruby
def create_proc
a = 10
b = 20
->(c) { a + b + c } # A sample proc
end
my_proc = create_proc
# Create a proc that takes one argument (c) and closes over a and b.
# Note: For the binding to capture local variables like 'a' and 'b',
# they must be referenced by a Proc defined in the same scope.
# A simple `proc {}` or `->{}` might not capture them as expected
# unless they are used within that proc.
# To ensure 'a' and 'b' are part of the environment captured by the binding
# from `my_proc.binding`, we ensure `my_proc` itself uses them or is defined
# in a scope where they are present and then `binding` is called on a proc
# that has access to this environment.
# Let's define a new proc specifically for getting a binding
# that captures the desired local variables.
local_var_scope_proc = nil
a_val = 1
b_val = 2
local_var_scope_proc = -> {
# 'a_val' and 'b_val' are now in this proc's lexical scope
}
bind = local_var_scope_proc.binding
```
### Inspecting Local Variables
You can list the names of local variables within the proc's scope:
```ruby
# Continuing from the previous example:
# Variables 'a_val', 'b_val', and 'local_var_scope_proc' are expected.
p bind.local_variables
# Expected output (order may vary):
# => [:a_val, :b_val, :local_var_scope_proc, :bind]
# Note: The binding itself and other variables defined in the
# same scope might also be listed.
```
### Getting Local Variable Values
Retrieve the value of a specific local variable:
```ruby
p bind.local_variable_get(:a_val) # => 1
p bind.local_variable_get(:b_val) # => 2
```
### Setting Local Variable Values
You can also modify the values of local variables within the binding's scope:
```ruby
bind.local_variable_set(:a_val, 100)
p bind.local_variable_get(:a_val) # => 100
# This also affects evaluation within the binding
p bind.eval("a_val + b_val") # => 102 (100 + 2)
```
### Evaluating Code
Execute arbitrary Ruby code within the binding's context:
```ruby
# Define some variables in a scope
def get_binding_for_eval
x = 5
y = 10
proc {}.binding # Create a binding in this scope
end
eval_bind = get_binding_for_eval
p eval_bind.eval("x * y") # => 50
p eval_bind.eval("self") # Shows the receiver of the proc
```
### Getting Source Location
If `mruby-proc-ext` is also available, you can get the source location of a proc:
```ruby
# Assuming __FILE__ is "test.rb" and this line is line 50
my_lambda = -> { } # This proc is defined at [__FILE__, __LINE__]
location_binding = my_lambda.binding
# This requires mruby-proc-ext
if location_binding.respond_to?(:source_location)
p location_binding.source_location # => ["test.rb", 50] (approximately)
else
puts "Binding#source_location not available. Is mruby-proc-ext included?"
end
```
A more robust example for capturing variables for `Proc#binding`:
```ruby
def execution_binding
name = "Ruby"
# The proc must be created in the scope where variables exist
# and it doesn't necessarily need to *use* them for them to be available in the binding.
# However, the most reliable way to ensure they are part of the environment
# is if the proc is created in that environment.
binding_proc = proc {} # This proc is created in the current scope
binding_proc.binding # Returns a binding for this scope
end
b = execution_binding
p b.local_variables.sort # => [:b, :binding_proc, :name] (or similar)
p b.local_variable_get(:name) # => "Ruby"
b.local_variable_set(:name, "mruby")
p b.eval("name") # => "mruby"
```
## Dependencies
This mrbgem has the following dependencies:
- **`mruby-binding`**: Provides the core `Binding` object functionality. This gem is a prerequisite.
- **`mruby-proc-ext`**: Required for the `Binding#source_location` method. If `mruby-proc-ext` is not included in your mruby build, the `source_location` method may not be available on binding objects, or it might return `nil`.
## License
MIT

Some files were not shown because too many files have changed in this diff Show More