Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mruby_mbed_web mirb_mbed
eval.c
00001 #include "mruby.h" 00002 #include "mruby/class.h" 00003 #include "mruby/compile.h" 00004 #include "mruby/irep.h" 00005 #include "mruby/proc.h" 00006 #include "mruby/opcode.h" 00007 00008 static struct mrb_irep * 00009 get_closure_irep(mrb_state *mrb, int level) 00010 { 00011 struct REnv *e = mrb->c->ci[-1].proc->env; 00012 struct RProc *proc; 00013 00014 if (level == 0) { 00015 proc = mrb->c->ci[-1].proc; 00016 if (MRB_PROC_CFUNC_P(proc)) { 00017 return NULL; 00018 } 00019 return proc->body.irep; 00020 } 00021 00022 while (--level) { 00023 e = (struct REnv*)e->c; 00024 if (!e) return NULL; 00025 } 00026 00027 if (!e) return NULL; 00028 proc = mrb->c->cibase[e->cioff].proc; 00029 00030 if (MRB_PROC_CFUNC_P(proc)) { 00031 return NULL; 00032 } 00033 return proc->body.irep; 00034 } 00035 00036 static inline mrb_code 00037 search_variable(mrb_state *mrb, mrb_sym vsym, int bnest) 00038 { 00039 mrb_irep *virep; 00040 int level; 00041 int pos; 00042 00043 for (level = 0; (virep = get_closure_irep(mrb, level)); level++) { 00044 if (!virep || virep->lv == NULL) { 00045 continue; 00046 } 00047 for (pos = 0; pos < virep->nlocals - 1; pos++) { 00048 if (vsym == virep->lv[pos].name) { 00049 return (MKARG_B(pos + 1) | MKARG_C(level + bnest)); 00050 } 00051 } 00052 } 00053 00054 return 0; 00055 } 00056 00057 00058 static void 00059 patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest) 00060 { 00061 size_t i; 00062 mrb_code c; 00063 00064 for (i = 0; i < irep->ilen; i++) { 00065 c = irep->iseq[i]; 00066 switch(GET_OPCODE(c)){ 00067 case OP_EPUSH: 00068 patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1); 00069 break; 00070 00071 case OP_LAMBDA: 00072 { 00073 int arg_c = GETARG_c(c); 00074 if (arg_c & OP_L_CAPTURE) { 00075 patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1); 00076 } 00077 } 00078 break; 00079 00080 case OP_SEND: 00081 if (GETARG_C(c) != 0) { 00082 break; 00083 } 00084 { 00085 mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest); 00086 if (arg != 0) { 00087 /* must replace */ 00088 irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; 00089 } 00090 } 00091 break; 00092 00093 case OP_MOVE: 00094 /* src part */ 00095 if (GETARG_B(c) < irep->nlocals) { 00096 mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest); 00097 if (arg != 0) { 00098 /* must replace */ 00099 irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; 00100 } 00101 } 00102 /* dst part */ 00103 if (GETARG_A(c) < irep->nlocals) { 00104 mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest); 00105 if (arg != 0) { 00106 /* must replace */ 00107 irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg; 00108 } 00109 } 00110 break; 00111 } 00112 } 00113 } 00114 00115 static struct RProc* 00116 create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, char *file, mrb_int line) 00117 { 00118 mrbc_context *cxt; 00119 struct mrb_parser_state *p; 00120 struct RProc *proc; 00121 struct REnv *e; 00122 00123 if (!mrb_nil_p(binding)) { 00124 mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil."); 00125 } 00126 00127 cxt = mrbc_context_new(mrb); 00128 cxt->lineno = line; 00129 if (file) { 00130 mrbc_filename(mrb, cxt, file); 00131 } 00132 cxt->capture_errors = TRUE; 00133 00134 p = mrb_parse_nstring(mrb, s, len, cxt); 00135 00136 /* only occur when memory ran out */ 00137 if (!p) { 00138 mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state."); 00139 } 00140 00141 if (0 < p->nerr) { 00142 /* parse error */ 00143 char buf[256]; 00144 int n; 00145 n = snprintf(buf, sizeof(buf), "line %d: %s\n", p->error_buffer[0].lineno, p->error_buffer[0].message); 00146 mrb_parser_free(p); 00147 mrbc_context_free(mrb, cxt); 00148 mrb_exc_raise(mrb, mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); 00149 } 00150 00151 proc = mrb_generate_code(mrb, p); 00152 if (proc == NULL) { 00153 /* codegen error */ 00154 mrb_parser_free(p); 00155 mrbc_context_free(mrb, cxt); 00156 mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error"); 00157 } 00158 if (mrb->c->ci[-1].proc->target_class) { 00159 proc->target_class = mrb->c->ci[-1].proc->target_class; 00160 } 00161 e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci[-1].proc->env); 00162 e->mid = mrb->c->ci[-1].mid; 00163 e->cioff = mrb->c->ci - mrb->c->cibase - 1; 00164 e->stack = mrb->c->ci->stackent; 00165 mrb->c->ci->env = e; 00166 proc->env = e; 00167 patch_irep(mrb, proc->body.irep, 0); 00168 00169 mrb_parser_free(p); 00170 mrbc_context_free(mrb, cxt); 00171 00172 return proc; 00173 } 00174 00175 static mrb_value 00176 f_eval(mrb_state *mrb, mrb_value self) 00177 { 00178 char *s; 00179 mrb_int len; 00180 mrb_value binding = mrb_nil_value(); 00181 char *file = NULL; 00182 mrb_int line = 1; 00183 mrb_value ret; 00184 struct RProc *proc; 00185 00186 mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line); 00187 00188 proc = create_proc_from_string(mrb, s, len, binding, file, line); 00189 ret = mrb_toplevel_run(mrb, proc); 00190 if (mrb->exc) { 00191 mrb_exc_raise(mrb, mrb_obj_value(mrb->exc)); 00192 } 00193 00194 return ret; 00195 } 00196 00197 mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self); 00198 00199 #define CI_ACC_SKIP -1 00200 00201 static mrb_value 00202 f_instance_eval(mrb_state *mrb, mrb_value self) 00203 { 00204 mrb_value b; 00205 mrb_int argc; mrb_value *argv; 00206 00207 mrb_get_args(mrb, "*&", &argv, &argc, &b); 00208 00209 if (mrb_nil_p(b)) { 00210 char *s; 00211 mrb_int len; 00212 char *file = NULL; 00213 mrb_int line = 1; 00214 00215 mrb_get_args(mrb, "s|zi", &s, &len, &file, &line); 00216 mrb->c->ci->acc = CI_ACC_SKIP; 00217 if (mrb->c->ci->target_class->tt == MRB_TT_ICLASS) { 00218 mrb->c->ci->target_class = mrb->c->ci->target_class->c; 00219 } 00220 return mrb_run(mrb, create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line), self); 00221 } 00222 else { 00223 mrb_get_args(mrb, "&", &b); 00224 return mrb_obj_instance_eval(mrb, self); 00225 } 00226 } 00227 00228 void 00229 mrb_mruby_eval_gem_init(mrb_state* mrb) 00230 { 00231 mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3)); 00232 mrb_define_method(mrb, mrb->kernel_module, "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2)); 00233 } 00234 00235 void 00236 mrb_mruby_eval_gem_final(mrb_state* mrb) 00237 { 00238 } 00239
Generated on Tue Jul 12 2022 18:00:34 by
1.7.2