Exemple #1
0
func outputNumbersToStrings(L *lua.State) {
	L.GetGlobal("output")

	if !L.IsTable(-1) {
		L.NewTable()
		L.SetGlobal("output")
	}

	L.GetField(-1, "tags")
	if L.IsTable(-1) {
		// First key.
		L.PushNil()
		for L.Next(-2) != 0 {
			// Use 'key' at index -2 and 'value' at index -1.
			if L.IsString(-2) && L.IsString(-1) {
				// Convert numbers to strings.
				L.ToString(-1)
				L.SetField(-3, L.ToString(-2))
			} else {
				// Remove 'value' and keep 'key' for next iteration.
				L.Pop(1)
			}
		}
	}
	L.Pop(1)

	L.Pop(1)
}
Exemple #2
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 pop {
		L.Pop(1)
	}
}
Exemple #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)
}
Exemple #4
0
// Register makes a number of Go values available in Lua code.
// 'values' is a map of strings to Go values.
//
// - If table is non-nil, then create or reuse a global table of that name and
// put the values in it.
//
// - If table is '' then put the values in the global table (_G).
//
// - If table is '*' then assume that the table is already on the stack.
func Register(L *lua.State, table string, values Map) {
	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 {
		GoToLua(L, nil, reflect.ValueOf(val), false)
		L.SetField(-2, name)
	}
	if pop {
		L.Pop(1)
	}
}
Exemple #5
0
func initializeProxies(L *lua.State) {
	flagValue := func() {
		L.SetMetaMethod("__tostring", proxy__tostring)
		L.SetMetaMethod("__gc", proxy__gc)
		L.SetMetaMethod("__eq", proxy__eq)
		L.PushBoolean(true)
		L.SetField(-2, "luago.value")
		L.Pop(1)
	}
	L.NewMetaTable(cSLICE_META)
	L.SetMetaMethod("__index", slice__index)
	L.SetMetaMethod("__newindex", slice__newindex)
	L.SetMetaMethod("__len", slicemap__len)
	L.SetMetaMethod("__ipairs", slice__ipairs)
	flagValue()
	L.NewMetaTable(cMAP_META)
	L.SetMetaMethod("__index", map__index)
	L.SetMetaMethod("__newindex", map__newindex)
	L.SetMetaMethod("__len", slicemap__len)
	L.SetMetaMethod("__pairs", map__pairs)
	flagValue()
	L.NewMetaTable(cSTRUCT_META)
	L.SetMetaMethod("__index", struct__index)
	L.SetMetaMethod("__newindex", struct__newindex)
	flagValue()
	L.NewMetaTable(cINTERFACE_META)
	L.SetMetaMethod("__index", interface__index)
	flagValue()
	L.NewMetaTable(cCHANNEL_META)
	//~ RegisterFunctions(L,"*",FMap {
	//~ "Send":channel_send,
	//~ "Recv":channel_recv,
	//~ })
	L.NewTable()
	L.PushGoFunction(channel_send)
	L.SetField(-2, "Send")
	L.PushGoFunction(channel_recv)
	L.SetField(-2, "Recv")
	L.SetField(-2, "__index")
	flagValue()
}
Exemple #6
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)
	}
}
Exemple #7
0
func installWorld(state *lua.State) {
	log.Println("Installing world")
	printStackTypes(state)

	state.NewMetaTable(ThingMetaTableName)         // ( -- mtbl )
	state.SetMetaMethod("__index", MessThingIndex) // ( mtbl -- mtbl )
	state.Pop(1)                                   // ( mtbl -- )

	worldTable := map[string]interface{}{
	/*
		"Root":
		"Create": func...
	*/
	}
	pushValue(state, worldTable)

	// Install Thing types as singleton sentinel values. As userdata, these will only compare if the values are exactly equal.
	state.NewUserdata(uintptr(0))
	state.SetField(-2, "Player")
	state.NewUserdata(uintptr(0))
	state.SetField(-2, "Place")
	state.NewUserdata(uintptr(0))
	state.SetField(-2, "Program")
	state.NewUserdata(uintptr(0))
	state.SetField(-2, "Action")
	state.NewUserdata(uintptr(0))
	state.SetField(-2, "Thing")

	state.SetGlobal("world")

	state.GetGlobal("table") // ( -- tblTable )
	state.PushGoFunction(TableFormat)
	state.SetField(-2, "format")
	state.Pop(1) // ( tblTable -- )

	log.Println("Finished installing world")
	printStackTypes(state)
}
Exemple #8
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
}