Exemple #1
0
func mruby2go(mrb *C.mrb_state, o C.mrb_value) interface{} {
	switch o.tt {
	case C.MRB_TT_TRUE:
		return true
	case C.MRB_TT_FALSE:
		return false
	case C.MRB_TT_FLOAT:
		return float32(C._mrb_float(o))
	case C.MRB_TT_FIXNUM:
		return int32(C._mrb_fixnum(o))
	case C.MRB_TT_ARRAY:
		{
			var list []interface{}
			for i := 0; i < int(C._RARRAY_LEN(o)); i++ {
				list = append(list, mruby2go(mrb, C.mrb_ary_ref(mrb, o, C.mrb_int(i))))
			}
			return list
		}
	case C.MRB_TT_HASH:
		{
			hash := make(map[string]interface{})
			keys := C.mrb_hash_keys(mrb, o)
			for i := 0; i < int(C._RARRAY_LEN(keys)); i++ {
				key := C.mrb_ary_ref(mrb, keys, C.mrb_int(i))
				val := C.mrb_hash_get(mrb, o, key)
				hash[C.GoString(C.mrb_string_value_ptr(mrb, key))] = mruby2go(mrb, val)
			}
			return hash
		}
	case C.MRB_TT_STRING:
		return C.GoString(C.mrb_string_value_ptr(mrb, o))
	}
	return nil
}
Exemple #2
0
func (v *MrbValue) call(method string, args []Value, block Value) (*MrbValue, error) {
	var argv []C.mrb_value = nil
	var argvPtr *C.mrb_value = nil

	if len(args) > 0 {
		// Make the raw byte slice to hold our arguments we'll pass to C
		argv = make([]C.mrb_value, len(args))
		for i, arg := range args {
			argv[i] = arg.MrbValue(&Mrb{v.state}).value
		}

		argvPtr = &argv[0]
	}

	var blockV *C.mrb_value
	if block != nil {
		val := block.MrbValue(&Mrb{v.state}).value
		blockV = &val
	}

	cs := C.CString(method)
	defer C.free(unsafe.Pointer(cs))

	// If we have a block, we have to call a separate function to
	// pass a block in. Otherwise, we just call it directly.
	var result C.mrb_value
	if blockV == nil {
		result = C.mrb_funcall_argv(
			v.state,
			v.value,
			C.mrb_intern_cstr(v.state, cs),
			C.mrb_int(len(argv)),
			argvPtr)
	} else {
		result = C.mrb_funcall_with_block(
			v.state,
			v.value,
			C.mrb_intern_cstr(v.state, cs),
			C.mrb_int(len(argv)),
			argvPtr,
			*blockV)
	}

	if exc := checkException(v.state); exc != nil {
		return nil, exc
	}

	return newValue(v.state, result), nil
}
Exemple #3
0
// Yield yields to a block with the given arguments.
//
// This should be called within the context of a Func.
func (m *Mrb) Yield(block Value, args ...Value) (*MrbValue, error) {
	mrbBlock := block.MrbValue(m)

	var argv []C.mrb_value = nil
	var argvPtr *C.mrb_value = nil
	if len(args) > 0 {
		// Make the raw byte slice to hold our arguments we'll pass to C
		argv = make([]C.mrb_value, len(args))
		for i, arg := range args {
			argv[i] = arg.MrbValue(m).value
		}

		argvPtr = &argv[0]
	}

	result := C.mrb_yield_argv(
		m.state,
		mrbBlock.value,
		C.mrb_int(len(argv)),
		argvPtr)
	if m.state.exc != nil {
		return nil, newExceptionValue(m.state)
	}

	return newValue(m.state, result), nil
}
Exemple #4
0
// Converts Go value to mruby value.
func (m *MRuby) mrubyValue(i interface{}) C.mrb_value {
	v := reflect.ValueOf(i)
	switch v.Kind() {
	case reflect.Invalid:
		return C.mrb_nil_value() // mrb_undef_value() explodes
	case reflect.Bool:
		b := v.Bool()
		if b {
			return C.mrb_true_value()
		} else {
			return C.mrb_false_value()
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return C.mrb_fixnum_value(C.mrb_int(v.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return C.mrb_fixnum_value(C.mrb_int(v.Uint()))
	case reflect.Float32, reflect.Float64:
		return C.mrb_float_value((*C.struct_mrb_state)(m.state), C.mrb_float(v.Float()))
	case reflect.String:
		cs := C.CString(v.String())
		defer C.free(unsafe.Pointer(cs))
		if v.Type() == symbolT {
			return C.mrb_check_intern_cstr(m.state, cs)
		} else {
			return C.mrb_str_new_cstr(m.state, cs)
		}
	case reflect.Array, reflect.Slice:
		l := v.Len()
		res := C.mrb_ary_new_capa(m.state, C.mrb_int(l))
		for i := 0; i < l; i++ {
			C.mrb_ary_set(m.state, res, C.mrb_int(i), m.mrubyValue(v.Index(i).Interface()))
		}
		return res
	case reflect.Map:
		l := v.Len()
		res := C.mrb_hash_new_capa(m.state, C.int(l))
		for _, key := range v.MapKeys() {
			val := v.MapIndex(key)
			C.mrb_hash_set(m.state, res, m.mrubyValue(key.Interface()), m.mrubyValue(val.Interface()))
		}
		return res
	}

	panic(fmt.Errorf("gomruby bug: failed to convert Go value %#v (%T) to mruby value", i, i))
}
Exemple #5
0
// 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
}
Exemple #6
0
// Get gets an element form the Array by index.
//
// This does not copy the element. This is a pointer/reference directly
// to the element in the array.
func (v *Array) Get(idx int) (*MrbValue, error) {
	result := C.mrb_ary_entry(v.value, C.mrb_int(idx))

	val := newValue(v.state, result)
	if val.Type() == TypeNil {
		val = nil
	}

	return val, nil
}
Exemple #7
0
// Converts mruby value to Go value.
func (m *MRuby) goValue(v C.mrb_value) interface{} {
	switch v.tt {
	case C.MRB_TT_UNDEF: // for example, result of syntax error
		return nil
	case C.MRB_TT_TRUE:
		return true
	case C.MRB_TT_FALSE:
		if C._gomruby_is_nil(v) == 0 {
			return false
		}
		return nil
	case C.MRB_TT_FIXNUM:
		return int(C._gomruby_fixnum(v))
	case C.MRB_TT_FLOAT:
		return float64(C._gomruby_float(v))
	case C.MRB_TT_SYMBOL:
		cs := C.mrb_string_value_ptr(m.state, v)
		return Symbol(C.GoString(cs))
	case C.MRB_TT_STRING:
		cs := C.mrb_string_value_ptr(m.state, v)
		return C.GoString(cs)
	case C.MRB_TT_ARRAY:
		l := int(C.mrb_ary_len(m.state, v))
		res := make([]interface{}, l)
		for i := 0; i < l; i++ {
			res[i] = m.goValue(C.mrb_ary_ref(m.state, v, C.mrb_int(i)))
		}
		return res
	case C.MRB_TT_HASH:
		keys := C.mrb_hash_keys(m.state, v)
		l := int(C.mrb_ary_len(m.state, keys))
		res := make(map[interface{}]interface{}, l)
		for i := 0; i < l; i++ {
			key := C.mrb_ary_ref(m.state, keys, C.mrb_int(i))
			val := C.mrb_hash_get(m.state, v, key)
			res[m.goValue(key)] = m.goValue(val)
		}
		return res
	}

	panic(fmt.Errorf("gomruby bug: failed to convert mruby value %#v to Go value", v))
}
Exemple #8
0
// Get gets an element form the Array by index.
//
// This does not copy the element. This is a pointer/reference directly
// to the element in the array.
func (v *Array) Get(idx int) (*MrbValue, error) {
	result := C.mrb_ary_entry(v.value, C.mrb_int(idx))
	if v.state.exc != nil {
		return nil, newExceptionValue(v.state)
	}

	val := newValue(v.state, result)
	if val.Type() == TypeFalse {
		val = nil
	}

	return val, nil
}
Exemple #9
0
func go2mruby(mrb *C.mrb_state, o interface{}) C.mrb_value {
	v := reflect.ValueOf(o)
	switch v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return C.mrb_fixnum_value(C.mrb_int(v.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return C.mrb_fixnum_value(C.mrb_int(v.Uint()))
	case reflect.Float32, reflect.Float64:
		return C.mrb_float_value((C.mrb_float)(v.Float()))
	case reflect.Complex64, reflect.Complex128:
		return C.mrb_float_value((C.mrb_float)(v.Float()))
	case reflect.String:
		ptr := C.CString(v.String())
		return C.mrb_str_new(mrb, ptr, C.strlen(ptr))
	case reflect.Bool:
		if v.Bool() {
			return C.mrb_true_value()
		}
		return C.mrb_false_value()
	case reflect.Array, reflect.Slice:
		ary := C.mrb_ary_new(mrb)
		for i := 0; i < v.Len(); i++ {
			C.mrb_ary_push(mrb, ary, go2mruby(mrb, v.Index(i).Interface()))
		}
		return ary
	case reflect.Map:
		hash := C.mrb_hash_new(mrb, 32)
		for _, key := range v.MapKeys() {
			val := v.MapIndex(key)
			C.mrb_hash_set(mrb, hash, go2mruby(mrb, key.String()), go2mruby(mrb, val.Interface()))
		}
		return hash
	case reflect.Interface:
		return go2mruby(mrb, v.Elem().Interface())
	}
	return C.mrb_nil_value()
}
Exemple #10
0
// Instantiate the class with the given args.
func (c *Class) New(args ...Value) (*MrbValue, error) {
	var argv []C.mrb_value = nil
	var argvPtr *C.mrb_value = nil
	if len(args) > 0 {
		// Make the raw byte slice to hold our arguments we'll pass to C
		argv = make([]C.mrb_value, len(args))
		for i, arg := range args {
			argv[i] = arg.MrbValue(c.mrb).value
		}

		argvPtr = &argv[0]
	}

	result := C.mrb_obj_new(c.mrb.state, c.class, C.mrb_int(len(argv)), argvPtr)
	if c.mrb.state.exc != nil {
		return nil, newExceptionValue(c.mrb.state)
	}

	return newValue(c.mrb.state, result), nil
}
Exemple #11
0
// Returns a Value for a fixed number.
func (m *Mrb) FixnumValue(v int) *MrbValue {
	return newValue(m.state, C.mrb_fixnum_value(C.mrb_int(v)))
}