Граф коммитов

199 Коммитов

Автор SHA1 Сообщение Дата
Aaron Patterson 371256775f Anonymous rest nodes should increase the local table size
When we calculate the local table size, we need to account for anonymous
"rest" parameters.  Since they don't have a name, they won't be in the
"locals" table that Prism provides, but we need to reserve room for them
anyway.

Fixes: https://github.com/ruby/prism/issues/2154
2024-01-11 15:53:52 -08:00
Peter Zhu 45dd8edf82 [PRISM] Fix splat inside of aset
Fixes ruby/prism#2146.
2024-01-11 14:58:24 -05:00
Aaron Patterson f2149dc094 [PRISM] Support repeated required parameter names.
Fixes: https://github.com/ruby/prism/issues/2062

This patch only fixes positional parameters, we still need to fix the
other cases spelled out in test/prism/fixtures/repeat_parameters.txt
2024-01-11 11:31:59 -08:00
Peter Zhu 51061b6631 [PRISM] Don't increment argc for PM_ASSOC_SPLAT_NODE
Fixes ruby/prism#2087.
2024-01-10 13:32:19 -05:00
Peter Zhu 55b7121358 [PRISM] Frozen string literals should be fstrings
Frozen string literals should not just be frozen, but deduplicated as an
fstring so that two string literals with the same contents are the exact
same object.

Fixes ruby/prism#2095.
2024-01-09 12:24:18 -05:00
Matt Valentine-House 47ff4a1658 [PRISM] Blocks should track the found local depth
Rather than rely purely on local depth offset. This is because we can't
assume a specific depth offset for all variable accesses happening
within a block in the same way that we can for rescue/ensure/for or
other nodes that push scopes.

This is because block parameters are defined in the scope level, so we
always need to start from the top most scope and walk backwards.

Fixes ruby/prism@2053
2024-01-08 19:55:26 +00:00
Kevin Newton 04f64608e8 Sync to latest prism 2024-01-02 09:13:43 -08:00
Matt Valentine-House 3d984366ca [PRISM] Correct the jump target for redo in FOR_NODE 2023-12-19 22:50:59 +00:00
Matt Valentine-House 371ff80840 [PRISM] Fix parameter numbering in For Node 2023-12-19 22:50:59 +00:00
eileencodes b8074c2f04 [PRISM] Fix incorrect instructions for `default_proc=`
This is kind of specific and was found via debugging ruby/prism#2061 but
does not actually fix that issue.

The change here checks for `!popped` for the additional instructions
that are normally added for nodes with the `attribute_write` flag.

I also removed the extra catch table by deleting the
`ISEQ_COMPILE_DATA(iseq)->catch_except_p = true;` line. I'm...not
entirely sure why it was added but it doesn't match the upstream
compiler
[code](92b10f5be7/compile.c (L887-L892)).

The changes here unfortunately don't improve the test failures mentioned in
the linked issue so we still have other issues with instructions for
hashes.

Instructions before:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(34,8)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] h@0
0000 putnil                                                           (  32)[Li]
0001 putobject                              true
0003 getconstant                            :Hash
0005 send                                   <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil
0008 setlocal                               h@0, 0
0011 getlocal                               h@0, 0                    (  33)[Li]
0014 putspecialobject                       1
0016 send                                   <calldata!mid:lambda, argc:0, FCALL>, block in <compiled>
0019 send                                   <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil
0022 pop
0023 getlocal                               h@0, 0                    (  34)[Li]
0026 putobject                              :nope
0028 send                                   <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil
0031 leave

== disasm: #<ISeq:block in <compiled>@<compiled>:33 (33,19)-(33,32)>
local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] _@0<Arg>   [ 1] _@1<Arg>
0000 putobject                              true                      (  33)[LiBc]
0002 leave                                  [Br]
true
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:31 (31,0)-(33,8)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] h@0
0000 putnil                                                           (  31)[Li]
0001 putobject                              true
0003 getconstant                            :Hash
0005 send                                   <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil
0008 setlocal                               h@0, 0
0011 putnil                                                           (  32)[Li]
0012 getlocal                               h@0, 0
0015 putspecialobject                       1
0017 send                                   <calldata!mid:lambda, argc:0, FCALL>, block in <compiled>
0020 setn                                   2
0022 send                                   <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil
0025 pop
0026 pop
0027 getlocal                               h@0, 0                    (  33)[Li]
0030 putobject                              :nope
0032 send                                   <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil
0035 leave                                                            (  31)

