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

497 Коммитов

Автор SHA1 Сообщение Дата
Aaron Patterson 7a33a1aee2 Insert all locals in the locals index table
Prism provides an index (local_body_index) which is supposed to point at
the start of locals declared in the method body. Prism assumed that
method body locals would only occur _after_ parameter names.
Unfortunately this assumption is not correct, which meant that we would
in some cases not insert all locals in the local table.  This commit
iterates over locals a second time, inserting any that didn't get
inserted on the first pass.

Fixes: https://github.com/ruby/prism/issues/2245

Co-Authored-By: Matt Valentine-House <matt@eightbitraptor.com>
2024-01-24 09:40:30 -08:00
Peter Zhu 927928badb [PRISM] Fix anonymous keyword arguments
Fixes ruby/prism#2256.
2024-01-24 11:41:08 -05:00
Kevin Newton 4220bdba39 [PRISM] Remove dead code from prism_compile.c
Previously, we were using the main pm_compile_node switch to compile
target nodes. Eventually we switched to pm_compile_target_node and
updated all the call sites. As such, all of this has become dead
code.

However, the multi target code was reused for both parameters and
multi writes (it was just incorrect for multi writes). So that code
has now been moved into its own function that is more specific to
destructured parameters (and has more assertions to that effect).

Overall now you should not see target nodes when you call into
pm_compile_node, since they are more specialized and require more
special handling.
2024-01-24 11:18:58 -05:00
Kevin Newton 767f5d045f [PRISM] Use lvar depths for starting 2024-01-24 10:37:08 -05:00
Peter Zhu 529700d314 [PRISM] Nested MultiWriteNode with method calls
Fixes ruby/prism#2247.
2024-01-24 10:08:25 -05:00
Peter Zhu 909a710a69 [PRISM] Fix anonymous splat nodes
Fixes ruby/prism#2257.
2024-01-23 17:45:51 -05:00
Peter Zhu cecf42601a [PRISM] Fix block fowarding 2024-01-23 15:23:13 -05:00
Peter Zhu 333f4b4930 [PRISM] Support block parameters with no name
Fixes ruby/prism#2249.
2024-01-23 15:23:13 -05:00
Aaron Patterson cfa15bb173 Handle trailing commas on blocks
We need to set a special flag on block iseqs when there is a trailing
comma.

Fixes: https://github.com/ruby/prism/issues/2244
2024-01-22 16:35:58 -08:00
Aaron Patterson 270a46e392 Check keyword parameters correctly
We weren't checking the right offsets when compiling methods with
keyword parameters that had complex code.

Fixes: https://github.com/ruby/prism/issues/2228
2024-01-22 16:02:41 -08:00
Peter Zhu 708fa77404 [PRISM] Fix keyword arguments in IndexOrWriteNode
Fixes ruby/prism#2236.
2024-01-22 15:07:52 -08:00
Peter Zhu 1838dbf6e7 [PRISM] Fix splat and block in aset 2024-01-22 15:07:39 -08:00
Peter Zhu 1847192366 [PRISM] Fix block in aset
Fixes ruby/prism#2223.
2024-01-22 15:07:39 -08:00
Peter Zhu 8065672d99 [PRISM] Force semicolon at the end of PM macros 2024-01-22 15:22:12 -05:00
Peter Zhu 2630941696 [PRISM] Use PM_SWAP macro 2024-01-22 15:21:09 -05:00
Peter Zhu 789de5972b [PRISM] Use PM_POP macro 2024-01-22 15:16:14 -05:00
Aaron Patterson 7db6832225 Fix compiling rescue + ensure
When we're compiling begin / rescue / ensure nodes, we need to "wrap"
the code in the begin statements correctly.  The wrapping is like this:
(ensure code (rescue code (begin code)))

This patch pulls the each leg in to its own function, then calls the
appropriate wrapping function depending on whether there are ensure /
rescue legs.

Fixes: https://github.com/ruby/prism/issues/2221
2024-01-22 12:02:03 -08:00
Peter Zhu dbd76d9101 [PRISM] Fix keyword splat in IndexAndWriteNode and IndexOrWriteNode
Fixes ruby/prism#2232 and ruby/prism#2234.
2024-01-22 12:56:43 -05:00
Kevin Newton ab99ce910c [PRISM] Insert concatarray for index targets with splat 2024-01-22 12:55:06 -05:00
Kevin Newton e5f8585a29 [PRISM] Fix line for leave instructions 2024-01-22 12:54:32 -05:00
Peter Zhu a7af34fa8b [PRISM] Fix keywords arguments in IndexAndWriteNode
Fixes ruby/prism#2233.
2024-01-22 11:26:21 -05:00
Kevin Newton 6401f282d2
[PRISM] Fix up source line for 1-indexed line numbers 2024-01-22 11:21:04 -05:00
Kevin Newton d68aaa6672 [PRISM] Freeze regex literals in iseqs 2024-01-22 11:12:38 -05:00
Peter Zhu 580429d27c [PRISM] Fix incorrect ordering of MultiTargetNode
Fixes ruby/prism#2218.
2024-01-22 10:51:43 -05:00
Matt Valentine-House 2abf153016 [PRISM] Add TP call/return events to method ISEQs 2024-01-22 09:40:52 -05:00
Kevin Newton 99d6e2f1ee [PRISM] Revisit target nodes 2024-01-19 20:12:07 -05:00
eileencodes ed50161bd6 [PRISM] Fix ensure code running twice
Fixes: ruby/prism#2212
2024-01-19 13:04:01 -08:00
Aaron Patterson 4778b0eeda Fix kwarg ordering
Required keyword arguments need to come first.

