113 Commits

Author SHA1 Message Date
dearblue 36f822d9af Fixed Kernel#.eval crash when given a custom defined Binding instance
```console
% bin/mruby -e 'class Binding; end; eval "1", Binding.new'
zsh: segmentation fault (core dumped)  bin/mruby -e 'class Binding; end; eval "1", Binding.new'
```
2023-01-20 21:26:21 +09:00
Yukihiro "Matz" Matsumoto 3a7e138c05 mruby/internal.h: add mrb_env_new to the internal function header 2023-01-18 10:37:48 +09:00
Yukihiro "Matz" Matsumoto 55eea005c8 mruby/internal.h: add codedump functions to the internal function header
ref #5906
2023-01-18 10:37:48 +09:00
Yukihiro "Matz" Matsumoto ddefcea151 mruby-eval/eval.c (f_instance_eval): skip mrb_value to get singleton
Use mrb_singleton_class_ptr() instead of mrb_instance_class(), because
the former returns NULL, when the latter raises error for immediate
objects.

```
1.instance_eval <<END
  def foo
    :foo
  end
END
```
2022-12-13 10:51:44 +09:00
Yukihiro "Matz" Matsumoto 4107cc95a2 internal.c: move some functions to <mruby/internal.h>.
Ref #5776
2022-08-15 18:13:59 +09:00
Yukihiro "Matz" Matsumoto dccd66f9ef Support Ruby3.0 keyword arguments.
The Difference

Since Ruby1.9, the keyword arguments were emulated by Ruby using the hash
object at the bottom of the arguments. But we have gradually moved toward
keyword arguments separated from normal (positinal) arguments.

At the same time, we value compatibility, so that Ruby3.0 keyword
arguments are somewhat compromise. Basically, keyword arguments are
separated from positional arguments, except when the method does not
take any formal keyword arguments, given keyword arguments (packed
in the hash object) are considered as the last argument.

And we also allow non symbol keys in the keyword arguments. In that
case, those keys are just passed in the `**` hash (or raise
`ArgumentError` for unknown keys).

The Instruction Changes

We have changed `OP_SEND` instruction. `OP_SEND` instruction used to
take 3 operands, the register, the symbol, the number of (positional)
arguments. The meaning of the third operand has been changed. It is now
considered as `n|(nk<<4)`, where `n` is the number of positional
arguments, and `nk` is the number of keyword arguments, both occupies
4 bits in the operand.

The number `15` in both `n` and `nk` means variable sized arguments are
packed in the object. Positional arguments will be packed in the array,
and keyword arguments will be packed in the hash object. That means
arguments more than 14 values are always packed in the object.

Arguments information for other instructions (`OP_SENDB` and `OP_SUPER`)
are also changed. It works as the third operand of `OP_SEND`. the
difference between `OP_SEND` and `OP_SENDB` is just trivial. It assigns
`nil` to the block hidden arguments (right after arguments).

The instruction `OP_SENDV` and `OP_SENDVB` are removed. Those
instructions are replaced by `OP_SEND` and `OP_SENDB` respectively with
the `15` (variable sized) argument information.

Calling Convention

When calling a method, the stack elements shall be in the order of the
receiver of the method, positional arguments, keyword arguments and the
block argument. If the number of positional or keyword arugument (`n` or
`nk`) is zero, corresponding arguments will be empty. So when `n=0` and
`nk=0` the stack layout (from bottom to top) will be:

+-----------------------+
| recv | block (or nil) |
+-----------------------+

The last elements `block` should be explicitly filled before `OP_SEND`
or assigned to `nil` by `OP_SENDB` internally. In other words, the
following have exactly same behavior:

OP_SENDB clears `block` implicitly:

```
OP_SENDB reg sym 0
```

OP_SEND clears `block` implicitly:

```
OP_LOADNIL  R2
OP_SEND     R2 sym 0
```

When calling a method with only positional arguments (n=0..14) without
keyword arguments, the stack layout will be like following:

+--------------------------------------------+
| recv | arg1 | ... | arg_n | block (or nil) |
+--------------------------------------------+

When calling a method with arguments packed in the array (n=15) which
means argument splat (*) is used in the actual arguments, or more than
14 arguments are passed the stack layout will be like following:

+-------------------------------+
| recv | array | block (or nil) |
+-------------------------------+

The number of the actual arguments is determined by the length of the
argument array.