== disasm: #<ISeq:block in <compiled>@<compiled>:32 (32,17)-(32,32)>
== catch table
| catch type: redo   st: 0000 ed: 0002 sp: 0000 cont: 0000
| catch type: next   st: 0000 ed: 0002 sp: 0000 cont: 0002
|------------------------------------------------------------------------
local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] _@0<Arg>   [ 1] _@1<Arg>
0000 putobject                              true                      (  32)[LiBc]
0002 leave                                  [Br]
```

Instructions after:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(34,8)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] h@0
0000 putnil                                                           (  32)[Li]
0001 putobject                              true
0003 getconstant                            :Hash
0005 send                                   <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil
0008 setlocal                               h@0, 0
0011 getlocal                               h@0, 0                    (  33)[Li]
0014 putspecialobject                       1
0016 send                                   <calldata!mid:lambda, argc:0, FCALL>, block in <compiled>
0019 send                                   <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil
0022 pop
0023 getlocal                               h@0, 0                    (  34)[Li]
0026 putobject                              :nope
0028 send                                   <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil
0031 leave

== disasm: #<ISeq:block in <compiled>@<compiled>:33 (33,19)-(33,32)>
local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] _@0<Arg>   [ 1] _@1<Arg>
0000 putobject                              true                      (  33)[LiBc]
0002 leave                                  [Br]

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:31 (31,0)-(33,8)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] h@0
0000 putnil                                                           (  31)[Li]
0001 putobject                              true
0003 getconstant                            :Hash
0005 send                                   <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil
0008 setlocal                               h@0, 0
0011 getlocal                               h@0, 0                    (  32)[Li]
0014 putspecialobject                       1
0016 send                                   <calldata!mid:lambda, argc:0, FCALL>, block in <compiled>
0019 send                                   <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil
0022 pop
0023 getlocal                               h@0, 0                    (  33)[Li]
0026 putobject                              :nope
0028 send                                   <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil
0031 leave                                                            (  31)

== disasm: #<ISeq:block in <compiled>@<compiled>:32 (32,17)-(32,32)>
local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] _@0<Arg>   [ 1] _@1<Arg>
0000 putobject                              true                      (  32)[LiBc]
0002 leave                                  [Br]
```
2023-12-15 16:23:06 -05:00
Matt Valentine-House 161787f9be [PRISM] Compile CallTargetNode 2023-12-15 16:15:10 -05:00
Matt Valentine-House 5b6a4d8c12 [PRISM] Compile IndexTargetNode 2023-12-15 16:15:10 -05:00
Jemma Issroff 5587bd4b37 [PRISM] Implement safe navigation in CallNodes
This commit implements safe navigation for CallNodes,
CallAndWriteNodes and CallOperatorWriteNodes
2023-12-14 17:11:54 -05:00
Kevin Newton d3deb1b823
[prism] Fix build with no asserts 2023-12-14 15:26:01 -05:00
Ufuk Kayserilioglu d07fdc5ede [PRISM] Fix keyword hash handling in method calls
* Start using the renamed `PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS` flag
to check if all keys of the keyword hash node are symbols.
* For arguments passed as a hash, start marking them as `KW_SPLAT_MUT` only if the number of entries in the hash is greater than 1 (which is what the old compiler used to do).
2023-12-14 14:08:37 -05:00
Kevin Newton 295d97ab4d Pattern matching 2023-12-14 14:06:26 -05:00
eileencodes 5a66832952 [Prism] Fix cvar or assignment instructions
The instructions for `PM_CLASS_VARIABLE_OR_WRITE_NODE` were incorrect as
they were missing a `putnil`, a `defined`, and a `branchunless`.

I verified this is fixed via the instructions and running the following:
`RUBY_ISEQ_DUMP_DEBUG=prism make test/csv/interface/test_read_write.rb`.

These new instructions can't go in the defined function because
`defined?(@@fop ||= 1)` should return "assignment" not "class variable".

