source: EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-eval/src/eval.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 7.2 KB
Line 
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
9mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p);
10mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
11
12static struct mrb_irep *
13get_closure_irep(mrb_state *mrb, int level)
14{
15 struct mrb_context *c = mrb->c;
16 struct REnv *e = c->ci[-1].proc->env;
17 struct RProc *proc;
18
19 if (level == 0) {
20 proc = c->ci[-1].proc;
21 if (MRB_PROC_CFUNC_P(proc)) {
22 return NULL;
23 }
24 return proc->body.irep;
25 }
26
27 while (--level) {
28 e = (struct REnv*)e->c;
29 if (!e) return NULL;
30 }
31
32 if (!e) return NULL;
33 if (!MRB_ENV_STACK_SHARED_P(e)) return NULL;
34 c = e->cxt.c;
35 proc = c->cibase[e->cioff].proc;
36
37 if (!proc || MRB_PROC_CFUNC_P(proc)) {
38 return NULL;
39 }
40 return proc->body.irep;
41}
42
43static inline mrb_code
44search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
45{
46 mrb_irep *virep;
47 int level;
48 int pos;
49
50 for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
51 if (!virep || virep->lv == NULL) {
52 continue;
53 }
54 for (pos = 0; pos < virep->nlocals - 1; pos++) {
55 if (vsym == virep->lv[pos].name) {
56 return (MKARG_B(pos + 1) | MKARG_C(level + bnest));
57 }
58 }
59 }
60
61 return 0;
62}
63
64static mrb_bool
65potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
66{
67 if (v >= nlocals) return FALSE;
68 /* skip arguments */
69 if (v < argc+1) return FALSE;
70 return TRUE;
71}
72
73static void
74patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
75{
76 size_t i;
77 mrb_code c;
78 int argc = 0;
79
80 for (i = 0; i < irep->ilen; i++) {
81 c = irep->iseq[i];
82 switch(GET_OPCODE(c)){
83 case OP_ENTER:
84 {
85 mrb_aspec ax = GETARG_Ax(c);
86 /* extra 1 means a slot for block */
87 argc = MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
88 }
89 break;
90
91 case OP_EPUSH:
92 patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1);
93 break;
94
95 case OP_LAMBDA:
96 {
97 int arg_c = GETARG_c(c);
98 if (arg_c & OP_L_CAPTURE) {
99 patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1);
100 }
101 }
102 break;
103
104 case OP_SEND:
105 if (GETARG_C(c) != 0) {
106 break;
107 }
108 {
109 mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest);
110 if (arg != 0) {
111 /* must replace */
112 irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
113 }
114 }
115 break;
116
117 case OP_MOVE:
118 /* src part */
119 if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) {
120 mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest);
121 if (arg != 0) {
122 /* must replace */
123 irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
124 }
125 }
126 /* dst part */
127 if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) {
128 mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest);
129 if (arg != 0) {
130 /* must replace */
131 irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg;
132 }
133 }
134 break;
135
136 case OP_STOP:
137 if (mrb->c->ci->acc >= 0) {
138 irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
139 }
140 break;
141 }
142 }
143}
144
145void mrb_codedump_all(mrb_state*, struct RProc*);
146
147static struct RProc*
148create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, const char *file, mrb_int line)
149{
150 mrbc_context *cxt;
151 struct mrb_parser_state *p;
152 struct RProc *proc;
153 struct REnv *e;
154 struct mrb_context *c = mrb->c;
155
156 if (!mrb_nil_p(binding)) {
157 mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil.");
158 }
159
160 cxt = mrbc_context_new(mrb);
161 cxt->lineno = line;
162
163 mrbc_filename(mrb, cxt, file ? file : "(eval)");
164 cxt->capture_errors = TRUE;
165 cxt->no_optimize = TRUE;
166
167 p = mrb_parse_nstring(mrb, s, len, cxt);
168
169 /* only occur when memory ran out */
170 if (!p) {
171 mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state.");
172 }
173
174 if (0 < p->nerr) {
175 /* parse error */
176 mrb_value str;
177
178 if (file) {
179 str = mrb_format(mrb, " file %S line %S: %S",
180 mrb_str_new_cstr(mrb, file),
181 mrb_fixnum_value(p->error_buffer[0].lineno),
182 mrb_str_new_cstr(mrb, p->error_buffer[0].message));
183 }
184 else {
185 str = mrb_format(mrb, " line %S: %S",
186 mrb_fixnum_value(p->error_buffer[0].lineno),
187 mrb_str_new_cstr(mrb, p->error_buffer[0].message));
188 }
189 mrb_parser_free(p);
190 mrbc_context_free(mrb, cxt);
191 mrb_exc_raise(mrb, mrb_exc_new_str(mrb, E_SYNTAX_ERROR, str));
192 }
193
194 proc = mrb_generate_code(mrb, p);
195 if (proc == NULL) {
196 /* codegen error */
197 mrb_parser_free(p);
198 mrbc_context_free(mrb, cxt);
199 mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error");
200 }
201 if (c->ci[-1].proc->target_class) {
202 proc->target_class = c->ci[-1].proc->target_class;
203 }
204 e = c->ci[-1].proc->env;
205 if (!e) e = c->ci[-1].env;
206 e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e);
207 e->cxt.c = c;
208 e->cioff = c->ci - c->cibase;
209 e->stack = c->ci->stackent;
210 MRB_SET_ENV_STACK_LEN(e, c->ci->proc->body.irep->nlocals);
211 c->ci->target_class = proc->target_class;
212 c->ci->env = 0;
213 proc->env = e;
214 patch_irep(mrb, proc->body.irep, 0);
215
216 mrb_parser_free(p);
217 mrbc_context_free(mrb, cxt);
218
219 return proc;
220}
221
222static mrb_value
223exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
224{
225 if (mrb->c->ci->acc < 0) {
226 mrb_value ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0);
227 if (mrb->exc) {
228 mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
229 }
230 return ret;
231 }
232 return mrb_exec_irep(mrb, self, proc);
233}
234
235static mrb_value
236f_eval(mrb_state *mrb, mrb_value self)
237{
238 char *s;
239 mrb_int len;
240 mrb_value binding = mrb_nil_value();
241 char *file = NULL;
242 mrb_int line = 1;
243 struct RProc *proc;
244
245 mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line);
246
247 proc = create_proc_from_string(mrb, s, len, binding, file, line);
248 mrb_assert(!MRB_PROC_CFUNC_P(proc));
249 return exec_irep(mrb, self, proc);
250}
251
252static mrb_value
253f_instance_eval(mrb_state *mrb, mrb_value self)
254{
255 mrb_value b;
256 mrb_int argc; mrb_value *argv;
257
258 mrb_get_args(mrb, "*&", &argv, &argc, &b);
259
260 if (mrb_nil_p(b)) {
261 char *s;
262 mrb_int len;
263 char *file = NULL;
264 mrb_int line = 1;
265 mrb_value cv;
266 struct RProc *proc;
267
268 mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
269 cv = mrb_singleton_class(mrb, self);
270 proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line);
271 proc->target_class = mrb_class_ptr(cv);
272 mrb->c->ci->env = NULL;
273 mrb_assert(!MRB_PROC_CFUNC_P(proc));
274 return exec_irep(mrb, self, proc);
275 }
276 else {
277 mrb_get_args(mrb, "&", &b);
278 return mrb_obj_instance_eval(mrb, self);
279 }
280}
281
282void
283mrb_mruby_eval_gem_init(mrb_state* mrb)
284{
285 mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
286 mrb_define_method(mrb, mrb->kernel_module, "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
287}
288
289void
290mrb_mruby_eval_gem_final(mrb_state* mrb)
291{
292}
Note: See TracBrowser for help on using the repository browser.