Fixes: https://github.com/ruby/prism/issues/2158

Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2024-01-19 12:32:20 -08:00
Peter Zhu 740f0b52e0 [PRISM] Fix typo with pm_scope_node_destroy
We need to run the pm_scope_node_destroy after compiling the iseq.
2024-01-19 14:09:32 -05:00
Aaron Patterson efe4b8ac0f Fix ensure code when running break in a while loop
We need to run ensure code when breaking from a while loop

Co-authored-by: John Hawthorn <jhawthorn@github.com>
Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2024-01-19 09:35:36 -08:00
Peter Zhu 5a5cf23d02 [PRISM] Fix indentation for PM_SCOPE_NODE [ci skip] 2024-01-19 11:18:47 -05:00
Peter Zhu c28094d385 [PRISM] Add function to free scope node
pm_scope_node_destroy frees the scope node after we're done using it to
make sure that the index_lookup_table is not leaked.

For example:

    10.times do
      100_000.times do
        RubyVM::InstructionSequence.compile_prism("begin; 1; rescue; 2; end")
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

    33056
    50304
    67776
    84544
    101520
    118448
    135712
    152352
    169136
    186656

After:

    15264
    15296
    15408
    17040
    17152
    17152
    18320
    18352
    18400
    18608
2024-01-18 16:33:25 -05:00
Peter Zhu 47081c3ee3 [PRISM] Pass pm_scope_node_t by reference
We can pass pm_scope_node_t by reference to pm_new_child_iseq rather
than by value.
2024-01-18 16:33:25 -05:00
Matt Valentine-House 60dd731125 [PRISM] Correct checkmatch flags for splat in rescue 2024-01-18 20:25:28 +00:00
Matt Valentine-House 8a3e7f08b8 [PRISM] Fix case splat with no predicate 2024-01-18 20:03:27 +00:00
Peter Zhu 686b1655a0 [PRISM] Fix indentation in switch [ci skip] 2024-01-18 14:59:59 -05:00
Peter Zhu d8ac96efc5 [PRISM] Fix memory leak in case nodes
The temporary array conditions_labels is heap allocated and never freed.
We can use alloca instead to stack allocate it so that we don't need to
manually free it.

For example:

    code = "case; #{100.times.map { "when #{it}; " }.join}; end"

    10.times do
      10_000.times do
        RubyVM::InstructionSequence.compile_prism(code)
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

    21376
    30304
    38800
    47184
    55456
    64192
    72288
    80400
    89040
    97104

After:

    13088
    13632
    13760
    14016
    14688
    14992
    15120
    15232
    15744
    15744
2024-01-18 13:40:14 -05:00
Peter Zhu 00814fd672 [PRISM] Fix memory leak in iseq
rb_iseq_compile_prism_node calls both rb_translate_prism and iseq_setup.
Both of these functions call iseq_set_sequence. This means that the first
iseq_set_sequence will leak because the iseq will be overwritten.

For example:

    10.times do
      100_000.times do
        RubyVM::InstructionSequence.compile_prism("")
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

    20528
    27328
    33840
    40208
    46400
    52960
    59168
    65600
    71888
    78352

After:

    13696
    13712
    13712
    13712
    13712
    14352
    14352
    14992
    14992
    14992
2024-01-18 10:35:46 -05:00
eileencodes db9f5fc916 [Prism] Implement defined? for PM_UNLESS_NODE
Ruby code:

```ruby
defined?(unless true; 1; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes 555af5e599 [Prism] Implement defined? for PM_UNTIL_NODE
Ruby code:

```ruby
defined?(until a == 1; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes 24d02cd485 [Prism] Implement defined? for PM_WHILE_NODE
Ruby code:

```ruby
defined?(while a != 1; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes b5d3d61130 [Prism] Implement defined? for PM_SINGLETON_CLASS_NODE
Ruby code:

```ruby
defined?(class << self; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes d2000e0e6c [Prism] Implement defined? for PM_RATIONAL_NODE
Ruby code:

```ruby
defined?(1.2r)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes 913772a08a [Prism] Implement defined? for PM_MODULE_NODE
Ruby code:

```ruby
defined?(module M; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes a9a22b9f2d [Prism] Implement defined? for PM_MATCH_REQUIRED_NODE
Ruby code:

```ruby
defined?(1 => 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes b40fc4f0a7 [Prism] Implement defined? for PM_MATCH_WRITE_NODE
Ruby code:

```ruby
defined?(/(?<foo>bar)/ =~ 'barbar')
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,35)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] foo@0
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,35)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] foo@0
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes a2092ef207 [Prism] Implement defined? for PM_IF_NODE
Ruby code:

```ruby
defined?(if true; 1; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,43)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,43)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes fb1eed3f70 [Prism] Implement defined? for PM_FOR_NODE
Ruby code:

```ruby
defined?(for i in [1,2] do; i; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,43)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,43)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes 7460820fec [Prism] Implement defined? for PM_DEF_NODE
Ruby code:

```ruby
defined?(def prism_test_def_node; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,43)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,43)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes 30e7dbb78d [Prism] Implement defined? for PM_CLASS_NODE
Ruby code:

```ruby
defined?(class PrismClassA; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,43)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,43)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes 9bcd42c378 [Prism] Implement defined? for PM_CASE_MATCH_NODE
Ruby code:

