Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mruby
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
mruby
Commits
8c9e7127
Commit
8c9e7127
authored
Jul 30, 2018
by
Yukihiro "Matz" Matsumoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Keyword argument implemented.
parent
891839b9
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
887 additions
and
292 deletions
+887
-292
doc/opcode.md
doc/opcode.md
+4
-4
include/mruby/hash.h
include/mruby/hash.h
+25
-2
include/mruby/ops.h
include/mruby/ops.h
+6
-5
mrbgems/mruby-compiler/core/codegen.c
mrbgems/mruby-compiler/core/codegen.c
+114
-35
mrbgems/mruby-compiler/core/node.h
mrbgems/mruby-compiler/core/node.h
+4
-0
mrbgems/mruby-compiler/core/parse.y
mrbgems/mruby-compiler/core/parse.y
+311
-182
mrbgems/mruby-objectspace/src/mruby_objectspace.c
mrbgems/mruby-objectspace/src/mruby_objectspace.c
+1
-1
mrbgems/mruby-proc-ext/src/proc.c
mrbgems/mruby-proc-ext/src/proc.c
+9
-1
src/codedump.c
src/codedump.c
+34
-16
src/hash.c
src/hash.c
+75
-11
src/kernel.c
src/kernel.c
+9
-1
src/vm.c
src/vm.c
+112
-34
test/t/syntax.rb
test/t/syntax.rb
+183
-0
No files found.
doc/opcode.md
View file @
8c9e7127
...
@@ -77,7 +77,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
...
@@ -77,7 +77,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|OP_ARGARY' |BS |R(a) = argument array (16=
6:1:5
:4)
|OP_ARGARY' |BS |R(a) = argument array (16=
5:1:5:1
:4)
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
...
@@ -85,7 +85,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
...
@@ -85,7 +85,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|OP_RETURN' |B |return R(a) (normal)
|OP_RETURN' |B |return R(a) (normal)
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|OP_BREAK' |B |break R(a)
|OP_BREAK' |B |break R(a)
|OP_BLKPUSH' |BS |R(a) = block (16=
6:1:5
:4)
|OP_BLKPUSH' |BS |R(a) = block (16=
5:1:5:1
:4)
|OP_ADD" |BB |R(a) = R(a)+R(a+1) (Syms[b]=:+)
|OP_ADD" |BB |R(a) = R(a)+R(a+1) (Syms[b]=:+)
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c) (Syms[b]=:+)
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c) (Syms[b]=:+)
|OP_SUB" |BB |R(a) = R(a)-R(a+1) (Syms[b]=:-)
|OP_SUB" |BB |R(a) = R(a)-R(a+1) (Syms[b]=:-)
...
@@ -207,7 +207,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
...
@@ -207,7 +207,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|OP_ARGARY' |BS |R(a) = argument array (16=
6:1:5
:4)
|OP_ARGARY' |BS |R(a) = argument array (16=
5:1:5:1
:4)
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
...
@@ -215,7 +215,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
...
@@ -215,7 +215,7 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|OP_RETURN' |B |return R(a) (normal)
|OP_RETURN' |B |return R(a) (normal)
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|OP_BREAK' |B |break R(a)
|OP_BREAK' |B |break R(a)
|OP_BLKPUSH' |BS |R(a) = block (16=
6:1:5
:4)
|OP_BLKPUSH' |BS |R(a) = block (16=
5:1:5:1
:4)
|OP_ADD" |BB |R(a) = R(a)+R(a+1) (Syms[b]=:+)
|OP_ADD" |BB |R(a) = R(a)+R(a+1) (Syms[b]=:+)
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c) (Syms[b]=:+)
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c) (Syms[b]=:+)
|OP_SUB" |BB |R(a) = R(a)-R(a+1) (Syms[b]=:-)
|OP_SUB" |BB |R(a) = R(a)-R(a+1) (Syms[b]=:-)
...
...
include/mruby/hash.h
View file @
8c9e7127
...
@@ -25,6 +25,7 @@ struct RHash {
...
@@ -25,6 +25,7 @@ struct RHash {
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
MRB_API
mrb_value
mrb_hash_new_capa
(
mrb_state
*
,
mrb_int
);
MRB_API
mrb_value
mrb_hash_new_capa
(
mrb_state
*
,
mrb_int
);
MRB_API
mrb_value
mrb_check_hash_type
(
mrb_state
*
mrb
,
mrb_value
hash
);
/*
/*
* Initializes a new hash.
* Initializes a new hash.
...
@@ -110,7 +111,19 @@ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value
...
@@ -110,7 +111,19 @@ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value
* @return An array with the keys of the hash.
* @return An array with the keys of the hash.
*/
*/
MRB_API
mrb_value
mrb_hash_keys
(
mrb_state
*
mrb
,
mrb_value
hash
);
MRB_API
mrb_value
mrb_hash_keys
(
mrb_state
*
mrb
,
mrb_value
hash
);
MRB_API
mrb_value
mrb_check_hash_type
(
mrb_state
*
mrb
,
mrb_value
hash
);
/*
* Check if the hash has the key.
*
* Equivalent to:
*
* hash.key?(key)
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @param key The key to check existence.
* @return True if the hash has the key
*/
MRB_API
mrb_bool
mrb_hash_key_p
(
mrb_state
*
mrb
,
mrb_value
hash
,
mrb_value
key
);
/*
/*
* Check if the hash is empty
* Check if the hash is empty
...
@@ -123,7 +136,7 @@ MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
...
@@ -123,7 +136,7 @@ MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
* @param self The target hash.
* @param self The target hash.
* @return True if the hash is empty, false otherwise.
* @return True if the hash is empty, false otherwise.
*/
*/
MRB_API
mrb_
value
mrb_hash_empty_p
(
mrb_state
*
mrb
,
mrb_value
self
);
MRB_API
mrb_
bool
mrb_hash_empty_p
(
mrb_state
*
mrb
,
mrb_value
self
);
/*
/*
* Gets an array of values.
* Gets an array of values.
...
@@ -151,6 +164,16 @@ MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash);
...
@@ -151,6 +164,16 @@ MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash);
*/
*/
MRB_API
mrb_value
mrb_hash_clear
(
mrb_state
*
mrb
,
mrb_value
hash
);
MRB_API
mrb_value
mrb_hash_clear
(
mrb_state
*
mrb
,
mrb_value
hash
);
/*
* Copies the hash.
*
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @return The copy of the hash
*/
MRB_API
mrb_value
mrb_hash_dup
(
mrb_state
*
mrb
,
mrb_value
hash
);
/* declaration of struct kh_ht */
/* declaration of struct kh_ht */
/* be careful when you touch the internal */
/* be careful when you touch the internal */
typedef
struct
{
typedef
struct
{
...
...
include/mruby/ops.h
View file @
8c9e7127
...
@@ -61,15 +61,16 @@ OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */
...
@@ -61,15 +61,16 @@ OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */
OPCODE
(
SENDB
,
BBB
)
/* R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1)) */
OPCODE
(
SENDB
,
BBB
)
/* R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1)) */
OPCODE
(
CALL
,
Z
)
/* R(0) = self.call(frame.argc, frame.argv) */
OPCODE
(
CALL
,
Z
)
/* R(0) = self.call(frame.argc, frame.argv) */
OPCODE
(
SUPER
,
BB
)
/* R(a) = super(R(a+1),... ,R(a+b+1)) */
OPCODE
(
SUPER
,
BB
)
/* R(a) = super(R(a+1),... ,R(a+b+1)) */
OPCODE
(
ARGARY
,
BS
)
/* R(a) = argument array (16=6:1:5:4) */
OPCODE
(
ARGARY
,
BS
)
/* R(a) = argument array (16=m5:r1:m5:d1:lv4) */
OPCODE
(
ENTER
,
W
)
/* arg setup according to flags (23=5:5:1:5:5:1:1) */
OPCODE
(
ENTER
,
W
)
/* arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1) */
OPCODE
(
KARG
,
BB
)
/* R(a) = kdict[Syms(Bx)] # todo */
OPCODE
(
KEY_P
,
BB
)
/* R(a) = kdict.key?(Syms(b)) # todo */
OPCODE
(
KARG2
,
BB
)
/* R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo */
OPCODE
(
KEYEND
,
Z
)
/* raise unless kdict.empty? # todo */
OPCODE
(
KARG
,
BB
)
/* R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) # todo */
OPCODE
(
KDICT
,
B
)
/* R(a) = kdict # todo */
OPCODE
(
KDICT
,
B
)
/* R(a) = kdict # todo */
OPCODE
(
RETURN
,
B
)
/* return R(a) (normal) */
OPCODE
(
RETURN
,
B
)
/* return R(a) (normal) */
OPCODE
(
RETURN_BLK
,
B
)
/* return R(a) (in-block return) */
OPCODE
(
RETURN_BLK
,
B
)
/* return R(a) (in-block return) */
OPCODE
(
BREAK
,
B
)
/* break R(a) */
OPCODE
(
BREAK
,
B
)
/* break R(a) */
OPCODE
(
BLKPUSH
,
BS
)
/* R(a) = block (16=
6:1:5:
4) */
OPCODE
(
BLKPUSH
,
BS
)
/* R(a) = block (16=
m5:r1:m5:d1:lv
4) */
OPCODE
(
ADD
,
BB
)
/* R(a) = R(a)+R(a+1) (Syms[b]=:+) */
OPCODE
(
ADD
,
BB
)
/* R(a) = R(a)+R(a+1) (Syms[b]=:+) */
OPCODE
(
ADDI
,
BBB
)
/* R(a) = R(a)+mrb_int(c) (Syms[b]=:+) */
OPCODE
(
ADDI
,
BBB
)
/* R(a) = R(a)+mrb_int(c) (Syms[b]=:+) */
OPCODE
(
SUB
,
BB
)
/* R(a) = R(a)-R(a+1) (Syms[b]=:-) */
OPCODE
(
SUB
,
BB
)
/* R(a) = R(a)-R(a+1) (Syms[b]=:-) */
...
...
mrbgems/mruby-compiler/core/codegen.c
View file @
8c9e7127
...
@@ -420,6 +420,9 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
...
@@ -420,6 +420,9 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
if
(
no_peephole
(
s
))
{
if
(
no_peephole
(
s
))
{
normal:
normal:
genop_2
(
s
,
OP_MOVE
,
dst
,
src
);
genop_2
(
s
,
OP_MOVE
,
dst
,
src
);
if
(
on_eval
(
s
))
{
genop_0
(
s
,
OP_NOP
);
}
return
;
return
;
}
}
else
{
else
{
...
@@ -453,6 +456,25 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
...
@@ -453,6 +456,25 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
}
}
}
}
static
void
gen_return
(
codegen_scope
*
s
,
uint8_t
op
,
uint16_t
src
)
{
if
(
no_peephole
(
s
))
{
genop_1
(
s
,
op
,
src
);
}
else
{
struct
mrb_insn_data
data
=
mrb_last_insn
(
s
);
if
(
data
.
insn
==
OP_MOVE
&&
src
==
data
.
a
)
{
s
->
pc
=
s
->
lastpc
;
genop_1
(
s
,
op
,
data
.
b
);
}
else
{
genop_1
(
s
,
op
,
src
);
}
}
}
static
void
static
void
gen_addsub
(
codegen_scope
*
s
,
uint8_t
op
,
uint16_t
dst
,
uint16_t
idx
)
gen_addsub
(
codegen_scope
*
s
,
uint8_t
op
,
uint16_t
dst
,
uint16_t
idx
)
{
{
...
@@ -514,30 +536,28 @@ dispatch_linked(codegen_scope *s, uint16_t pos)
...
@@ -514,30 +536,28 @@ dispatch_linked(codegen_scope *s, uint16_t pos)
#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
static
void
static
void
push_
(
codegen_scope
*
s
)
push_
n_
(
codegen_scope
*
s
,
int
n
)
{
{
if
(
s
->
sp
>=
0xffff
)
{
if
(
s
->
sp
+
n
>=
0xffff
)
{
codegen_error
(
s
,
"too complex expression"
);
codegen_error
(
s
,
"too complex expression"
);
}
}
s
->
sp
+
+
;
s
->
sp
+
=
n
;
nregs_update
;
nregs_update
;
}
}
static
void
static
void
p
ush
_n_
(
codegen_scope
*
s
,
int
n
)
p
op
_n_
(
codegen_scope
*
s
,
int
n
)
{
{
if
(
s
->
sp
+
n
>=
0xffff
)
{
if
(
(
int
)
s
->
sp
-
n
<
0
)
{
codegen_error
(
s
,
"
too complex expression
"
);
codegen_error
(
s
,
"
stack pointer underflow
"
);
}
}
s
->
sp
+=
n
;
s
->
sp
-=
n
;
nregs_update
;
}
}
#define push() push_
(s
)
#define push() push_
n_(s,1
)
#define push_n(n) push_n_(s,n)
#define push_n(n) push_n_(s,n)
#define pop_(s) ((s)->sp--)
#define pop() pop_n_(s,1)
#define pop() pop_(s)
#define pop_n(n) pop_n_(s,n)
#define pop_n(n) (s->sp-=(n))
#define cursp() (s->sp)
#define cursp() (s->sp)
static
inline
int
static
inline
int
...
@@ -644,8 +664,12 @@ node_len(node *tree)
...
@@ -644,8 +664,12 @@ node_len(node *tree)
return
n
;
return
n
;
}
}
#define nint(x) ((int)(intptr_t)(x))
#define nchar(x) ((char)(intptr_t)(x))
#define nsym(x) ((mrb_sym)(intptr_t)(x))
#define nsym(x) ((mrb_sym)(intptr_t)(x))
#define lv_name(lv) nsym((lv)->car)
#define lv_name(lv) nsym((lv)->car)
static
int
static
int
lv_idx
(
codegen_scope
*
s
,
mrb_sym
id
)
lv_idx
(
codegen_scope
*
s
,
mrb_sym
id
)
{
{
...
@@ -694,7 +718,7 @@ for_body(codegen_scope *s, node *tree)
...
@@ -694,7 +718,7 @@ for_body(codegen_scope *s, node *tree)
/* loop body */
/* loop body */
codegen
(
s
,
tree
->
cdr
->
cdr
->
car
,
VAL
);
codegen
(
s
,
tree
->
cdr
->
cdr
->
car
,
VAL
);
pop
();
pop
();
gen
op_1
(
s
,
OP_RETURN
,
cursp
());
gen
_return
(
s
,
OP_RETURN
,
cursp
());
loop_pop
(
s
,
NOVAL
);
loop_pop
(
s
,
NOVAL
);
scope_finish
(
s
);
scope_finish
(
s
);
s
=
prev
;
s
=
prev
;
...
@@ -726,32 +750,44 @@ lambda_body(codegen_scope *s, node *tree, int blk)
...
@@ -726,32 +750,44 @@ lambda_body(codegen_scope *s, node *tree, int blk)
int
ma
,
oa
,
ra
,
pa
,
ka
,
kd
,
ba
;
int
ma
,
oa
,
ra
,
pa
,
ka
,
kd
,
ba
;
int
pos
,
i
;
int
pos
,
i
;
node
*
n
,
*
opt
;
node
*
n
,
*
opt
;
node
*
tail
;
/* mandatory arguments */
ma
=
node_len
(
tree
->
car
->
car
);
ma
=
node_len
(
tree
->
car
->
car
);
n
=
tree
->
car
->
car
;
n
=
tree
->
car
->
car
;
while
(
n
)
{
while
(
n
)
{
n
=
n
->
cdr
;
n
=
n
->
cdr
;
}
}
tail
=
tree
->
car
->
cdr
->
cdr
->
cdr
->
cdr
;
/* optional arguments */
oa
=
node_len
(
tree
->
car
->
cdr
->
car
);
oa
=
node_len
(
tree
->
car
->
cdr
->
car
);
/* rest argument? */
ra
=
tree
->
car
->
cdr
->
cdr
->
car
?
1
:
0
;
ra
=
tree
->
car
->
cdr
->
cdr
->
car
?
1
:
0
;
/* mandatory arugments after rest argument */
pa
=
node_len
(
tree
->
car
->
cdr
->
cdr
->
cdr
->
car
);
pa
=
node_len
(
tree
->
car
->
cdr
->
cdr
->
cdr
->
car
);
ka
=
kd
=
0
;
/* keyword arguments */
ba
=
tree
->
car
->
cdr
->
cdr
->
cdr
->
cdr
?
1
:
0
;
ka
=
tail
?
node_len
(
tail
->
cdr
->
car
)
:
0
;
/* keyword dictionary? */
kd
=
tail
&&
tail
->
cdr
->
cdr
->
car
?
1
:
0
;
/* block argument? */
ba
=
tail
&&
tail
->
cdr
->
cdr
->
cdr
->
car
?
1
:
0
;
if
(
ma
>
0x1f
||
oa
>
0x1f
||
pa
>
0x1f
||
ka
>
0x1f
)
{
if
(
ma
>
0x1f
||
oa
>
0x1f
||
pa
>
0x1f
||
ka
>
0x1f
)
{
codegen_error
(
s
,
"too many formal arguments"
);
codegen_error
(
s
,
"too many formal arguments"
);
}
}
a
=
((
mrb_aspec
)(
ma
&
0x1f
)
<<
18
)
a
=
MRB_ARGS_REQ
(
ma
)
|
((
mrb_aspec
)(
oa
&
0x1f
)
<<
13
)
|
MRB_ARGS_OPT
(
oa
)
|
(
(
ra
&
1
)
<<
12
)
|
(
ra
?
MRB_ARGS_REST
()
:
0
)
|
((
pa
&
0x1f
)
<<
7
)
|
MRB_ARGS_POST
(
pa
)
|
((
ka
&
0x1f
)
<<
2
)
|
MRB_ARGS_KEY
(
ka
,
kd
)
|
(
(
kd
&
1
)
<<
1
)
|
(
ba
?
MRB_ARGS_BLOCK
()
:
0
);
|
(
ba
&
1
);
s
->
ainfo
=
(((
ma
+
oa
)
&
0x3f
)
<<
7
)
/* (12bits = 5:1:5:1) */
s
->
ainfo
=
(((
ma
+
oa
)
&
0x3f
)
<<
6
)
/* (12bits = 6:1:5) */
|
((
ra
&
0x1
)
<<
6
)
|
((
ra
&
1
)
<<
5
)
|
((
pa
&
0x1f
)
<<
1
)
|
(
pa
&
0x1f
);
|
(
kd
&
0x1
);
genop_W
(
s
,
OP_ENTER
,
a
);
genop_W
(
s
,
OP_ENTER
,
a
);
/* generate jump table for optional arguments initializer */
pos
=
new_label
(
s
);
pos
=
new_label
(
s
);
for
(
i
=
0
;
i
<
oa
;
i
++
)
{
for
(
i
=
0
;
i
<
oa
;
i
++
)
{
new_label
(
s
);
new_label
(
s
);
...
@@ -776,11 +812,50 @@ lambda_body(codegen_scope *s, node *tree, int blk)
...
@@ -776,11 +812,50 @@ lambda_body(codegen_scope *s, node *tree, int blk)
if
(
oa
>
0
)
{
if
(
oa
>
0
)
{
dispatch
(
s
,
pos
+
i
*
3
+
1
);
dispatch
(
s
,
pos
+
i
*
3
+
1
);
}
}
if
(
tail
)
{
node
*
kwds
=
tail
->
cdr
->
car
;
int
kwrest
=
0
;
if
(
tail
->
cdr
->
cdr
->
car
)
{
kwrest
=
1
;
}
mrb_assert
(
nint
(
tail
->
car
)
==
NODE_ARGS_TAIL
);
mrb_assert
(
node_len
(
tail
)
==
4
);
while
(
kwds
)
{
int
jmpif_key_p
,
jmp_def_set
=
-
1
;
node
*
kwd
=
kwds
->
car
,
*
def_arg
=
kwd
->
cdr
->
cdr
->
car
;
mrb_sym
kwd_sym
=
nsym
(
kwd
->
cdr
->
car
);
mrb_assert
(
nint
(
kwd
->
car
)
==
NODE_KW_ARG
);
if
(
def_arg
)
{
genop_2
(
s
,
OP_KEY_P
,
cursp
(),
new_sym
(
s
,
kwd_sym
));
jmpif_key_p
=
genjmp2
(
s
,
OP_JMPIF
,
cursp
(),
0
,
0
);
codegen
(
s
,
def_arg
,
VAL
);
pop
();
gen_move
(
s
,
lv_idx
(
s
,
kwd_sym
),
cursp
(),
0
);
jmp_def_set
=
genjmp
(
s
,
OP_JMP
,
0
);
dispatch
(
s
,
jmpif_key_p
);
}
genop_2
(
s
,
OP_KARG
,
lv_idx
(
s
,
kwd_sym
),
new_sym
(
s
,
kwd_sym
));
if
(
jmp_def_set
!=
-
1
)
{
dispatch
(
s
,
jmp_def_set
);
}
i
++
;
kwds
=
kwds
->
cdr
;
}
if
(
tail
->
cdr
->
car
&&
!
kwrest
)
{
genop_0
(
s
,
OP_KEYEND
);
}
}
}
}
codegen
(
s
,
tree
->
cdr
->
car
,
VAL
);
codegen
(
s
,
tree
->
cdr
->
car
,
VAL
);
pop
();
pop
();
if
(
s
->
pc
>
0
)
{
if
(
s
->
pc
>
0
)
{
gen
op_1
(
s
,
OP_RETURN
,
cursp
());
gen
_return
(
s
,
OP_RETURN
,
cursp
());
}
}
if
(
blk
)
{
if
(
blk
)
{
loop_pop
(
s
,
NOVAL
);
loop_pop
(
s
,
NOVAL
);
...
@@ -798,7 +873,7 @@ scope_body(codegen_scope *s, node *tree, int val)
...
@@ -798,7 +873,7 @@ scope_body(codegen_scope *s, node *tree, int val)
}
}
codegen
(
scope
,
tree
->
cdr
,
VAL
);
codegen
(
scope
,
tree
->
cdr
,
VAL
);
gen
op_1
(
scope
,
OP_RETURN
,
scope
->
sp
-
1
);
gen
_return
(
scope
,
OP_RETURN
,
scope
->
sp
-
1
);
if
(
!
s
->
iseq
)
{
if
(
!
s
->
iseq
)
{
genop_0
(
scope
,
OP_STOP
);
genop_0
(
scope
,
OP_STOP
);
}
}
...
@@ -810,9 +885,6 @@ scope_body(codegen_scope *s, node *tree, int val)
...
@@ -810,9 +885,6 @@ scope_body(codegen_scope *s, node *tree, int val)
return
s
->
irep
->
rlen
-
1
;
return
s
->
irep
->
rlen
-
1
;
}
}
#define nint(x) ((int)(intptr_t)(x))
#define nchar(x) ((char)(intptr_t)(x))
static
mrb_bool
static
mrb_bool
nosplat
(
node
*
t
)
nosplat
(
node
*
t
)
{
{
...
@@ -1703,11 +1775,18 @@ codegen(codegen_scope *s, node *tree, int val)
...
@@ -1703,11 +1775,18 @@ codegen(codegen_scope *s, node *tree, int val)
break
;
break
;
case
NODE_HASH
:
case
NODE_HASH
:
case
NODE_KW_HASH
:
{
{
int
len
=
0
;
int
len
=
0
;
mrb_bool
update
=
FALSE
;
mrb_bool
update
=
FALSE
;
while
(
tree
)
{
while
(
tree
)
{
if
(
nt
==
NODE_KW_HASH
&&
nint
(
tree
->
car
->
car
->
car
)
==
NODE_KW_REST_ARGS
)
{
tree
=
tree
->
cdr
;
continue
;
}
codegen
(
s
,
tree
->
car
->
car
,
val
);
codegen
(
s
,
tree
->
car
->
car
,
val
);
codegen
(
s
,
tree
->
car
->
cdr
,
val
);
codegen
(
s
,
tree
->
car
->
cdr
,
val
);
len
++
;
len
++
;
...
@@ -2055,10 +2134,10 @@ codegen(codegen_scope *s, node *tree, int val)
...
@@ -2055,10 +2134,10 @@ codegen(codegen_scope *s, node *tree, int val)
genop_1
(
s
,
OP_LOADNIL
,
cursp
());
genop_1
(
s
,
OP_LOADNIL
,
cursp
());
}
}
if
(
s
->
loop
)
{
if
(
s
->
loop
)
{
gen
op_1
(
s
,
OP_RETURN_BLK
,
cursp
());
gen
_return
(
s
,
OP_RETURN_BLK
,
cursp
());
}
}
else
{
else
{
gen
op_1
(
s
,
OP_RETURN
,
cursp
());
gen
_return
(
s
,
OP_RETURN
,
cursp
());
}
}
if
(
val
)
push
();
if
(
val
)
push
();
break
;
break
;
...
@@ -2116,7 +2195,7 @@ codegen(codegen_scope *s, node *tree, int val)
...
@@ -2116,7 +2195,7 @@ codegen(codegen_scope *s, node *tree, int val)
else
{
else
{
genop_1
(
s
,
OP_LOADNIL
,
cursp
());
genop_1
(
s
,
OP_LOADNIL
,
cursp
());
}
}
gen
op_1
(
s
,
OP_RETURN
,
cursp
());
gen
_return
(
s
,
OP_RETURN
,
cursp
());
}
}
if
(
val
)
push
();
if
(
val
)
push
();
break
;
break
;
...
@@ -2999,7 +3078,7 @@ loop_break(codegen_scope *s, node *tree)
...
@@ -2999,7 +3078,7 @@ loop_break(codegen_scope *s, node *tree)
if
(
!
tree
)
{
if
(
!
tree
)
{
genop_1
(
s
,
OP_LOADNIL
,
cursp
());
genop_1
(
s
,
OP_LOADNIL
,
cursp
());
}
}
gen
op_1
(
s
,
OP_BREAK
,
cursp
());
gen
_return
(
s
,
OP_BREAK
,
cursp
());
}
}
}
}
}
}
...
...
mrbgems/mruby-compiler/core/node.h
View file @
8c9e7127
...
@@ -46,6 +46,7 @@ enum node_type {
...
@@ -46,6 +46,7 @@ enum node_type {
NODE_ARRAY
,
NODE_ARRAY
,
NODE_ZARRAY
,
NODE_ZARRAY
,
NODE_HASH
,
NODE_HASH
,
NODE_KW_HASH
,
NODE_RETURN
,
NODE_RETURN
,
NODE_YIELD
,
NODE_YIELD
,
NODE_LVAR
,
NODE_LVAR
,
...
@@ -73,6 +74,9 @@ enum node_type {
...
@@ -73,6 +74,9 @@ enum node_type {
NODE_DREGX_ONCE
,
NODE_DREGX_ONCE
,
NODE_LIST
,
NODE_LIST
,
NODE_ARG
,
NODE_ARG
,
NODE_ARGS_TAIL
,
NODE_KW_ARG
,
NODE_KW_REST_ARGS
,
NODE_ARGSCAT
,
NODE_ARGSCAT
,
NODE_ARGSPUSH
,
NODE_ARGSPUSH
,
NODE_SPLAT
,
NODE_SPLAT
,
...
...
mrbgems/mruby-compiler/core/parse.y
View file @
8c9e7127
...
@@ -568,6 +568,13 @@ new_hash(parser_state *p, node *a)
...
@@ -568,6 +568,13 @@ new_hash(parser_state *p, node *a)
return cons((node*)NODE_HASH, a);
return cons((node*)NODE_HASH, a);
}
}
/* (:kw_hash (k . v) (k . v)...) */
static node*
new_kw_hash(parser_state *p, node *a)
{
return cons((node*)NODE_KW_HASH, a);
}
/* (:sym . a) */
/* (:sym . a) */
static node*
static node*
new_sym(parser_state *p, mrb_sym sym)
new_sym(parser_state *p, mrb_sym sym)
...
@@ -671,23 +678,61 @@ new_arg(parser_state *p, mrb_sym sym)
...
@@ -671,23 +678,61 @@ new_arg(parser_state *p, mrb_sym sym)
return cons((node*)NODE_ARG, nsym(sym));
return cons((node*)NODE_ARG, nsym(sym));
}
}
/* (m o r m2
b
) */
/* (m o r m2
tail
) */
/* m: (a b c) */
/* m: (a b c) */
/* o: ((a . e1) (b . e2)) */
/* o: ((a . e1) (b . e2)) */
/* r: a */
/* r: a */
/* m2: (a b c) */
/* m2: (a b c) */
/* b: a */
/* b: a */
static node*
static node*
new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2,
mrb_sym blk
)
new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2,
node *tail
)
{
{
node *n;
node *n;
n = cons(m2,
nsym(blk)
);
n = cons(m2,
tail
);
n = cons(nsym(rest), n);
n = cons(nsym(rest), n);
n = cons(opt, n);
n = cons(opt, n);
return cons(m, n);
return cons(m, n);
}
}
/* (:args_tail keywords rest_keywords_sym block_sym) */
static node*
new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
{
node *k;
/* allocate register for keywords hash */
if (kws || kwrest) {
local_add_f(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : mrb_intern_lit(p->mrb, "**"));
}
/* allocate register for block */
local_add_f(p, blk? blk : mrb_intern_lit(p->mrb, "&"));
// allocate register for keywords arguments
// order is for Proc#parameters
for (k = kws; k; k = k->cdr) {
if (!k->car->cdr->cdr->car) { // allocate required keywords
local_add_f(p, sym(k->car->cdr->car));
}
}
for (k = kws; k; k = k->cdr) {
if (k->car->cdr->cdr->car) { // allocate keywords with default
local_add_f(p, sym(k->car->cdr->car));
}
}
return list4((node*)NODE_ARGS_TAIL, kws, kwrest, nsym(blk));
}
/* (:kw_arg kw_sym def_arg) */
static node*
new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
{
mrb_assert(kw);
return list3((node*)NODE_KW_ARG, nsym(kw), def_arg);
}
/* (:block_arg . a) */
/* (:block_arg . a) */
static node*
static node*
new_block_arg(parser_state *p, node *a)
new_block_arg(parser_state *p, node *a)
...
@@ -1134,6 +1179,10 @@ heredoc_end(parser_state *p)
...
@@ -1134,6 +1179,10 @@ heredoc_end(parser_state *p)
%type <nd> heredoc words symbols
%type <nd> heredoc words symbols
%type <num> call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */
%type <num> call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */
%type <nd> args_tail opt_args_tail f_kwarg f_kw arg_value f_kwrest
%type <nd> f_block_kwarg f_block_kw block_args_tail opt_block_args_tail
%type <id> f_label
%token tUPLUS /* unary+ */
%token tUPLUS /* unary+ */
%token tUMINUS /* unary- */
%token tUMINUS /* unary- */
%token tPOW /* ** */
%token tPOW /* ** */
...
@@ -1159,6 +1208,7 @@ heredoc_end(parser_state *p)
...
@@ -1159,6 +1208,7 @@ heredoc_end(parser_state *p)
%token tLBRACE /* { */
%token tLBRACE /* { */
%token tLBRACE_ARG /* { */
%token tLBRACE_ARG /* { */
%token tSTAR /* * */
%token tSTAR /* * */
%token tDSTAR /* ** */
%token tAMPER /* & */
%token tAMPER /* & */
%token tLAMBDA /* -> */
%token tLAMBDA /* -> */
%token tANDDOT /* &. */
%token tANDDOT /* &. */
...
@@ -1736,6 +1786,7 @@ op : '|' { $$ = intern_c('|'); }
...
@@ -1736,6 +1786,7 @@ op : '|' { $$ = intern_c('|'); }
| '/' { $$ = intern_c('/'); }
| '/' { $$ = intern_c('/'); }
| '%' { $$ = intern_c('%'); }
| '%' { $$ = intern_c('%'); }
| tPOW { $$ = intern("**",2); }
| tPOW { $$ = intern("**",2); }
| tDSTAR { $$ = intern("**",2); }
| '!' { $$ = intern_c('!'); }
| '!' { $$ = intern_c('!'); }
| '~' { $$ = intern_c('~'); }
| '~' { $$ = intern_c('~'); }
| tUPLUS { $$ = intern("+@",2); }
| tUPLUS { $$ = intern("+@",2); }
...
@@ -1944,11 +1995,11 @@ aref_args : none
...
@@ -1944,11 +1995,11 @@ aref_args : none
}
}
| args comma assocs trailer
| args comma assocs trailer
{
{
$$ = push($1, new_hash(p, $3));
$$ = push($1, new_
kw_
hash(p, $3));
}
}
| assocs trailer
| assocs trailer
{
{
$$ = cons(new_hash(p, $1), 0);
$$ = cons(new_
kw_
hash(p, $1), 0);
NODE_LINENO($$, $1);
NODE_LINENO($$, $1);
}
}
;
;
...
@@ -1984,12 +2035,12 @@ opt_call_args : none
...
@@ -1984,12 +2035,12 @@ opt_call_args : none
}
}
| args comma assocs ','
| args comma assocs ','
{
{
$$ = cons(push($1, new_hash(p, $3)), 0);
$$ = cons(push($1, new_
kw_
hash(p, $3)), 0);
NODE_LINENO($$, $1);
NODE_LINENO($$, $1);
}
}
| assocs ','
| assocs ','
{
{
$$ = cons(list1(new_hash(p, $1)), 0);
$$ = cons(list1(new_
kw_
hash(p, $1)), 0);
NODE_LINENO($$, $1);
NODE_LINENO($$, $1);
}
}
;
;
...
@@ -2007,12 +2058,12 @@ call_args : command
...
@@ -2007,12 +2058,12 @@ call_args : command
}
}
| assocs opt_block_arg
| assocs opt_block_arg
{
{
$$ = cons(list1(new_hash(p, $1)), $2);
$$ = cons(list1(new_
kw_
hash(p, $1)), $2);
NODE_LINENO($$, $1);
NODE_LINENO($$, $1);
}
}
| args comma assocs opt_block_arg
| args comma assocs opt_block_arg
{
{
$$ = cons(push($1, new_hash(p, $3)), $4);
$$ = cons(push($1, new_
kw_
hash(p, $3)), $4);
NODE_LINENO($$, $1);
NODE_LINENO($$, $1);
}
}
| block_arg
| block_arg
...
@@ -2451,23 +2502,51 @@ f_margs : f_marg_list
...
@@ -2451,23 +2502,51 @@ f_margs : f_marg_list
}
}
;
;
block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, $3, $4);
}
| f_block_kwarg opt_f_block_arg
{
$$ = new_args_tail(p, $1, 0, $2);
}
| f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, 0, $1, $2);
}
| f_block_arg
{
$$ = new_args_tail(p, 0, 0, $1);
}
;
opt_block_args_tail : ',' block_args_tail
{
$$ = $2;
}
| /* none */
{
$$ = new_args_tail(p, 0, 0, 0);
}
;
block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
{
{
$$ = new_args(p, $1, $3, $5, 0, $6);
$$ = new_args(p, $1, $3, $5, 0, $6);
}
}
| f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_
f_block_arg
| f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_
block_args_tail
{
{
$$ = new_args(p, $1, $3, $5, $7, $8);
$$ = new_args(p, $1, $3, $5, $7, $8);
}
}
| f_arg ',' f_block_optarg opt_
f_block_arg
| f_arg ',' f_block_optarg opt_
block_args_tail
{
{
$$ = new_args(p, $1, $3, 0, 0, $4);
$$ = new_args(p, $1, $3, 0, 0, $4);
}
}
| f_arg ',' f_block_optarg ',' f_arg opt_
f_block_arg
| f_arg ',' f_block_optarg ',' f_arg opt_
block_args_tail
{
{
$$ = new_args(p, $1, $3, 0, $5, $6);
$$ = new_args(p, $1, $3, 0, $5, $6);
}
}
| f_arg ',' f_rest_arg opt_
f_block_arg
| f_arg ',' f_rest_arg opt_
block_args_tail
{
{
$$ = new_args(p, $1, 0, $3, 0, $4);
$$ = new_args(p, $1, 0, $3, 0, $4);
}
}
...
@@ -2475,39 +2554,39 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
...
@@ -2475,39 +2554,39 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
{
{
$$ = new_args(p, $1, 0, 0, 0, 0);
$$ = new_args(p, $1, 0, 0, 0, 0);
}
}
| f_arg ',' f_rest_arg ',' f_arg opt_
f_block_arg
| f_arg ',' f_rest_arg ',' f_arg opt_
block_args_tail
{
{
$$ = new_args(p, $1, 0, $3, $5, $6);
$$ = new_args(p, $1, 0, $3, $5, $6);
}
}
| f_arg opt_
f_block_arg
| f_arg opt_
block_args_tail
{
{
$$ = new_args(p, $1, 0, 0, 0, $2);
$$ = new_args(p, $1, 0, 0, 0, $2);
}
}
| f_block_optarg ',' f_rest_arg opt_
f_block_arg
| f_block_optarg ',' f_rest_arg opt_
block_args_tail
{
{
$$ = new_args(p, 0, $1, $3, 0, $4);
$$ = new_args(p, 0, $1, $3, 0, $4);
}
}
| f_block_optarg ',' f_rest_arg ',' f_arg opt_
f_block_arg
| f_block_optarg ',' f_rest_arg ',' f_arg opt_
block_args_tail
{
{
$$ = new_args(p, 0, $1, $3, $5, $6);
$$ = new_args(p, 0, $1, $3, $5, $6);
}
}
| f_block_optarg opt_
f_block_arg
| f_block_optarg opt_
block_args_tail
{
{
$$ = new_args(p, 0, $1, 0, 0, $2);
$$ = new_args(p, 0, $1, 0, 0, $2);
}
}
| f_block_optarg ',' f_arg opt_
f_block_arg
| f_block_optarg ',' f_arg opt_
block_args_tail
{
{
$$ = new_args(p, 0, $1, 0, $3, $4);
$$ = new_args(p, 0, $1, 0, $3, $4);
}
}
| f_rest_arg opt_
f_block_arg
| f_rest_arg opt_
block_args_tail
{
{
$$ = new_args(p, 0, 0, $1, 0, $2);
$$ = new_args(p, 0, 0, $1, 0, $2);
}
}
| f_rest_arg ',' f_arg opt_
f_block_arg
| f_rest_arg ',' f_arg opt_
block_args_tail
{
{
$$ = new_args(p, 0, 0, $1, $3, $4);
$$ = new_args(p, 0, 0, $1, $3, $4);
}
}
|
f_block_arg
|
block_args_tail
{
{
$$ = new_args(p, 0, 0, 0, 0, $1);
$$ = new_args(p, 0, 0, 0, 0, $1);
}
}
...
@@ -3021,65 +3100,153 @@ f_arglist : '(' f_args rparen
...
@@ -3021,65 +3100,153 @@ f_arglist : '(' f_args rparen
}
}
;
;
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
f_label : tIDENTIFIER tLABEL_TAG
;
arg_value : arg
;
f_kw : f_label arg_value
{
$$ = new_kw_arg(p, $1, $2);
}
| f_label
{
$$ = new_kw_arg(p, $1, 0);
}
;
f_block_kw : f_label primary_value
{
$$ = new_kw_arg(p, $1, $2);
}
| f_label
{
$$ = new_kw_arg(p, $1, 0);
}
;
f_block_kwarg : f_block_kw
{
$$ = list1($1);
}
| f_block_kwarg ',' f_block_kw
{
$$ = push($1, $3);
}
;
f_kwarg : f_kw
{
$$ = list1($1);
}
| f_kwarg ',' f_kw
{
$$ = push($1, $3);
}
;
kwrest_mark : tPOW
| tDSTAR
;
f_kwrest : kwrest_mark tIDENTIFIER
{
$$ = cons((node*)NODE_KW_REST_ARGS, nsym($2));
}
| kwrest_mark
{
$$ = cons((node*)NODE_KW_REST_ARGS, 0);
}
;
args_tail : f_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, $3, $4);
}
| f_kwarg opt_f_block_arg
{
$$ = new_args_tail(p, $1, 0, $2);
}
| f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, 0, $1, $2);
}
| f_block_arg
{
$$ = new_args_tail(p, 0, 0, $1);
}
;
opt_args_tail : ',' args_tail
{
$$ = $2;
}
| /* none */
{
$$ = new_args_tail(p, 0, 0, 0);
}
;
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
{
{
$$ = new_args(p, $1, $3, $5, 0, $6);
$$ = new_args(p, $1, $3, $5, 0, $6);
}
}
| f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_
f_block_arg
| f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_
args_tail
{
{
$$ = new_args(p, $1, $3, $5, $7, $8);
$$ = new_args(p, $1, $3, $5, $7, $8);
}
}
| f_arg ',' f_optarg opt_
f_block_arg
| f_arg ',' f_optarg opt_
args_tail
{
{
$$ = new_args(p, $1, $3, 0, 0, $4);
$$ = new_args(p, $1, $3, 0, 0, $4);
}
}
| f_arg ',' f_optarg ',' f_arg opt_
f_block_arg
| f_arg ',' f_optarg ',' f_arg opt_
args_tail
{
{
$$ = new_args(p, $1, $3, 0, $5, $6);
$$ = new_args(p, $1, $3, 0, $5, $6);
}
}
| f_arg ',' f_rest_arg opt_
f_block_arg
| f_arg ',' f_rest_arg opt_
args_tail
{
{
$$ = new_args(p, $1, 0, $3, 0, $4);
$$ = new_args(p, $1, 0, $3, 0, $4);
}
}
| f_arg ',' f_rest_arg ',' f_arg opt_
f_block_arg
| f_arg ',' f_rest_arg ',' f_arg opt_
args_tail
{
{
$$ = new_args(p, $1, 0, $3, $5, $6);
$$ = new_args(p, $1, 0, $3, $5, $6);
}
}
| f_arg opt_
f_block_arg
| f_arg opt_
args_tail
{
{
$$ = new_args(p, $1, 0, 0, 0, $2);
$$ = new_args(p, $1, 0, 0, 0, $2);
}
}
| f_optarg ',' f_rest_arg opt_
f_block_arg
| f_optarg ',' f_rest_arg opt_
args_tail
{
{
$$ = new_args(p, 0, $1, $3, 0, $4);
$$ = new_args(p, 0, $1, $3, 0, $4);
}
}
| f_optarg ',' f_rest_arg ',' f_arg opt_
f_block_arg
| f_optarg ',' f_rest_arg ',' f_arg opt_
args_tail
{
{
$$ = new_args(p, 0, $1, $3, $5, $6);
$$ = new_args(p, 0, $1, $3, $5, $6);
}
}
| f_optarg opt_
f_block_arg
| f_optarg opt_
args_tail
{
{
$$ = new_args(p, 0, $1, 0, 0, $2);
$$ = new_args(p, 0, $1, 0, 0, $2);
}
}
| f_optarg ',' f_arg opt_
f_block_arg
| f_optarg ',' f_arg opt_
args_tail
{
{
$$ = new_args(p, 0, $1, 0, $3, $4);
$$ = new_args(p, 0, $1, 0, $3, $4);
}
}
| f_rest_arg opt_
f_block_arg
| f_rest_arg opt_
args_tail
{
{
$$ = new_args(p, 0, 0, $1, 0, $2);
$$ = new_args(p, 0, 0, $1, 0, $2);
}
}
| f_rest_arg ',' f_arg opt_
f_block_arg
| f_rest_arg ',' f_arg opt_
args_tail
{
{
$$ = new_args(p, 0, 0, $1, $3, $4);
$$ = new_args(p, 0, 0, $1, $3, $4);
}
}
|
f_block_arg
|
args_tail
{
{
$$ = new_args(p, 0, 0, 0, 0, $1);
$$ = new_args(p, 0, 0, 0, 0, $1);
}
}
| /* none */
| /* none */
{
{
local_add_f(p,
0
);
local_add_f(p,
mrb_intern_lit(p->mrb, "&")
);
$$ = new_args(p, 0, 0, 0, 0, 0);
$$ = new_args(p, 0, 0, 0, 0, 0);
}
}
;
;
...
@@ -3189,7 +3356,7 @@ f_rest_arg : restarg_mark tIDENTIFIER
...
@@ -3189,7 +3356,7 @@ f_rest_arg : restarg_mark tIDENTIFIER
}
}
| restarg_mark
| restarg_mark
{
{
local_add_f(p,
0
);
local_add_f(p,
mrb_intern_lit(p->mrb, "*")
);
$$ = -1;
$$ = -1;
}
}
;
;
...
@@ -3200,7 +3367,6 @@ blkarg_mark : '&'
...
@@ -3200,7 +3367,6 @@ blkarg_mark : '&'
f_block_arg : blkarg_mark tIDENTIFIER
f_block_arg : blkarg_mark tIDENTIFIER
{
{
local_add_f(p, $2);
$$ = $2;
$$ = $2;
}
}
;
;
...
@@ -3211,7 +3377,6 @@ opt_f_block_arg : ',' f_block_arg
...
@@ -3211,7 +3377,6 @@ opt_f_block_arg : ',' f_block_arg
}
}
| none
| none
{
{
local_add_f(p, 0);
$$ = 0;
$$ = 0;
}
}
;
;
...
@@ -3285,6 +3450,10 @@ assoc : arg tASSOC arg
...
@@ -3285,6 +3450,10 @@ assoc : arg tASSOC arg
$$ = cons(new_sym(p, new_strsym(p, $1)), $3);
$$ = cons(new_sym(p, new_strsym(p, $1)), $3);
}
}
}
}
| tDSTAR arg_value
{
$$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2);
}
;
;
operation : tIDENTIFIER
operation : tIDENTIFIER
...
@@ -3450,13 +3619,13 @@ backref_error(parser_state *p, node *n)
...
@@ -3450,13 +3619,13 @@ backref_error(parser_state *p, node *n)
{
{
int c;
int c;
c =
(int)(intptr_t)n->car
;
c =
intn(n->car)
;
if (c == NODE_NTH_REF) {
if (c == NODE_NTH_REF) {
yyerror_i(p, "can't set variable $%" MRB_PRId,
(int)(intptr_t)n->cdr
);
yyerror_i(p, "can't set variable $%" MRB_PRId,
intn(n->cdr)
);
}
}
else if (c == NODE_BACK_REF) {
else if (c == NODE_BACK_REF) {
yyerror_i(p, "can't set variable $%c",
(int)(intptr_t)n->cdr
);
yyerror_i(p, "can't set variable $%c",
intn(n->cdr)
);
}
}
else {
else {
mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
...
@@ -3469,7 +3638,7 @@ void_expr_error(parser_state *p, node *n)
...
@@ -3469,7 +3638,7 @@ void_expr_error(parser_state *p, node *n)
int c;
int c;
if (n == NULL) return;
if (n == NULL) return;
c =
(int)(intptr_t)n->car
;
c =
intn(n->car)
;
switch (c) {
switch (c) {
case NODE_BREAK:
case NODE_BREAK:
case NODE_RETURN:
case NODE_RETURN:
...
@@ -3508,7 +3677,7 @@ nextc(parser_state *p)
...
@@ -3508,7 +3677,7 @@ nextc(parser_state *p)
if (p->pb) {
if (p->pb) {
node *tmp;
node *tmp;
c =
(int)(intptr_t)p->pb->car
;
c =
intn(p->pb->car)
;
tmp = p->pb;
tmp = p->pb;
p->pb = p->pb->cdr;
p->pb = p->pb->cdr;
cons_free(tmp);
cons_free(tmp);
...
@@ -3557,7 +3726,7 @@ pushback(parser_state *p, int c)
...
@@ -3557,7 +3726,7 @@ pushback(parser_state *p, int c)
if (c >= 0) {
if (c >= 0) {
p->column--;
p->column--;
}
}
p->pb = cons(
(node*)(intptr_t)c
, p->pb);
p->pb = cons(
nint(c)
, p->pb);
}
}
static void
static void
...
@@ -3582,7 +3751,7 @@ peekc_n(parser_state *p, int n)
...
@@ -3582,7 +3751,7 @@ peekc_n(parser_state *p, int n)
c0 = nextc(p);
c0 = nextc(p);
if (c0 == -1) return c0; /* do not skip partial EOF */
if (c0 == -1) return c0; /* do not skip partial EOF */
if (c0 >= 0) --p->column;
if (c0 >= 0) --p->column;
list = push(list,
(node*)(intptr_t)c0
);
list = push(list,
nint(c0)
);
} while(n--);
} while(n--);
if (p->pb) {
if (p->pb) {
p->pb = append((node*)list, p->pb);
p->pb = append((node*)list, p->pb);
...
@@ -4019,11 +4188,11 @@ parse_string(parser_state *p)
...
@@ -4019,11 +4188,11 @@ parse_string(parser_state *p)
}
}
else if (c == beg) {
else if (c == beg) {
nest_level++;
nest_level++;
p->lex_strterm->cdr->car =
(node*)(intptr_t)nest_level
;
p->lex_strterm->cdr->car =
nint(nest_level)
;
}
}
else if (c == end) {
else if (c == end) {
nest_level--;
nest_level--;
p->lex_strterm->cdr->car =
(node*)(intptr_t)nest_level
;
p->lex_strterm->cdr->car =
nint(nest_level)
;
}
}
else if (c == '\\') {
else if (c == '\\') {
c = nextc(p);
c = nextc(p);
...
@@ -4365,7 +4534,16 @@ parser_yylex(parser_state *p)
...
@@ -4365,7 +4534,16 @@ parser_yylex(parser_state *p)
return tOP_ASGN;
return tOP_ASGN;
}
}
pushback(p, c);
pushback(p, c);
c = tPOW;
if (IS_SPCARG(c)) {
yywarning(p, "`**' interpreted as argument prefix");
c = tDSTAR;
}
else if (IS_BEG()) {
c = tDSTAR;
}
else {
c = tPOW; /* "**", "argument prefix" */
}
}
}
else {
else {
if (c == '=') {
if (c == '=') {
...
@@ -5547,7 +5725,7 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt)
...
@@ -5547,7 +5725,7 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt)
int i = 0;
int i = 0;
if (!cxt) return;
if (!cxt) return;
if (
(int)(intptr_t)p->tree->car
!= NODE_SCOPE) return;
if (
intn(p->tree->car)
!= NODE_SCOPE) return;
n0 = n = p->tree->cdr->car;
n0 = n = p->tree->cdr->car;
while (n) {
while (n) {
i++;
i++;
...
@@ -5897,6 +6075,48 @@ dump_recur(mrb_state *mrb, node *tree, int offset)
...
@@ -5897,6 +6075,48 @@ dump_recur(mrb_state *mrb, node *tree, int offset)
}
}
}
}
static void
dump_args(mrb_state *mrb, node *n, int offset)
{
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=\n", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, offset+3);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n) {
mrb_assert(intn(n->car) == NODE_ARGS_TAIL);
mrb_parser_dump(mrb, n, offset);
}
}
#endif
#endif
void
void
...
@@ -5908,7 +6128,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -5908,7 +6128,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
if (!tree) return;
if (!tree) return;
again:
again:
dump_prefix(tree, offset);
dump_prefix(tree, offset);
nodetype =
(int)(intptr_t)tree->car
;
nodetype =
intn(tree->car)
;
tree = tree->cdr;
tree = tree->cdr;
switch (nodetype) {
switch (nodetype) {
case NODE_BEGIN:
case NODE_BEGIN:
...
@@ -5968,7 +6188,8 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -5968,7 +6188,8 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
break;
case NODE_LAMBDA:
case NODE_LAMBDA:
printf("NODE_BLOCK:\n");
printf("NODE_LAMBDA:\n");
dump_prefix(tree, offset);
goto block;
goto block;
case NODE_BLOCK:
case NODE_BLOCK:
...
@@ -5976,43 +6197,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -5976,43 +6197,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
printf("NODE_BLOCK:\n");
printf("NODE_BLOCK:\n");
tree = tree->cdr;
tree = tree->cdr;
if (tree->car) {
if (tree->car) {
node *n = tree->car;
dump_args(mrb, tree->car, offset+1);
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, 0);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
if (n->cdr) {
dump_prefix(n, offset+1);
printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
}
}
}
dump_prefix(tree, offset+1);
dump_prefix(tree, offset+1);
printf("body:\n");
printf("body:\n");
...
@@ -6164,7 +6349,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6164,7 +6349,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
dump_prefix(tree, offset+1);
dump_prefix(tree, offset+1);
printf("method='%s' (%d)\n",
printf("method='%s' (%d)\n",
mrb_sym2name(mrb, sym(tree->cdr->car)),
mrb_sym2name(mrb, sym(tree->cdr->car)),
(int)(intptr_t)tree->cdr->car
);
intn(tree->cdr->car)
);
tree = tree->cdr->cdr->car;
tree = tree->cdr->cdr->car;
if (tree) {
if (tree) {
dump_prefix(tree, offset+1);
dump_prefix(tree, offset+1);
...
@@ -6281,7 +6466,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6281,7 +6466,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
mrb_parser_dump(mrb, tree->car, offset+2);
mrb_parser_dump(mrb, tree->car, offset+2);
tree = tree->cdr;
tree = tree->cdr;
dump_prefix(tree, offset+1);
dump_prefix(tree, offset+1);
printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)),
(int)(intptr_t)tree->car
);
printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)),
intn(tree->car)
);
tree = tree->cdr;
tree = tree->cdr;
mrb_parser_dump(mrb, tree->car, offset+1);
mrb_parser_dump(mrb, tree->car, offset+1);
break;
break;
...
@@ -6363,11 +6548,11 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6363,11 +6548,11 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
break;
case NODE_BACK_REF:
case NODE_BACK_REF:
printf("NODE_BACK_REF: $%c\n",
(int)(intptr_t)tree
);
printf("NODE_BACK_REF: $%c\n",
intn(tree)
);
break;
break;
case NODE_NTH_REF:
case NODE_NTH_REF:
printf("NODE_NTH_REF: $%
" MRB_PRId "\n", (mrb_int)(intptr_t)tree
);
printf("NODE_NTH_REF: $%
d\n", intn(tree)
);
break;
break;
case NODE_ARG:
case NODE_ARG:
...
@@ -6380,7 +6565,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6380,7 +6565,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
break;
case NODE_INT:
case NODE_INT:
printf("NODE_INT %s base %d\n", (char*)tree->car,
(int)(intptr_t)tree->cdr->car
);
printf("NODE_INT %s base %d\n", (char*)tree->car,
intn(tree->cdr->car)
);
break;
break;
case NODE_FLOAT:
case NODE_FLOAT:
...
@@ -6393,7 +6578,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6393,7 +6578,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
break;
case NODE_STR:
case NODE_STR:
printf("NODE_STR \"%s\" len %d\n", (char*)tree->car,
(int)(intptr_t)tree->cdr
);
printf("NODE_STR \"%s\" len %d\n", (char*)tree->car,
intn(tree->cdr)
);
break;
break;
case NODE_DSTR:
case NODE_DSTR:
...
@@ -6402,7 +6587,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6402,7 +6587,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
break;
case NODE_XSTR:
case NODE_XSTR:
printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car,
(int)(intptr_t)tree->cdr
);
printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car,
intn(tree->cdr)
);
break;
break;
case NODE_DXSTR:
case NODE_DXSTR:
...
@@ -6431,7 +6616,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6431,7 +6616,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_SYM:
case NODE_SYM:
printf("NODE_SYM :%s (%d)\n", mrb_sym2name(mrb, sym(tree)),
printf("NODE_SYM :%s (%d)\n", mrb_sym2name(mrb, sym(tree)),
(int)(intptr_t)tree
);
intn(tree)
);
break;
break;
case NODE_SELF:
case NODE_SELF:
...
@@ -6547,43 +6732,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6547,43 +6732,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
}
}
tree = tree->cdr;
tree = tree->cdr;
if (tree->car) {
if (tree->car) {
node *n = tree->car;
dump_args(mrb, tree->car, offset);
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, 0);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
if (n->cdr) {
dump_prefix(n, offset+1);
printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
}
}
}
mrb_parser_dump(mrb, tree->cdr->car, offset+1);
mrb_parser_dump(mrb, tree->cdr->car, offset+1);
break;
break;
...
@@ -6596,44 +6745,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6596,44 +6745,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
tree = tree->cdr->cdr;
tree = tree->cdr->cdr;
if (tree->car) {
if (tree->car) {
node *n = tree->car;
dump_args(mrb, tree->car, offset+1);
if (n->car) {
dump_prefix(n, offset+1);
printf("mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("optional args:\n");
{
node *n2 = n->car;
while (n2) {
dump_prefix(n2, offset+2);
printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
mrb_parser_dump(mrb, n2->car->cdr, 0);
n2 = n2->cdr;
}
}
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
}
n = n->cdr;
if (n->car) {
dump_prefix(n, offset+1);
printf("post mandatory args:\n");
dump_recur(mrb, n->car, offset+2);
}
n = n->cdr;
if (n) {
dump_prefix(n, offset+1);
printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
}
}
}
tree = tree->cdr;
tree = tree->cdr;
mrb_parser_dump(mrb, tree->car, offset+1);
mrb_parser_dump(mrb, tree->car, offset+1);
...
@@ -6649,18 +6761,35 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
...
@@ -6649,18 +6761,35 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
break;
break;
case NODE_LITERAL_DELIM:
case NODE_ARGS_TAIL:
printf("NODE_LITERAL_DELIM\n");
printf("NODE_ARGS_TAIL:\n");
{
node *kws = tree->car;
while (kws) {
mrb_parser_dump(mrb, kws->car, offset+1);
kws = kws->cdr;
}
}
tree = tree->cdr;
if (tree->car) {
mrb_assert(intn(tree->car->car) == NODE_KW_REST_ARGS);
mrb_parser_dump(mrb, tree->car, offset+1);
}
tree = tree->cdr;
if (tree->car) {
dump_prefix(tree, offset+1);
printf("block='%s'\n", mrb_sym2name(mrb, sym(tree->car)));
}
break;
break;
case NODE_
SYMBOLS
:
case NODE_
KW_ARG
:
printf("NODE_
SYMBOLS:\n"
);
printf("NODE_
KW_ARG %s\n", mrb_sym2name(mrb, sym(tree->car))
);
dump_recur(mrb, tree, offset+
1);
mrb_parser_dump(mrb, tree->cdr->car, offset +
1);
break;
break;
case NODE_WORDS:
case NODE_KW_REST_ARGS:
printf("NODE_SYMBOLS:\n");
printf("NODE_KW_REST_ARGS %s\n", mrb_sym2name(mrb, sym(tree)));
dump_recur(mrb, tree, offset+1);
break;
break;
default:
default:
...
...
mrbgems/mruby-objectspace/src/mruby_objectspace.c
View file @
8c9e7127
...
@@ -57,7 +57,7 @@ os_count_objects(mrb_state *mrb, mrb_value self)
...
@@ -57,7 +57,7 @@ os_count_objects(mrb_state *mrb, mrb_value self)
hash
=
mrb_hash_new
(
mrb
);
hash
=
mrb_hash_new
(
mrb
);
}
}
if
(
!
mrb_
test
(
mrb_hash_empty_p
(
mrb
,
hash
)
))
{
if
(
!
mrb_
hash_empty_p
(
mrb
,
hash
))
{
mrb_hash_clear
(
mrb
,
hash
);
mrb_hash_clear
(
mrb
,
hash
);
}
}
...
...
mrbgems/mruby-proc-ext/src/proc.c
View file @
8c9e7127
...
@@ -149,7 +149,15 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
...
@@ -149,7 +149,15 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
a
=
mrb_ary_new
(
mrb
);
a
=
mrb_ary_new
(
mrb
);
mrb_ary_push
(
mrb
,
a
,
sname
);
mrb_ary_push
(
mrb
,
a
,
sname
);
if
(
i
<
max
&&
irep
->
lv
[
i
].
name
)
{
if
(
i
<
max
&&
irep
->
lv
[
i
].
name
)
{
mrb_ary_push
(
mrb
,
a
,
mrb_symbol_value
(
irep
->
lv
[
i
].
name
));
mrb_sym
sym
=
irep
->
lv
[
i
].
name
;
const
char
*
name
=
mrb_sym2name
(
mrb
,
sym
);
switch
(
name
[
0
])
{
case
'*'
:
case
'&'
:
break
;
default:
mrb_ary_push
(
mrb
,
a
,
mrb_symbol_value
(
sym
));
break
;
}
}
}
mrb_ary_push
(
mrb
,
parameters
,
a
);
mrb_ary_push
(
mrb
,
parameters
,
a
);
}
}
...
...
src/codedump.c
View file @
8c9e7127
...
@@ -78,6 +78,16 @@ codedump(mrb_state *mrb, mrb_irep *irep)
...
@@ -78,6 +78,16 @@ codedump(mrb_state *mrb, mrb_irep *irep)
printf
(
"irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d
\n
"
,
(
void
*
)
irep
,
printf
(
"irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d
\n
"
,
(
void
*
)
irep
,
irep
->
nregs
,
irep
->
nlocals
,
(
int
)
irep
->
plen
,
(
int
)
irep
->
slen
,
(
int
)
irep
->
rlen
);
irep
->
nregs
,
irep
->
nlocals
,
(
int
)
irep
->
plen
,
(
int
)
irep
->
slen
,
(
int
)
irep
->
rlen
);
if
(
irep
->
lv
)
{
int
i
;
printf
(
"local variable names:
\n
"
);
for
(
i
=
1
;
i
<
irep
->
nlocals
;
++
i
)
{
char
const
*
n
=
mrb_sym2name
(
mrb
,
irep
->
lv
[
i
-
1
].
name
);
printf
(
" R%d:%s
\n
"
,
irep
->
lv
[
i
-
1
].
r
,
n
?
n
:
""
);
}
}
pc
=
irep
->
iseq
;
pc
=
irep
->
iseq
;
pcend
=
pc
+
irep
->
ilen
;
pcend
=
pc
+
irep
->
ilen
;
while
(
pc
<
pcend
)
{
while
(
pc
<
pcend
)
{
...
@@ -246,10 +256,11 @@ codedump(mrb_state *mrb, mrb_irep *irep)
...
@@ -246,10 +256,11 @@ codedump(mrb_state *mrb, mrb_irep *irep)
printf
(
"OP_SUPER
\t
R%d
\t
%d
\n
"
,
a
,
b
);
printf
(
"OP_SUPER
\t
R%d
\t
%d
\n
"
,
a
,
b
);
break
;
break
;
CASE
(
OP_ARGARY
,
BS
)
:
CASE
(
OP_ARGARY
,
BS
)
:
printf
(
"OP_ARGARY
\t
R%d
\t
%d:%d:%d:%d"
,
a
,
printf
(
"OP_ARGARY
\t
R%d
\t
%d:%d:%d:%d (%d)"
,
a
,
(
b
>>
10
)
&
0x3f
,
(
b
>>
11
)
&
0x3f
,
(
b
>>
9
)
&
0x1
,
(
b
>>
10
)
&
0x1
,
(
b
>>
4
)
&
0x1f
,
(
b
>>
5
)
&
0x1f
,
(
b
>>
4
)
&
0x1
,
(
b
>>
0
)
&
0xf
);
(
b
>>
0
)
&
0xf
);
print_lv_a
(
mrb
,
irep
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
...
@@ -263,32 +274,39 @@ codedump(mrb_state *mrb, mrb_irep *irep)
...
@@ -263,32 +274,39 @@ codedump(mrb_state *mrb, mrb_irep *irep)
(
a
>>
1
)
&
0x1
,
(
a
>>
1
)
&
0x1
,
a
&
0x1
);
a
&
0x1
);
break
;
break
;
CASE
(
OP_KARG
,
BB
)
:
CASE
(
OP_KEY_P
,
BB
)
:
printf
(
"OP_KARG
\t
R(%d)
\t
K(%d)
\n
"
,
a
,
b
);
printf
(
"OP_KEY_P
\t
R%d
\t
:%s
\t
"
,
a
,
mrb_sym2name
(
mrb
,
irep
->
syms
[
b
]));
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
CASE
(
OP_KARG2
,
BB
)
:
CASE
(
OP_KEYEND
,
Z
)
:
printf
(
"OP_KARG2
\t
R(%d)
\t
K(%d)
\n
"
,
a
,
b
);
printf
(
"OP_KEYEND
\n
"
);
break
;
CASE
(
OP_KARG
,
BB
)
:
printf
(
"OP_KARG
\t
R%d
\t
:%s
\t
"
,
a
,
mrb_sym2name
(
mrb
,
irep
->
syms
[
b
]));
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
CASE
(
OP_KDICT
,
B
)
:
CASE
(
OP_KDICT
,
B
)
:
printf
(
"OP_KDICt
\t
R(%d)
\n
"
,
a
);
printf
(
"OP_KDICT
\t
R%d
\t\t
"
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
CASE
(
OP_RETURN
,
B
)
:
CASE
(
OP_RETURN
,
B
)
:
printf
(
"OP_RETURN
\t
R%d"
,
a
);
printf
(
"OP_RETURN
\t
R%d
\t\t
"
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
CASE
(
OP_RETURN_BLK
,
B
)
:
CASE
(
OP_RETURN_BLK
,
B
)
:
printf
(
"OP_RETURN_BLK
\t
R%d"
,
a
);
printf
(
"OP_RETURN_BLK
\t
R%d
\t\t
"
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
CASE
(
OP_BREAK
,
B
)
:
CASE
(
OP_BREAK
,
B
)
:
printf
(
"OP_BREAK
\t
R%d"
,
a
);
printf
(
"OP_BREAK
\t
R%d
\t\t
"
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
CASE
(
OP_BLKPUSH
,
BS
)
:
CASE
(
OP_BLKPUSH
,
BS
)
:
printf
(
"OP_BLKPUSH
\t
R%d
\t
%d:%d:%d:%d"
,
a
,
printf
(
"OP_BLKPUSH
\t
R%d
\t
%d:%d:%d:%d (%d)"
,
a
,
(
b
>>
10
)
&
0x3f
,
(
b
>>
11
)
&
0x3f
,
(
b
>>
9
)
&
0x1
,
(
b
>>
10
)
&
0x1
,
(
b
>>
4
)
&
0x1f
,
(
b
>>
5
)
&
0x1f
,
(
b
>>
4
)
&
0x1
,
(
b
>>
0
)
&
0xf
);
(
b
>>
0
)
&
0xf
);
print_lv_a
(
mrb
,
irep
,
a
);
print_lv_a
(
mrb
,
irep
,
a
);
break
;
break
;
...
...
src/hash.c
View file @
8c9e7127
...
@@ -208,6 +208,54 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
...
@@ -208,6 +208,54 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
return
vret
;
return
vret
;
}
}
void
mrb_hash_check_kdict
(
mrb_state
*
mrb
,
mrb_value
self
)
{
khash_t
(
ht
)
*
orig_h
;
khiter_t
k
;
int
nosym
=
FALSE
;
orig_h
=
RHASH_TBL
(
self
);
if
(
!
orig_h
||
kh_size
(
orig_h
)
==
0
)
return
;
for
(
k
=
kh_begin
(
orig_h
);
k
!=
kh_end
(
orig_h
);
k
++
)
{
if
(
kh_exist
(
orig_h
,
k
))
{
mrb_value
key
=
kh_key
(
orig_h
,
k
);
if
(
!
mrb_symbol_p
(
key
))
nosym
=
TRUE
;
}
}
if
(
nosym
)
{
mrb_raise
(
mrb
,
E_ARGUMENT_ERROR
,
"keyword argument hash with non symbol keys"
);
}
}
MRB_API
mrb_value
mrb_hash_dup
(
mrb_state
*
mrb
,
mrb_value
self
)
{
struct
RHash
*
copy
;
khash_t
(
ht
)
*
orig_h
;
orig_h
=
RHASH_TBL
(
self
);
copy
=
(
struct
RHash
*
)
mrb_obj_alloc
(
mrb
,
MRB_TT_HASH
,
mrb
->
hash_class
);
copy
->
ht
=
kh_init
(
ht
,
mrb
);
if
(
orig_h
&&
kh_size
(
orig_h
)
>
0
)
{
int
ai
=
mrb_gc_arena_save
(
mrb
);
khash_t
(
ht
)
*
copy_h
=
copy
->
ht
;
khiter_t
k
,
copy_k
;
for
(
k
=
kh_begin
(
orig_h
);
k
!=
kh_end
(
orig_h
);
k
++
)
{
if
(
kh_exist
(
orig_h
,
k
))
{
copy_k
=
kh_put
(
ht
,
mrb
,
copy_h
,
KEY
(
kh_key
(
orig_h
,
k
)));
mrb_gc_arena_restore
(
mrb
,
ai
);
kh_val
(
copy_h
,
copy_k
).
v
=
kh_val
(
orig_h
,
k
).
v
;
kh_val
(
copy_h
,
copy_k
).
n
=
kh_size
(
copy_h
)
-
1
;
}
}
}
return
mrb_obj_value
(
copy
);
}
MRB_API
mrb_value
MRB_API
mrb_value
mrb_hash_get
(
mrb_state
*
mrb
,
mrb_value
hash
,
mrb_value
key
)
mrb_hash_get
(
mrb_state
*
mrb
,
mrb_value
hash
,
mrb_value
key
)
{
{
...
@@ -716,13 +764,21 @@ mrb_hash_size_m(mrb_state *mrb, mrb_value self)
...
@@ -716,13 +764,21 @@ mrb_hash_size_m(mrb_state *mrb, mrb_value self)
* {}.empty? #=> true
* {}.empty? #=> true
*
*
*/
*/
MRB_API
mrb_
value
MRB_API
mrb_
bool
mrb_hash_empty_p
(
mrb_state
*
mrb
,
mrb_value
self
)
mrb_hash_empty_p
(
mrb_state
*
mrb
,
mrb_value
self
)
{
{
khash_t
(
ht
)
*
h
=
RHASH_TBL
(
self
);
khash_t
(
ht
)
*
h
=
RHASH_TBL
(
self
);
if
(
h
)
return
mrb_bool_value
(
kh_size
(
h
)
==
0
);
if
(
h
)
return
kh_size
(
h
)
==
0
;
return
mrb_true_value
();
return
TRUE
;
}
static
mrb_value
mrb_hash_empty_m
(
mrb_state
*
mrb
,
mrb_value
self
)
{
if
(
mrb_hash_empty_p
(
mrb
,
self
))
return
mrb_true_value
();
return
mrb_false_value
();
}
}
/* 15.2.13.4.29 (x)*/
/* 15.2.13.4.29 (x)*/
...
@@ -833,21 +889,29 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash)
...
@@ -833,21 +889,29 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash)
*
*
*/
*/
static
mrb_value
MRB_API
mrb_bool
mrb_hash_
has_key
(
mrb_state
*
mrb
,
mrb_value
hash
)
mrb_hash_
key_p
(
mrb_state
*
mrb
,
mrb_value
hash
,
mrb_value
key
)
{
{
mrb_value
key
;
khash_t
(
ht
)
*
h
;
khash_t
(
ht
)
*
h
;
khiter_t
k
;
khiter_t
k
;
mrb_get_args
(
mrb
,
"o"
,
&
key
);
h
=
RHASH_TBL
(
hash
);
h
=
RHASH_TBL
(
hash
);
if
(
h
)
{
if
(
h
)
{
k
=
kh_get
(
ht
,
mrb
,
h
,
key
);
k
=
kh_get
(
ht
,
mrb
,
h
,
key
);
return
mrb_bool_value
(
k
!=
kh_end
(
h
)
);
return
k
!=
kh_end
(
h
);
}
}
return
mrb_false_value
();
return
FALSE
;
}
static
mrb_value
mrb_hash_has_key
(
mrb_state
*
mrb
,
mrb_value
hash
)
{
mrb_value
key
;
mrb_bool
key_p
;
mrb_get_args
(
mrb
,
"o"
,
&
key
);
key_p
=
mrb_hash_key_p
(
mrb
,
hash
,
key
);
return
mrb_bool_value
(
key_p
);
}
}
/* 15.2.13.4.14 */
/* 15.2.13.4.14 */
...
@@ -904,7 +968,7 @@ mrb_init_hash(mrb_state *mrb)
...
@@ -904,7 +968,7 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method
(
mrb
,
h
,
"default_proc"
,
mrb_hash_default_proc
,
MRB_ARGS_NONE
());
/* 15.2.13.4.7 */
mrb_define_method
(
mrb
,
h
,
"default_proc"
,
mrb_hash_default_proc
,
MRB_ARGS_NONE
());
/* 15.2.13.4.7 */
mrb_define_method
(
mrb
,
h
,
"default_proc="
,
mrb_hash_set_default_proc
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.7 */
mrb_define_method
(
mrb
,
h
,
"default_proc="
,
mrb_hash_set_default_proc
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.7 */
mrb_define_method
(
mrb
,
h
,
"__delete"
,
mrb_hash_delete
,
MRB_ARGS_REQ
(
1
));
/* core of 15.2.13.4.8 */
mrb_define_method
(
mrb
,
h
,
"__delete"
,
mrb_hash_delete
,
MRB_ARGS_REQ
(
1
));
/* core of 15.2.13.4.8 */
mrb_define_method
(
mrb
,
h
,
"empty?"
,
mrb_hash_empty_
p
,
MRB_ARGS_NONE
());
/* 15.2.13.4.12 */
mrb_define_method
(
mrb
,
h
,
"empty?"
,
mrb_hash_empty_
m
,
MRB_ARGS_NONE
());
/* 15.2.13.4.12 */
mrb_define_method
(
mrb
,
h
,
"has_key?"
,
mrb_hash_has_key
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.13 */
mrb_define_method
(
mrb
,
h
,
"has_key?"
,
mrb_hash_has_key
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.13 */
mrb_define_method
(
mrb
,
h
,
"has_value?"
,
mrb_hash_has_value
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.14 */
mrb_define_method
(
mrb
,
h
,
"has_value?"
,
mrb_hash_has_value
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.14 */
mrb_define_method
(
mrb
,
h
,
"include?"
,
mrb_hash_has_key
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.15 */
mrb_define_method
(
mrb
,
h
,
"include?"
,
mrb_hash_has_key
,
MRB_ARGS_REQ
(
1
));
/* 15.2.13.4.15 */
...
...
src/kernel.c
View file @
8c9e7127
...
@@ -1194,7 +1194,15 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
...
@@ -1194,7 +1194,15 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
if
(
!
irep
->
lv
)
break
;
if
(
!
irep
->
lv
)
break
;
for
(
i
=
0
;
i
+
1
<
irep
->
nlocals
;
++
i
)
{
for
(
i
=
0
;
i
+
1
<
irep
->
nlocals
;
++
i
)
{
if
(
irep
->
lv
[
i
].
name
)
{
if
(
irep
->
lv
[
i
].
name
)
{
mrb_hash_set
(
mrb
,
vars
,
mrb_symbol_value
(
irep
->
lv
[
i
].
name
),
mrb_true_value
());
mrb_sym
sym
=
irep
->
lv
[
i
].
name
;
const
char
*
name
=
mrb_sym2name
(
mrb
,
sym
);
switch
(
name
[
0
])
{
case
'*'
:
case
'&'
:
break
;
default:
mrb_hash_set
(
mrb
,
vars
,
mrb_symbol_value
(
sym
),
mrb_true_value
());
break
;
}
}
}
}
}
if
(
!
MRB_PROC_ENV_P
(
proc
))
break
;
if
(
!
MRB_PROC_ENV_P
(
proc
))
break
;
...
...
src/vm.c
View file @
8c9e7127
...
@@ -969,6 +969,8 @@ check_target_class(mrb_state *mrb)
...
@@ -969,6 +969,8 @@ check_target_class(mrb_state *mrb)
return
TRUE
;
return
TRUE
;
}
}
void
mrb_hash_check_kdict
(
mrb_state
*
mrb
,
mrb_value
self
);
MRB_API
mrb_value
MRB_API
mrb_value
mrb_vm_exec
(
mrb_state
*
mrb
,
struct
RProc
*
proc
,
mrb_code
*
pc
)
mrb_vm_exec
(
mrb_state
*
mrb
,
struct
RProc
*
proc
,
mrb_code
*
pc
)
{
{
...
@@ -1639,9 +1641,10 @@ RETRY_TRY_BLOCK:
...
@@ -1639,9 +1641,10 @@ RETRY_TRY_BLOCK:
}
}
CASE
(
OP_ARGARY
,
BS
)
{
CASE
(
OP_ARGARY
,
BS
)
{
int
m1
=
(
b
>>
10
)
&
0x3f
;
int
m1
=
(
b
>>
11
)
&
0x3f
;
int
r
=
(
b
>>
9
)
&
0x1
;
int
r
=
(
b
>>
10
)
&
0x1
;
int
m2
=
(
b
>>
4
)
&
0x1f
;
int
m2
=
(
b
>>
5
)
&
0x1f
;
int
kd
=
(
b
>>
4
)
&
0x1
;
int
lv
=
(
b
>>
0
)
&
0xf
;
int
lv
=
(
b
>>
0
)
&
0xf
;
mrb_value
*
stack
;
mrb_value
*
stack
;
...
@@ -1657,12 +1660,12 @@ RETRY_TRY_BLOCK:
...
@@ -1657,12 +1660,12 @@ RETRY_TRY_BLOCK:
else
{
else
{
struct
REnv
*
e
=
uvenv
(
mrb
,
lv
-
1
);
struct
REnv
*
e
=
uvenv
(
mrb
,
lv
-
1
);
if
(
!
e
)
goto
L_NOSUPER
;
if
(
!
e
)
goto
L_NOSUPER
;
if
(
MRB_ENV_STACK_LEN
(
e
)
<=
m1
+
r
+
m2
+
1
)
if
(
MRB_ENV_STACK_LEN
(
e
)
<=
m1
+
r
+
m2
+
kd
+
1
)
goto
L_NOSUPER
;
goto
L_NOSUPER
;
stack
=
e
->
stack
+
1
;
stack
=
e
->
stack
+
1
;
}
}
if
(
r
==
0
)
{
if
(
r
==
0
)
{
regs
[
a
]
=
mrb_ary_new_from_values
(
mrb
,
m1
+
m2
,
stack
);
regs
[
a
]
=
mrb_ary_new_from_values
(
mrb
,
m1
+
m2
+
kd
,
stack
);
}
}
else
{
else
{
mrb_value
*
pp
=
NULL
;
mrb_value
*
pp
=
NULL
;
...
@@ -1675,7 +1678,7 @@ RETRY_TRY_BLOCK:
...
@@ -1675,7 +1678,7 @@ RETRY_TRY_BLOCK:
pp
=
ARY_PTR
(
ary
);
pp
=
ARY_PTR
(
ary
);
len
=
(
int
)
ARY_LEN
(
ary
);
len
=
(
int
)
ARY_LEN
(
ary
);
}
}
regs
[
a
]
=
mrb_ary_new_capa
(
mrb
,
m1
+
len
+
m2
);
regs
[
a
]
=
mrb_ary_new_capa
(
mrb
,
m1
+
len
+
m2
+
kd
);
rest
=
mrb_ary_ptr
(
regs
[
a
]);
rest
=
mrb_ary_ptr
(
regs
[
a
]);
if
(
m1
>
0
)
{
if
(
m1
>
0
)
{
stack_copy
(
ARY_PTR
(
rest
),
stack
,
m1
);
stack_copy
(
ARY_PTR
(
rest
),
stack
,
m1
);
...
@@ -1686,7 +1689,10 @@ RETRY_TRY_BLOCK:
...
@@ -1686,7 +1689,10 @@ RETRY_TRY_BLOCK:
if
(
m2
>
0
)
{
if
(
m2
>
0
)
{
stack_copy
(
ARY_PTR
(
rest
)
+
m1
+
len
,
stack
+
m1
+
1
,
m2
);
stack_copy
(
ARY_PTR
(
rest
)
+
m1
+
len
,
stack
+
m1
+
1
,
m2
);
}
}
ARY_SET_LEN
(
rest
,
m1
+
len
+
m2
);
if
(
kd
)
{
stack_copy
(
ARY_PTR
(
rest
)
+
m1
+
len
+
m2
,
stack
+
m1
+
m2
+
1
,
kd
);
}
ARY_SET_LEN
(
rest
,
m1
+
len
+
m2
+
kd
);
}
}
regs
[
a
+
1
]
=
stack
[
m1
+
r
+
m2
];
regs
[
a
+
1
]
=
stack
[
m1
+
r
+
m2
];
mrb_gc_arena_restore
(
mrb
,
ai
);
mrb_gc_arena_restore
(
mrb
,
ai
);
...
@@ -1698,74 +1704,114 @@ RETRY_TRY_BLOCK:
...
@@ -1698,74 +1704,114 @@ RETRY_TRY_BLOCK:
int
o
=
MRB_ASPEC_OPT
(
a
);
int
o
=
MRB_ASPEC_OPT
(
a
);
int
r
=
MRB_ASPEC_REST
(
a
);
int
r
=
MRB_ASPEC_REST
(
a
);
int
m2
=
MRB_ASPEC_POST
(
a
);
int
m2
=
MRB_ASPEC_POST
(
a
);
int
kd
=
(
MRB_ASPEC_KEY
(
a
)
>
0
||
MRB_ASPEC_KDICT
(
a
))
?
1
:
0
;
/* unused
/* unused
int k = MRB_ASPEC_KEY(a);
int kd = MRB_ASPEC_KDICT(a);
int b = MRB_ASPEC_BLOCK(a);
int b = MRB_ASPEC_BLOCK(a);
*/
*/
int
argc
=
mrb
->
c
->
ci
->
argc
;
int
argc
=
mrb
->
c
->
ci
->
argc
;
mrb_value
*
argv
=
regs
+
1
;
mrb_value
*
argv
=
regs
+
1
;
mrb_value
*
argv0
=
argv
;
mrb_value
*
const
argv0
=
argv
;
int
len
=
m1
+
o
+
r
+
m2
;
int
const
len
=
m1
+
o
+
r
+
m2
;
int
const
blk_pos
=
len
+
kd
+
1
;
mrb_value
*
blk
=
&
argv
[
argc
<
0
?
1
:
argc
];
mrb_value
*
blk
=
&
argv
[
argc
<
0
?
1
:
argc
];
mrb_value
kdict
;
int
kargs
=
kd
;
/* arguments is passed with Array */
if
(
argc
<
0
)
{
if
(
argc
<
0
)
{
struct
RArray
*
ary
=
mrb_ary_ptr
(
regs
[
1
]);
struct
RArray
*
ary
=
mrb_ary_ptr
(
regs
[
1
]);
argv
=
ARY_PTR
(
ary
);
argv
=
ARY_PTR
(
ary
);
argc
=
(
int
)
ARY_LEN
(
ary
);
argc
=
(
int
)
ARY_LEN
(
ary
);
mrb_gc_protect
(
mrb
,
regs
[
1
]);
mrb_gc_protect
(
mrb
,
regs
[
1
]);
}
}
/* strict argument check */
if
(
mrb
->
c
->
ci
->
proc
&&
MRB_PROC_STRICT_P
(
mrb
->
c
->
ci
->
proc
))
{
if
(
mrb
->
c
->
ci
->
proc
&&
MRB_PROC_STRICT_P
(
mrb
->
c
->
ci
->
proc
))
{
if
(
argc
>=
0
)
{
if
(
argc
>=
0
&&
!
(
argc
<=
1
&&
kd
)
)
{
if
(
argc
<
m1
+
m2
||
(
r
==
0
&&
argc
>
len
))
{
if
(
argc
<
m1
+
m2
+
kd
||
(
r
==
0
&&
argc
>
len
+
kd
))
{
argnum_error
(
mrb
,
m1
+
m2
);
argnum_error
(
mrb
,
m1
+
m2
);
goto
L_RAISE
;
goto
L_RAISE
;
}
}
}
}
}
}
/* extract first argument array to arguments */
else
if
(
len
>
1
&&
argc
==
1
&&
mrb_array_p
(
argv
[
0
]))
{
else
if
(
len
>
1
&&
argc
==
1
&&
mrb_array_p
(
argv
[
0
]))
{
mrb_gc_protect
(
mrb
,
argv
[
0
]);
mrb_gc_protect
(
mrb
,
argv
[
0
]);
argc
=
(
int
)
RARRAY_LEN
(
argv
[
0
]);
argc
=
(
int
)
RARRAY_LEN
(
argv
[
0
]);
argv
=
RARRAY_PTR
(
argv
[
0
]);
argv
=
RARRAY_PTR
(
argv
[
0
]);
}
}
if
(
kd
)
{
/* check last arguments is hash if method takes keyword arguments */
if
(
argc
==
m1
+
m2
)
{
kdict
=
mrb_hash_new
(
mrb
);
kargs
=
0
;
}
else
{
if
(
!
mrb_hash_p
(
argv
[
argc
-
1
]))
{
if
(
r
)
{
kdict
=
mrb_hash_new
(
mrb
);
kargs
=
0
;
}
else
{
mrb_value
str
=
mrb_str_new_lit
(
mrb
,
"Excepcted `Hash` as last argument for keyword arguments"
);
mrb_exc_set
(
mrb
,
mrb_exc_new_str
(
mrb
,
E_ARGUMENT_ERROR
,
str
));
goto
L_RAISE
;
}
}
else
{
kdict
=
argv
[
argc
-
1
];
}
mrb_hash_check_kdict
(
mrb
,
kdict
);
if
(
MRB_ASPEC_KEY
(
a
)
>
0
)
{
kdict
=
mrb_hash_dup
(
mrb
,
kdict
);
}
}
}
/* no rest arguments */
if
(
argc
<
len
)
{
if
(
argc
<
len
)
{
int
mlen
=
m2
;
int
mlen
=
m2
;
if
(
argc
<
m1
+
m2
)
{
if
(
argc
<
m1
+
m2
)
{
if
(
m1
<
argc
)
mlen
=
m1
<
argc
?
argc
-
m1
:
0
;
mlen
=
argc
-
m1
;
else
mlen
=
0
;
}
}
regs
[
len
+
1
]
=
*
blk
;
/* move block */
regs
[
blk_pos
]
=
*
blk
;
/* move block */
if
(
kd
)
regs
[
len
+
1
]
=
kdict
;
SET_NIL_VALUE
(
regs
[
argc
+
1
]);
SET_NIL_VALUE
(
regs
[
argc
+
1
]);
/* copy mandatory and optional arguments */
if
(
argv0
!=
argv
)
{
if
(
argv0
!=
argv
)
{
value_move
(
&
regs
[
1
],
argv
,
argc
-
mlen
);
/* m1 + o */
value_move
(
&
regs
[
1
],
argv
,
argc
-
mlen
);
/* m1 + o */
}
}
if
(
argc
<
m1
)
{
if
(
argc
<
m1
)
{
stack_clear
(
&
regs
[
argc
+
1
],
m1
-
argc
);
stack_clear
(
&
regs
[
argc
+
1
],
m1
-
argc
);
}
}
/* copy post mandatory arguments */
if
(
mlen
)
{
if
(
mlen
)
{
value_move
(
&
regs
[
len
-
m2
+
1
],
&
argv
[
argc
-
mlen
],
mlen
);
value_move
(
&
regs
[
len
-
m2
+
1
],
&
argv
[
argc
-
mlen
],
mlen
);
}
}
if
(
mlen
<
m2
)
{
if
(
mlen
<
m2
)
{
stack_clear
(
&
regs
[
len
-
m2
+
mlen
+
1
],
m2
-
mlen
);
stack_clear
(
&
regs
[
len
-
m2
+
mlen
+
1
],
m2
-
mlen
);
}
}
/* initalize rest arguments with empty Array */
if
(
r
)
{
if
(
r
)
{
regs
[
m1
+
o
+
1
]
=
mrb_ary_new_capa
(
mrb
,
0
);
regs
[
m1
+
o
+
1
]
=
mrb_ary_new_capa
(
mrb
,
0
);
}
}
if
(
o
>
0
&&
argc
>=
m1
+
m2
)
/* skip initailizer of passed arguments */
pc
+=
(
argc
-
m1
-
m2
)
*
3
;
if
(
o
>
0
&&
argc
-
kargs
>=
m1
+
m2
)
pc
+=
(
argc
-
kargs
-
m1
-
m2
)
*
3
;
}
}
else
{
else
{
int
rnum
=
0
;
int
rnum
=
0
;
if
(
argv0
!=
argv
)
{
if
(
argv0
!=
argv
)
{
regs
[
len
+
1
]
=
*
blk
;
/* move block */
regs
[
blk_pos
]
=
*
blk
;
/* move block */
if
(
kd
)
regs
[
len
+
1
]
=
kdict
;
value_move
(
&
regs
[
1
],
argv
,
m1
+
o
);
value_move
(
&
regs
[
1
],
argv
,
m1
+
o
);
}
}
if
(
r
)
{
if
(
r
)
{
mrb_value
ary
;
mrb_value
ary
;
rnum
=
argc
-
m1
-
o
-
m2
;
rnum
=
argc
-
m1
-
o
-
m2
-
kargs
;
ary
=
mrb_ary_new_from_values
(
mrb
,
rnum
,
argv
+
m1
+
o
);
ary
=
mrb_ary_new_from_values
(
mrb
,
rnum
,
argv
+
m1
+
o
);
regs
[
m1
+
o
+
1
]
=
ary
;
regs
[
m1
+
o
+
1
]
=
ary
;
}
}
...
@@ -1775,29 +1821,60 @@ RETRY_TRY_BLOCK:
...
@@ -1775,29 +1821,60 @@ RETRY_TRY_BLOCK:
}
}
}
}
if
(
argv0
==
argv
)
{
if
(
argv0
==
argv
)
{
regs
[
len
+
1
]
=
*
blk
;
/* move block */
regs
[
blk_pos
]
=
*
blk
;
/* move block */
if
(
kd
)
regs
[
len
+
1
]
=
kdict
;
}
}
pc
+=
o
*
3
;
pc
+=
o
*
3
;
}
}
mrb
->
c
->
ci
->
argc
=
len
;
/* format arguments for generated code */
mrb
->
c
->
ci
->
argc
=
len
+
kd
;
/* clear local (but non-argument) variables */
/* clear local (but non-argument) variables */
if
(
irep
->
nlocals
-
len
-
2
>
0
)
{
if
(
irep
->
nlocals
-
blk_pos
-
1
>
0
)
{
stack_clear
(
&
regs
[
len
+
2
],
irep
->
nlocals
-
len
-
2
);
stack_clear
(
&
regs
[
blk_pos
+
1
],
irep
->
nlocals
-
blk_pos
-
1
);
}
}
JUMP
;
JUMP
;
}
}
CASE
(
OP_KARG
,
BB
)
{
CASE
(
OP_KARG
,
BB
)
{
/* not implemented yet */
mrb_value
k
=
mrb_symbol_value
(
syms
[
b
]);
mrb_value
kdict
=
regs
[
mrb
->
c
->
ci
->
argc
];
if
(
!
mrb_hash_key_p
(
mrb
,
kdict
,
k
))
{
mrb_value
str
=
mrb_format
(
mrb
,
"missing keyword: %S"
,
k
);
mrb_exc_set
(
mrb
,
mrb_exc_new_str
(
mrb
,
E_ARGUMENT_ERROR
,
str
));
goto
L_RAISE
;
}
regs
[
a
]
=
mrb_hash_get
(
mrb
,
kdict
,
k
);
mrb_hash_delete_key
(
mrb
,
kdict
,
k
);
NEXT
;
NEXT
;
}
}
CASE
(
OP_KARG2
,
BB
)
{
/* not implemented yet */
CASE
(
OP_KEY_P
,
BB
)
{
mrb_value
k
=
mrb_symbol_value
(
syms
[
b
]);
mrb_value
kdict
=
regs
[
mrb
->
c
->
ci
->
argc
];
mrb_bool
key_p
=
mrb_hash_key_p
(
mrb
,
kdict
,
k
);
regs
[
a
]
=
mrb_bool_value
(
key_p
);
NEXT
;
}
CASE
(
OP_KEYEND
,
Z
)
{
mrb_value
kdict
=
regs
[
mrb
->
c
->
ci
->
argc
];
if
(
mrb_hash_p
(
kdict
)
&&
!
mrb_hash_empty_p
(
mrb
,
kdict
))
{
mrb_value
keys
=
mrb_hash_keys
(
mrb
,
kdict
);
mrb_value
key1
=
RARRAY_PTR
(
keys
)[
0
];
mrb_value
str
=
mrb_format
(
mrb
,
"unknown keyword: %S"
,
key1
);
mrb_exc_set
(
mrb
,
mrb_exc_new_str
(
mrb
,
E_ARGUMENT_ERROR
,
str
));
goto
L_RAISE
;
}
NEXT
;
NEXT
;
}
}
CASE
(
OP_KDICT
,
B
)
{
CASE
(
OP_KDICT
,
B
)
{
/* not implemented yet */
regs
[
a
]
=
regs
[
mrb
->
c
->
ci
->
argc
];
NEXT
;
NEXT
;
}
}
...
@@ -2064,9 +2141,10 @@ RETRY_TRY_BLOCK:
...
@@ -2064,9 +2141,10 @@ RETRY_TRY_BLOCK:
}
}
CASE
(
OP_BLKPUSH
,
BS
)
{
CASE
(
OP_BLKPUSH
,
BS
)
{
int
m1
=
(
b
>>
10
)
&
0x3f
;
int
m1
=
(
b
>>
11
)
&
0x3f
;
int
r
=
(
b
>>
9
)
&
0x1
;
int
r
=
(
b
>>
10
)
&
0x1
;
int
m2
=
(
b
>>
4
)
&
0x1f
;
int
m2
=
(
b
>>
5
)
&
0x1f
;
int
kd
=
(
b
>>
4
)
&
0x1
;
int
lv
=
(
b
>>
0
)
&
0xf
;
int
lv
=
(
b
>>
0
)
&
0xf
;
mrb_value
*
stack
;
mrb_value
*
stack
;
...
@@ -2084,7 +2162,7 @@ RETRY_TRY_BLOCK:
...
@@ -2084,7 +2162,7 @@ RETRY_TRY_BLOCK:
localjump_error
(
mrb
,
LOCALJUMP_ERROR_YIELD
);
localjump_error
(
mrb
,
LOCALJUMP_ERROR_YIELD
);
goto
L_RAISE
;
goto
L_RAISE
;
}
}
regs
[
a
]
=
stack
[
m1
+
r
+
m2
];
regs
[
a
]
=
stack
[
m1
+
r
+
m2
+
kd
];
NEXT
;
NEXT
;
}
}
...
...
test/t/syntax.rb
View file @
8c9e7127
...
@@ -403,6 +403,9 @@ assert('External command execution.') do
...
@@ -403,6 +403,9 @@ assert('External command execution.') do
assert_equal
'test dynamic `'
,
t
assert_equal
'test dynamic `'
,
t
assert_equal
[
'test'
,
'test dynamic `'
,
'test'
,
'test dynamic `'
],
results
assert_equal
[
'test'
,
'test dynamic `'
,
'test'
,
'test dynamic `'
],
results
results
=
[]
assert_equal
'test sym test sym test'
,
`test
#{
:sym
}
test
#{
:sym
}
test`
alias_method
sym
,
:old_cmd
alias_method
sym
,
:old_cmd
end
end
true
true
...
@@ -466,3 +469,183 @@ this is a comment that has extra after =begin and =end with tabs after it
...
@@ -466,3 +469,183 @@ this is a comment that has extra after =begin and =end with tabs after it
=end
xxxxxxxxxxxxxxxxxxxxxxxxxx
=end
xxxxxxxxxxxxxxxxxxxxxxxxxx
assert_equal
(
line
+
4
,
__LINE__
)
assert_equal
(
line
+
4
,
__LINE__
)
end
end
assert
'keyword arguments'
do
def
m
(
a
,
b
:)
[
a
,
b
]
end
assert_equal
[
1
,
2
],
m
(
1
,
b:
2
)
assert_raise
(
ArgumentError
)
{
m
b:
1
}
assert_raise
(
ArgumentError
)
{
m
1
}
def
m
(
a
:)
a
end
assert_equal
1
,
m
(
a:
1
)
assert_raise
(
ArgumentError
)
{
m
}
assert_raise
(
ArgumentError
)
{
m
'a'
=>
1
,
a:
1
}
h
=
{
a:
1
}
assert_equal
1
,
m
(
h
)
assert_equal
({
a:
1
},
h
)
def
m
(
a:
1
)
a
end
assert_equal
1
,
m
assert_equal
2
,
m
(
a:
2
)
assert_raise
(
ArgumentError
)
{
m
1
}
def
m
(
**
)
end
assert_nil
m
assert_nil
m
a:
1
,
b:
2
assert_raise
(
ArgumentError
)
{
m
2
}
def
m
(
a
,
**
)
a
end
assert_equal
1
,
m
(
1
)
assert_equal
1
,
m
(
1
,
a:
2
,
b:
3
)
assert_equal
({
'a'
=>
1
,
b:
2
},
m
(
'a'
=>
1
,
b:
2
))
def
m
(
a
,
**
k
)
[
a
,
k
]
end
assert_equal
[
1
,
{}],
m
(
1
)
assert_equal
[
1
,
{
a:
2
,
b:
3
}],
m
(
1
,
a:
2
,
b:
3
)
assert_equal
[{
'a'
=>
1
,
b:
2
},
{}],
m
(
'a'
=>
1
,
b:
2
)
def
m
(
a
=
1
,
**
)
a
end
assert_equal
1
,
m
assert_equal
2
,
m
(
2
,
a:
1
,
b:
0
)
assert_raise
(
ArgumentError
)
{
m
(
'a'
=>
1
,
a:
2
)
}
def
m
(
a
=
1
,
**
k
)
[
a
,
k
]
end
assert_equal
[
1
,
{}],
m
assert_equal
[
2
,
{
a:
1
,
b:
2
}],
m
(
2
,
a:
1
,
b:
2
)
assert_equal
[{
a:
1
},
{
b:
2
}],
m
({
a:
1
},
{
b:
2
})
def
m
(
*
,
a
:)
a
end
assert_equal
1
,
m
(
a:
1
)
assert_equal
3
,
m
(
1
,
2
,
a:
3
)
assert_raise
(
ArgumentError
)
{
m
(
'a'
=>
1
,
a:
2
)
}
def
m
(
*
a
,
b
:)
[
a
,
b
]
end
assert_equal
[[],
1
],
m
(
b:
1
)
assert_equal
[[
1
,
2
],
3
],
m
(
1
,
2
,
b:
3
)
assert_raise
(
ArgumentError
)
{
m
(
'a'
=>
1
,
b:
2
)
}
def
m
(
*
a
,
b:
1
)
[
a
,
b
]
end
assert_equal
[[],
1
],
m
assert_equal
[[
1
,
2
,
3
],
4
],
m
(
1
,
2
,
3
,
b:
4
)
assert_raise
(
ArgumentError
)
{
m
(
'a'
=>
1
,
b:
2
)
}
def
m
(
*
,
**
)
end
assert_nil
m
()
assert_nil
m
(
a:
1
,
b:
2
)
assert_nil
m
(
1
,
2
,
3
,
a:
4
,
b:
5
)
def
m
(
*
a
,
**
)
a
end
assert_equal
[],
m
()
assert_equal
[
1
,
2
,
3
],
m
(
1
,
2
,
3
,
a:
4
,
b:
5
)
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
)
}
assert_equal
[
1
],
m
(
1
,
**
{
a:
2
})
def
m
(
*
,
**
k
)
k
end
assert_equal
({},
m
())
assert_equal
({
a:
4
,
b:
5
},
m
(
1
,
2
,
3
,
a:
4
,
b:
5
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
)
}
def
m
(
a
=
nil
,
b
=
nil
,
**
k
)
[
a
,
k
]
end
assert_equal
[
nil
,
{}],
m
()
assert_equal
([
nil
,
{
a:
1
}],
m
(
a:
1
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
)
}
assert_equal
([{
"a"
=>
1
},
{
a:
1
}],
m
({
"a"
=>
1
},
a:
1
))
assert_equal
([{
a:
1
},
{}],
m
({
a:
1
},
{}))
assert_equal
([
nil
,
{}],
m
({}))
def
m
(
*
a
,
**
k
)
[
a
,
k
]
end
assert_equal
([[],
{}],
m
())
assert_equal
([[
1
],
{}],
m
(
1
))
assert_equal
([[],
{
a:
1
,
b:
2
}],
m
(
a:
1
,
b:
2
))
assert_equal
([[
1
,
2
,
3
],
{
a:
2
}],
m
(
1
,
2
,
3
,
a:
2
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
)
}
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
)
}
assert_equal
([[],
{
a:
1
}],
m
(
a:
1
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
)
}
assert_equal
([[{
"a"
=>
1
}],
{
a:
1
}],
m
({
"a"
=>
1
},
a:
1
))
assert_equal
([[{
a:
1
}],
{}],
m
({
a:
1
},
{}))
assert_raise
(
ArgumentError
)
{
m
({
a:
1
},
{
"a"
=>
1
})
}
def
m
(
a
:,
b
:)
[
a
,
b
]
end
assert_equal
([
1
,
2
],
m
(
a:
1
,
b:
2
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
,
b:
2
)
}
def
m
(
a
:,
b:
1
)
[
a
,
b
]
end
assert_equal
([
1
,
1
],
m
(
a:
1
))
assert_equal
([
1
,
2
],
m
(
a:
1
,
b:
2
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
,
b:
2
)
}
def
m
(
a
:,
**
)
a
end
assert_equal
(
1
,
m
(
a:
1
))
assert_equal
(
1
,
m
(
a:
1
,
b:
2
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
,
b:
2
)
}
def
m
(
a
:,
**
k
)
[
a
,
k
]
end
assert_equal
([
1
,
{}],
m
(
a:
1
))
assert_equal
([
1
,
{
b:
2
,
c:
3
}],
m
(
a:
1
,
b:
2
,
c:
3
))
assert_raise
(
ArgumentError
)
{
m
(
"a"
=>
1
,
a:
1
,
b:
2
)
}
=begin
def m(a:, &b) [a, b] end
assert_equal([1, nil], m(a: 1))
assert_equal([1, l], m(a: 1, &(l = ->{})))
=end
def
m
(
a:
1
,
b
:)
[
a
,
b
]
end
assert_equal
([
1
,
0
],
m
(
b:
0
))
assert_equal
([
3
,
2
],
m
(
b:
2
,
a:
3
))
assert_raise
(
ArgumentError
)
{
m
a:
1
}
def
m
(
a:
def
m
(
a:
1
)
a
end
,
b
:)
[
a
,
b
]
end
assert_equal
([
2
,
3
],
m
(
a:
2
,
b:
3
))
assert_equal
([
:m
,
1
],
m
(
b:
1
))
# Note the default value of a: in the original method.
assert_equal
(
1
,
m
())
def
m
(
a:
1
,
b:
2
)
[
a
,
b
]
end
assert_equal
([
1
,
2
],
m
())
assert_equal
([
4
,
3
],
m
(
b:
3
,
a:
4
))
def
m
(
a:
1
,
**
)
a
end
assert_equal
(
1
,
m
())
assert_equal
(
2
,
m
(
a:
2
,
b:
1
))
def
m
(
a:
1
,
**
k
)
[
a
,
k
]
end
assert_equal
([
1
,
{
b:
2
,
c:
3
}],
m
(
b:
2
,
c:
3
))
def
m
(
a
:,
**
)
yield
end
assert_raise
(
ArgumentError
)
{
m
{
:blk
}
}
assert_equal
:blk
,
m
(
a:
1
){
:blk
}
def
m
(
a
:,
**
k
,
&
b
)
[
b
.
call
,
k
]
end
assert_raise
(
ArgumentError
)
{
m
{
:blk
}
}
assert_equal
[
:blk
,
{
b:
2
}],
m
(
a:
1
,
b:
2
){
:blk
}
def
m
(
**
k
,
&
b
)
[
k
,
b
]
end
assert_equal
([{
a:
1
,
b:
2
},
nil
],
m
(
a:
1
,
b:
2
))
assert_equal
:blk
,
m
{
:blk
}[
1
].
call
def
m
(
hsh
=
{})
hsh
end
assert_equal
({
a:
1
,
b:
2
},
m
(
a:
1
,
b:
2
))
assert_equal
({
a:
1
,
'b'
=>
2
},
m
(
a:
1
,
'b'
=>
2
))
def
m
(
hsh
)
hsh
end
assert_equal
({
a:
1
,
b:
2
},
m
(
a:
1
,
b:
2
))
assert_equal
({
a:
1
,
'b'
=>
2
},
m
(
a:
1
,
'b'
=>
2
))
=begin
def m(a, b=1, *c, (*d, (e)), f: 2, g:, h:, **k, &l)
[a, b, c, d, e, f, g, h, k, l]
end
result = m(9, 8, 7, 6, f: 5, g: 4, h: 3, &(l = ->{}))
assert_equal([9, 8, [7], [], 6, 5, 4, 3, {}, l], result)
def m a, b=1, *c, d, e:, f: 2, g:, **k, &l
[a, b, c, d, e, f, g, k, l]
end
result = m(1, 2, e: 3, g: 4, h: 5, i: 6, &(l = ->{}))
assert_equal([1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l], result)
=end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment