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, } }
// Restores the arena index so the objects between the save and this point // can be garbage collected in the future. // // See ArenaSave for more documentation. func (m *Mrb) ArenaRestore(idx ArenaIndex) { C.mrb_gc_arena_restore(m.state, C.int(idx)) }