Example #1
1
File: luar.go Project: imvu/Tetra
// Copy matching Lua table entries to a struct, given the struct type
// and the index on the Lua stack.
func CopyTableToStruct(L *lua.State, t reflect.Type, idx int) interface{} {
	was_ptr := t.Kind() == reflect.Ptr
	if was_ptr {
		t = t.Elem()
	}
	s := reflect.New(t) // T -> *T
	ref := s.Elem()
	L.PushNil()
	if idx < 0 {
		idx--
	}
	for L.Next(idx) != 0 {
		key := L.ToString(-2)
		f := ref.FieldByName(strings.Title(key))
		if f.IsValid() {
			val := luaToGoValue(L, f.Type(), -1)
			f.Set(val)
		}
		L.Pop(1)
	}
	if was_ptr {
		return s.Interface()
	}
	return s.Elem().Interface()
}
Example #2
0
func LuaIntColumnQuery(L *lua.State) int {
	if (L.GetTop() != 1) && (L.GetTop() != 3) {
		panic(errors.New("Wrong number of arguments to columnq"))
		return 0
	}

	name := L.ToString(1)
	op := ""
	value := ""
	if L.GetTop() == 3 {
		op = L.ToString(2)
		value = L.ToString(3)
		L.Pop(3)
	} else {
		L.Pop(1)
	}

	if name[0] == ':' {
		panic(errors.New("Column name can not start with ':'"))
		return 0
	}

	L.CheckStack(1)
	tl := GetTasklistFromLua(L)

	tl.luaState.PushGoStruct(&SimpleExpr{name, op, value, nil, 0, ""})
	return 1
}
Example #3
0
func copyTableToMap(L *lua.State, t reflect.Type, idx int, visited map[uintptr]interface{}) interface{} {
	if t == nil {
		t = tmap
	}
	te, tk := t.Elem(), t.Key()
	m := reflect.MakeMap(t)

	// See copyTableToSlice.
	ptr := L.ToPointer(idx)
	if !luaIsEmpty(L, idx) {
		visited[ptr] = m.Interface()
	}

	L.PushNil()
	if idx < 0 {
		idx--
	}
	for L.Next(idx) != 0 {
		// key at -2, value at -1
		key := reflect.ValueOf(luaToGo(L, tk, -2, visited))
		val := reflect.ValueOf(luaToGo(L, te, -1, visited))
		if val.Interface() == nullv.Interface() {
			val = reflect.Zero(te)
		}
		m.SetMapIndex(key, val)
		L.Pop(1)
	}
	return m.Interface()
}
Example #4
0
func popMap(L *lua.State) map[string]interface{} {
	m := make(map[string]interface{})
	L.PushNil()
	for L.Next(-2) != 0 {
		if L.IsString(-2) {
			var v interface{}
			if L.IsBoolean(-1) {
				v = L.ToBoolean(-1)
			} else if L.IsNumber(-1) {
				var t float64
				t = L.ToNumber(-1)
				if t == float64(int64(t)) {
					v = int(t)
				} else {
					v = t
				}
			} else if L.IsString(-1) {
				v = L.ToString(-1)
			} else if L.IsNil(-1) {
				v = nil
			} else if L.IsTable(-1) {
				v = popMap(L)
			}
			m[L.ToString(-2)] = v
		}
		L.Pop(1)
	}
	return m
}
Example #5
0
File: luar.go Project: imvu/Tetra
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)
	}
}
Example #6
0
func MessThingIndex(state *lua.State) int {
	log.Println("HEY WE MADE IT")
	printStackTypes(state)

	state.GetMetaTable(1)
	state.LGetMetaTable(ThingMetaTableName)
	isThing := state.RawEqual(-1, -2)
	state.Pop(2)
	if !isThing {
		log.Println("!!! OMG ARG #1 IS NOT A MESS.THING !!!")
	}

	fieldName := state.CheckString(2)
	log.Println("Arg #2 checks out, it's a string")
	thing := checkThing(state, 1)
	log.Println("So we're tryin'a look up", fieldName, "on thing", thing.Id)

	if member, ok := MessThingMembers[fieldName]; ok {
		return member(state, thing)
	}

	// That wasn't one of our members, so look it up in our Table.
	if data, ok := thing.Table[fieldName]; ok {
		// TODO: instead of pushing a whole map if the script asks for one, maybe we should use another kind of userdata that tracks the name & can access its submembers until the script asks for the leaf (or a non-existent branch)?
		pushValue(state, data)
		return 1
	}

	// uh... I guess we didn't do anything, so...?
	return 0
}
Example #7
0
func GetTasklistFromLua(L *lua.State) *Tasklist {
	L.CheckStack(1)
	L.GetGlobal(TASKLIST)
	rawptr := L.ToUserdata(-1)
	var ptr **Tasklist = (**Tasklist)(rawptr)
	L.Pop(1)
	return *ptr
}
Example #8
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
}
Example #9
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
}
Example #10
0
func luaIsEmpty(L *lua.State, idx int) bool {
	L.PushNil()
	if idx < 0 {
		idx--
	}
	if L.Next(idx) != 0 {
		L.Pop(2)
		return false
	}
	return true
}
Example #11
0
func GetEntryFromLua(L *lua.State, name string, fname string) *Entry {
	L.CheckStack(1)
	L.GetGlobal(name)
	rawptr := L.ToUserdata(-1)
	var ptr **Entry = (**Entry)(rawptr)
	L.Pop(1)
	if ptr == nil {
		panic(errors.New("No cursor set, can not use " + fname))
	}
	return *ptr

}
Example #12
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)
	}
}
Example #13
0
func copyTableToStruct(L *lua.State, t reflect.Type, idx int, visited map[uintptr]interface{}) interface{} {
	if t == nil {
		RaiseError(L, "type argument must be non-nill")
	}
	wasPtr := t.Kind() == reflect.Ptr
	if wasPtr {
		t = t.Elem()
	}
	s := reflect.New(t) // T -> *T
	ref := s.Elem()

	// See copyTableToSlice.
	ptr := L.ToPointer(idx)
	if !luaIsEmpty(L, idx) {
		if wasPtr {
			visited[ptr] = s.Interface()
		} else {
			visited[ptr] = s.Elem().Interface()
		}
	}

	// Associate Lua keys with Go fields: tags have priority over matching field
	// name.
	fields := map[string]string{}
	st := ref.Type()
	for i := 0; i < ref.NumField(); i++ {
		field := st.Field(i)
		tag := field.Tag.Get("lua")
		if tag != "" {
			fields[tag] = field.Name
			continue
		}
		fields[field.Name] = field.Name
	}

	L.PushNil()
	if idx < 0 {
		idx--
	}
	for L.Next(idx) != 0 {
		key := L.ToString(-2)
		f := ref.FieldByName(fields[key])
		if f.CanSet() && f.IsValid() {
			val := reflect.ValueOf(luaToGo(L, f.Type(), -1, visited))
			f.Set(val)
		}
		L.Pop(1)
	}
	if wasPtr {
		return s.Interface()
	}
	return s.Elem().Interface()
}
Example #14
0
File: luar.go Project: imvu/Tetra
func isValueProxy(L *lua.State, idx int) bool {
	res := false
	if L.IsUserdata(idx) {
		L.GetMetaTable(idx)
		if !L.IsNil(-1) {
			L.GetField(-1, "luago.value")
			res = !L.IsNil(-1)
			L.Pop(1)
		}
		L.Pop(1)
	}
	return res
}
Example #15
0
func MessThingTellMethod(state *lua.State, thing *Thing) int {
	state.PushGoFunction(func(state *lua.State) int {
		thing := checkThing(state, 1)
		text := state.CheckString(2)

		if thing.Client != nil {
			thing.Client.Send(text)
		}
		state.Pop(2) // ( udataThing strText -- )
		return 0
	})
	return 1
}
Example #16
0
func LuaIntStringFunction(L *lua.State, name string, n int, fn func(tl *Tasklist, argv []string) int) int {
	luaAssertArgnum(L, n, name)

	argv := make([]string, 0)

	for i := 1; i <= n; i++ {
		argv = append(argv, L.ToString(i))
	}
	L.Pop(n)
	L.CheckStack(1)
	tl := GetTasklistFromLua(L)
	return fn(tl, argv)
}
Example #17
0
File: luar.go Project: kdar/luar
// return the Lua table at 'idx' as a copied Go slice. If 't' is nil then the slice
// type is []interface{}
func CopyTableToSlice(L *lua.State, t reflect.Type, idx int) interface{} {
	if t == nil {
		t = reflect.TypeOf(tslice)
	}
	te := t.Elem()
	n := int(L.ObjLen(idx))
	slice := reflect.MakeSlice(t, n, n)
	for i := 1; i <= n; i++ {
		L.RawGeti(idx, i)
		val := LuaToGo(L, te, -1)
		slice.Index(i - 1).Set(valueOf(val))
		L.Pop(1)
	}
	return slice.Interface()
}
Example #18
0
// Also for arrays.
func copyTableToSlice(L *lua.State, t reflect.Type, idx int, visited map[uintptr]interface{}) interface{} {
	if t == nil {
		t = tslice
	}

	ref := t
	// There is probably no point at accepting more than one level of dreference.
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	n := int(L.ObjLen(idx))

	var slice reflect.Value
	if t.Kind() == reflect.Array {
		slice = reflect.New(t)
		slice = slice.Elem()
	} else {
		slice = reflect.MakeSlice(t, n, n)
	}

	// Do not add empty slices to the list of visited elements.
	// The empty Lua table is a single instance object and gets re-used across maps, slices and others.
	if n > 0 {
		ptr := L.ToPointer(idx)
		if ref.Kind() == reflect.Ptr {
			visited[ptr] = slice.Addr().Interface()
		} else {
			visited[ptr] = slice.Interface()
		}
	}

	te := t.Elem()
	for i := 1; i <= n; i++ {
		L.RawGeti(idx, i)
		val := reflect.ValueOf(luaToGo(L, te, -1, visited))
		if val.Interface() == nullv.Interface() {
			val = reflect.Zero(te)
		}
		slice.Index(i - 1).Set(val)
		L.Pop(1)
	}

	if ref.Kind() == reflect.Ptr {
		return slice.Addr().Interface()
	}
	return slice.Interface()
}
Example #19
0
File: luar.go Project: imvu/Tetra
// Return the Lua table at 'idx' as a copied Go slice. If 't' is nil then the slice
// type is []interface{}
func CopyTableToSlice(L *lua.State, t reflect.Type, idx int) interface{} {
	if t == nil {
		t = tslice
	}
	te := t.Elem()
	n := int(L.ObjLen(idx))
	slice := reflect.MakeSlice(t, n, n)
	for i := 1; i <= n; i++ {
		L.RawGeti(idx, i)
		val := luaToGoValue(L, te, -1)
		if val == nullv {
			val = reflect.Zero(te)
		}
		slice.Index(i - 1).Set(val)
		L.Pop(1)
	}
	return slice.Interface()
}
Example #20
0
File: luar.go Project: kdar/luar
// return the Lua table at 'idx' as a copied Go map. If 't' is nil then the map
// type is map[string]interface{}
func CopyTableToMap(L *lua.State, t reflect.Type, idx int) interface{} {
	if t == nil {
		t = reflect.TypeOf(tmap)
	}
	te, tk := t.Elem(), t.Key()
	m := reflect.MakeMap(t)
	L.PushNil()
	if idx < 0 {
		idx--
	}
	for L.Next(idx) != 0 {
		// key at -2, value at -1
		key := valueOf(LuaToGo(L, tk, -2))
		val := valueOf(LuaToGo(L, te, -1))
		m.SetMapIndex(key, val)
		L.Pop(1)
	}
	return m.Interface()
}
Example #21
0
File: luar.go Project: imvu/Tetra
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()
}
Example #22
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
}
Example #23
0
File: luar.go Project: yinlei/luar
// Copy matching Lua table entries to a struct, given the struct type
// and the index on the Lua stack.
func CopyTableToStruct(L *lua.State, t reflect.Type, idx int) interface{} {
	was_ptr := t.Kind() == reflect.Ptr
	if was_ptr {
		t = t.Elem()
	}
	s := reflect.New(t) // T -> *T
	ref := s.Elem()

	// Associate Lua keys with Go fields: tags have priority over matching field
	// name.
	fields := map[string]string{}
	st := ref.Type()
	for i := 0; i < ref.NumField(); i++ {
		field := st.Field(i)
		tag := field.Tag.Get("lua")
		if tag != "" {
			fields[tag] = field.Name
			continue
		}
		fields[field.Name] = field.Name
	}

	L.PushNil()
	if idx < 0 {
		idx--
	}
	for L.Next(idx) != 0 {
		key := L.ToString(-2)
		f := ref.FieldByName(fields[key])
		if f.CanSet() && f.IsValid() {
			val := luaToGoValue(L, f.Type(), -1)
			f.Set(val)
		}
		L.Pop(1)
	}
	if was_ptr {
		return s.Interface()
	}
	return s.Elem().Interface()
}
Example #24
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)
}
Example #25
0
File: luar.go Project: imvu/Tetra
// Return the Lua table at 'idx' as a copied Go map. If 't' is nil then the map
// type is map[string]interface{}
func CopyTableToMap(L *lua.State, t reflect.Type, idx int) interface{} {
	if t == nil {
		t = tmap
	}
	te, tk := t.Elem(), t.Key()
	m := reflect.MakeMap(t)
	L.PushNil()
	if idx < 0 {
		idx--
	}
	for L.Next(idx) != 0 {
		// key at -2, value at -1
		key := luaToGoValue(L, tk, -2)
		val := luaToGoValue(L, te, -1)
		if val == nullv {
			val = reflect.Zero(te)
		}
		m.SetMapIndex(key, val)
		L.Pop(1)
	}
	return m.Interface()
}
Example #26
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)
	}
}
Example #27
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)
}
Example #28
0
File: luar.go Project: imvu/Tetra
// new LuaObject refering to the global environment
func Global(L *lua.State) *LuaObject {
	L.GetGlobal("_G")
	val := NewLuaObject(L, -1)
	L.Pop(1)
	return val
}
Example #29
0
File: luar.go Project: imvu/Tetra
// A new LuaObject from global qualified name, using Lookup.
func NewLuaObjectFromName(L *lua.State, path string) *LuaObject {
	Lookup(L, path, 0)
	val := NewLuaObject(L, -1)
	L.Pop(1)
	return val
}
Example #30
0
File: luar.go Project: imvu/Tetra
// raise a Lua error from Go code
func RaiseError(L *lua.State, msg string) {
	L.Where(1)
	pos := L.ToString(-1)
	L.Pop(1)
	panic(L.NewError(pos + " " + msg))
}