```ruby
defined?(case [1, 2, 3]; in [1, 2, 3]; 4; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,43)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,43)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
eileencodes 75bed8c61a [Prism] Implement defined? for PM_CASE_NODE
Ruby code:

```ruby
defined?(case :a; when :a; 1; else; 2; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,43)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,43)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 17:21:29 -05:00
Peter Zhu 9f0d38960f [PRISM] Refactor keyword hash nodes
Follow up to #9540.
2024-01-17 17:07:51 -05:00
Peter Zhu 00f9456f16 [PRISM] Remove unnecessary flag setting
VM_CALL_KW_SPLAT and VM_CALL_KW_SPLAT_MUT are guaranteeed to be set in
this code path, so we don't need to set it again.
2024-01-17 17:07:51 -05:00
eileencodes e1bae2c693 [Prism] Implement defined? for PM_INDEX_OR_WRITE_NODE
Ruby code:

```ruby
defined?([0][0] ||= 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes ff54a8f4c7 [Prism] Implement defined? for PM_INDEX_OPERATOR_WRITE_NODE
Ruby code:

```ruby
defined?([0][0] += 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes f8ef77af3b [Prism] Implement defined? for PM_INDEX_AND_WRITE_NODE
Ruby code:

```ruby
defined?([0][0] &&= 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes e217c5772b [Prism] Implement defined? for PM_CONSTANT_PATH_WRITE_NODE
Ruby code:

```ruby
defined?(Prism::CPWN = 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes 54b8330e45 [Prism] Implement defined? for PM_CONSTANT_PATH_OR_WRITE_NODE
Ruby code:

```ruby
defined?(Prism::CPOrWN ||= 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes 3c9dc2f806 [Prism] Implement defined? for PM_CONSTANT_PATH_OPERATOR_WRITE_NODE
Ruby code:

```ruby
defined?(Prism::CPOWN += 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes 98d6f50312 [Prism] Implement defined? for PM_CONSTANT_PATH_AND_WRITE_NODE
Ruby code:

```ruby
defined?(Prism::CPAWN &&= 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes 7522e867ee [Prism] Implement defined? for PM_CALL_OR_WRITE_NODE
Ruby code:

```ruby
defined?(PrismTestSubclass.test_call_or_write_node ||= 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes 9c5391d7dc [Prism] Implement defined? for PM_CALL_OPERATOR_WRITE_NODE
Ruby code:

```ruby
defined?(PrismTestSubclass.test_call_operator_write_node += 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
eileencodes f657fd150f [Prism] Implement defined? for PM_CALL_AND_WRITE_NODE
Ruby code:

```ruby
defined?(PrismTestSubclass.test_call_and_write_node &&= 1)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,58)>
0000 putobject                              "assignment"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,58)>
0000 putobject                              "assignment"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 13:08:49 -08:00
Peter Zhu ebc4704696 [PRISM] Fix indentation in pm_setup_args [ci skip] 2024-01-17 14:45:05 -05:00
Peter Zhu f43a919be4 [PRISM] Fix fallthrough for PM_ENSURE_NODE
This caused it to fall into PM_ELSE_NODE which caused ensure nodes to be
compiled twice.

Fixes ruby/prism#2176.
2024-01-17 13:17:44 -05:00
Peter Zhu 947194aacb [PRISM] Fix memory leak of ST table
This commit fixes a memory leak in rb_translate_prism because the ST
table is never freed. There are still more memory leaks which still need
to be fixed.

For example:

    10.times do
      100_000.times do
        RubyVM::InstructionSequence.compile_prism("")
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

    34544
    57120
    79360
    102176
    123712
    146320
    168192
    190592
    212192
    234896

After:

    18336
    24592
    31488
    37648
    44592
    50944
    57280
    63632
    69904
    76160
2024-01-17 11:35:30 -05:00
eileencodes 78ad91f83f [Prism] Fix more method call argumnents
In #2087 it was noted that there was a bug in the number of arguments in
`SplatNode` and `KeywordHashNode`. I looked into this with Aaron before
the linked PR was merged and we found a bunch of cases that weren't
working quite right. This PR aims to fix some of those cases, but there
may be more.

A splat argument followed by a positional argument will concat the array
until the end or unless the argument is a kwarg or splat kwarg. For
example

```
foo(a, *b, c, *d, e)
```

Will have an `argc` of 2, because `b`, `c`, `d`, and `e` will be
concatenated together.

```
foo(a, *b, c, *d, **e)
```

Will have an `argc` of 3, because `b`, `c`, and `d` will be concatenated
together and `e` is a separate argument.
2024-01-17 10:57:19 -05:00
eileencodes dcf9d77b45 [Prism] Implement defined? for PM_BEGIN_NODE
Ruby code:

```ruby
defined?(begin; 1; end)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,23)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,23)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes 338aa465c0 [Prism] Implement defined? for PM_RETRY_NODE
Ruby code:

```ruby
defined?(retry)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,15)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,15)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes 8774abad55 [Prism] Implement defined? for PM_RETURN_NODE
Ruby code:

```ruby
defined?(return)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,16)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,16)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes d0a7c33f05 [Prism] Implement defined? for PM_REDO_NODE
Ruby code:

```ruby
defined?(redo)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,14)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,14)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes 2697acf7ff [Prism] Implement defined? for PM_INTERPOLATED_X_STRING_NODE
Ruby code:

```ruby
defined?(`echo #{1}`)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,21)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,21)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes e0c90199c9 [Prism] Implement defined? for PM_INTERPOLATED_SYMBOL_NODE
Ruby code:

```ruby
defined?(:"1 #{1 + 2} 1")
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,25)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,25)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes 25f1a8e447 [Prism] Implement defined? for PM_DEFINED_NODE
Ruby code:

```ruby
defined?(defined?(a))
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,21)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,21)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes 82ed90950e [Prism] Implement defined? for PM_BREAK_NODE
Ruby code:

