Esempio n. 1
0
// Also for arrays.
func copySliceToTable(L *lua.State, vslice reflect.Value, visited visitor) int {
	ref := vslice
	for vslice.Kind() == reflect.Ptr {
		// For arrays.
		vslice = vslice.Elem()
	}

	if vslice.IsValid() && (vslice.Kind() == reflect.Slice || vslice.Kind() == reflect.Array) {
		n := vslice.Len()
		L.CreateTable(n, 0)
		if vslice.Kind() == reflect.Slice {
			visited.mark(vslice)
		} else if ref.Kind() == reflect.Ptr {
			visited.mark(ref)
		}

		for i := 0; i < n; i++ {
			L.PushInteger(int64(i + 1))
			v := vslice.Index(i)
			if isNil(v) {
				v = nullv
			}
			goToLua(L, nil, v, true, visited)
			L.SetTable(-3)
		}
		return 1
	}
	L.PushNil()
	L.PushString("not a slice/array")
	return 2
}
Esempio n. 2
0
func copyStructToTable(L *lua.State, vstruct reflect.Value, visited visitor) int {
	// If 'vstruct' is a pointer to struct, use the pointer to mark as visited.
	ref := vstruct
	for vstruct.Kind() == reflect.Ptr {
		vstruct = vstruct.Elem()
	}

	if vstruct.IsValid() && vstruct.Type().Kind() == reflect.Struct {
		n := vstruct.NumField()
		L.CreateTable(n, 0)
		if ref.Kind() == reflect.Ptr {
			visited.mark(ref)
		}

		for i := 0; i < n; i++ {
			st := vstruct.Type()
			field := st.Field(i)
			key := field.Name
			tag := field.Tag.Get("lua")
			if tag != "" {
				key = tag
			}
			goToLua(L, nil, reflect.ValueOf(key), true, visited)
			v := vstruct.Field(i)
			goToLua(L, nil, v, true, visited)
			L.SetTable(-3)
		}
		return 1
	}
	L.PushNil()
	L.PushString("not a struct")
	return 2
}
Esempio n. 3
0
// Registers a Go function as a global variable and add it to the sandbox.
func sandboxRegister(L *lua.State, name string, f interface{}) {
	goToLua(L, name, f)

	L.PushString(registryWhitelist)
	L.GetTable(lua.LUA_REGISTRYINDEX)
	L.GetGlobal(name)
	L.SetField(-2, name)
}
Esempio n. 4
0
func GetTableInt(L *lua.State, name string) int {
	// Remember to check stack for 1 extra location
	L.PushString(name)
	L.GetTable(-2)
	r := L.ToInteger(-1)
	L.Pop(1)
	return r
}
Esempio n. 5
0
func LuaTableGetString(L *lua.State, key string) string {
	L.PushString(key)
	L.GetTable(-2)
	r := ""
	if !L.IsNil(-1) {
		r = L.ToString(-1)
	}
	L.Pop(1)
	return r
}
Esempio n. 6
0
File: luar.go Progetto: imvu/Tetra
// GoLuaFunc converts an arbitrary Go function into a Lua-compatible GoFunction.
// There are special optimized cases for functions that go from strings to strings,
// and doubles to doubles, but otherwise Go
// reflection is used to provide a generic wrapper function
func GoLuaFunc(L *lua.State, fun interface{}) lua.LuaGoFunction {
	switch f := fun.(type) {
	case func(*lua.State) int:
		return f
	case func(string) string:
		return func(L *lua.State) int {
			L.PushString(f(L.ToString(1)))
			return 1
		}
	case func(float64) float64:
		return func(L *lua.State) int {
			L.PushNumber(f(L.ToNumber(1)))
			return 1
		}
	default:
	}
	var funv reflect.Value
	switch ff := fun.(type) {
	case reflect.Value:
		funv = ff
	default:
		funv = valueOf(fun)
	}
	funt := funv.Type()
	targs, tout := functionArgRetTypes(funt)
	return func(L *lua.State) int {
		var lastT reflect.Type
		orig_targs := targs
		isVariadic := funt.IsVariadic()
		if isVariadic {
			n := len(targs)
			lastT = targs[n-1].Elem()
			targs = targs[0 : n-1]
		}
		args := make([]reflect.Value, len(targs))
		for i, t := range targs {
			val := LuaToGo(L, t, i+1)
			args[i] = valueOfNil(val)
			//println(i,args[i].String())
		}
		if isVariadic {
			n := L.GetTop()
			for i := len(targs) + 1; i <= n; i++ {
				ival := LuaToGo(L, lastT, i)
				args = append(args, valueOfNil(ival))
			}
			targs = orig_targs
		}
		resv := callGo(L, funv, args)
		for i, val := range resv {
			GoToLua(L, tout[i], val, false)
		}
		return len(resv)
	}
}
Esempio n. 7
0
func sandboxCompile(L *lua.State, registryIndex string, name, code string) {
	L.PushString(registryIndex)
	L.GetTable(lua.LUA_REGISTRYINDEX)
	L.PushString(name)
	err := L.LoadString(code)
	if err != 0 {
		log.Fatalf("%s: %s", name, L.ToString(-1))
		L.Pop(2)
	} else {
		L.SetTable(-3)
	}
}
Esempio n. 8
0
File: luar.go Progetto: kdar/luar
// copy a Go slice to a Lua table
func CopySliceToTable(L *lua.State, vslice reflect.Value) int {
	if vslice.IsValid() && vslice.Type().Kind() == reflect.Slice {
		n := vslice.Len()
		L.CreateTable(n, 0)
		for i := 0; i < n; i++ {
			L.PushInteger(int64(i + 1))
			GoToLua(L, nil, vslice.Index(i))
			L.SetTable(-3)
		}
		return 1
	} else {
		L.PushNil()
		L.PushString("not a slice!")
	}
	return 2
}
Esempio n. 9
0
File: luar.go Progetto: kdar/luar
// copy a Go map to a Lua table
func CopyMapToTable(L *lua.State, vmap reflect.Value) int {
	if vmap.IsValid() && vmap.Type().Kind() == reflect.Map {
		n := vmap.Len()
		L.CreateTable(0, n)
		for _, key := range vmap.MapKeys() {
			val := vmap.MapIndex(key)
			GoToLua(L, nil, key)
			GoToLua(L, nil, val)
			L.SetTable(-3)
		}
		return 1
	} else {
		L.PushNil()
		L.PushString("not a map!")
	}
	return 2
}
Esempio n. 10
0
func copyMapToTable(L *lua.State, vmap reflect.Value, visited visitor) int {
	if vmap.IsValid() && vmap.Type().Kind() == reflect.Map {
		n := vmap.Len()
		L.CreateTable(0, n)
		visited.mark(vmap)
		for _, key := range vmap.MapKeys() {
			v := vmap.MapIndex(key)
			goToLua(L, nil, key, false, visited)
			if isNil(v) {
				v = nullv
			}
			goToLua(L, nil, v, true, visited)
			L.SetTable(-3)
		}
		return 1
	}
	L.PushNil()
	L.PushString("not a map!")
	return 2
}
Esempio n. 11
0
func MessThingPronounsubMethod(state *lua.State, thing *Thing) int {
	state.PushGoFunction(func(state *lua.State) int {
		thing := checkThing(state, 1)
		text := state.CheckString(2)

		for code, pronoun := range thing.Pronouns() {
			lowerCode := fmt.Sprintf(`%%%s`, code)
			upperCode := fmt.Sprintf(`%%%s`, strings.ToUpper(code))
			text = strings.Replace(text, lowerCode, pronoun, -1)
			text = strings.Replace(text, upperCode, strings.ToTitle(pronoun), -1)
		}

		text = strings.Replace(text, `%n`, thing.Name, -1)
		text = strings.Replace(text, `%N`, thing.Name, -1)

		state.Pop(2)           // ( udataThing str -- )
		state.PushString(text) // ( -- str' )
		return 1
	})
	return 1
}
Esempio n. 12
0
func pushMap(L *lua.State, m map[string]interface{}, lower bool) {
	L.CreateTable(0, len(m))
	for k, v := range m {
		if lower {
			L.PushString(strings.ToLower(k))
		} else {
			L.PushString(k)
		}
		switch t := v.(type) {
		case string:
			L.PushString(t)
		case int64:
			L.PushInteger(t)
		case int:
			L.PushInteger(int64(t))
		case float64:
			L.PushNumber(t)
		case bool:
			L.PushBoolean(t)
		case map[string]interface{}:
			pushMap(L, t, false)
		default:
			L.PushNil()
		}
		L.SetTable(-3)
	}
}
Esempio n. 13
0
func LuaIntGetterSetterFunction(fname string, L *lua.State, getter func(tl *Tasklist, entry *Entry) string, setter func(tl *Tasklist, entry *Entry, value string)) int {
	argNum := L.GetTop()

	if argNum == 0 {
		entry := GetEntryFromLua(L, CURSOR, fname)
		tl := GetTasklistFromLua(L)
		L.PushString(getter(tl, entry))
		return 1
	} else if argNum == 1 {
		value := L.ToString(1)
		entry := GetEntryFromLua(L, CURSOR, fname)
		tl := GetTasklistFromLua(L)
		setter(tl, entry, value)
		if !tl.luaFlags.cursorCloned {
			tl.luaFlags.cursorEdited = true
		}
		return 0
	}

	panic(errors.New(fmt.Sprintf("Incorrect number of argoments to %s (only 0 or 1 accepted)", fname)))
	return 0
}
Esempio n. 14
0
func LuaIntColumn(L *lua.State) int {
	argNum := L.GetTop()

	if argNum == 1 {
		name := L.ToString(1)
		entry := GetEntryFromLua(L, CURSOR, "column()")
		L.PushString(entry.Column(name))
		return 1
	} else if argNum == 2 {
		name := L.ToString(1)
		value := L.ToString(2)
		entry := GetEntryFromLua(L, CURSOR, "column()")
		entry.SetColumn(name, value)
		tl := GetTasklistFromLua(L)
		if !tl.luaFlags.cursorCloned {
			tl.luaFlags.cursorEdited = true
		}
		return 0
	}

	panic(errors.New("Incorrect number of arguments to column (only 1 or 2 accepted)"))
	return 0
}
Esempio n. 15
0
File: luar.go Progetto: yinlei/luar
// Copy a Go struct to a Lua table. nils in both slices and structs
// are represented as luar.null. Defines luar.struct2table
// Use tags to set field names.
func CopyStructToTable(L *lua.State, vstruct reflect.Value) int {
	if vstruct.IsValid() && vstruct.Type().Kind() == reflect.Struct {
		n := vstruct.NumField()
		L.CreateTable(n, 0)
		for i := 0; i < n; i++ {
			st := vstruct.Type()
			field := st.Field(i)
			key := field.Name
			tag := field.Tag.Get("lua")
			if tag != "" {
				key = tag
			}
			GoToLua(L, nil, reflect.ValueOf(key), true)
			v := vstruct.Field(i)
			GoToLua(L, nil, v, true)
			L.SetTable(-3)
		}
		return 1
	} else {
		L.PushNil()
		L.PushString("not a struct!")
	}
	return 2
}
Esempio n. 16
0
func TableFormat(state *lua.State) int {
	state.CheckType(1, lua.LUA_TTABLE)
	state.CheckType(2, lua.LUA_TTABLE) // ( ??? -- tbl tblFields )
	log.Println("Formatting a table by a table")
	printStackTypes(state)

	numFields := int(state.ObjLen(-1))
	fields := make([]string, numFields)
	maxFieldLen := make(map[string]int)
	for i := 0; i < numFields; i++ {
		state.RawGeti(-1, i+1) // ( tbl tblFields -- tbl tblFields strHeader )
		fieldName := state.ToString(-1)
		fields[i] = fieldName
		maxFieldLen[fieldName] = len(fieldName)
		state.Pop(1) // ( tbl tblFields strField -- tbl tblFields )
	}
	state.Pop(1) // ( tbl tblFields -- tbl )
	log.Println("Slurped up the fields list (table #2)")
	printStackTypes(state)

	numRows := int(state.ObjLen(-1))
	rows := make([]map[string]string, numRows)
	for i := 0; i < numRows; i++ {
		state.RawGeti(-1, i+1) // ( tbl -- tbl tblRow )
		row := make(map[string]string)
		for _, field := range fields {
			state.PushString(field) // ( tbl tblRow -- tbl tblRow strField )
			state.RawGet(-2)        // ( tbl tblRow strField -- tbl tblRow tblField )

			row[field] = state.ToString(-1)

			if maxFieldLen[field] < len(row[field]) {
				maxFieldLen[field] = len(row[field])
			}

			state.Pop(1) // ( tbl tblRow tblField -- tbl tblRow )
		}
		rows[i] = row
		state.Pop(1) // ( tbl tblRow -- tbl )
	}
	state.Pop(1) // ( tbl -- )
	log.Println("Slurped up the data table (table #1)")
	printStackTypes(state)

	// %5s  %10s  %13s
	fmtStrings := make([]string, numFields)
	for i, field := range fields {
		fmtStrings[i] = fmt.Sprintf("%%-%ds", maxFieldLen[field])
	}
	fmtString := strings.Join(fmtStrings, "  ")
	log.Println("Figured out the format string:", fmtString)

	rowStrings := make([]string, numRows+1)
	rowFields := make([]interface{}, numFields)
	for i, row := range rows {
		for j, field := range fields {
			rowFields[j] = row[field]
		}
		rowStrings[i+1] = fmt.Sprintf(fmtString, rowFields...)
	}
	for i := 0; i < numFields; i++ {
		rowFields[i] = strings.Title(fields[i])
	}
	rowStrings[0] = fmt.Sprintf(fmtString, rowFields...)
	log.Println("Yay formatted all the strings")

	formattedTable := strings.Join(rowStrings, "\n")
	state.PushString(formattedTable) // ( -- str )
	log.Println("All done formatting this table!")
	printStackTypes(state)

	return 1
}
Esempio n. 17
0
File: luar.go Progetto: imvu/Tetra
// Push a Go value 'val' of type 't' on the Lua stack.
// If we haven't been given a concrete type, use the type of the value
// and unbox any interfaces.  You can force slices and maps to be copied
// over as tables by setting 'dontproxify' to true.
func GoToLua(L *lua.State, t reflect.Type, val reflect.Value, dontproxify bool) {
	if !val.IsValid() {
		L.PushNil()
		return
	}
	if t == nil {
		t = val.Type()
	}
	if t.Kind() == reflect.Interface && !val.IsNil() { // unbox interfaces!
		val = valueOf(val.Interface())
		t = val.Type()
	}
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	kind := t.Kind()

	// underlying type is 'primitive' ? wrap it as a proxy!
	if isPrimitiveDerived(t, kind) != nil {
		makeValueProxy(L, val, cINTERFACE_META)
		return
	}

	switch kind {
	case reflect.Float64, reflect.Float32:
		{
			L.PushNumber(val.Float())
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		{
			L.PushNumber(float64(val.Int()))
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		{
			L.PushNumber(float64(val.Uint()))
		}
	case reflect.String:
		{
			L.PushString(val.String())
		}
	case reflect.Bool:
		{
			L.PushBoolean(val.Bool())
		}
	case reflect.Slice:
		{
			if !dontproxify {
				makeValueProxy(L, val, cSLICE_META)
			} else {
				CopySliceToTable(L, val)
			}
		}
	case reflect.Map:
		{
			if !dontproxify {
				makeValueProxy(L, val, cMAP_META)
			} else {
				CopyMapToTable(L, val)
			}
		}
	case reflect.Struct:
		{
			if v, ok := val.Interface().(error); ok {
				L.PushString(v.Error())
			} else if v, ok := val.Interface().(*LuaObject); ok {
				v.Push()
			} else {
				if (val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface) && !val.Elem().IsValid() {
					L.PushNil()
					return
				}
				makeValueProxy(L, val, cSTRUCT_META)
			}
		}
	default:
		{
			if v, ok := val.Interface().(error); ok {
				L.PushString(v.Error())
			} else if val.IsNil() {
				L.PushNil()
			} else {
				makeValueProxy(L, val, cINTERFACE_META)
			}
		}
	}
}
Esempio n. 18
0
File: luar.go Progetto: imvu/Tetra
func proxy__tostring(L *lua.State) int {
	obj, _ := valueOfProxy(L, 1)
	L.PushString(obj.Type().String())
	return 1
}
Esempio n. 19
0
func SetTableIntString(L *lua.State, idx int64, value string) {
	L.PushInteger(idx)
	L.PushString(value)
	L.SetTable(-3)
}
Esempio n. 20
0
// TODO: Check if we really need multiple pointer levels since pointer methods
// can be called on non-pointers.
func goToLua(L *lua.State, t reflect.Type, val reflect.Value, dontproxify bool, visited visitor) {
	if !val.IsValid() {
		L.PushNil()
		return
	}

	// Unbox interface.
	if val.Kind() == reflect.Interface && !val.IsNil() {
		val = reflect.ValueOf(val.Interface())
	}

	// Follow pointers if not proxifying. We save the original pointer Value in case we proxify.
	ptrVal := val
	for val.Kind() == reflect.Ptr {
		val = val.Elem()
	}

	if !val.IsValid() {
		L.PushNil()
		return
	}

	// As a special case, we always proxify nullv, the empty element for slices and maps.
	if val.CanInterface() && val.Interface() == nullv.Interface() {
		makeValueProxy(L, val, cInterfaceMeta)
		return
	}

	switch val.Kind() {
	case reflect.Float64, reflect.Float32:
		if !dontproxify && predeclaredScalarType(val.Type()) != nil {
			makeValueProxy(L, ptrVal, cNumberMeta)
		} else {
			L.PushNumber(val.Float())
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if !dontproxify && predeclaredScalarType(val.Type()) != nil {
			makeValueProxy(L, ptrVal, cNumberMeta)
		} else {
			L.PushNumber(float64(val.Int()))
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if !dontproxify && predeclaredScalarType(val.Type()) != nil {
			makeValueProxy(L, ptrVal, cNumberMeta)
		} else {
			L.PushNumber(float64(val.Uint()))
		}
	case reflect.String:
		if !dontproxify && predeclaredScalarType(val.Type()) != nil {
			makeValueProxy(L, ptrVal, cStringMeta)
		} else {
			L.PushString(val.String())
		}
	case reflect.Bool:
		if !dontproxify && predeclaredScalarType(val.Type()) != nil {
			makeValueProxy(L, ptrVal, cInterfaceMeta)
		} else {
			L.PushBoolean(val.Bool())
		}
	case reflect.Complex128, reflect.Complex64:
		makeValueProxy(L, ptrVal, cComplexMeta)
	case reflect.Array:
		// It needs be a pointer to be a proxy, otherwise values won't be settable.
		if !dontproxify && ptrVal.Kind() == reflect.Ptr {
			makeValueProxy(L, ptrVal, cSliceMeta)
		} else {
			// See the case of struct.
			if ptrVal.Kind() == reflect.Ptr && visited.push(ptrVal) {
				return
			}
			copySliceToTable(L, ptrVal, visited)
		}
	case reflect.Slice:
		if !dontproxify {
			makeValueProxy(L, ptrVal, cSliceMeta)
		} else {
			if visited.push(val) {
				return
			}
			copySliceToTable(L, val, visited)
		}
	case reflect.Map:
		if !dontproxify {
			makeValueProxy(L, ptrVal, cMapMeta)
		} else {
			if visited.push(val) {
				return
			}
			copyMapToTable(L, val, visited)
		}
	case reflect.Struct:
		if !dontproxify && ptrVal.Kind() == reflect.Ptr {
			if ptrVal.CanInterface() {
				switch v := ptrVal.Interface().(type) {
				case error:
					L.PushString(v.Error())
				case *LuaObject:
					v.Push()
				default:
					makeValueProxy(L, ptrVal, cStructMeta)
				}
			} else {
				makeValueProxy(L, ptrVal, cStructMeta)
			}
		} else {
			// Use ptrVal instead of val to detect cycles from the very first element, if a pointer.
			if ptrVal.Kind() == reflect.Ptr && visited.push(ptrVal) {
				return
			}
			copyStructToTable(L, ptrVal, visited)
		}
	case reflect.Chan:
		makeValueProxy(L, ptrVal, cChannelMeta)
	case reflect.Func:
		L.PushGoFunction(goLuaFunc(L, val))
	default:
		if v, ok := val.Interface().(error); ok {
			L.PushString(v.Error())
		} else if val.IsNil() {
			L.PushNil()
		} else {
			makeValueProxy(L, ptrVal, cInterfaceMeta)
		}
	}
}
Esempio n. 21
0
File: luar.go Progetto: kdar/luar
// Push a Go value 'val' of type 't' on the Lua stack.
// If we haven't been given a concrete type, use the type of the value
// and unbox any interfaces.
func GoToLua(L *lua.State, t reflect.Type, val reflect.Value) {
	proxify := true
	if t == nil {
		t = val.Type()
		if t.Kind() == reflect.Interface { // unbox interfaces!
			val = valueOf(val.Interface())
			t = val.Type()
		}
		proxify = false
	}
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	switch t.Kind() {
	case reflect.Float64:
	case reflect.Float32:
		{
			L.PushNumber(val.Float())
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
		{
			L.PushNumber(float64(val.Int()))
		}
	case reflect.Uint, reflect.Uint8:
		{
			L.PushNumber(float64(val.Uint()))
		}
	case reflect.String:
		{
			L.PushString(val.String())
		}
	case reflect.Bool:
		{
			L.PushBoolean(val.Bool())
		}
	case reflect.Slice:
		{
			if proxify {
				makeValueProxy(L, val, SLICE_META)
			} else {
				CopySliceToTable(L, val)
			}
		}
	case reflect.Map:
		{
			if proxify {
				makeValueProxy(L, val, MAP_META)
			} else {
				CopyMapToTable(L, val)
			}
		}
	case reflect.Struct:
		{
			makeValueProxy(L, val, STRUCT_META)
		}
	default:
		{
			if val.IsNil() {
				L.PushNil()
			} else {
				makeValueProxy(L, val, INTERFACE_META)
			}
		}
	}
}
Esempio n. 22
0
// 'exist' is optional.
func run(L *lua.State, registryIndex string, code string, input *inputInfo, output *outputInfo, exist *inputInfo) error {
	// Restore the sandbox.
	err := L.DoString(luaRestoreSandbox)
	if err != nil {
		log.Fatal("Cannot load function to restore sandbox", err)
	}
	L.PushString(registryWhitelist)
	L.GetTable(lua.LUA_REGISTRYINDEX)
	err = L.Call(1, 0)
	if err != nil {
		log.Fatal("Failed to restore sandbox", err)
	}

	goToLua(L, "input", *input)
	goToLua(L, "output", *output)

	if exist != nil {
		goToLua(L, "existinfo", *exist)
	}

	// Shortcut (mostly for prescript and postscript).
	L.GetGlobal("input")
	L.GetField(-1, "tags")
	L.SetGlobal("i")
	L.Pop(1)
	L.GetGlobal("output")
	L.GetField(-1, "tags")
	L.SetGlobal("o")
	L.Pop(1)

	// Call the compiled script.
	L.PushString(registryIndex)
	L.GetTable(lua.LUA_REGISTRYINDEX)
	L.PushString(code)
	if L.IsTable(-2) {
		L.GetTable(-2)
		if L.IsFunction(-1) {
			err := L.Call(0, 0)
			if err != nil {
				L.SetTop(0)
				return fmt.Errorf("%s", err)
			}
		} else {
			L.Pop(1)
		}
	} else {
		L.Pop(1)
	}
	L.Pop(1)

	// Allow tags to be numbers for convenience.
	outputNumbersToStrings(L)

	L.GetGlobal("output")
	r := luar.LuaToGo(L, reflect.TypeOf(*output), -1)
	L.Pop(1)

	*output = r.(outputInfo)

	return nil
}
Esempio n. 23
0
func SetTableInt(L *lua.State, name string, value int64) {
	// Remember to check stack for 2 extra locations
	L.PushString(name)
	L.PushInteger(value)
	L.SetTable(-3)
}
Esempio n. 24
0
func pushValue(state *lua.State, value interface{}) error {
	switch v := value.(type) {
	default:
		return fmt.Errorf("An item of unknown type was included in the environment or arguments of a Lua call (skipping it): %v",
			value)
	case nil:
		log.Println("Pushing nil onto lua stack")
		state.PushNil()
	case string:
		log.Println("Pushing string onto lua stack")
		state.PushString(v)
	case int:
		log.Println("Pushing int onto lua stack")
		state.PushInteger(int64(v))
	case int64:
		log.Println("Pushing int64 onto lua stack")
		state.PushInteger(v)
	case float64:
		log.Println("Pushing float64 onto lua stack")
		state.PushNumber(v)
	case bool:
		log.Println("Pushing bool onto lua stack")
		state.PushBoolean(v)

	case map[string]interface{}:
		log.Println("Pushing map[string]interface{} onto lua stack")
		state.CreateTable(0, len(v))
		for name, value := range v {
			err := pushValue(state, value)
			if err != nil {
				// error means nothing was added to stack. So pop our new table so *we* leave nothing added to the stack.
				state.Pop(1)
				return err
			}
			state.SetField(-2, name)
		}
		// then leave the table on the stack

	case ThingType:
		// These are singleton sentinel values, so load them from Lua-land.
		state.GetGlobal("world")
		state.GetField(-1, strings.Title(v.String()))
		state.Remove(-2)

	case *Thing:
		log.Println("Pushing *Thing onto lua stack")
		return pushValue(state, v.Id)
	case ThingId:
		log.Println("Pushing ThingId onto lua stack")
		// We're pushing a ThingId, so make a new userdata for it, with the Thing metatable.
		userdata := state.NewUserdata(uintptr(unsafe.Sizeof(int64(0))))
		thingPtr := (*int64)(userdata)
		*thingPtr = int64(v)
		if !state.IsUserdata(-1) {
			log.Println("!!! HOGAD JUST PUSHED NEW USERDATA BUT IT ISN'T OMG !!!")
		}
		log.Println("Pushed ThingId", *thingPtr, "onto lua stack")

		// Now make it act like a Thing.
		state.LGetMetaTable(ThingMetaTableName) // ( udata -- udata mtbl )
		state.SetMetaTable(-2)                  // ( udata mtbl -- udata )

		// Let's just check that it's that, for sures.
		if !state.IsUserdata(-1) {
			log.Println("!!! WOOP WOOP DID NOT SET METATABLE RIGHT :( !!!")
		}
	}
	return nil
}
Esempio n. 25
0
func MessThingName(state *lua.State, thing *Thing) int {
	state.PushString(thing.Name)
	return 1
}