1 #include <mruby.h>
2 #include <mruby/class.h>
3 #include <mruby/compile.h>
4 #include <mruby/irep.h>
5 #include <mruby/proc.h>
6 #include <mruby/opcode.h>
7 #include <mruby/error.h>
8 
9 mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p);
10 mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
11 
12 void mrb_codedump_all(mrb_state*, struct RProc*);
13 
14 static struct RProc*
create_proc_from_string(mrb_state * mrb,char * s,mrb_int len,mrb_value binding,const char * file,mrb_int line)15 create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line)
16 {
17   mrbc_context *cxt;
18   struct mrb_parser_state *p;
19   struct RProc *proc;
20   struct REnv *e;
21   mrb_callinfo *ci; /* callinfo of eval caller */
22   struct RClass *target_class = NULL;
23   int bidx;
24 
25   if (!mrb_nil_p(binding)) {
26     mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil.");
27   }
28 
29   cxt = mrbc_context_new(mrb);
30   cxt->lineno = (uint16_t)line;
31 
32   mrbc_filename(mrb, cxt, file ? file : "(eval)");
33   cxt->capture_errors = TRUE;
34   cxt->no_optimize = TRUE;
35   ci = (mrb->c->ci > mrb->c->cibase) ? mrb->c->ci - 1 : mrb->c->cibase;
36   cxt->upper = ci->proc && MRB_PROC_CFUNC_P(ci->proc) ? NULL : ci->proc;
37 
38   p = mrb_parse_nstring(mrb, s, len, cxt);
39 
40   /* only occur when memory ran out */
41   if (!p) {
42     mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state.");
43   }
44 
45   if (0 < p->nerr) {
46     /* parse error */
47     mrb_value str;
48 
49     if (file) {
50       str = mrb_format(mrb, "file %s line %d: %s",
51                        file,
52                        p->error_buffer[0].lineno,
53                        p->error_buffer[0].message);
54     }
55     else {
56       str = mrb_format(mrb, "line %d: %s",
57                        p->error_buffer[0].lineno,
58                        p->error_buffer[0].message);
59     }
60     mrb_parser_free(p);
61     mrbc_context_free(mrb, cxt);
62     mrb_exc_raise(mrb, mrb_exc_new_str(mrb, E_SYNTAX_ERROR, str));
63   }
64 
65   proc = mrb_generate_code(mrb, p);
66   if (proc == NULL) {
67     /* codegen error */
68     mrb_parser_free(p);
69     mrbc_context_free(mrb, cxt);
70     mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error");
71   }
72   if (mrb->c->ci > mrb->c->cibase) {
73     ci = &mrb->c->ci[-1];
74   }
75   else {
76     ci = mrb->c->cibase;
77   }
78   if (ci->proc) {
79     target_class = MRB_PROC_TARGET_CLASS(ci->proc);
80   }
81   if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
82     if (ci->env) {
83       e = ci->env;
84     }
85     else {
86       e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV,
87                                       (struct RClass*)target_class);
88       e->mid = ci->mid;
89       e->stack = ci[1].stackent;
90       e->cxt = mrb->c;
91       MRB_ENV_SET_LEN(e, ci->proc->body.irep->nlocals);
92       bidx = ci->argc;
93       if (ci->argc < 0) bidx = 2;
94       else bidx += 1;
95       MRB_ENV_SET_BIDX(e, bidx);
96       ci->env = e;
97     }
98     proc->e.env = e;
99     proc->flags |= MRB_PROC_ENVSET;
100     mrb_field_write_barrier(mrb, (struct RBasic*)proc, (struct RBasic*)e);
101   }
102   proc->upper = ci->proc;
103   mrb->c->ci->target_class = target_class;
104   /* mrb_codedump_all(mrb, proc); */
105 
106   mrb_parser_free(p);
107   mrbc_context_free(mrb, cxt);
108 
109   return proc;
110 }
111 
112 static mrb_value
exec_irep(mrb_state * mrb,mrb_value self,struct RProc * proc)113 exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
114 {
115   /* no argument passed from eval() */
116   mrb->c->ci->argc = 0;
117   if (mrb->c->ci->acc < 0) {
118     ptrdiff_t cioff = mrb->c->ci - mrb->c->cibase;
119     mrb_value ret = mrb_top_run(mrb, proc, self, 0);
120     if (mrb->exc) {
121       mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
122     }
123     mrb->c->ci = mrb->c->cibase + cioff;
124     return ret;
125   }
126   /* clear block */
127   mrb->c->stack[1] = mrb_nil_value();
128   return mrb_exec_irep(mrb, self, proc);
129 }
130 
131 static mrb_value
f_eval(mrb_state * mrb,mrb_value self)132 f_eval(mrb_state *mrb, mrb_value self)
133 {
134   char *s;
135   mrb_int len;
136   mrb_value binding = mrb_nil_value();
137   char *file = NULL;
138   mrb_int line = 1;
139   struct RProc *proc;
140 
141   mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line);
142 
143   proc = create_proc_from_string(mrb, s, len, binding, file, line);
144   mrb_assert(!MRB_PROC_CFUNC_P(proc));
145   return exec_irep(mrb, self, proc);
146 }
147 
148 static mrb_value
f_instance_eval(mrb_state * mrb,mrb_value self)149 f_instance_eval(mrb_state *mrb, mrb_value self)
150 {
151   mrb_value b;
152   mrb_int argc; mrb_value *argv;
153 
154   mrb_get_args(mrb, "*!&", &argv, &argc, &b);
155 
156   if (mrb_nil_p(b)) {
157     char *s;
158     mrb_int len;
159     char *file = NULL;
160     mrb_int line = 1;
161     mrb_value cv;
162     struct RProc *proc;
163 
164     mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
165     cv = mrb_singleton_class(mrb, self);
166     proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line);
167     MRB_PROC_SET_TARGET_CLASS(proc, mrb_class_ptr(cv));
168     mrb_assert(!MRB_PROC_CFUNC_P(proc));
169     mrb->c->ci->target_class = mrb_class_ptr(cv);
170     return exec_irep(mrb, self, proc);
171   }
172   else {
173     mrb_get_args(mrb, "&", &b);
174     return mrb_obj_instance_eval(mrb, self);
175   }
176 }
177 
178 void
mrb_mruby_eval_gem_init(mrb_state * mrb)179 mrb_mruby_eval_gem_init(mrb_state* mrb)
180 {
181   mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
182   mrb_define_method(mrb, mrb_class_get(mrb, "BasicObject"), "instance_eval", f_instance_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
183 }
184 
185 void
mrb_mruby_eval_gem_final(mrb_state * mrb)186 mrb_mruby_eval_gem_final(mrb_state* mrb)
187 {
188 }
189