static mrb_value exc_equal(mrb_state *mrb, mrb_value exc) { mrb_value obj; mrb_value mesg; mrb_bool equal_p; mrb_sym id_mesg = mrb_intern2(mrb, "mesg", 4); mrb_get_args(mrb, "o", &obj); if (mrb_obj_equal(mrb, exc, obj)) { equal_p = 1; } else { if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { if (mrb_respond_to(mrb, obj, mrb_intern2(mrb, "message", 7))) { mesg = mrb_funcall(mrb, obj, "message", 0); } else return mrb_false_value(); } else { mesg = mrb_attr_get(mrb, obj, id_mesg); } equal_p = mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg); } return mrb_bool_value(equal_p); }
static mrb_value mrb_ary_equal(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; mrb_get_args(mrb, "o", &ary2); if (mrb_obj_equal(mrb, ary1,ary2)) return mrb_true_value(); if (mrb_type(ary2) != MRB_TT_ARRAY) { if (!mrb_respond_to(mrb, ary2, mrb_intern(mrb, "to_ary"))) { return mrb_false_value(); } if (mrb_equal(mrb, ary2, ary1)){ return mrb_true_value(); } else { return mrb_false_value(); } } if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); else { int i; for (i=0; i<RARRAY_LEN(ary1); i++) { if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) return mrb_false_value(); } return mrb_true_value(); } }
MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value v) { mrb_value a, recv_class; if (mrb_array_p(v)) { return v; } if (!mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { return mrb_ary_new_from_values(mrb, 1, &v); } a = mrb_funcall(mrb, v, "to_a", 0); if (mrb_array_p(a)) { return a; } else if (mrb_nil_p(a)) { return mrb_ary_new_from_values(mrb, 1, &v); } else { recv_class = mrb_obj_value(mrb_obj_class(mrb, v)); mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Array (%S#to_a gives %S)", recv_class, recv_class, mrb_obj_value(mrb_obj_class(mrb, a)) ); /* not reached */ return mrb_undef_value(); } }
/* * call-seq: * obj.method_missing(symbol [, *args] ) -> result * * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle. * <i>symbol</i> is the symbol for the method called, and <i>args</i> * are any arguments that were passed to it. By default, the interpreter * raises an error when this method is called. However, it is possible * to override the method to provide more dynamic behavior. * If it is decided that a particular method should not be handled, then * <i>super</i> should be called, so that ancestors can pick up the * missing method. * The example below creates * a class <code>Roman</code>, which responds to methods with names * consisting of roman numerals, returning the corresponding integer * values. * * class Roman * def romanToInt(str) * # ... * end * def method_missing(methId) * str = methId.id2name * romanToInt(str) * end * end * * r = Roman.new * r.iv #=> 4 * r.xxiii #=> 23 * r.mm #=> 2000 */ static mrb_value mrb_bob_missing(mrb_state *mrb, mrb_value mod) { mrb_value name, *a; int alen; mrb_value inspect; mrb_get_args(mrb, "o*", &name, &a, &alen); if (!mrb_symbol_p(name)) { mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol"); } if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){ inspect = mrb_funcall(mrb, mod, "inspect", 0); if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mod); } } else { inspect = mrb_any_to_s(mrb, mod); } mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S", mrb_sym2str(mrb, mrb_symbol(name)), inspect); /* not reached */ return mrb_nil_value(); }
static mrb_value exc_equal(mrb_state *mrb, mrb_value exc) { mrb_value obj; mrb_value mesg; mrb_sym id_mesg = mrb_intern(mrb, "mesg"); mrb_get_args(mrb, "o", &obj); if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value(); if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { if ( mrb_respond_to(mrb, obj, mrb_intern(mrb, "message")) ) { mesg = mrb_funcall(mrb, obj, "message", 0); } else return mrb_false_value(); } else { mesg = mrb_attr_get(mrb, obj, id_mesg); } if (!mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg)) return mrb_false_value(); return mrb_true_value(); }
static mrb_value mrb_ary_equal(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; mrb_int i; mrb_get_args(mrb, "o", &ary2); if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); if (mrb_special_const_p(ary2)) return mrb_false_value(); if (!mrb_array_p(ary2)) { if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) { return mrb_false_value(); } else { return mrb_bool_value(mrb_equal(mrb, ary2, ary1)); } } if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); for (i=0; i<RARRAY_LEN(ary1); i++) { if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { return mrb_false_value(); } } return mrb_true_value(); }
mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) { mrb_value mesg; int n; mesg = mrb_nil_value(); switch (argc) { case 0: break; case 1: if (mrb_nil_p(argv[0])) break; if (isstr) { mesg = mrb_check_string_type(mrb, argv[0]); if (!mrb_nil_p(mesg)) { mesg = mrb_exc_new3(mrb, E_RUNTIME_ERROR, mesg); break; } } n = 0; goto exception_call; case 2: case 3: n = 1; exception_call: //if (argv[0] == sysstack_error) return argv[0]; //CONST_ID(mrb, exception, "exception"); //mesg = mrb_check_funcall(mrb, argv[0], exception, n, argv+1); //if (mrb_nil_p(mesg)) { // /* undef */ // mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); //} if (mrb_respond_to(mrb, argv[0], mrb_intern(mrb, "exception"))) { mesg = mrb_funcall_argv(mrb, argv[0], "exception", n, argv+1); } else { /* undef */ mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); } break; default: mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 0..3)", argc); break; } if (argc > 0) { if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class)) mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); if (argc > 2) set_backtrace(mrb, mesg, argv[2]); } return mesg; }
/* * Class: org_jamruby_mruby_RClass * Method: n_respondTo * Signature: (JLorg/jamruby/mruby/Value;J)Z */ JNIEXPORT jboolean JNICALL Java_org_jamruby_mruby_RClass_n_1respondTo (JNIEnv *env, jclass, jlong mrb, jobject obj, jlong mid) { mrb_value obj_val; if (!create_mrb_value(getEnv(), obj, obj_val)) { return JNI_FALSE; } int const &ret = mrb_respond_to(to_ptr<mrb_state>(mrb), obj_val, static_cast<mrb_sym>(mid)); return (0 != ret) ? JNI_TRUE : JNI_FALSE; }
static mrb_value make_exception(mrb_state *mrb, int argc, const mrb_value *argv, mrb_bool isstr) { mrb_value mesg; int n; mesg = mrb_nil_value(); switch (argc) { case 0: break; case 1: if (mrb_nil_p(argv[0])) break; if (isstr) { mesg = mrb_check_string_type(mrb, argv[0]); if (!mrb_nil_p(mesg)) { mesg = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mesg); break; } } n = 0; goto exception_call; case 2: case 3: n = 1; exception_call: { mrb_sym exc = mrb_intern_lit(mrb, "exception"); if (mrb_respond_to(mrb, argv[0], exc)) { mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); } else { /* undef */ mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); } } break; default: mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 0..3)", mrb_fixnum_value(argc)); break; } if (argc > 0) { if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class)) mrb_raise(mrb, mrb->eException_class, "exception object expected"); if (argc > 2) set_backtrace(mrb, mesg, argv[2]); } return mesg; }
MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value v) { if (mrb_array_p(v)) { return v; } if (mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { return mrb_funcall(mrb, v, "to_a", 0); } else { return mrb_ary_new_from_values(mrb, 1, &v); } }
static void close_body_obj(h2o_mruby_generator_t *generator) { h2o_mruby_chunked_t *chunked = generator->chunked; mrb_state *mrb = generator->ctx->shared->mrb; if (!mrb_nil_p(chunked->body_obj)) { /* call close and throw away error */ if (mrb_respond_to(mrb, chunked->body_obj, generator->ctx->shared->symbols.sym_close)) mrb_funcall_argv(mrb, chunked->body_obj, generator->ctx->shared->symbols.sym_close, 0, NULL); mrb->exc = NULL; mrb_gc_unregister(mrb, chunked->body_obj); chunked->body_obj = mrb_nil_value(); } }
static mrb_value convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise) { mrb_sym m = 0; m = mrb_intern_cstr(mrb, method); if (!mrb_respond_to(mrb, val, m)) { if (raise) { mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", inspect_type(mrb, val), mrb_str_new_cstr(mrb, tname)); } return mrb_nil_value(); } return mrb_funcall_argv(mrb, val, m, 0, 0); }
static mrb_value hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) { khash_t(ht) *h1, *h2; mrb_bool eq; if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (!mrb_hash_p(hash2)) { if (!mrb_respond_to(mrb, hash2, mrb_intern_lit(mrb, "to_hash"))) { return mrb_false_value(); } else { if (eql) { eq = mrb_eql(mrb, hash2, hash1); } else { eq = mrb_equal(mrb, hash2, hash1); } return mrb_bool_value(eq); } } h1 = RHASH_TBL(hash1); h2 = RHASH_TBL(hash2); if (!h1) { return mrb_bool_value(!h2); } if (!h2) return mrb_false_value(); if (kh_size(h1) != kh_size(h2)) return mrb_false_value(); else { khiter_t k1, k2; mrb_value key; for (k1 = kh_begin(h1); k1 != kh_end(h1); k1++) { if (!kh_exist(h1, k1)) continue; key = kh_key(h1,k1); k2 = kh_get(ht, mrb, h2, key); if (k2 != kh_end(h2)) { if (eql) eq = mrb_eql(mrb, kh_value(h1,k1), kh_value(h2,k2)); else eq = mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2)); if (eq) { continue; /* next key */ } } return mrb_false_value(); } } return mrb_true_value(); }
static mrb_value cfunc_call(mrb_state *mrb, mrb_value self) { int margc; mrb_value mresult_type, mname, *margs; mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc); void *dlh = dlopen(NULL, RTLD_LAZY); void *fp = dlsym(dlh, RSTRING_PTR(mname)); ffi_type **args = malloc(sizeof(ffi_type*) * margc); void **values = malloc(sizeof(void*) * margc); mrb_sym to_pointer = mrb_intern(mrb, "to_pointer"); for(int i = 0; i < margc; ++i) { if(!mrb_respond_to(mrb, margs[i], to_pointer)) { // Todo: should free some malloc-ed pointers mrb_raise(mrb, E_TYPE_ERROR, "ignore argument type"); } args[i] = mrb_value_to_mrb_ffi_type(mrb, margs[i])->ffi_type_value; values[i] = mobi_pointer_ptr(mrb_funcall(mrb, margs[i], "to_pointer", 0)); } ffi_type *result_type = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(mresult_type))->ffi_type_value; if (result_type == NULL) { mrb_raise(mrb, E_ARGUMENT_ERROR, "ignore return type"); } mrb_value mresult = mrb_nil_value(); ffi_cif cif; if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, margc, result_type, args) == FFI_OK) { void *result = result_type->size ? malloc(result_type->size) : NULL; ffi_call(&cif, fp, result, values); if(result) { mrb_value result_ptr = cfunc_pointer_new_with_pointer(mrb, result, 1); mresult = mrb_funcall(mrb, mresult_type, "refer", 1, result_ptr); } } else { // todo mrb_raise(mrb, E_NAME_ERROR, "can't find C function"); } cfunc_call_exit: free(values); free(args); return mresult; }
static mrb_value hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) { if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (mrb_type(hash2) != MRB_TT_HASH) { if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) { return mrb_false_value(); } if (eql) return mrb_fixnum_value(mrb_eql(mrb, hash2, hash1)); else return mrb_fixnum_value(mrb_equal(mrb, hash2, hash1)); } if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2)) return mrb_false_value(); if (!RHASH(hash1)->ht || !RHASH(hash2)->ht) return mrb_true_value(); return mrb_exec_recursive_paired(mrb, recursive_eql, hash1, hash2, (void*)0); }
MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value v) { mrb_value a; if (mrb_array_p(v)) { return v; } if (!mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { return mrb_ary_new_from_values(mrb, 1, &v); } a = mrb_funcall(mrb, v, "to_a", 0); if (mrb_nil_p(a)) { return mrb_ary_new_from_values(mrb, 1, &v); } mrb_ensure_array_type(mrb, a); return a; }
static mrb_value hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) { khash_t(ht) *h1, *h2; if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (mrb_type(hash2) != MRB_TT_HASH) { if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) { return mrb_false_value(); } if (eql) return mrb_fixnum_value(mrb_eql(mrb, hash2, hash1)); else return mrb_fixnum_value(mrb_equal(mrb, hash2, hash1)); } h1 = RHASH_TBL(hash1); h2 = RHASH_TBL(hash2); if (!h2) { if (!h2) return mrb_true_value(); return mrb_false_value(); } if (!h2) return mrb_false_value(); if (kh_size(h1) != kh_size(h2)) return mrb_false_value(); else { khiter_t k1, k2; mrb_value key; for (k1 = kh_begin(h1); k1 != kh_end(h1); k1++) { if (!kh_exist(h1, k1)) continue; key = kh_key(h1,k1); k2 = kh_get(ht, h2, key); if (k2 != kh_end(h2)) { if (mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2))) { continue; /* next key */ } } return mrb_false_value(); } } return mrb_true_value(); }
mrb_value convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, int raise) { mrb_sym m = 0; m = mrb_intern(mrb, method); if (!mrb_respond_to(mrb, val, m)) { if (raise) { mrb_raise(mrb, E_TYPE_ERROR, "can't convert %s into %s", mrb_nil_p(val) ? "nil" : (mrb_type(val) == MRB_TT_TRUE) ? "true" : (mrb_type(val) == MRB_TT_FALSE) ? "false" : mrb_obj_classname(mrb, val), tname); return mrb_nil_value(); } else { return mrb_nil_value(); } } return mrb_funcall(mrb, val, method, 0); }
static mrb_value mrb_ary_equal(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; mrb_bool equal_p; mrb_get_args(mrb, "o", &ary2); if (mrb_obj_equal(mrb, ary1, ary2)) { equal_p = 1; } else if (mrb_special_const_p(ary2)) { equal_p = 0; } else if (!mrb_array_p(ary2)) { if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) { equal_p = 0; } else { equal_p = mrb_equal(mrb, ary2, ary1); } } else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) { equal_p = 0; } else { mrb_int i; equal_p = 1; for (i=0; i<RARRAY_LEN(ary1); i++) { if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { equal_p = 0; break; } } } return mrb_bool_value(equal_p); }
static mrb_value const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) { struct RClass *c = base; mrb_value v; iv_tbl *t; mrb_bool retry = 0; mrb_sym cm; L_RETRY: while (c) { if (c->iv) { t = c->iv; if (iv_get(mrb, t, sym, &v)) return v; } c = c->super; } if (!retry && base && base->tt == MRB_TT_MODULE) { c = mrb->object_class; retry = 1; goto L_RETRY; } c = base; cm = mrb_intern2(mrb, "const_missing", 13); while (c) { if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) { mrb_value name = mrb_symbol_value(sym); return mrb_funcall_argv(mrb, mrb_obj_value(c), cm, 1, &name); } c = c->super; } mrb_raisef(mrb, E_NAME_ERROR, "uninitialized constant %s", mrb_sym2name(mrb, sym)); /* not reached */ return mrb_nil_value(); }
int main() { mrb_state *mrb = mrb_open(); init_TestClass(mrb); char code[] = "$t = Test.new; res = $t.run; p res"; printf("Executing Ruby code from C!\n"); auto c = mrbc_context_new(mrb); auto p = mrb_parse_string(mrb, code, c); auto n = mrb_generate_code(mrb, p); // mrb_run(mrb, n, mrb_top_self(mrb)); unsigned stack_keep = 0; auto result = mrb_vm_run(mrb, n, mrb_top_self(mrb), stack_keep); if (mrb->exc) // have exception { mrb_p(mrb, mrb_obj_value(mrb->exc)); mrb->exc = 0; } else { if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))) result = mrb_any_to_s(mrb, result); mrb_p(mrb, result); } mrbc_context_free(mrb, c); mrb_close(mrb); return 0; }
static void mrb_search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, struct RClass **owner, struct RProc **proc, mrb_bool unbound) { mrb_value ret; const char *s; *owner = c; *proc = method_search_vm(mrb, owner, name); if (!*proc) { if (unbound) { goto name_error; } if (!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "respond_to_missing?"))) { goto name_error; } ret = mrb_funcall(mrb, obj, "respond_to_missing?", 2, mrb_symbol_value(name), mrb_true_value()); if (!mrb_test(ret)) { goto name_error; } *owner = c; } while ((*owner)->tt == MRB_TT_ICLASS) *owner = (*owner)->c; return; name_error: s = mrb_class_name(mrb, c); mrb_raisef( mrb, E_NAME_ERROR, "undefined method `%S' for class `%S'", mrb_sym2str(mrb, name), mrb_str_new_static(mrb, s, strlen(s)) ); }
int main(void) { char ruby_code[1024] = { 0 }; char last_code_line[1024] = { 0 }; #ifndef ENABLE_READLINE int last_char; int char_index; #endif mrbc_context *cxt; struct mrb_parser_state *parser; mrb_state *mrb; mrb_value result; int n; int code_block_open = FALSE; int ai; print_hint(); /* new interpreter instance */ mrb = mrb_open(); if (mrb == NULL) { fprintf(stderr, "Invalid mrb interpreter, exiting mirb"); return EXIT_FAILURE; } cxt = mrbc_context_new(mrb); cxt->capture_errors = 1; ai = mrb_gc_arena_save(mrb); while (TRUE) { #ifndef ENABLE_READLINE print_cmdline(code_block_open); char_index = 0; while ((last_char = getchar()) != '\n') { if (last_char == EOF) break; last_code_line[char_index++] = last_char; } if (last_char == EOF) { printf("\n"); break; } last_code_line[char_index] = '\0'; #else char* line = readline(code_block_open ? "* " : "> "); if(line == NULL) { printf("\n"); break; } strncat(last_code_line, line, sizeof(last_code_line)-1); add_history(line); free(line); #endif if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) { if (!code_block_open) { break; } else{ /* count the quit/exit commands as strings if in a quote block */ strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } } else { if (code_block_open) { strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } else { strcpy(ruby_code, last_code_line); } } /* parse code */ parser = mrb_parser_new(mrb); parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); parser->lineno = 1; mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); if (code_block_open) { /* no evaluation of code */ } else { if (0 < parser->nerr) { /* syntax error */ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); } else { /* generate bytecode */ n = mrb_generate_code(mrb, parser); /* evaluate the bytecode */ result = mrb_run(mrb, /* pass a proc for evaulation */ mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); /* did an exception occur? */ if (mrb->exc) { p(mrb, mrb_obj_value(mrb->exc)); mrb->exc = 0; } else { /* no */ printf(" => "); if (!mrb_respond_to(mrb,result,mrb_intern(mrb,"inspect"))){ result = mrb_any_to_s(mrb,result); } p(mrb, result); } } ruby_code[0] = '\0'; last_code_line[0] = '\0'; mrb_parser_free(parser); mrb_gc_arena_restore(mrb, ai); } } mrbc_context_free(mrb, cxt); mrb_close(mrb); return 0; }
int main(int argc, char **argv) { char ruby_code[1024] = { 0 }; char last_code_line[1024] = { 0 }; #ifndef ENABLE_READLINE int last_char; int char_index; #else char *home = NULL; #endif mrbc_context *cxt; struct mrb_parser_state *parser; mrb_state *mrb; mrb_value result; struct _args args; int n; mrb_bool code_block_open = FALSE; mrb_value MIRB_BIN; int ai; unsigned int stack_keep = 0; /* new interpreter instance */ mrb = mrb_open(); if (mrb == NULL) { fputs("Invalid mrb interpreter, exiting mirb\n", stderr); return EXIT_FAILURE; } mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0)); n = parse_args(mrb, argc, argv, &args); if (n == EXIT_FAILURE) { cleanup(mrb, &args); usage(argv[0]); return n; } print_hint(); cxt = mrbc_context_new(mrb); cxt->capture_errors = 1; cxt->lineno = 1; mrbc_filename(mrb, cxt, "(mirb)"); if (args.verbose) cxt->dump_result = 1; MIRB_BIN= mrb_str_new(mrb, argv[0], strlen(argv[0])); mrb_define_global_const(mrb, "MIRB_BIN", MIRB_BIN); #ifdef ENABLE_REQUIRE mrb_value LOAD_PATH = mrb_gv_get(mrb, mrb_intern(mrb, "$:")); if (mrb_str_cmp(mrb, MIRB_BIN, mrb_str_new2(mrb, "mirb")) != 0) { int len = strrchr(RSTRING_PTR(MIRB_BIN), '/') - RSTRING_PTR(MIRB_BIN); mrb_value extdir = mrb_str_substr(mrb, mrb_str_dup(mrb, MIRB_BIN), 0, len); mrb_str_cat2(mrb, extdir, "/../ext"); if (mrb_obj_eq(mrb, mrb_file_exist(mrb, extdir), mrb_true_value())) { mrb_ary_push(mrb, LOAD_PATH, extdir); } } #endif /* ENABLE_REQUIRE */ ai = mrb_gc_arena_save(mrb); #ifdef ENABLE_READLINE MIRB_USING_HISTORY(); home = getenv("HOME"); #ifdef _WIN32 if (!home) home = getenv("USERPROFILE"); #endif if (home) { strcpy(history_path, home); strcat(history_path, "/"); strcat(history_path, history_file_name); MIRB_READ_HISTORY(history_path); } #endif while (TRUE) { #ifndef ENABLE_READLINE print_cmdline(code_block_open); char_index = 0; while ((last_char = getchar()) != '\n') { if (last_char == EOF) break; last_code_line[char_index++] = last_char; } if (last_char == EOF) { fputs("\n", stdout); break; } last_code_line[char_index] = '\0'; #else char* line = MIRB_READLINE(code_block_open ? "* " : "> "); if (line == NULL) { printf("\n"); break; } strncpy(last_code_line, line, sizeof(last_code_line)-1); MIRB_ADD_HISTORY(line); free(line); #endif if (code_block_open) { strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } else { if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) { break; } strcpy(ruby_code, last_code_line); } /* parse code */ parser = mrb_parser_new(mrb); parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); parser->lineno = cxt->lineno; mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); if (code_block_open) { /* no evaluation of code */ } else { if (0 < parser->nerr) { /* syntax error */ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); } else { /* generate bytecode */ struct RProc *proc = mrb_generate_code(mrb, parser); if (args.verbose) { mrb_codedump_all(mrb, proc); } /* pass a proc for evaulation */ /* evaluate the bytecode */ result = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); stack_keep = proc->body.irep->nlocals; /* did an exception occur? */ if (mrb->exc) { p(mrb, mrb_obj_value(mrb->exc), 0); mrb->exc = 0; } else { /* no */ if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){ result = mrb_any_to_s(mrb,result); } p(mrb, result, 1); } } ruby_code[0] = '\0'; last_code_line[0] = '\0'; mrb_gc_arena_restore(mrb, ai); } mrb_parser_free(parser); cxt->lineno++; } mrbc_context_free(mrb, cxt); mrb_close(mrb); #ifdef ENABLE_READLINE MIRB_WRITE_HISTORY(history_path); #endif return 0; }
static mrb_value mrb_sdl2_misc_bytebuffer_initialize(mrb_state *mrb, mrb_value self) { mrb_value arg; mrb_get_args(mrb, "o", &arg); mrb_sdl2_misc_buffer_data_t *data = (mrb_sdl2_misc_buffer_data_t*)DATA_PTR(self); if (NULL == data) { data = (mrb_sdl2_misc_buffer_data_t*)mrb_malloc(mrb, sizeof(mrb_sdl2_misc_buffer_data_t)); if (NULL == data) { mrb_raise(mrb, E_RUNTIME_ERROR, "insufficient memory."); } data->buffer = NULL; data->size = 0; } enum mrb_vtype const arg_type = mrb_type(arg); switch (arg_type) { case MRB_TT_FIXNUM: data->size = (size_t)mrb_fixnum(arg); break; case MRB_TT_FLOAT: data->size = (size_t)mrb_float(arg); break; case MRB_TT_STRING: data->size = (size_t)mrb_float(mrb_funcall(mrb, arg, "to_f", 0)); break; case MRB_TT_ARRAY: { mrb_int const n = mrb_ary_len(mrb, arg); if (0 == n) { mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot accept empty array."); } data->size = n * sizeof(uint8_t); } break; default: if (mrb_respond_to(mrb, arg, mrb_intern(mrb, "to_f", 4))) { data->size = (size_t)mrb_float(mrb_funcall(mrb, arg, "to_f", 0)); } else if (mrb_respond_to(mrb, arg, mrb_intern(mrb, "to_i", 4))) { data->size = (size_t)mrb_fixnum(mrb_funcall(mrb, arg, "to_i", 0)); } else { mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum/Float/String/Array or comvertible type"); } break; } data->buffer = mrb_malloc(mrb, data->size); if (NULL == data->buffer) { mrb_free(mrb, data); mrb_raise(mrb, E_RUNTIME_ERROR, "insufficient memory."); } size_t i = 0; for (i = 0; i < data->size/sizeof(uint8_t); ++i) { ((uint8_t*)data->buffer)[i] = 0; } if (arg_type == MRB_TT_ARRAY) { mrb_int const n = mrb_ary_len(mrb, arg); mrb_int i; for (i = 0; i < n; ++i) { mrb_value const item = mrb_ary_ref(mrb, arg, i); switch (mrb_type(item)) { case MRB_TT_FIXNUM: ((uint8_t*)data->buffer)[i] = (uint8_t)(mrb_fixnum(item) & 0xffu); break; case MRB_TT_FLOAT: ((uint8_t*)data->buffer)[i] = (uint8_t)((uint32_t)mrb_float(item) & 0xffu); break; case MRB_TT_STRING: ((uint8_t*)data->buffer)[i] = (uint8_t)((uint32_t)mrb_float(mrb_funcall(mrb, item, "to_f", 0)) & 0xffu); break; default: if (mrb_respond_to(mrb, item, mrb_intern(mrb, "to_f", 4))) { ((uint8_t*)data->buffer)[i] = (uint8_t)((uint32_t)mrb_float(mrb_funcall(mrb, item, "to_f", 0)) & 0xffu); } else if (mrb_respond_to(mrb, item, mrb_intern(mrb, "to_i", 4))) { ((uint8_t*)data->buffer)[i] = (uint8_t)(mrb_fixnum(mrb_funcall(mrb, item, "to_i", 0)) & 0xffu); } else { mrb_free(mrb, data->buffer); mrb_free(mrb, data); mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum/Float/String or convertible type"); } break; } } } DATA_PTR(self) = data; DATA_TYPE(self) = &mrb_sdl2_misc_buffer_data_type; return self; }
static inline mrb_bool basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) { return mrb_respond_to(mrb, obj, id); }
static mrb_value cfunc_call(mrb_state *mrb, mrb_value self) { int margc; mrb_value mresult_type, mname, *margs; void **values = NULL; ffi_type **args = NULL; mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc); void *fp = NULL; if(mrb_string_p(mname) || mrb_symbol_p(mname)) { void *dlh = dlopen(NULL, RTLD_LAZY); fp = dlsym(dlh, mrb_string_value_ptr(mrb, mname)); dlclose(dlh); } else { fp = cfunc_pointer_ptr(mname); } if(fp == NULL) { mrb_raisef(mrb, E_NAME_ERROR, "can't find C function %s", mrb_string_value_ptr(mrb, mname)); goto cfunc_call_exit; } args = malloc(sizeof(ffi_type*) * margc); values = malloc(sizeof(void*) * margc); mrb_sym sym_to_ffi_value = mrb_intern(mrb, "to_ffi_value"); mrb_value nil_ary[1]; nil_ary[0] = mrb_nil_value(); for(int i = 0; i < margc; ++i) { if(mrb_respond_to(mrb, margs[i], sym_to_ffi_value)) { args[i] = mrb_value_to_mrb_ffi_type(mrb, margs[i])->ffi_type_value; values[i] = cfunc_pointer_ptr(mrb_funcall_argv(mrb, margs[i], sym_to_ffi_value, 1, nil_ary)); } else { cfunc_mrb_raise_without_jump(mrb, E_TYPE_ERROR, "ignore argument type %s", mrb_obj_classname(mrb, margs[i])); goto cfunc_call_exit; } } ffi_type *result_type = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(mresult_type))->ffi_type_value; if (result_type == NULL) { cfunc_mrb_raise_without_jump(mrb, E_ARGUMENT_ERROR, "ignore return type %s", mrb_class_name(mrb, mrb_class_ptr(mresult_type))); goto cfunc_call_exit; } mrb_value mresult = mrb_nil_value(); ffi_cif cif; if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, margc, result_type, args) == FFI_OK) { void *result; if(result_type->size > sizeof(long)) { result = malloc(result_type->size); } else if(result_type->size) { result = malloc(sizeof(long)); } else { result = NULL; } ffi_call(&cif, fp, result, values); if(result) { mrb_value result_ptr = cfunc_pointer_new_with_pointer(mrb, result, true); mresult = mrb_funcall(mrb, mresult_type, "refer", 1, result_ptr); } } else { mrb_raisef(mrb, E_NAME_ERROR, "Can't find C function %s", mname); goto cfunc_call_exit; } cfunc_call_exit: free(values); free(args); return mresult; }
void loop() { if (Serial.available() > 0) { char_index = 0; while (true) { if (Serial.available() > 0) { incommingByte = Serial.read(); if (incommingByte == 13) { // New Line last_code_line[char_index] = '\0'; break; } else { last_code_line[char_index++] = incommingByte; Serial.write(incommingByte); } } } Serial.println(""); Serial.flush(); is_exit = false; if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) { // Exit Interactive Mode if (!code_block_open) { is_exit = true; } else { /* count the quit/exit commands as strings if in a quote block */ strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); is_exit = false; } } else { if (code_block_open) { strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); is_exit = false; } else { strcpy(ruby_code, last_code_line); is_exit = false; } } if (!is_exit) { // Not Exit or Quit! /* parse code */ parser = mrb_parser_new(mrb); parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); parser->lineno = 1; mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); if (code_block_open) { /* no evaluation of code */ } else { if (0 < parser->nerr) { /* syntax error */ Serial.write("Syntax Error: "); Serial.println(parser->error_buffer[0].message); } else { /* generate bytecode */ n = mrb_generate_code(mrb, parser); /* evaluate the bytecode */ result = mrb_run(mrb, /* pass a proc for evaulation */ mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); /* did an exception occur? */ if (mrb->exc) { /* yes */ p(mrb, mrb_obj_value(mrb->exc), 0); mrb->exc = 0; } else { /* no */ if (!mrb_respond_to(mrb,result,mrb_intern(mrb, "inspect"))){ result = mrb_any_to_s(mrb,result); } p(mrb, result, 1); } } ruby_code[0] = '\0'; last_code_line[0] = '\0'; mrb_gc_arena_restore(mrb, ai); } mrb_parser_free(parser); } else { // User Enter 'exit' or 'quit' Serial.println("quit IAS"); ruby_code[0] = '\0'; last_code_line[0] = '\0'; mrb_parser_free(parser); mrbc_context_free(mrb, cxt); mrb_close(mrb); mrb_setup_arduino(); } print_cmdline(code_block_open); } }
static inline int basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) { return mrb_respond_to(mrb, obj, id); //return TRUE; }
int main(int argc, char **argv) { char ruby_code[1024] = { 0 }; char last_code_line[1024] = { 0 }; #ifndef ENABLE_READLINE int last_char; int char_index; #else char *home = NULL; #endif mrbc_context *cxt; struct mrb_parser_state *parser; mrb_state *mrb; mrb_value result; struct _args args; int n; mrb_bool code_block_open = FALSE; int ai; mrb_bool first_command = TRUE; unsigned int nregs; /* new interpreter instance */ mrb = mrb_open(); if (mrb == NULL) { fputs("Invalid mrb interpreter, exiting mirb\n", stderr); return EXIT_FAILURE; } mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0)); n = parse_args(mrb, argc, argv, &args); if (n == EXIT_FAILURE) { cleanup(mrb, &args); usage(argv[0]); return n; } print_hint(); cxt = mrbc_context_new(mrb); cxt->capture_errors = 1; cxt->lineno = 1; mrbc_filename(mrb, cxt, "(mirb)"); if (args.verbose) cxt->dump_result = 1; ai = mrb_gc_arena_save(mrb); #ifdef ENABLE_READLINE using_history(); home = getenv("HOME"); #ifdef _WIN32 if (!home) home = getenv("USERPROFILE"); #endif if (home) { strcpy(history_path, home); strcat(history_path, "/"); strcat(history_path, history_file_name); read_history(history_path); } #endif while (TRUE) { #ifndef ENABLE_READLINE print_cmdline(code_block_open); char_index = 0; while ((last_char = getchar()) != '\n') { if (last_char == EOF) break; last_code_line[char_index++] = last_char; } if (last_char == EOF) { fputs("\n", stdout); break; } last_code_line[char_index] = '\0'; #else char* line = readline(code_block_open ? "* " : "> "); if (line == NULL) { printf("\n"); break; } strncpy(last_code_line, line, sizeof(last_code_line)-1); add_history(line); free(line); #endif if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) { if (!code_block_open) { break; } else{ /* count the quit/exit commands as strings if in a quote block */ strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } } else { if (code_block_open) { strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } else { strcpy(ruby_code, last_code_line); } } /* parse code */ parser = mrb_parser_new(mrb); parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); parser->lineno = cxt->lineno; mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); if (code_block_open) { /* no evaluation of code */ } else { if (0 < parser->nerr) { /* syntax error */ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); } else { /* generate bytecode */ struct RProc *proc = mrb_generate_code(mrb, parser); if (args.verbose) { mrb_codedump_all(mrb, proc); } /* pass a proc for evaulation */ nregs = first_command ? 0: proc->body.irep->nregs; /* evaluate the bytecode */ result = mrb_context_run(mrb, proc, mrb_top_self(mrb), nregs); /* did an exception occur? */ if (mrb->exc) { p(mrb, mrb_obj_value(mrb->exc), 0); mrb->exc = 0; } else { /* no */ if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){ result = mrb_any_to_s(mrb,result); } p(mrb, result, 1); } } ruby_code[0] = '\0'; last_code_line[0] = '\0'; mrb_gc_arena_restore(mrb, ai); } mrb_parser_free(parser); cxt->lineno++; first_command = FALSE; } mrbc_context_free(mrb, cxt); mrb_close(mrb); #ifdef ENABLE_READLINE write_history(history_path); #endif return 0; }