When keyword arguments are given (nk>0), keyword arguments are passed
between positional arguments and the block argument. For example, when
we pass one positional argument `1` and one keyword argument `a: 2`,
the stack layout will be like:

+------------------------------------+
| recv | 1 | :a | 2 | block (or nil) |
+------------------------------------+

Note that keyword arguments consume `2*nk` elements in the stack when
`nk=0..14` (unpacked).

When calling a method with keyword arguments packed in the hash object
(nk=15) which means keyword argument splat (**) is used or more than
14 keyword arguments in the actual arguments, the stack layout will
be like:

+------------------------------+
| recv | hash | block (or nil) |
+------------------------------+

Note for mruby/c

When mruby/c authors try to support new keyword arguments, they need
to handle the new meaning of the argument information operand. If they
choose not to support keyword arguments in mruby/c, it just raise
error when `nk` (taken by `(c>>4)&0xf`) is not zero. And combine
`OP_SENDV` behavior with `OP_SEND` when `n` is `15`.

If they want to support keyword arguments seriously, contact me at
<matz@ruby.or.jp> or `@yukihiro_matz`. I can help you.
2021-10-12 20:16:36 +09:00
Yukihiro "Matz" Matsumoto 674d841ead eval.c: if the parser raises an exception without an error message
`eval` would have crashed in formatting.
2021-09-07 07:37:19 +09:00
Yukihiro "Matz" Matsumoto 711f06a562 eval.c: check length of the file name.
It should be lexx than `UINT16_MAX`. If you don't check here, the parser
would raise an exception.
2021-09-07 07:35:35 +09:00
Yukihiro "Matz" Matsumoto 013365498d test/eval.c: add test for #5528 2021-08-12 11:57:56 +09:00
Yukihiro "Matz" Matsumoto 43f6f765b0 Remove unused prototypes for mrb_proc_merge_lvar(); ref #5511 2021-07-19 07:42:49 +09:00
Yukihiro "Matz" Matsumoto d63c0df6bc Merge pull request #5493 from dearblue/binding.2
Fixed finding variables from `proc` in `binding.eval` failed
2021-06-28 09:13:54 +09:00
dearblue c182903ea0 Fixed finding variables from proc in binding.eval failed
Previously the following code did not produce the expected results:
```ruby
bx = binding
block = bx.eval("a = 1; proc { a }")
bx.eval("a = 2")
p block.call  # Expect 2 but return 1 due to a bug
```

The previous implementation of `Binding#eval` evaluated the code and then merged the top layer variables.
This patch will parse and expand the variable space before making a call to `eval`.
This means that the call to `Binding#eval` will do the parsing twice.

In addition, the following changes will be made:
- Make `mrb_parser_foreach_top_variable()`, `mrb_binding_extract_proc()` and `mrb_binding_extract_env()` functions private global functions.
- Remove the `posthook` argument from `mrb_exec_irep()`.
  The `posthook` argument was introduced to implement the `binding` method.
  This patch is unnecessary because it uses a different implementation method.

ref #5362
fixed #5491
2021-06-26 13:43:36 +09:00
dearblue cf38fc2f9e Fix memory leak in Kernel#eval
The `mrbc_context` remained unreleased when the `mrb_parse_nstring()` function returned `NULL`.
2021-06-26 10:59:39 +09:00
dearblue c40802865a Added MRB_API function to get block arguments info.
- ` mrb_block_given_p()` -- The name comes from CRuby's `rb_block_given_p ()`

At the same time, it applies to `f_instance_eval()` and `f_class_eval()` of `mruby-eval`.
2021-06-19 21:15:02 +09:00
Yukihiro "Matz" Matsumoto 651c234f9c eval.c: implement class_eval with string; close #5478 2021-06-16 09:12:03 +09:00
dearblue dd34ac647f Make mrb_exec_irep() allow non-VM to enter.
Change the old `mrb_exec_irep()` as-is to static `mrb_exec_irep_vm()`.
Extract the VM entry part from the old `exec_irep()` in `mruby-eval/src/eval.c` and make it the core of the new `mrb_exec_irep()`.
2021-04-03 21:17:48 +09:00
Yukihiro "Matz" Matsumoto 5d37160455 Use MRB_SYM() more extensively. 2021-02-26 15:05:55 +09:00
dearblue 927615e1f0 Added other methods for Binding
- Added to `mruby-binding-core`
  - `Binding#local_variable_defined?`
  - `Binding#local_variable_get`
  - `Binding#local_variable_set`
  - `Binding#local_variables`
  - `Binding#receiver`
  - `Binding#source_location`
  - `Binding#inspect`
