summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-12-17 03:20:58 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-12-17 03:20:58 +0000
commit467830e86751e864410791334e36c4c8c4d54937 (patch)
treeeff61c98cf143fc265760a639e80eea4fc74e244 /compile.c
parentfd639a4c3bb7f5a9f0f33c2230ab58fd4bd3d70b (diff)
compile.c: struct accessors
* compile.c (rb_method_for_self_aref, rb_method_for_self_aset): move from iseq.c to build from node instead of arrays. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48876 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/compile.c b/compile.c
index d607f50..c59402d 100644
--- a/compile.c
+++ b/compile.c
@@ -6234,3 +6234,89 @@ rb_parse_in_main(void)
{
return GET_THREAD()->parse_in_eval < 0;
}
+
+static int
+caller_location(VALUE *path, VALUE *absolute_path)
+{
+ const rb_thread_t *const th = GET_THREAD();
+ const rb_control_frame_t *const cfp =
+ rb_vm_get_ruby_level_next_cfp(th, th->cfp);
+
+ if (cfp) {
+ int line = rb_vm_get_sourceline(cfp);
+ *path = cfp->iseq->location.path;
+ *absolute_path = cfp->iseq->location.absolute_path;
+ return line;
+ }
+ else {
+ *path = rb_str_new2("<compiled>");
+ *absolute_path = *path;
+ return 1;
+ }
+}
+
+typedef struct {
+ VALUE arg;
+ rb_insn_func_t func;
+ int line;
+} accessor_args;
+
+static VALUE
+method_for_self(VALUE name, VALUE arg, rb_insn_func_t func,
+ VALUE (*build)(rb_iseq_t *, LINK_ANCHOR *, VALUE))
+{
+ VALUE path, absolute_path;
+ accessor_args acc;
+
+ acc.arg = arg;
+ acc.func = func;
+ acc.line = caller_location(&path, &absolute_path);
+ return rb_iseq_new_with_opt(NEW_IFUNC(build, (VALUE)&acc),
+ rb_sym2str(name), path, absolute_path,
+ INT2FIX(acc.line), 0, ISEQ_TYPE_METHOD, 0);
+}
+
+static VALUE
+for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a)
+{
+ const accessor_args *const args = (void *)a;
+ const int line = args->line;
+
+ iseq_set_local_table(iseq, 0);
+ iseq->param.lead_num = 0;
+ iseq->param.size = 0;
+
+ ADD_INSN1(ret, line, putobject, args->arg);
+ ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func);
+ return Qnil;
+}
+
+static VALUE
+for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a)
+{
+ const accessor_args *const args = (void *)a;
+ const int line = args->line;
+ static const ID vars[] = {1, idUScore};
+
+ iseq_set_local_table(iseq, vars);
+ iseq->param.lead_num = 1;
+ iseq->param.size = 1;
+
+ ADD_INSN2(ret, line, getlocal, INT2FIX(numberof(vars)-0), INT2FIX(0));
+ ADD_INSN1(ret, line, putobject, args->arg);
+ ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func);
+ ADD_INSN(ret, line, pop);
+ return Qnil;
+}
+
+VALUE
+rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
+{
+ return method_for_self(name, arg, func, for_self_aref);
+}
+
+VALUE
+rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
+{
+ return method_for_self(name, arg, func, for_self_aset);
+}