Instructions before:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(30,11)>
0000 putnil                                                           (  30)[Li]
0001 defined                                class variable, :@@foo, true
0005 branchunless                           14
0007 getclassvariable                       :@@foo, <is:0>
0010 dup
0011 branchif                               20
0013 pop
0014 putobject                              1
0016 dup
0017 setclassvariable                       :@@foo, <is:0>
0020 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:29 (29,0)-(29,11)>
0000 getclassvariable                       :@@foo, <is:0>            (  29)[Li]
0003 dup
0004 branchif                               13
0006 pop
0007 putobject                              1
0009 dup
0010 setclassvariable                       :@@foo, <is:0>
0013 leave
```

Instructions after:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(30,11)>
0000 putnil                                                           (  30)[Li]
0001 defined                                class variable, :@@foo, true
0005 branchunless                           14
0007 getclassvariable                       :@@foo, <is:0>
0010 dup
0011 branchif                               20
0013 pop
0014 putobject                              1
0016 dup
0017 setclassvariable                       :@@foo, <is:0>
0020 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:29 (29,0)-(29,11)>
0000 putnil                                                           (  29)[Li]
0001 defined                                class variable, :@@foo, true
0005 branchunless                           14
0007 getclassvariable                       :@@foo, <is:0>
0010 dup
0011 branchif                               20
0013 pop
0014 putobject                              1
0016 dup
0017 setclassvariable                       :@@foo, <is:0>
0020 leave
```

Fixes ruby/prism#2064
2023-12-14 13:48:38 -05:00
Jemma Issroff 7ac93e99a3 [PRISM] Account for multiple anonymous locals
This commit adjusts the local table size to be consistent regardless
of the number of anonymous locals.
2023-12-14 13:45:41 -05:00
Jemma Issroff 157e6c8a51 [PRISM] Check for static literal, excluding array, hash, range 2023-12-14 11:46:54 -05:00
Jemma Issroff e71f011713 [PRISM] Fix bugs in compiling optional keyword parameters
This PR fixes two bugs when compiling optional keyword parameters:
- It moves keyword parameter compilation to STEP 5 in the parameters
sequence, where the rest of compilation happens. This is important
because keyword parameter compilation relies on the value of
body->param.keyword->bits_start which gets set in an earlier step
- It compiles array and hash values for keyword parameters, which
it didn't previously
2023-12-14 11:46:54 -05:00
Jemma Issroff 8e1c148fd9 [PRISM] Use frozen flag on StringNode 2023-12-14 11:14:45 -05:00
Matt Valentine-House a10c11a66b [PRISM] Add anon KW args to the block local table 2023-12-14 07:01:19 -05:00
eileencodes 110dbf62ac [Prism] Fix InterpolatedMatchLastLine Instructions
I looked at this at RubyConf with Kevin, and we noticed that there was a
`putobject` empty string missing from the instructions. I just got back
around to implementing this and pushing a PR and while doing that
noticed that we also have a `getspecial` when we want a `getglobal`.

This change adds the `putobject` instruction and replaces the
`getspecial` with a `getglobal`. If we look at the parsetree for the
following code:

```ruby
$pit = '.oo'; if /"#{$pit}"/mix; end
```

We can see it has a `NODE_GVAR` and the [Ruby
compiler](a4b43e9264/compile.c (L10024-L10030)) shows that should
use `getglobal.

```
 @ NODE_SCOPE (id: 14, line: 1, location: (1,0)-(22,36))
 +- nd_tbl: (empty)
 +- nd_args:
 |   (null node)
 +- nd_body:
     @ NODE_BLOCK (id: 12, line: 22, location: (22,0)-(22,36))
     +- nd_head (1):
     |   @ NODE_GASGN (id: 0, line: 22, location: (22,0)-(22,12))*
     |   +- nd_vid: :$pit
     |   +- nd_value:
     |       @ NODE_STR (id: 1, line: 22, location: (22,7)-(22,12))
     |       +- nd_lit: ".oo"
     +- nd_head (2):
         @ NODE_IF (id: 11, line: 22, location: (22,14)-(22,36))*
         +- nd_cond:
         |   @ NODE_MATCH2 (id: 10, line: 22, location: (22,14)-(22,36))
         |   +- nd_recv:
         |   |   @ NODE_DREGX (id: 2, line: 22, location: (22,17)-(22,31))
         |   |   +- nd_lit: "\""
         |   |   +- nd_next->nd_head:
         |   |   |   @ NODE_EVSTR (id: 4, line: 22, location: (22,19)-(22,26))
         |   |   |   +- nd_body:
         |   |   |       @ NODE_GVAR (id: 3, line: 22, location: (22,21)-(22,25))
         |   |   |       +- nd_vid: :$pit
         |   |   +- nd_next->nd_next:
         |   |       @ NODE_LIST (id: 7, line: 22, location: (22,26)-(22,27))
         |   |       +- as.nd_alen: 1
         |   |       +- nd_head:
         |   |       |   @ NODE_STR (id: 6, line: 22, location: (22,26)-(22,27))
         |   |       |   +- nd_lit: "\""
         |   |       +- nd_next:
         |   |           (null node)
         |   +- nd_value:
         |       @ NODE_GVAR (id: 9, line: 22, location: (22,14)-(22,36))
         |       +- nd_vid: :$_
         +- nd_body:
         |   @ NODE_BEGIN (id: 8, line: 22, location: (22,32)-(22,32))
         |   +- nd_body:
         |       (null node)
         +- nd_else:
             (null node)