```ruby
defined?(break)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,15)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,15)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
eileencodes 0c814092ee [Prism] Implement defined for PM_NEXT_NODE
Ruby code:

```ruby
defined?(next)
```

Instructions

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(59,15)>
0000 putobject                              "expression"              (  59)[Li]
0002 leave
"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:58 (58,0)-(58,15)>
0000 putobject                              "expression"              (  58)[Li]
0002 leave
```

Related: ruby/prism#2188
2024-01-17 10:17:59 -05:00
Matt Valentine-House ef4a08eb65 [PRISM] Fix stack inconsistency in MultiWriteNode 2024-01-17 14:48:46 +00:00
Peter Zhu 07b9b53459 [PRISM] Fix crash with empty ensure blocks
Fixes ruby/prism#2179.
2024-01-16 12:55:57 -05:00
Matt Valentine-House 7bd7030a96 [PRISM] Replace local lookup recursion with loop 2024-01-16 12:43:53 -05:00
Peter Zhu 70a8ed0775 [PRISM] Don't allocate labels when not needed
The labels lstart, lend, lcont are only needed when there is a rescue
clause. They are not needed when there is only an ensure clause or
neither.
2024-01-16 12:43:14 -05:00
Peter Zhu 1caa881a56 [PRISM] Fix splat assignment
Fixes ruby/prism#2177
2024-01-16 11:12:06 -05:00
Matt Valentine-House fef8ccff11 Rename pm_lookup_local_index_any_scope
Now it's the only local lookup function we can just call it
pm_lookup_local_index
2024-01-16 14:58:55 +00:00
Matt Valentine-House 543bd7f3db Remove scope_node->local_depth_offset 2024-01-16 14:58:55 +00:00
Matt Valentine-House 1b97f61168 Remove pm_lookup_local_index_with_depth 2024-01-16 14:58:55 +00:00
Matt Valentine-House 0d705b342f Remove the found_depth pointer
Now that we're returning pm_local_index_t
2024-01-16 14:58:55 +00:00
Matt Valentine-House da383c0d74 Return pm_local_index_t when looking up local indexes
instead of returning the index and updating found_depth in the parent
scope
2024-01-16 14:58:55 +00:00
Matt Valentine-House f4b299a1ed Bind index & depth together into pm_local_index_t 2024-01-16 14:58:55 +00:00
Matt Valentine-House 3d45b743e4 Replace pm_lookup_local_index with lookup_local_index_with_depth 2024-01-16 14:58:55 +00:00
Peter Zhu 0520e9675b [PRISM] Fix defined? for chained calls
Fixes ruby/prism#2148.
2024-01-16 08:32:21 -05:00
Peter Zhu 6a175902f4 [PRISM] Fix keyword splat inside of array
Fixes ruby/prism#2155.
2024-01-15 17:12:53 -05:00
Peter Zhu 7c6d7fbc28 [PRISM] Fix case without predicate
Fixes ruby/prism#2149.
2024-01-15 09:58:44 -05:00
Aaron Patterson 475663f039 Only intern constants upon compilation entry
Before this commit the Prism compiler would try to intern constants
every time it re-entered. This pool of constants is "constant" (there is
only one pool per parser instance), so we should do it only once: upon
the top level entry to the compiler.

This change does just that: it populates the interned constants once.

Fixes: https://github.com/ruby/prism/issues/2152
2024-01-12 14:53:14 -08:00
Aaron Patterson 2c27a3a0dd Fix splat assigns with no lefties
We still need to emit an expand array even if there's no "left side"
variables

Fixes: https://github.com/ruby/prism/issues/2153
2024-01-12 12:46:28 -08:00
Aaron Patterson 774eef692c Always freeze strings that are in the instructions
Any objects that the instructions reference should be frozen.

Co-Authored-By: Matt Valentine-House <matt@eightbitraptor.com>
2024-01-12 12:20:04 -08:00
Jemma Issroff 84f14ff089 [PRISM] Pre-concatenate Strings in InterpolatedStringNode
This commit concatenates String VALUEs within
InterpolatedStringNodes to allow us to preserve frozenness of
concatenated strings such as `"a""b"`

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2024-01-12 12:20:04 -08:00
Peter Zhu 0462b1b350 [PRISM] Fix splat in when
Fixes ruby/prism#2147.
2024-01-12 13:04:23 -05:00
Kevin Newton 2d9db72d37 Write to constant path, call, and index in rescue
When compiling a rescue reference, you can write to a constant
path, a call, or an index. In these cases we need to compile the
prefix expression first, then handle actually doing the write/call.
2024-01-12 11:30:25 -05:00
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
Jemma Issroff b8df6b9e01 [PRISM] Don't pop arguments on a return node
Since ReturnNodes don't get popped, their arguments shouldn't either
2023-12-07 10:34:39 -05:00
Matt Valentine-House 8e86a4347e [PRISM] Ensure should set correct end_label 2023-12-07 09:38:24 -05:00
Matt Valentine-House c4b9695350 [PRISM] Rescue should set correct end_label
In order for a break inside the rescue to have the correct jump target
2023-12-07 09:38:24 -05:00
Matt Valentine-House c8b60c8ac2 [PRISM] Correct depth offset for block local vars
Blocks should always look at their own local table first, even when
defined inside an ensure/rescue or something else that uses depth
offset. We can ignore the depth offset if we're doing local lookups
inside a block
2023-12-06 21:12:08 +00:00
Kevin Newton 153c09f24b [prism] Handle string and xstring encodings 2023-12-06 14:23:38 -05:00
Jemma Issroff 9620ca6789 [PRISM] Extract a PM_NOP helper 2023-12-06 13:05:03 -05:00
Jemma Issroff 0316e666c0 [PRISM] Fix ReturnNodes
This code is almost exactly the same (fixed variable names) as
what exists already in compile.c
2023-12-06 12:25:49 -05:00
Jemma Issroff f80262b14d [PRISM] Account for nil parent in Call{Operator,And,Or}PathWriteNodes
Prior to this commit, we were not accounting for the case of a nil
parent in a CallXPathWriteNode, for example ::A ||= 1. This commit
checks if the parent exists, and if not, uses Object as the inferred
parent
2023-12-06 11:31:43 -05:00
eileencodes da1519b223 [PRISM] Implement `PM_MATCH_PREDICATE_NODE` for `defined?`
Ruby code:

