メソッド引数の処理
pos_num
位置仮引数の数。req の他に optional, rest 引数を含み、子引数(分割代入で用いられる仮引数)は含まない。
ex. def f(a,(b,c),d,e=42,f:100) => pos_num = 4
Caller
- 位置引数を callee のフレームにコピー(あふれた引数はメソッド呼び出しの場合は rest に集める)
- splat 引数を展開
- callerにkeyword 引数・hash splat引数があり、かつcalleeにkeyword 仮引数・keyword rest仮引数がない場合、渡されるkeyword 引数をHashオブジェクトとし、1個の位置引数として引き渡す。
- callee がブロックかつ必須仮引数+rest仮引数が複数の場合、もし引数が1個の Array なら展開する。
- 余ったreqは nil 、余ったoptは None で埋める
- 位置引数の個数をチェックして不正ならエラーを返す
- keyword・hash splat 引数の割り当て
- 余った keyword 引数を keyword rest 仮引数に集める
Callee側の処理
prologue での処理 (InitMethod)
- スタックの調整
- 一時変数スロットを nil で初期化。
bytecode での処理 (bytecode.rs/compile_func())
- 分割代入がある場合は分割されるスロットを再帰的に展開(余った子引数は nil で埋める)
+--------------+
| +----------+----+
a , ( b , c ) , d | |
| | | | | |
v +-+-+ v v v
0 1 2 3 4
- opt引数がある場合は実引数が引き渡されていなければ初期化
<------pos_num------>
<---reqopt_num---->
<-req_num->
+---------+-------+-+----+-+-----+-
| req | opt |r| kw |b|decon|
+---------+-------+-+----+-+-----+-
+---------+-------+---+-----
ARG >= pos_num | ARG |
+---------+-------+---+-----
| | | /
+---------+-------+-+--------
| req | opt |r|
+---------+-------+-+--------
+---------+--+----+-+--------
req_num <= ARG | ARG | 0 | |
+---------+--+----+-+--------
+---------+--+----+=+--------
ARG < req_num | ARG |nil| 0 | |
+---------+--+----+-+--------