```

I'm struggling with writing a failing test, but the before/after
instructions show that `getglobal` is correct here. I compared the
instructions for the  other `InterpolatedMatchLastLine` node tests
and they also used `getglobal`. I've edited the existing
`InterpolatedLastMatchLineNode` test so that it will use that instruction when
copied out of the test. Without the quotes it thinks it's just a
`MatchLastLineNode`.

Incorrect instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(22,36)>
0000 putstring                              ".oo"                     (  22)[Li]
0002 setglobal                              :$pit
0004 putobject                              "\""
0006 getglobal                              :$pit
0008 dup
0009 objtostring                            <calldata!mid:to_s, argc:0, FCALL|ARGS_SIMPLE>
0011 anytostring
0012 putobject                              "\""
0014 toregexp                               7, 3
0017 getglobal                              :$_
0019 send                                   <calldata!mid:=~, argc:1, ARGS_SIMPLE>, nil
0022 branchunless                           30
0024 jump                                   26
0026 putnil
0027 jump                                   31
0029 pop
0030 putnil
0031 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:21 (21,0)-(21,36)>
0000 putstring                              ".oo"                     (  21)[Li]
0002 setglobal                              :$pit
0004 putobject                              "\""
0006 getglobal                              :$pit
0008 dup
0009 objtostring                            <calldata!mid:to_s, argc:0, FCALL|ARGS_SIMPLE>
0011 anytostring
0012 putobject                              "\""
0014 toregexp                               7, 3
0017 getspecial                             0, 0
0020 send                                   <calldata!mid:=~, argc:1, ARGS_SIMPLE>, nil
0023 branchunless                           31
0025 jump                                   27
0027 putnil
0028 jump                                   32
0030 pop
0031 putnil
0032 leave
```

Fixed instructions:

```
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(22,36)>
0000 putstring                              ".oo"                     (  22)[Li]
0002 setglobal                              :$pit
0004 putobject                              "\""
0006 getglobal                              :$pit
0008 dup
0009 objtostring                            <calldata!mid:to_s, argc:0, FCALL|ARGS_SIMPLE>
0011 anytostring
0012 putobject                              "\""
0014 toregexp                               7, 3
0017 getglobal                              :$_
0019 send                                   <calldata!mid:=~, argc:1, ARGS_SIMPLE>, nil
0022 branchunless                           30
0024 jump                                   26
0026 putnil
0027 jump                                   31
0029 pop
0030 putnil
0031 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:21 (21,0)-(21,36)>
0000 putstring                              ".oo"                     (  21)[Li]
0002 setglobal                              :$pit
0004 putobject                              "\""
0006 getglobal                              :$pit
0008 dup
0009 objtostring                            <calldata!mid:to_s, argc:0, FCALL|ARGS_SIMPLE>
0011 anytostring
0012 putobject                              "\""
0014 toregexp                               7, 3
0017 getglobal                              :$_
0019 send                                   <calldata!mid:=~, argc:1, ARGS_SIMPLE>, nil
0022 branchunless                           30
0024 jump                                   26
0026 putnil
0027 jump                                   31
0029 pop
0030 putnil
0031 leave
```
2023-12-13 13:42:17 -05:00
Takashi Kokubun ea4a4c302c [PRISM] Fix a -Wformat-zero-length warning
../prism_compile.c: In function ‘pm_compile_node’:
../prism_compile.c:2330:20: warning: zero-length gnu_printf format string [-Wformat-zero-length]
 2330 |             rb_bug("");
      |                    ^~
2023-12-13 10:28:20 -08:00
John Hawthorn 02528f647d [PRISM] Use xcalloc for iseq id table
We use xfree on the other end, so we need to use a form of xmalloc here.

