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
c2c37e14
Unverified
Commit
c2c37e14
authored
Apr 09, 2021
by
Yukihiro "Matz" Matsumoto
Committed by
GitHub
Apr 09, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5401 from dearblue/mcall
Reorganize `mcall()` in `mruby-method`
parents
6d3c0227
4c196dcd
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
162 additions
and
53 deletions
+162
-53
mrbgems/mruby-eval/src/eval.c
mrbgems/mruby-eval/src/eval.c
+0
-9
mrbgems/mruby-method/src/method.c
mrbgems/mruby-method/src/method.c
+133
-40
src/vm.c
src/vm.c
+29
-4
No files found.
mrbgems/mruby-eval/src/eval.c
View file @
c2c37e14
...
...
@@ -131,15 +131,6 @@ exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc, mrb_func_t posthoo
{
/* no argument passed from eval() */
mrb
->
c
->
ci
->
argc
=
0
;
if
(
mrb
->
c
->
ci
->
acc
<
0
)
{
ptrdiff_t
cioff
=
mrb
->
c
->
ci
-
mrb
->
c
->
cibase
;
mrb_value
ret
=
mrb_top_run
(
mrb
,
proc
,
self
,
0
);
if
(
mrb
->
exc
)
{
mrb_exc_raise
(
mrb
,
mrb_obj_value
(
mrb
->
exc
));
}
mrb
->
c
->
ci
=
mrb
->
c
->
cibase
+
cioff
;
return
ret
;
}
/* clear block */
mrb
->
c
->
ci
->
stack
[
1
]
=
mrb_nil_value
();
return
mrb_exec_irep
(
mrb
,
self
,
proc
,
posthook
);
...
...
mrbgems/mruby-method/src/method.c
View file @
c2c37e14
...
...
@@ -6,12 +6,126 @@
#include "mruby/string.h"
#include "mruby/presym.h"
mrb_noreturn
void
mrb_method_missing
(
mrb_state
*
mrb
,
mrb_sym
name
,
mrb_value
self
,
mrb_value
args
);
mrb_value
mrb_exec_irep
(
mrb_state
*
mrb
,
mrb_value
self
,
struct
RProc
*
p
,
mrb_func_t
posthook
);
static
mrb_value
args_shift
(
mrb_state
*
mrb
)
{
mrb_value
*
argv
=
mrb
->
c
->
ci
->
stack
+
1
;
if
(
mrb
->
c
->
ci
->
argc
>
0
)
{
mrb_value
obj
=
argv
[
0
];
memmove
(
argv
,
argv
+
1
,
(
mrb
->
c
->
ci
->
argc
+
1
/* block */
-
1
/* first value */
)
*
sizeof
(
mrb_value
));
mrb
->
c
->
ci
->
argc
--
;
return
obj
;
}
else
if
(
mrb
->
c
->
ci
->
argc
<
0
&&
RARRAY_LEN
(
*
argv
)
>
0
)
{
return
mrb_ary_shift
(
mrb
,
*
argv
);
}
else
{
mrb_argnum_error
(
mrb
,
0
,
1
,
-
1
);
return
mrb_undef_value
();
/* not reached */
}
}
static
void
args_unshift
(
mrb_state
*
mrb
,
mrb_value
obj
)
{
mrb_value
*
argv
=
mrb
->
c
->
ci
->
stack
+
1
;
if
(
mrb
->
c
->
ci
->
argc
>=
0
)
{
mrb_value
block
=
argv
[
mrb
->
c
->
ci
->
argc
];
argv
[
0
]
=
mrb_ary_new_from_values
(
mrb
,
mrb
->
c
->
ci
->
argc
,
argv
);
argv
[
1
]
=
block
;
mrb
->
c
->
ci
->
argc
=
-
1
;
}
mrb_ary_unshift
(
mrb
,
*
argv
,
obj
);
}
static
struct
RProc
*
method_missing_prepare
(
mrb_state
*
mrb
,
mrb_sym
*
mid
,
mrb_value
recv
,
struct
RClass
**
tc
)
{
const
mrb_sym
id_method_missing
=
MRB_SYM
(
method_missing
);
if
(
*
mid
==
id_method_missing
)
{
method_missing:
;
int
argc
=
mrb
->
c
->
ci
->
argc
;
mrb_value
*
argv
=
mrb
->
c
->
ci
->
stack
+
1
;
mrb_value
args
=
(
argc
<
0
)
?
argv
[
0
]
:
mrb_ary_new_from_values
(
mrb
,
argc
,
argv
);
mrb_method_missing
(
mrb
,
*
mid
,
recv
,
args
);
}
*
tc
=
mrb_class
(
mrb
,
recv
);
mrb_method_t
m
=
mrb_method_search_vm
(
mrb
,
tc
,
id_method_missing
);
if
(
MRB_METHOD_UNDEF_P
(
m
))
{
goto
method_missing
;
}
struct
RProc
*
proc
;
if
(
MRB_METHOD_FUNC_P
(
m
))
{
proc
=
mrb_proc_new_cfunc
(
mrb
,
MRB_METHOD_FUNC
(
m
));
MRB_PROC_SET_TARGET_CLASS
(
proc
,
*
tc
);
}
else
{
proc
=
MRB_METHOD_PROC
(
m
);
}
args_unshift
(
mrb
,
mrb_symbol_value
(
*
mid
));
*
mid
=
id_method_missing
;
return
proc
;
}
static
struct
RObject
*
method_object_alloc
(
mrb_state
*
mrb
,
struct
RClass
*
mclass
)
{
return
(
struct
RObject
*
)
mrb_obj_alloc
(
mrb
,
MRB_TT_OBJECT
,
mclass
);
}
static
struct
RProc
*
method_extract_proc
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
obj
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_proc
));
if
(
mrb_nil_p
(
obj
))
{
return
NULL
;
}
else
{
mrb_check_type
(
mrb
,
obj
,
MRB_TT_PROC
);
return
mrb_proc_ptr
(
obj
);
}
}
static
mrb_value
method_extract_receiver
(
mrb_state
*
mrb
,
mrb_value
self
)
{
return
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_recv
));
}
static
mrb_sym
method_extract_mid
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
obj
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_name
));
mrb_check_type
(
mrb
,
obj
,
MRB_TT_SYMBOL
);
return
mrb_symbol
(
obj
);
}
static
struct
RClass
*
method_extract_owner
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
obj
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_owner
));
switch
(
mrb_type
(
obj
))
{
case
MRB_TT_CLASS
:
case
MRB_TT_MODULE
:
case
MRB_TT_SCLASS
:
break
;
default:
mrb_raise
(
mrb
,
E_TYPE_ERROR
,
"not class/module as owner of method object"
);
}
return
mrb_class_ptr
(
obj
);
}
static
void
bind_check
(
mrb_state
*
mrb
,
mrb_value
recv
,
mrb_value
owner
)
{
...
...
@@ -109,61 +223,40 @@ method_eql(mrb_state *mrb, mrb_value self)
#undef IV_GET
static
mrb_value
mcall
(
mrb_state
*
mrb
,
mrb_value
recv
,
mrb_value
proc
,
mrb_value
name
,
struct
RClass
*
owner
,
mrb_int
argc
,
const
mrb_value
*
argv
,
mrb_value
block
)
mcall
(
mrb_state
*
mrb
,
mrb_value
self
,
mrb_value
recv
)
{
mrb_value
ret
;
mrb_sym
orig_mid
=
mrb
->
c
->
ci
->
mid
;
struct
RProc
*
proc
=
method_extract_proc
(
mrb
,
self
);
mrb_sym
mid
=
method_extract_mid
(
mrb
,
self
);
struct
RClass
*
tc
=
method_extract_owner
(
mrb
,
self
);
mrb
->
c
->
ci
->
mid
=
mrb_symbol
(
name
);
if
(
mrb_nil_p
(
proc
))
{
mrb_value
missing_argv
=
mrb_ary_new_from_values
(
mrb
,
argc
,
argv
);
mrb_ary_unshift
(
mrb
,
missing_argv
,
name
);
ret
=
mrb_funcall_argv
(
mrb
,
recv
,
MRB_SYM
(
method_missing
),
argc
+
1
,
RARRAY_PTR
(
missing_argv
));
}
else
if
(
!
mrb_nil_p
(
block
))
{
/*
workaround since `mrb_yield_with_class` does not support passing block as parameter
need new API that initializes `mrb->c->stack[argc+1]` with block passed by argument
*/
ret
=
mrb_funcall_with_block
(
mrb
,
recv
,
mrb_symbol
(
name
),
argc
,
argv
,
block
);
if
(
mrb_undef_p
(
recv
))
{
recv
=
method_extract_receiver
(
mrb
,
self
);
}
else
{
ret
=
mrb_yield_with_class
(
mrb
,
proc
,
argc
,
argv
,
recv
,
owner
);
bind_check
(
mrb
,
recv
,
mrb_obj_value
(
tc
)
);
}
mrb
->
c
->
ci
->
mid
=
orig_mid
;
return
ret
;
if
(
!
proc
)
{
proc
=
method_missing_prepare
(
mrb
,
&
mid
,
recv
,
&
tc
);
}
mrb
->
c
->
ci
->
mid
=
mid
;
mrb
->
c
->
ci
->
u
.
target_class
=
tc
;
return
mrb_exec_irep
(
mrb
,
recv
,
proc
,
NULL
);
}
static
mrb_value
method_call
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
proc
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_proc
));
mrb_value
name
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_name
));
mrb_value
recv
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_recv
));
struct
RClass
*
owner
=
mrb_class_ptr
(
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_owner
)));
mrb_int
argc
;
const
mrb_value
*
argv
;
mrb_value
block
;
mrb_get_args
(
mrb
,
"*&"
,
&
argv
,
&
argc
,
&
block
);
return
mcall
(
mrb
,
recv
,
proc
,
name
,
owner
,
argc
,
argv
,
block
);
return
mcall
(
mrb
,
self
,
mrb_undef_value
());
}
static
mrb_value
method_bcall
(
mrb_state
*
mrb
,
mrb_value
self
)
{
mrb_value
proc
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_proc
));
mrb_value
name
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_name
));
mrb_value
recv
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_recv
));
mrb_value
owner
=
mrb_iv_get
(
mrb
,
self
,
MRB_SYM
(
_owner
));
mrb_int
argc
;
const
mrb_value
*
argv
;
mrb_value
block
;
mrb_get_args
(
mrb
,
"o*&"
,
&
recv
,
&
argv
,
&
argc
,
&
block
);
bind_check
(
mrb
,
recv
,
owner
);
return
mcall
(
mrb
,
recv
,
proc
,
name
,
mrb_class_ptr
(
owner
),
argc
,
argv
,
block
);
mrb_value
recv
=
args_shift
(
mrb
);
mrb_gc_protect
(
mrb
,
recv
);
return
mcall
(
mrb
,
self
,
recv
);
}
static
mrb_value
...
...
src/vm.c
View file @
c2c37e14
...
...
@@ -543,8 +543,8 @@ mrb_exec_irep_prepare_posthook(mrb_state *mrb, mrb_callinfo *ci, int nregs, mrb_
*
* However, if `proc` is a C function, it will be ignored.
*/
mrb_value
mrb_exec_irep
(
mrb_state
*
mrb
,
mrb_value
self
,
struct
RProc
*
p
,
mrb_func_t
posthook
)
static
mrb_value
mrb_exec_irep
_vm
(
mrb_state
*
mrb
,
mrb_value
self
,
struct
RProc
*
p
,
mrb_func_t
posthook
)
{
mrb_callinfo
*
ci
=
mrb
->
c
->
ci
;
int
keep
,
nregs
;
...
...
@@ -575,6 +575,31 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t postho
return
self
;
}
mrb_value
mrb_exec_irep
(
mrb_state
*
mrb
,
mrb_value
self
,
struct
RProc
*
p
,
mrb_func_t
posthook
)
{
mrb_callinfo
*
ci
=
mrb
->
c
->
ci
;
if
(
ci
->
acc
>=
0
)
{
return
mrb_exec_irep_vm
(
mrb
,
self
,
p
,
posthook
);
}
else
{
mrb_value
ret
;
if
(
MRB_PROC_CFUNC_P
(
p
))
{
cipush
(
mrb
,
0
,
CI_ACC_DIRECT
,
mrb_vm_ci_target_class
(
ci
),
p
,
ci
->
mid
,
ci
->
argc
);
ret
=
MRB_PROC_CFUNC
(
p
)(
mrb
,
self
);
cipop
(
mrb
);
}
else
{
int
keep
=
(
ci
->
argc
<
0
?
1
:
ci
->
argc
)
+
2
/* receiver + block */
;
ret
=
mrb_top_run
(
mrb
,
p
,
self
,
keep
);
}
if
(
mrb
->
exc
&&
mrb
->
jmp
)
{
mrb_exc_raise
(
mrb
,
mrb_obj_value
(
mrb
->
exc
));
}
return
ret
;
}
}
/* 15.3.1.3.4 */
/* 15.3.1.3.44 */
/*
...
...
@@ -638,7 +663,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
}
return
MRB_METHOD_CFUNC
(
m
)(
mrb
,
self
);
}
return
mrb_exec_irep
(
mrb
,
self
,
MRB_METHOD_PROC
(
m
),
NULL
);
return
mrb_exec_irep
_vm
(
mrb
,
self
,
MRB_METHOD_PROC
(
m
),
NULL
);
}
static
mrb_value
...
...
@@ -826,7 +851,7 @@ mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const
mrb
->
c
->
ci
->
stack
[
1
]
=
mrb_ary_new_from_values
(
mrb
,
argc
,
argv
);
mrb
->
c
->
ci
->
stack
[
2
]
=
mrb_nil_value
();
ci
->
argc
=
-
1
;
return
mrb_exec_irep
(
mrb
,
self
,
p
,
NULL
);
return
mrb_exec_irep
_vm
(
mrb
,
self
,
p
,
NULL
);
}
static
struct
RBreak
*
...
...
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