1 /* -*- c-basic-offset: 2 -*- */ 2 /* 3 Copyright(C) 2016 Brazil 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License version 2.1 as published by the Free Software Foundation. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with this library; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 17 */ 18 19 #include "../grn_ctx_impl.h" 20 21 #ifdef GRN_WITH_MRUBY 22 #include <mruby.h> 23 #include <mruby/proc.h> 24 #include <mruby/compile.h> 25 #include <mruby/opcode.h> 26 27 #include "../grn_mrb.h" 28 #include "mrb_ctx.h" 29 #include "mrb_eval_context.h" 30 31 static mrb_value 32 eval_context_compile(mrb_state *mrb, mrb_value self) 33 { 34 char *script; 35 mrb_int script_length; 36 mrbc_context* compile_ctx; 37 struct mrb_parser_state *parser; 38 struct RProc *proc; 39 40 mrb_get_args(mrb, "s", &script, &script_length); 41 42 compile_ctx = mrbc_context_new(mrb); 43 if (!compile_ctx) { 44 mrb_raise(mrb, E_RUNTIME_ERROR, 45 "[mruby][eval][compile] failed to allocate context"); 46 } 47 compile_ctx->capture_errors = TRUE; 48 49 parser = mrb_parse_nstring(mrb, script, script_length, compile_ctx); 50 if (!parser) { 51 mrbc_context_free(mrb, compile_ctx); 52 mrb_raise(mrb, E_RUNTIME_ERROR, 53 "[mruby][eval][compile] failed to allocate parser"); 54 } 55 if (parser->nerr > 0) { 56 struct mrb_parser_message *error = &(parser->error_buffer[0]); 57 mrb_value new_args[1]; 58 mrb_value exception; 59 60 new_args[0] = mrb_format(mrb, 61 "line %S:%S: %S", 62 mrb_fixnum_value(error->lineno), 63 mrb_fixnum_value(error->column), 64 mrb_str_new_cstr(mrb, error->message)); 65 exception = mrb_obj_new(mrb, E_SYNTAX_ERROR, 1, new_args); 66 mrb_parser_free(parser); 67 mrbc_context_free(mrb, compile_ctx); 68 69 mrb_exc_raise(mrb, exception); 70 } 71 72 proc = mrb_generate_code(mrb, parser); 73 { 74 mrb_code *iseq = proc->body.irep->iseq; 75 while (GET_OPCODE(*iseq) != OP_STOP) { 76 iseq++; 77 } 78 *iseq = MKOP_AB(OP_RETURN, 1, OP_R_NORMAL); 79 } 80 mrb_parser_free(parser); 81 mrbc_context_free(mrb, compile_ctx); 82 return mrb_obj_value(proc); 83 } 84 85 void 86 grn_mrb_eval_context_init(grn_ctx *ctx) 87 { 88 grn_mrb_data *data = &(ctx->impl->mrb); 89 mrb_state *mrb = data->state; 90 struct RClass *module = data->module; 91 struct RClass *klass; 92 93 klass = mrb_define_class_under(mrb, module, "EvalContext", mrb->object_class); 94 95 mrb_define_method(mrb, klass, "compile", eval_context_compile, 96 MRB_ARGS_REQ(1)); 97 } 98 #endif 99