Co-authored-by: Matthew Draper <matthew@trebex.net>
2023-12-13 10:20:11 -08:00
John Hawthorn b55de590f3 [PRISM] Fix st_table memory leak
Co-authored-by: Matthew Draper <matthew@trebex.net>
2023-12-13 10:20:11 -08:00
Matt Valentine-House 9eba7a0892 [PRISM] Break nodes should add an entry to the parent catch table 2023-12-13 09:33:07 -05:00
Matt Valentine-House cb8a9851ca [PRISM] Remove errant NOP when redo_label is set 2023-12-13 09:33:07 -05:00
Matt Valentine-House 9267dbdd7a [PRISM] Generate instruction for when redo_label is set 2023-12-13 09:33:07 -05:00
Ufuk Kayserilioglu f390c51b15 [PRISM] Use `PM_KEYWORD_HASH_NODE_FLAGS_STATIC_KEYS` flag in compiler 2023-12-13 08:16:11 -05:00
Jemma Issroff 798a89fae1 [PRISM] If receiver on CallNode is SelfNode, use FCALL flags 2023-12-13 08:11:45 -05:00
eileencodes 1ad991c54d [PRISM] Fix attrset edge cases
In some cases code may look like an attrset ID but should actually
return the value of the method, not the passed values.

In ruby/prism#2051 a flag was added when we have a attribute write call.
I used this flag to add the proper instructions when we have a real
attrset instead of using `rb_is_attrset_id` which was kind of hacky
anyway.

The value that should be returned in the newly added test is 42, not 2.
Previously the changes we had made returned 2.

Related to ruby/prism#1715
2023-12-13 08:11:21 -05:00
Jemma Issroff 196c24620e [PRISM] Correctly parse non-base 10 integers in Prism
This commit passes an `end` to rb_int_parse_cstr which allows us
to correctly parse non-base 10 integers which are enclosed in
parenthesis. Prior to this commit, we were getting a putobject nil
when compiling `(0o0)` for example.
2023-12-12 22:00:50 -05:00
eileencodes a6526342f3 [PRISM] Fix segv with regex once flag
When you have an interpolated regex with a `once` flag and local
variable is outside the block created by the `once` flag, Prism would
see a segv. This is because it was not taking the depth into account.

To fix this, we need to add 1 to the `local_depth_offset` on the
`scope`.

Fixes: ruby/prism#2047
2023-12-12 15:15:02 -05:00
Matt Valentine-House 43ede3f26c [PRISM] Compile NextNode arguments 2023-12-12 13:46:36 -05:00
Jemma Issroff b9dfe04a73 [PRISM] Implementing forwarding of args for ForwardingSuperNode
ForwardingSuperNodes need to actually forward any applicable
arguments. This commit implements that logic, by using the data
stored on the local iseq about the parameters to forward the
appropriate arguments.
2023-12-12 13:45:21 -05:00
Jemma Issroff 68753e4408 [PRISM] Allow rest parameter to be `*`
Prior to this commit, if a rest parameters was `*`, we did not add
it to the locals table correctly. This commit fixes that.
2023-12-12 13:45:21 -05:00
Nobuyoshi Nakada f466afa176
[PRISM] Do not hide syntactically required parentheses within macros
It makes code formatters confused when auto indenting.
2023-12-12 23:57:27 +09:00
Jemma Issroff 69d60cc67b [PRISM] Properly compile MultiTargetNodes within parameters
If there are MultiTargetNodes within parameters, we need to
iterate over them and compile them individually correctly, once
the locals are all in the correct spaces. We need to add one
getlocal for the hidden variable, and then can recurse into the
MultiTargetNodes themselves
2023-12-11 17:04:46 -05:00
Jemma Issroff 5c8e1911ca [PRISM] Fixed rest in MultiTargetNodes 2023-12-11 17:04:46 -05:00
Jemma Issroff aaeccc2924 [PRISM] Correctly implemented forwarding parameters in methods 2023-12-11 17:04:46 -05:00
Jemma Issroff 85ad5be9ee [PRISM] Restructure parameters on ScopeNodes
This commit completely restructures how we handle parameters. The
motivation for this commit was the fix compilation of MultiTargetNodes
within parameters, including nested MultiTargetNodes. A subsequent
commit will actually do the compilation for the MultiTargetNodes.

This commit's main accomplishment is restructuring the locals table
and how we account for it on the ScopeNode, specifically with regards
to hidden variables.