- Added to `mruby-proc-binding`
  - `Proc#binding`

The reason for separating `Proc#binding` is that core-mrbgems has a method that returns a closure object to minimize possible problems with being able to manipulate internal variables.
By separating it as different mrbgem, each user can judge this problem and incorporate it arbitrarily.
2021-02-22 23:32:43 +09:00
dearblue 792f6ac670 Adjustment of the current HEAD and bindings, and separation
Make changes to make `Binding` work.
At the same time, it separates `Binding#eval`, which depends on `mruby-eval`, from `mruby-binding-core`.
2021-02-22 23:32:18 +09:00
dearblue 297c5ac598 Merge branch 'binding' of https://github.com/ksss/mruby into HEAD 2021-02-22 22:14:46 +09:00
Yukihiro "Matz" Matsumoto 17ecf14511 Revert "Minimize the changes in #5277"
This reverts commit dc51d89ac2.
2021-01-26 10:57:07 +09:00
Yukihiro "Matz" Matsumoto dc51d89ac2 Minimize the changes in #5277
Instead of including `mruby/presym.h` everywhere, we provided the
fallback `mruby/presym.inc` under `include/mruby` directory, and specify
`-I<build-dir>/include` before `-I<top-dir>/include` in `presym.rake`.
So even when someone drops `-I<build-dir>/include` in compiler options,
it just compiles without failure.
2021-01-22 18:38:53 +09:00
Yukihiro "Matz" Matsumoto 6c5ccd5abe Merge branch 'avoid-including-presym.inc-in-existing-header-files' of https://github.com/shuujii/mruby into shuujii-avoid-including-presym.inc-in-existing-header-files 2021-01-21 14:53:18 +09:00
KOBAYASHI Shuji 90b53f4c29 Avoid including presym.inc in existing header files
Addressed an issue where existing programs linking `libmruby.a` could only
be built by adding `<build-dir>/include` to compiler's include path.
2021-01-11 09:21:07 +09:00
dearblue 16baea0677 Changes stackent to stack of mrb_callinfo
This enhances self-containment.