```ruby
defined? 1 in 1
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,16)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,16)>
0000 putobject                              "expression"
0002 leave
```
2023-12-06 09:46:19 -05:00
eileencodes 4547108448 [PRISM] Implement `PM_KEYWORD_HASH_NODE` for `defined?`
Ruby code:

```ruby
defined? [a: [:b, :c]]
```

Instructions (without optimizations):

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,23)>
== catch table
| catch type: rescue st: 0001 ed: 0007 sp: 0000 cont: 0009
| == disasm: #<ISeq:defined guard in <compiled>@<compiled>:0 (0,0)-(-1,-1)>
| local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
| [ 1] "$!"@0
| 0000 putnil
| 0001 leave
|------------------------------------------------------------------------
0000 putnil
0001 putobject                              true
0003 branchunless                           9
0005 putobject                              "expression"
0007 swap
0008 pop
0009 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,23)>
== catch table
| catch type: rescue st: 0000 ed: 0009 sp: 0000 cont: 0009
| == disasm: #<ISeq:defined guard in <compiled>@<compiled>:0 (0,0)-(-1,-1)>
| local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
| [ 1] "$!"@0
| 0000 putnil
| 0001 leave
|------------------------------------------------------------------------
0000 putnil
0001 putobject                              true
0003 branchunless                           9
0005 putobject                              "expression"
0007 swap
0008 pop
0009 leave
```

Instructions (with optimizations):

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,23)>
== catch table
| catch type: rescue st: 0001 ed: 0003 sp: 0000 cont: 0005
| == disasm: #<ISeq:defined guard in <compiled>@<compiled>:0 (0,0)-(-1,-1)>
| local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
| [ 1] "$!"@0
| 0000 putnil
| 0001 leave
|------------------------------------------------------------------------
0000 putnil
0001 putobject                              "expression"
0003 swap
0004 pop
0005 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,23)>
== catch table
| catch type: rescue st: 0000 ed: 0005 sp: 0000 cont: 0005
| == disasm: #<ISeq:defined guard in <compiled>@<compiled>:0 (0,0)-(-1,-1)>
| local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
| [ 1] "$!"@0
| 0000 putnil
| 0001 leave
|------------------------------------------------------------------------
0000 putnil
0001 putobject                              "expression"
0003 swap
0004 pop
0005 leave
```
2023-12-06 09:46:19 -05:00
eileencodes 8649764522 [PRISM] Implement `PM_SPLAT_NODE` for `defined?`
In an array for `defined?` we need to check if there is a
`contains_splat` flag, if so bail early.

Ruby code:

```ruby
defined?([[*1..2], 3, *4..5])
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,29)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,29)>
0000 putobject                              "expression"
0002 leave
```
2023-12-06 09:46:19 -05:00
eileencodes 02961fdbab [PRISM] Implement `PM_SOURCE_LINE_NODE` for `defined?`
Ruby code:

```ruby
defined?(__LINE__)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,18)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,18)>
0000 putobject                              "expression"
0002 leave
```
2023-12-06 09:46:19 -05:00
eileencodes d474239537 [PRISM] Implement `PM_SOURCE_FILE_NODE` for `defined?`
Ruby code:

```ruby
defined?(__FILE__)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,18)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,18)>
0000 putobject                              "expression"
0002 leave
```
2023-12-06 09:46:19 -05:00
eileencodes 41b117e50c [PRISM] Implement `PM_SOURCE_ENCODING_NODE` for `defined?
Ruby code:

```ruby
defined?(__ENCODING__)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,22)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,22)>
0000 putobject                              "expression"
0002 leave
```
2023-12-06 09:46:19 -05:00
eileencodes b04255deff [PRISM] Implement `PM_IMAGINARY_NODE` for `defined?`
Ruby Code:

```
defined?(1i)
```

Instructions:

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)>
0000 putobject                              "expression"
0002 leave
```
2023-12-06 09:46:19 -05:00
Matt Valentine-House d6ec1aa0a7 [PRISM] Compile Rescue Modifier nodes 2023-12-06 07:02:04 -05:00
Matt Valentine-House 6b9622ebdf [PRISM] Implement Retry node. 2023-12-05 08:56:22 -05:00
Jemma Issroff 81a700853d [PRISM] Fixed redo node 2023-12-04 17:02:04 -05:00
eileencodes 7d371ca25d [PRISM] Handle percent literals for `defined?`
Tests all the possible percent literal with `defined?`. Implements the
missing `PM_X_STRING_NODE` for the `%x` literal.

Code:

