func newExceptionValue(s *C.mrb_state) *Exception { if s.exc == nil { panic("exception value init without exception") } arenaIndex := C.mrb_gc_arena_save(s) defer C.mrb_gc_arena_restore(s, C.int(arenaIndex)) // Convert the RObject* to an mrb_value value := C.mrb_obj_value(unsafe.Pointer(s.exc)) // Retrieve and convert backtrace to []string (avoiding reflection in Decode) var backtrace []string mrbBacktrace := newValue(s, C.mrb_exc_backtrace(s, value)).Array() for i := 0; i < mrbBacktrace.Len(); i++ { ln, _ := mrbBacktrace.Get(i) backtrace = append(backtrace, ln.String()) } // Extract file + line from first backtrace line file := "Unknown" line := 0 if len(backtrace) > 0 { fileAndLine := strings.Split(backtrace[0], ":") if len(fileAndLine) >= 2 { file = fileAndLine[0] line, _ = strconv.Atoi(fileAndLine[1]) } } result := newValue(s, value) return &Exception{ MrbValue: result, Message: result.String(), File: file, Line: line, Backtrace: backtrace, } }
func newExceptionValue(s *C.mrb_state) *Exception { if s.exc == nil { panic("exception value init without exception") } // Convert the RObject* to an mrb_value value := C.mrb_obj_value(unsafe.Pointer(s.exc)) result := newValue(s, value) return &Exception{MrbValue: result, cachedString: result.String()} }
func (m *MRuby) Eval(code string, args ...interface{}) C.mrb_value { c := C.CString(code) defer C.free(unsafe.Pointer(c)) value := C.mrb_load_string(m.state, c) mtype := C.struct_mrb_data_type{} C.mrb_get_datatype(m.state, value, &mtype) if m.state.exc != nil { exception := C.mrb_obj_value(unsafe.Pointer(m.state.exc)) fmt.Printf("exception: %#v\n", exception) } return value }
// Loads mruby code. Arguments are exposed as ARGV array. func (c *LoadContext) Load(code string, args ...interface{}) (res interface{}, err error) { l := len(args) ARGV := C.mrb_ary_new_capa(c.m.state, C.mrb_int(l)) for i := 0; i < l; i++ { ii := C.mrb_int(i) C.mrb_ary_set(c.m.state, ARGV, ii, c.m.mrubyValue(args[ii])) } C.mrb_define_global_const(c.m.state, argvCS, ARGV) codeC := C.CString(code) defer C.free(unsafe.Pointer(codeC)) v := C.mrb_load_string_cxt(c.m.state, codeC, c.context) res = c.m.goValue(v) if c.m.state.exc != nil { v = C.mrb_obj_value(unsafe.Pointer(c.m.state.exc)) err = errors.New(c.m.inspect(v)) } return }
func (m *MRuby) Run(code string, args ...interface{}) { c := C.CString(code) defer C.free(unsafe.Pointer(c)) x := C.mrbc_context_new(m.mrb) defer C.mrbc_context_free(m.mrb, x) p := C.mrb_parse_string(m.mrb, c, x) n := C.mrb_generate_code(m.mrb, p) C.mrb_pool_close((*C.mrb_pool)(p.pool)) a := C.CString("ARGV") defer C.free(unsafe.Pointer(a)) ARGV := C.mrb_ary_new(m.mrb) for i := 0; i < len(args); i++ { C.mrb_ary_push(m.mrb, ARGV, go2mruby(m.mrb, args[i])) } C.mrb_define_global_const(m.mrb, a, ARGV) C.mrb_run(m.mrb, n, C.mrb_top_self(m.mrb)) if m.mrb.exc != nil { C.mrb_p(m.mrb, C.mrb_obj_value(unsafe.Pointer(m.mrb.exc))) } }
// Value returns a *Value for this Class. *Values are sometimes required // as arguments where classes should be valid. func (c *Class) MrbValue(m *Mrb) *MrbValue { return newValue(c.mrb.state, C.mrb_obj_value(unsafe.Pointer(c.class))) }
// Returns the top-level `self` value. func (m *Mrb) TopSelf() *MrbValue { return newValue(m.state, C.mrb_obj_value(unsafe.Pointer(m.state.top_self))) }
// GenerateCode takes all the internal parser state and generates // executable Ruby code, returning the callable proc. func (p *Parser) GenerateCode() *MrbValue { proc := C.mrb_generate_code(p.mrb.state, p.parser) return newValue(p.mrb.state, C.mrb_obj_value(unsafe.Pointer(proc))) }