Previously `mrb_context::stack` had the current call level stack, but now it owns it.
The `mrb_context::stack` field, which is no longer needed, will be removed.
2021-01-10 13:23:35 +09:00
dearblue 58e9442737 Unified target_class and env of mrb_callinfo
If there is `env`, `env->c` means `target_class`.
2021-01-10 13:23:28 +09:00
dearblue 88a11d81b0 Improves out of memory messages for eval
The comment says that if `mrb_parse_nstring()` returns `NULL`, it is only out of memory.
I'm worried about compatibility if I set the exception class to `NoMemoryError`, so it's still `RuntimeError`.
2020-12-25 23:24:20 +09:00
dearblue 69a6bb1f12 Reorganize env_new() as mrb_env_new()
The `mrb_env_new()` function is a global function, but it is still treated as an internal function.
2020-10-24 22:29:31 +09:00
dearblue f0a64329b1 Prohibit array changes by "a"/"*" specifier of mrb_get_args()
The "a"/"*" specifier of the `mrb_get_args()` function will now return `const mrb_value *`.
This is because it is difficult for the caller to check if it is an array object and write-barrier if necessary.
And it requires calling `mrb_ary_modify()` on the unmodified array object, which is also difficult (this is similar to #5087).
2020-10-22 22:55:35 +09:00
Yukihiro "Matz" Matsumoto a127ded486 Fix warning from VC regarding implicit int conversion. 2020-10-12 18:20:17 +09:00
Yukihiro "Matz" Matsumoto 2a366ffba8 Use functions that take symbols to reduce string litrals in C. 2020-10-12 16:20:59 +09:00
dearblue 57611240a9 Prohibit string changes by "s"/"z" specifier of mrb_get_args()
- The `s` specifier is a string pointer obtained without performing `mrb_str_modify()`, so it cannot be changed.
- The `z` specifier cannot be changed because it is a string pointer obtained by `RSTRING_CSTR()` which returns `const char *`.
2020-09-25 21:02:58 +09:00
Yukihiro "Matz" Matsumoto c07f24cd18 Change flag names in preparation of REnv refactoring. 2020-06-25 06:57:41 +09:00
dearblue f85906b679 Remove patch_irep() in mruby-eval
- It can now deal with operands in the range of `OP_EXT*`.
- It can now call the same method as the variable name without arguments.

  ```ruby
  def a
    "Safe!"
  end

  a = "Auto!"

  eval "a()" # call method `a`
  ```
2020-06-02 14:49:27 +09:00
KOBAYASHI Shuji 8596edba09 Use proper PEEK macro for OP_EPUSH in patch_irep; fix #4833 2019-11-20 16:00:58 +09:00
KOBAYASHI Shuji 04baaab311 Fix argument specs to Kernel 2019-11-15 19:07:42 +09:00
dearblue 279c21b816 Prohibit changes to iseq in principle 2019-08-18 15:00:32 +09:00
KOBAYASHI Shuji 334afb167c Use new specifiers/modifiers of mrb_vfromat()
The binary sizes (gems are only `mruby-bin-mruby`) are reduced slightly in
my environment than before the introduction of new specifiers/modifiers
(5116789a) with this change.

  ------------+-------------------+-------------------+--------
   BINARY     | BEFORE (5116789a) |   AFTER (This PR) |  RATIO
  ------------+-------------------+-------------------+--------
   mruby      |      593416 bytes |      593208 bytes | -0.04%
   libmruby.a |      769048 bytes |      767264 bytes | -0.23%
  ------------+-------------------+-------------------+--------

BTW, I accidentally changed `tasks/toolchains/visualcpp.rake` at #4613,
so I put it back.
2019-08-05 13:18:50 +09:00
KOBAYASHI Shuji acad9567c1 Unify type of line number to uint16_t 2019-07-15 23:03:41 +09:00
KOBAYASHI Shuji 9c79c28604 Move Kernel#instance_eval to BasicObject 2019-05-18 21:17:47 +09:00
Yukihiro "Matz" Matsumoto b3a181aaa1 Fixed a bug in processing OP_EXT? instructions.
fix haconiwa/haconiwa#171
2018-10-23 21:10:03 +09:00
Yukihiro "Matz" Matsumoto 8392578216 Fixed SEGV from eval called form top-level mrb_funcall(); fix #4028 2018-10-02 17:26:43 +09:00
Yukihiro "Matz" Matsumoto b80e0ef742 Move Kernel#send to mruby-metaprog gem.
But `BasicObject#__send__` is still available from the core.
2018-09-01 11:20:30 +09:00
Yukihiro "Matz" Matsumoto e471d37ca5 Separate meta-programming features to mruby-metaprog gem.
We assume meta-programming is less used in embedded environments.
We have moved following methods:

 * Kernel module
   global_variables, local_variables, singleton_class,
   instance_variables, instance_variables_defined?, instance_variable_get,
   instance_variable_set, methods, private_methods, public_methods,
   protected_methods, singleton_methods, define_singleton_methods

 * Module class
   class_variables, class_variables_defined?, class_variable_get,
   class_variable_set, remove_class_variable, included_modules,
   instance_methods, remove_method, method_removed, constants

 * Module class methods
   constants, nesting

Note:
Following meta-programming methods are kept in the core:

 * Module class
   alias_method, undef_method, ancestors, const_defined?, const_get,
   const_set, remove_const, method_defined?, define_method

 * Toplevel object
   define_method

`mruby-metaprog` gem is linked by default (specified in default.gembox).
When it is removed, it will save 40KB (stripped:8KB) on x86-64
environment last time I measured.
2018-08-30 22:30:36 +09:00
Yukihiro "Matz" Matsumoto 471288f37d Reduce integer casting warnings. 2018-08-25 16:58:01 +09:00
Yukihiro "Matz" Matsumoto 8a18d1539b Should update ci->env to share the environment; fix #4073 2018-08-25 09:13:09 +09:00
Yukihiro "Matz" Matsumoto 891839b976 New bytecode implementation of mruby VM. 2018-07-30 22:57:54 +09:00
Yukihiro "Matz" Matsumoto b09d2eb900 Kernel#instance_eval should define singleton methods; fix #4069 2018-07-23 18:26:24 +09:00
Ichito Nagata 1dbeda5c9c add test for eval 2018-06-06 15:35:41 +09:00
Yukihiro "Matz" Matsumoto 181f980b6c Need to clear stack region for local variables in eval; fix #3844 2017-11-10 21:53:12 +09:00