```ruby
defined?(%x[1,2,3])
```

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,19)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,19)>
0000 putobject                              "expression"
0002 leave
```
2023-12-04 16:45:18 -05:00
eileencodes 09e8d37f5b [PRISM] Implement `PM_INTERPOLATED_REGULAR_EXPRESSION_NODE`
Implements `PM_INTERPOLATED_REGULAR_EXPRESSION_NODE` for `defined?`

Code:

```ruby
defined?(/#{1}/)
```

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,16)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,16)>
0000 putobject                              "expression"
0002 leave
```
2023-12-04 16:45:18 -05:00
eileencodes 33bc22efe5 [PRISM] Implement `PM_INTERPOLATED_STRING_NODE`
Implements `PM_INTERPOLATED_STRING_NODE` for `defined?`

Code:

```ruby
defined?("#{expr}")
```

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,19)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,19)>
0000 putobject                              "expression"
0002 leave
```
2023-12-04 16:45:18 -05:00
eileencodes c23b2e5353 [PRISM] Fix `PM_PARENTHESES_NODE`
In #9101 I only accounted for an empty paren. This change implements the
`PM_PARENTHESES_NODE` for when it's `nil` and when it's an expression.

Code:

```ruby
defined?(("a"))
```

```
"********* Ruby *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,15)>
0000 putobject                              "expression"
0002 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,15)>
0000 putobject                              "expression"
0002 leave
```
2023-12-04 16:45:18 -05:00
eileencodes 569750f624 [Prism] Implement backref and numbered reference for `defined?`
This PR implements `PM_BACK_REFERENCE_READ_NODE` and
`PM_NUMBERED_REFERENCE_READ_NODE` for `defined?`. The following now
works:

* `PM_NUMBERED_REFERENCE_READ_NODE`

```
defined? $1
defined? $2
```

Instructions:

```
"********* RUBY *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)>
0000 putnil
0001 defined                                ref, :$1, "global-variable"
0005 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)>
0000 putnil
0001 defined                                ref, :$1, "global-variable"
0005 leave
```

* `PM_BACK_REFERENCE_READ_NODE`

```
defined? $'
defined? $`
defined? $&
```

Instructions:

```
"********* RUBY *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)>
0000 putnil
0001 defined                                ref, :$`, "global-variable"
0005 leave

"********* PRISM *************"
== disasm: #<ISeq:<compiled>@<compiled>:0 (0,0)-(0,12)>
0000 putnil
0001 defined                                ref, :$`, "global-variable"
0005 leave
```
2023-12-04 12:03:22 -08:00
Jemma Issroff e3ca50b02f [PRISM] Fix compilation for NextNode
This code was almost enitrely the same as the existing compiler's
code for its NextNode.
2023-12-04 14:03:00 -05:00
eileencodes 818813c2bd Implement paren node for `defined?`
Implements and adds a test for passing a parentheses node to `defined?`.
2023-12-01 14:56:25 -08:00
eileencodes 39238888bc Implements missing literals for `defined?`
This PR implements the following literals:

- String
- Symbols
- Integers
- Floats
- Regexs
- Ranges
- Lambdas
- Hashes

