Esempio n. 1
0
func ipairsAux(L *lua.State) int {
	i := L.CheckInteger(2) + 1
	L.PushInteger(int64(i))
	L.PushInteger(int64(i))
	L.GetTable(1)
	if L.Type(-1) == lua.LUA_TNIL {
		return 1
	}
	return 2
}
Esempio n. 2
0
File: luar.go Progetto: imvu/Tetra
// Convert a Lua value 'idx' on the stack to the Go value of desired type 't'. Handles
// numerical and string types in a straightforward way, and will convert tables to
// either map or slice types.
func LuaToGo(L *lua.State, t reflect.Type, idx int) interface{} {
	var value interface{}
	var kind reflect.Kind

	if t != nil { // let the Lua type drive the conversion...
		if t.Kind() == reflect.Ptr {
			kind = t.Elem().Kind()
		} else if t.Kind() == reflect.Interface {
			t = nil
		} else {
			kind = t.Kind()
		}
	}

	switch L.Type(idx) {
	case lua.LUA_TNIL:
		if t == nil {
			return nil
		}
		switch kind {
		default:
			cannotConvert(L, idx, "nil", kind, t)
		}
	case lua.LUA_TBOOLEAN:
		if t == nil {
			kind = reflect.Bool
		}
		switch kind {
		case reflect.Bool:
			{
				ptr := new(bool)
				*ptr = bool(L.ToBoolean(idx))
				value = *ptr
			}
		default:
			cannotConvert(L, idx, "bool", kind, t)
		}
	case lua.LUA_TSTRING:
		if t == nil {
			kind = reflect.String
		}
		switch kind {
		case reflect.String:
			{
				tos := L.ToString(idx)
				ptr := new(string)
				*ptr = tos
				value = *ptr
			}
		default:
			cannotConvert(L, idx, "string", kind, t)
		}
	case lua.LUA_TNUMBER:
		if t == nil {
			kind = reflect.Float64
		}
		switch kind {
		case reflect.Float64:
			{
				ptr := new(float64)
				*ptr = L.ToNumber(idx)
				value = *ptr
			}
		case reflect.Float32:
			{
				ptr := new(float32)
				*ptr = float32(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Int:
			{
				ptr := new(int)
				*ptr = int(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Int8:
			{
				ptr := new(int8)
				*ptr = int8(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Int16:
			{
				ptr := new(int16)
				*ptr = int16(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Int32:
			{
				ptr := new(int32)
				*ptr = int32(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Int64:
			{
				ptr := new(int64)
				*ptr = int64(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Uint:
			{
				ptr := new(uint)
				*ptr = uint(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Uint8:
			{
				ptr := new(uint8)
				*ptr = uint8(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Uint16:
			{
				ptr := new(uint16)
				*ptr = uint16(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Uint32:
			{
				ptr := new(uint32)
				*ptr = uint32(L.ToNumber(idx))
				value = *ptr
			}
		case reflect.Uint64:
			{
				ptr := new(uint64)
				*ptr = uint64(L.ToNumber(idx))
				value = *ptr
			}
		default:
			cannotConvert(L, idx, "number", kind, t)
		}
	case lua.LUA_TTABLE:
		if t == nil {
			kind = reflect.Interface
		}
		fallthrough
	default:
		istable := L.IsTable(idx)
		// if we don't know the type and the Lua object is userdata,
		// then it might be a proxy for a Go object. Otherwise wrap
		// it up as a LuaObject.
		if t == nil && !istable {
			if isValueProxy(L, idx) {
				return unwrapProxy(L, idx)
			} else {
				return NewLuaObject(L, idx)
			}
		}
		switch kind {
		case reflect.Slice:
			{
				// if we get a table, then copy its values to a new slice
				if istable {
					value = CopyTableToSlice(L, t, idx)
				} else {
					value = unwrapProxyOrComplain(L, idx)
				}
			}
		case reflect.Map:
			{
				if istable {
					value = CopyTableToMap(L, t, idx)
				} else {
					value = unwrapProxyOrComplain(L, idx)
				}
			}
		case reflect.Struct:
			{
				if istable {
					value = CopyTableToStruct(L, t, idx)
				} else {
					value = unwrapProxyOrComplain(L, idx)
				}
			}
		case reflect.Interface:
			{
				if istable {
					// have to make an executive decision here: tables with non-zero
					// length are assumed to be slices!
					if L.ObjLen(idx) > 0 {
						value = CopyTableToSlice(L, nil, idx)
					} else {
						value = CopyTableToMap(L, nil, idx)
					}
				} else if L.IsNumber(idx) {
					value = L.ToNumber(idx)
				} else if L.IsString(idx) {
					value = L.ToString(idx)
				} else if L.IsBoolean(idx) {
					value = L.ToBoolean(idx)
				} else if L.IsNil(idx) {
					return nil
				} else {
					value = unwrapProxyOrComplain(L, idx)
				}
			}
		default:
			value = unwrapProxyOrComplain(L, idx)
			//cannotConvert(L,idx,"unknown",kind,t)
		}
	}

	return value
}
Esempio n. 3
0
func register(L *lua.State, table string, values Map, convertFun bool) {
	pop := true
	if table == "*" {
		pop = false
	} else if len(table) > 0 {
		L.GetGlobal(table)
		if L.IsNil(-1) {
			L.NewTable()
			L.SetGlobal(table)
			L.GetGlobal(table)
		}
	} else {
		L.GetGlobal("_G")
	}
	for name, val := range values {
		t := reflect.TypeOf(val)
		if t.Kind() == reflect.Func {
			if convertFun {
				L.PushGoFunction(GoLuaFunc(L, val))
			} else {
				lf := val.(func(*lua.State) int)
				L.PushGoFunction(lf)
			}
		} else {
			GoToLua(L, t, valueOf(val), false)
		}
		L.SetField(-2, name)

		if t.Kind() == reflect.Func {
			var lf func(*lua.State) int
			if convertFun {
				lf = GoLuaFunc(L, val)
			} else {
				lf = val.(func(*lua.State) int)
			}
			L.PushGoFunction(func(L *lua.State) (ret int) {
				defer func() {
					if err2 := recover(); err2 != nil {
						GoToLua(L, typeof(err2), valueOf(err2), false)
						ret = 1
						return
					}
				}()

				ret = lf(L)
				pos := L.GetTop() - ret + 1
				L.PushNil()
				L.Insert(pos)

				for i := 0; i < L.GetTop(); i++ {
					fmt.Println(L.Typename(int(L.Type(i + 1))))
				}
				return ret + 1
			})
			L.SetField(-2, "safe_"+name)
		}
	}
	if pop {
		L.Pop(1)
	}
}
Esempio n. 4
0
func luaToGo(L *lua.State, t reflect.Type, idx int, visited map[uintptr]interface{}) interface{} {
	var value interface{}

	var kind reflect.Kind
	if t != nil {
		if t.Kind() == reflect.Ptr {
			kind = t.Elem().Kind()
		} else if t.Kind() == reflect.Interface {
			// Let the Lua type drive the conversion.
			t = nil
		} else {
			kind = t.Kind()
		}
	}

	switch L.Type(idx) {
	case lua.LUA_TNIL:
		if t == nil {
			return nil
		}
		switch kind {
		default:
			value = reflect.Zero(t).Interface()
		}
	case lua.LUA_TBOOLEAN:
		if t == nil {
			kind = reflect.Bool
		}
		switch kind {
		case reflect.Bool:
			ptr := new(bool)
			*ptr = L.ToBoolean(idx)
			value = *ptr
		default:
			value = reflect.Zero(t).Interface()
		}
	case lua.LUA_TSTRING:
		if t == nil {
			kind = reflect.String
		}
		switch kind {
		case reflect.String:
			tos := L.ToString(idx)
			ptr := new(string)
			*ptr = tos
			value = *ptr
		default:
			value = reflect.Zero(t).Interface()
		}
	case lua.LUA_TNUMBER:
		if t == nil {
			// Infering the type here (e.g. int if round value) would break backward
			// compatibility and drift away from Lua's design: the numeric type is
			// specified at compile time.
			kind = reflect.Float64
		}
		switch kind {
		case reflect.Float64:
			ptr := new(float64)
			*ptr = L.ToNumber(idx)
			value = *ptr
		case reflect.Float32:
			ptr := new(float32)
			*ptr = float32(L.ToNumber(idx))
			value = *ptr
		case reflect.Int:
			ptr := new(int)
			*ptr = int(L.ToNumber(idx))
			value = *ptr
		case reflect.Int8:
			ptr := new(int8)
			*ptr = int8(L.ToNumber(idx))
			value = *ptr
		case reflect.Int16:
			ptr := new(int16)
			*ptr = int16(L.ToNumber(idx))
			value = *ptr
		case reflect.Int32:
			ptr := new(int32)
			*ptr = int32(L.ToNumber(idx))
			value = *ptr
		case reflect.Int64:
			ptr := new(int64)
			*ptr = int64(L.ToNumber(idx))
			value = *ptr
		case reflect.Uint:
			ptr := new(uint)
			*ptr = uint(L.ToNumber(idx))
			value = *ptr
		case reflect.Uint8:
			ptr := new(uint8)
			*ptr = uint8(L.ToNumber(idx))
			value = *ptr
		case reflect.Uint16:
			ptr := new(uint16)
			*ptr = uint16(L.ToNumber(idx))
			value = *ptr
		case reflect.Uint32:
			ptr := new(uint32)
			*ptr = uint32(L.ToNumber(idx))
			value = *ptr
		case reflect.Uint64:
			ptr := new(uint64)
			*ptr = uint64(L.ToNumber(idx))
			value = *ptr
		default:
			value = reflect.Zero(t).Interface()
		}
	case lua.LUA_TTABLE:
		if t == nil {
			kind = reflect.Interface
		}
		fallthrough
	default:
		istable := L.IsTable(idx)
		// If we don't know the type and the Lua object is userdata,
		// then it might be a proxy for a Go object. Otherwise wrap
		// it up as a LuaObject.
		if t == nil && !istable {
			if isValueProxy(L, idx) {
				v, _ := valueOfProxy(L, idx)
				return v.Interface()
			}
			return NewLuaObject(L, idx)
		}
		switch kind {
		case reflect.Array:
			if istable {
				ptr := L.ToPointer(idx)
				if val, ok := visited[ptr]; ok {
					return val
				}
				value = copyTableToSlice(L, t, idx, visited)
			} else {
				value = mustUnwrapProxy(L, idx)
			}
		case reflect.Slice:
			// if we get a table, then copy its values to a new slice
			if istable {
				ptr := L.ToPointer(idx)
				if val, ok := visited[ptr]; ok {
					return val
				}
				value = copyTableToSlice(L, t, idx, visited)
			} else {
				value = mustUnwrapProxy(L, idx)
			}
		case reflect.Map:
			if istable {
				ptr := L.ToPointer(idx)
				if val, ok := visited[ptr]; ok {
					return val
				}
				value = copyTableToMap(L, t, idx, visited)
			} else {
				value = mustUnwrapProxy(L, idx)
			}
		case reflect.Struct:
			if istable {
				ptr := L.ToPointer(idx)
				if val, ok := visited[ptr]; ok {
					return val
				}
				value = copyTableToStruct(L, t, idx, visited)
			} else {
				value = mustUnwrapProxy(L, idx)
			}
		case reflect.Interface:
			if istable {
				ptr := L.ToPointer(idx)
				if val, ok := visited[ptr]; ok {
					return val
				}
				// We have to make an executive decision here: tables with non-zero
				// length are assumed to be slices!
				if L.ObjLen(idx) > 0 {
					value = copyTableToSlice(L, nil, idx, visited)
				} else {
					value = copyTableToMap(L, nil, idx, visited)
				}
			} else if L.IsNumber(idx) {
				value = L.ToNumber(idx)
			} else if L.IsString(idx) {
				value = L.ToString(idx)
			} else if L.IsBoolean(idx) {
				value = L.ToBoolean(idx)
			} else if L.IsNil(idx) {
				return nil
			} else {
				value = mustUnwrapProxy(L, idx)
			}
		default:
			value = mustUnwrapProxy(L, idx)
		}
	}

	return value
}
Esempio n. 5
0
File: luar.go Progetto: kdar/luar
// Convert a Lua value 'idx' on the stack to the Go value of desired type 't'. Handles
// numerical and string types in a straightforward way, and will convert tables to
// either map or slice types.
func LuaToGo(L *lua.State, t reflect.Type, idx int) interface{} {
	var value interface{}
	var kind reflect.Kind

	if t == nil { // let the Lua type drive the conversion...
		switch L.Type(idx) {
		case lua.LUA_TNIL:
			return nil // well, d'oh
		case lua.LUA_TBOOLEAN:
			kind = reflect.Bool
		case lua.LUA_TSTRING:
			kind = reflect.String
		case lua.LUA_TTABLE:
			kind = reflect.Interface
		default:
			return NewLuaObject(L, idx)
		}
	} else if t.Kind() == reflect.Ptr {
		kind = t.Elem().Kind()
	} else {
		kind = t.Kind()
	}

	switch kind {
	// various numerical types are tedious but straightforward
	case reflect.Float64:
		{
			ptr := new(float64)
			*ptr = L.ToNumber(idx)
			value = *ptr
		}
	case reflect.Float32:
		{
			ptr := new(float32)
			*ptr = float32(L.ToNumber(idx))
			value = *ptr
		}
	case reflect.Int:
		{
			ptr := new(int)
			*ptr = int(L.ToNumber(idx))
			value = *ptr
		}
	case reflect.Int8:
		{
			ptr := new(byte)
			*ptr = byte(L.ToNumber(idx))
			value = *ptr
		}
	case reflect.String:
		{
			tos := L.ToString(idx)
			ptr := new(string)
			*ptr = tos
			value = *ptr
		}
	case reflect.Bool:
		{
			ptr := new(bool)
			*ptr = bool(L.ToBoolean(idx))
			value = *ptr
		}
	case reflect.Slice:
		{
			// if we get a table, then copy its values to a new slice
			if L.IsTable(idx) {
				value = CopyTableToSlice(L, t, idx)
			} else {
				value = unwrapProxy(L, idx)
			}
		}
	case reflect.Map:
		{
			if L.IsTable(idx) {
				value = CopyTableToMap(L, t, idx)
			} else {
				value = unwrapProxy(L, idx)
			}
		}
	case reflect.Struct:
		{
			if L.IsTable(idx) {
				value = CopyTableToStruct(L, t, idx)
			} else {
				value = unwrapProxy(L, idx)
			}
		}
	case reflect.Interface:
		{
			if L.IsTable(idx) {
				// have to make an executive decision here: tables with non-zero
				// length are assumed to be slices!
				if L.ObjLen(idx) > 0 {
					value = CopyTableToSlice(L, nil, idx)
				} else {
					value = CopyTableToMap(L, nil, idx)
				}
			} else if L.IsNumber(idx) {
				value = L.ToNumber(idx)
			} else if L.IsString(idx) {
				value = L.ToString(idx)
			} else if L.IsBoolean(idx) {
				value = L.ToBoolean(idx)
			} else {
				value = unwrapProxy(L, idx)
			}
		}
	default:
		{
			fmt.Println("unhandled type", t)
			value = 20
		}

	}
	return value
}