It has multiple steps, all commented within the code, to calculate
the locals table correctly and compile the parameters:
- Step 1: Caculate the table size for the locals
- Step 2: Populate iv index table and local table
- Step 3: Fill in parameter names of MultiTargetNodes on local table
- Step 4: Fill in method body locals on local table
- Step 5: Compile any locals
2023-12-11 17:04:46 -05:00
Jemma Issroff fb93535070 [PRISM] Define and use a pm_add_ensure_iseq
Prior to this commit, we were using `add_ensure_iseq` which compiled
a node as if it was a CRuby node. This commit defines
`pm_add_ensure_iseq` which compiles the Prism node appropriately.
2023-12-11 12:53:47 -05:00
Jemma Issroff c69d1367a7 [PRISM] Fix ElseNode within CaseNode
The logic within the consequent for the CaseNodes in popped cases
was incorrect as it wouldn't emit consequent instructions for a
popped CaseNode. This commit fixes that.
2023-12-11 09:47:59 -05:00
Ufuk Kayserilioglu 0562c246eb Add handling of implicit hash arguments
Arguments that are passed as a hash need special consideration since in certain case they are not treated as keyword arguments. For example, if a call is passing `"a" => 1` as an argument, this will be turned into an implicit hash argument and not a keyword argument.

The existing compiler checks to see if all hash nodes can be treated as keyword arguments. If they can, then it will treat them as keyword arguments. If not, then it will treat them as implicit hash arguments.

This commit implements the same logic inside the Prism compiler.
2023-12-11 09:47:33 -05:00
eileencodes 1cbe114d1c [PRISM] Fix `PM_CALL_NODE` assignment
This PR fixes ruby/prism#1963. Array and variable assignment was broken
for call nodes. The change checks if the `method_id` is related to
assignment and if is adds a `putnil`, `setn` and a `pop`.

The incorrect instructions meant that in some cases (demonstrated in
tests) the wrong value would be returned.

I verified that this fixes the test mentioned in the issue
(run: `RUBY_ISEQ_DUMP_DEBUG=prism make test/-ext-/st/test_numhash.rb`)

Incorrect instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(4,10)>
0000 putnil                                                           (   4)[Li]
0001 putself
0002 send                                   <calldata!mid:tbl, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0005 putself
0006 send                                   <calldata!mid:i, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0009 putself
0010 send                                   <calldata!mid:j, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0013 setn                                   3
0015 send                                   <calldata!mid:[]=, argc:2, ARGS_SIMPLE>, nil
0018 pop
0019 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:3 (3,0)-(3,10)>
0000 putself                                                          (   3)[Li]
0001 send                                   <calldata!mid:tbl, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0004 putself
0005 send                                   <calldata!mid:i, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0008 putself
0009 send                                   <calldata!mid:j, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0012 send                                   <calldata!mid:[]=, argc:2, ARGS_SIMPLE>, nil
0015 leave
```

Fixed instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(4,10)>
0000 putnil                                                           (   4)[Li]
0001 putself
0002 send                                   <calldata!mid:tbl, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0005 putself
0006 send                                   <calldata!mid:i, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0009 putself
0010 send                                   <calldata!mid:j, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0013 setn                                   3
0015 send                                   <calldata!mid:[]=, argc:2, ARGS_SIMPLE>, nil
0018 pop
0019 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:3 (3,0)-(3,10)>
0000 putnil                                                           (   3)[Li]
0001 putself
0002 send                                   <calldata!mid:tbl, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0005 putself
0006 send                                   <calldata!mid:i, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0009 putself
0010 send                                   <calldata!mid:j, argc:0, FCALL|VCALL|ARGS_SIMPLE>, nil
0013 setn                                   3
0015 send                                   <calldata!mid:[]=, argc:2, ARGS_SIMPLE>, nil
0018 pop
0019 leave
```

Fixes ruby/prism#1963
2023-12-08 12:45:40 -08:00
Aaron Patterson 9d696aa204 Support method calls inside `defined?`
This commit supports all kinds of method calls (including methods with
parameters) inside `defined?` calls.
2023-12-07 14:07:09 -08:00
Jemma Issroff b361a800c2 Added comment 2023-12-07 15:29:35 -05:00
Jemma Issroff a0c7bb4328 [PRISM] Account for multiple arguments when compiling ArgumentsNode
BreakNode, ReturnNode and NextNode all compile the ArgumentsNode
directly, but we weren't accounting for multiple arguments. If there
is more than one argument, we need to also emit a newarray
instruction to put the arguments onto the stack
2023-12-07 15:29:35 -05:00
Matt Valentine-House 41b299d639 [PRISM] Stop catch table entries being deleted by the optimiser 2023-12-07 14:12:20 -05:00