and tests for them.
2023-12-01 12:05:22 -08:00
Jemma Issroff 2a8d9c59ff [PRISM] Account for RescueNodes with no statements
We need a PUTNIL if a RescueNode has no statements.
2023-12-01 13:23:23 -05:00
Jemma Issroff d6584a0201 [PRISM] Fix behavior of BlockParameters with only one parameter
This commit sets the ambiguous param flag if there is only one
parameter on a block node. It also fixes a small bug with a trailing
comma on params.
2023-12-01 13:07:59 -05:00
Jemma Issroff 9d20909342
[PRISM] Clean up trailing comment 2023-12-01 12:20:16 -05:00
Jemma Issroff d224618bea [PRISM] Restructure parameters
Prior to this commit, we weren't accounting for hidden variables
on the locals table, so we would have inconsistencies on the stack.
This commit fixes params, and introduces a hidden_variable_count
on the scope, both of which fix parameters.
2023-12-01 12:14:54 -05:00
Kevin Newton 5150ba0dbe [prism] Update to latest numbered parameters 2023-12-01 12:03:09 -05:00
Matt Valentine-House 90d9c20a0c [PRISM] Compile RescueNode 2023-12-01 16:40:25 +00:00
Matt Valentine-House 3b21932d14 [PRISM] Use depth_offset not transparent scopes for FOR 2023-12-01 15:04:13 +00:00
Matt Valentine-House 0c7c654b4d [Prism] Fix local variable access for POST_EXECUTION_NODE 2023-11-30 21:31:57 +00:00
Matt Valentine-House 57782d3d47 Store depth offset inside the scope node.
Instead of incrementing the depth using call by reference as we're
recursing up the stack we could instead store an offset for each known
scope where we know the depth is going to represented differently in the
Prism ast.
2023-11-30 21:31:57 +00:00
Aaron Patterson 630c97acc7 Add a rescue for `defined?(A::B::C)`
It's possible for `defined?(A::B::C)` to raise an exception.  `defined?`
must swallow the exception and return nil, so this commit adds a rescue
entry for `defined?` expressions on constant paths
2023-11-30 09:48:14 -05:00
Jemma Issroff 8234763816 [PRISM] Compile empty array as newarray 0
Prior to this commit, we were compiling an empty array as a
duparray of [] which meant we were allocating a new value
unnecessarily. With this commit, we emit a newarray with size 0
instead.
2023-11-29 16:20:30 -05:00
Jemma Issroff 853fd44745 [PRISM] Implement CallNodes with splat followed by args 2023-11-29 16:19:14 -05:00
Jemma Issroff 2233204cc1 [PRISM] Account for ImplicitRestNode
Prism introduced a new ImplicitRestNode. This adds tests for the
ImplicitRestNode cases, and changes one assert which is no longer
accurate.
2023-11-29 16:14:28 -05:00
Jemma Issroff 53841941f0 [PRISM] Fix EnsureNode, pass depth to get locals
This commit fixes a bug with locals in ensure nodes by setting
the local tables correctly. It also changes accessing locals to
look at local tables in parent scopes, and account for this
correctly on depths of get or setlocals.
2023-11-29 16:00:00 -05:00
Jemma Issroff a9c07cbd21 [PRISM] Don't calculate params size based on locals
Prior to this commit, we were conflating the size of the locals
list with the number of parameters. This commit distinguishes
the two, and fixes a related bug which would occur if we set a local
that was not a parameter
2023-11-28 17:01:34 -05:00
Jemma Issroff 7bd172744f [PRISM] Implement more compilation of SplatNodes
There was a bug with the rest argument in SplatNodes, this commit
fixes it, and adds more tests illustrating the behavior of
SplatNodes
2023-11-28 14:03:57 -05:00
Jemma Issroff 2760f23774 [PRISM] Compile YieldNode with different arguments 2023-11-28 14:02:53 -05:00
Jemma Issroff 1acea50100 [PRISM] Small fixes to parameters ordering and methods 2023-11-27 16:02:38 -05:00
Jemma Issroff e4dd8f6c9c [PRISM] Renamed some variables, added comments 2023-11-27 15:14:40 -05:00
Jemma Issroff ba26c6eae0 [PRISM] Compile IndexOperatorWriteNode 2023-11-27 15:14:40 -05:00
Jemma Issroff ec5eddf695 [PRISM] Compile IndexAndWriteNode 2023-11-27 15:14:40 -05:00
Jemma Issroff 13b7cddc2b [PRISM] Compile IndexOrWriteNode 2023-11-27 15:14:40 -05:00
Jemma Issroff 95064bb88d [PRISM] Fix compilation for SplatNodes within ArrayNodes
SplatNodes within ArrayNodes (e.g. [*1..2, 3]) need to be special
cased in the compiler because they use a combination of concatarray
and newarray instructions to treat each sequence of splat or non-splat
elements as independent arrays which get concatenated. This commit
implements those cases.
2023-11-27 12:52:07 -05:00
Jemma Issroff 6d447fa35f [PRISM] Don't pop several args related nodes 2023-11-27 12:51:50 -05:00
Matt Valentine-House 406dafbb34 [PRISM] Insert Tracepoint line events on line change 2023-11-24 12:54:35 +00:00
Jemma Issroff 3db21d2d4c [PRISM] Rename flag to CONTAINS_KEYWORD_SPLAT
We need to do this change first on ruby/ruby before merging to
ruby/prism to avoid breaking ruby/ruby CI
2023-11-21 17:29:07 -05:00
Kevin Newton a5b482837b Remove string concat node in prism 2023-11-21 11:35:46 -05:00
Kevin Newton 914640eadd Use new match write targets 2023-11-20 18:00:44 -05:00
Jemma Issroff 103bbd21f8 [PRISM] Updated LocalVariableTargetNodes too 2023-11-20 13:48:46 -08:00
Jemma Issroff b913626bea [PRISM] Fix LocalVariableWriteNodes within blocks
Prior to this commit, we weren't recursing up scopes to look for
the local definition. With this commit, we do so, fixing local writes
within blocks
2023-11-20 13:48:46 -08:00
eileencodes 2796e4ece2 [PRISM] Implement once node for interpolated regex
This PR implements the once node on interpolated regexes.

There is a bug in Prism where the interpolated regex with the once flag
only works when there is not a local variable so the test uses a "1".
We'll need to fix that.
2023-11-20 12:42:05 -08:00
Jemma Issroff c5d5929443 [PRISM] Don't pop args to YieldNode 2023-11-20 12:12:34 -08:00
eileencodes 4dd11c067d Switching first argument in pm_interpolated_node_compile
This changes the first argument in `pm_interpolated_node_compile` to use
a pointer.
2023-11-20 07:05:09 -08:00
Jemma Issroff 775ed27d6d [PRISM] Initialize keyword to silence warning 2023-11-13 17:48:55 -05:00
Jemma Issroff ae1fad4cd7 [PRISM] Implement compilation for ForwardingArgumentssNode 2023-11-09 09:45:59 -03:00
Nobuyoshi Nakada 0f02fbd9ff Range check in pm_constant_id_lookup 2023-11-09 18:21:45 +09:00
Nobuyoshi Nakada e824b69a86 Remove useless casts 2023-11-09 18:21:45 +09:00
Matt Valentine-House 5c8d2c2d45 [PRISM] Always lookup idERROR_INFO consistently.
We know where it is in the iseq local table, because we forced it using
`iseq_set_exception_local_table` when compiling the BEGIN_NODE, so we
can always look it up from the same place.

Co-Authored-By Peter Zhu <peter@peterzhu.ca>
2023-11-08 20:28:58 -05:00
Jemma Issroff f9e34a1fd3 [PRISM] Add tests for OptionalKeywordParameterNode
This commit adds tests for the compilation of the
OptionalKeywordParameterNode, and fixes cases on the
RequiredKeywordParameterNode
2023-11-08 18:15:47 -03:00
Jemma Issroff 70e4ff9feb [PRISM] Added tests for ForwardingParameterNode, KeywordRestParameterNode 2023-11-08 18:15:47 -03:00
Jemma Issroff 26cff6ae2b [PRISM] Add tests for several parameters nodes
This commit adds tests for BlockParameterNode, RequiredParameterNode,
RequiredKeywordParameterNode and RestParameterNode
2023-11-08 18:15:47 -03:00
Jemma Issroff bc07b0b9e1 [PRISM] Implement compilation for different parameters
This commit compiles most parameter types, setting appropriate values on
the ISEQ_BODY. It also adds tests for callers and callees of methods,
using many versions of tests from bootstraptest
2023-11-07 15:15:16 -03:00
Matt Valentine-House e7bdd9e498 [PRISM] Move Local table setup into EnsureNode compilation 2023-11-07 14:03:57 +00:00
Matt Valentine-House b7d5a63b9a [PRISM] Don't generate leave insns for Ensure nodes 2023-11-07 14:03:57 +00:00
Matt Valentine-House 8ef7f27321 [PRISM] CompileEnsureNode 2023-11-07 14:03:57 +00:00
Matt Valentine-House 237b85c256 [PRISM] PM_COMPILE into a specified LINK_ANCHOR 2023-11-07 14:03:57 +00:00
Jemma Issroff f6ba87ca88 [PRISM] Implement compilation for MultiWriteNodes, fix MultiTargetNodes
Compilation now works for MultiWriteNodes and MultiTargetNodes, with
nesting on MultiWrites. See the tests added in this commit for example
behavior.
2023-11-06 10:39:07 -03:00
Matt Valentine-House cdb410f688 [PRISM] Fix stack consistency with Popped begin
When a begin node is popped it only needs to putnil if that nil is going
to be the return value, otherwise it can successfully be optimised out.
2023-11-03 15:19:28 +00:00
Matt Valentine-House dcb9ded6c9 [PRISM] Fix CallNode with arguments when popped
Previously emitting a call node with an argument followed by another
node would cause the argument to be mistakenly omitted from the argument
list causing a stack underflow.

```
PRISM: **************************************************
-- raw disasm--------
   0000 putself                                                          (   0)
   0001 send                 <calldata:puts, 1>, nil                     (   0)
*  0004 pop                                                              (   0)
   0005 putobject            1                                           (   0)
   0007 leave                                                            (   0)
---------------------
```
2023-11-03 07:28:05 +00:00
Jemma Issroff c6f5c64639 [PRISM] Fix popped for ForNode 2023-11-02 17:46:43 -03:00
Jemma Issroff 7f18448a8e [PRISM] Fix popped for CallOperatorWriteNode 2023-11-02 17:46:43 -03:00
Jemma Issroff d8bdb15a8b [PRISM] Fix popped for Call{And,Or}WriteNode 2023-11-02 17:46:43 -03:00
Jemma Issroff 5acced49c2 [PRISM] Fix popped for SingletonClassNode 2023-11-02 17:46:43 -03:00
Jemma Issroff 33f18b3d2f [PRISM] Fix popped for CaseNode 2023-11-02 17:46:43 -03:00
Jemma Issroff 62baf723b6 [PRISM] Fix popped for AssocSplatNode 2023-11-02 17:46:43 -03:00
Jemma Issroff 8b4b3b1d38 [PRISM] Fix popped for MatchWriteNode 2023-11-02 17:46:43 -03:00
Jemma Issroff 0359f9ca67 [PRISM] Fix popped for ConstantPathOperatorWriteNode 2023-11-02 17:46:43 -03:00
Jemma Issroff ddf12e8a3b [PRISM] Fix popped for ConstantPathOrWriteNode 2023-11-02 17:46:43 -03:00
Jemma Issroff ca24136da6 [PRISM] Fix popped on DefinedNode 2023-11-02 17:46:43 -03:00
Jemma Issroff 698654ca84 [PRISM] Fixed popped for ConstantPathAndWriteNode 2023-11-02 17:46:43 -03:00
Kevin Newton 717fb5bb0b [prism] Use a pointer for optional node list 2023-11-01 10:36:21 -04:00
Jemma Issroff b7a3e2e71d
[PRISM] Remove unnecessary variable 2023-10-31 15:57:25 -03:00
Jemma Issroff b3744c749d [PRISM] Implement compilation for SuperNode 2023-10-31 13:59:40 -03:00
Jemma Issroff 57748ef2a2 [PRISM] Compile forwarding super node 2023-10-31 13:08:09 -03:00
Jemma Issroff 85ad102532 [PRISM] Implement compilation for PostExecutionNode
This commit implements compilation for the PostExeuctionNode by
using the ScopeNode to create child iseqs where appropriate.
2023-10-31 12:51:06 -03:00
HParker d8a9245513 Add defined array node 2023-10-31 07:01:00 -03:00
HParker b05a7bc512 compile defined with nested constants and stovetop 2023-10-31 07:01:00 -03:00
Matt Valentine-House 962c62057f Fix warning in Prism compile For Node 2023-10-31 09:01:56 +00:00
Jemma Issroff f0b7895637 [PRISM] Implement all argument types for CallNodes 2023-10-30 18:07:04 -03:00
Matt Valentine-House b17b0336b6 Document TEMP_CONSTANT_IDENTIFIER 2023-10-30 19:44:42 +00:00
Matt Valentine-House 9249b8622b Move constant indexing into rb_translate_prism 2023-10-30 19:44:42 +00:00
Matt Valentine-House 5dfba84cff [Prism] Compile ForNode
Fixes ruby/prism#1648
2023-10-30 19:44:42 +00:00
Matt Valentine-House b0f715fa3b More accurate functions documentation 2023-10-30 19:44:42 +00:00
Kevin Newton e3258dd627
Integrate new prism multi target names 2023-10-26 15:03:33 -04:00
eileencodes a082e560bb [PRISM] Implement regex encoding flags
Added the  correct encoding to the allocated regex. This required making
a new method to set the encoding and pass that to `rb_enc_reg_new`
instead of `rb_reg_new`. The former `rb_reg_new` would set the encoding
to ASCII8BIT regardless of encoding flag.
2023-10-26 11:11:52 -07:00
Jemma Issroff 4f8a33eb05 [PRISM] Cleanup macro usage for common ADD_INSN 2023-10-26 12:47:28 -03:00