Exemplo n.º 1
0
Arquivo: luar.go Projeto: 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)
	}
}
Exemplo n.º 2
0
func MessThingTellallMethod(state *lua.State, thing *Thing) int {
	state.PushGoFunction(func(state *lua.State) int {
		place := checkThing(state, 1)
		text := state.CheckString(2)

		// If arg 3 is present, it should be a table of Things to exclude.
		excludes := make(map[ThingId]bool)
		if 2 < state.GetTop() {
			if !state.IsTable(3) {
				state.ArgError(3, "expected `table` for exclude argument if present")
			}
			numExcludes := int(state.ObjLen(3))
			for i := 0; i < numExcludes; i++ {
				state.RawGeti(3, i+1)
				exclude := checkThing(state, -1)
				excludes[exclude.Id] = true
			}
		}

		for _, content := range place.GetContents() {
			if excludes[content.Id] {
				continue
			}
			if content.Client != nil {
				content.Client.Send(text)
			}
		}

		return 0
	})
	return 1
}
Exemplo n.º 3
0
Arquivo: luar.go Projeto: kdar/luar
func callGoMethod(L *lua.State, name string, st reflect.Value) {
	ret := st.MethodByName(name)
	if !ret.IsValid() {
		fmt.Println("whoops")
	}
	L.PushGoFunction(GoLuaFunc(L, ret))
}
Exemplo n.º 4
0
// goToLua copies Go values to Lua and sets the result to global 'name'.
// Compound types are deep-copied.
// Functions are automatically converted to 'func (L *lua.State) int'.
func goToLua(L *lua.State, name string, val interface{}) {
	t := reflect.TypeOf(val)
	if t.Kind() == reflect.Func {
		L.PushGoFunction(luar.GoLuaFunc(L, val))
	} else {
		luar.GoToLua(L, t, reflect.ValueOf(val), true)
	}
	L.SetGlobal(name)
}
Exemplo n.º 5
0
func MessThingMovetoMethod(state *lua.State, thing *Thing) int {
	state.PushGoFunction(func(state *lua.State) int {
		source := checkThing(state, 1)
		target := checkThing(state, 2)

		ok := source.MoveTo(target)

		state.PushBoolean(ok)
		return 1
	})
	return 1
}
Exemplo n.º 6
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
}
Exemplo n.º 7
0
// ProxyPairs implements Lua 5.2 'pairs' functions.
// It respects the __pairs metamethod.
//
// It is only useful for compatibility with Lua 5.1.
func ProxyPairs(L *lua.State) int {
	// See Lua >=5.2 source code.
	if L.GetMetaField(1, "__pairs") {
		L.PushValue(1)
		L.Call(1, 3)
		return 3
	}

	L.CheckType(1, lua.LUA_TTABLE)
	L.PushGoFunction(pairsAux)
	L.PushValue(1)
	L.PushNil()
	return 3
}
Exemplo n.º 8
0
Arquivo: luar.go Projeto: kdar/luar
func slice__index(L *lua.State) int {
	slice, _ := valueOfProxy(L, 1)
	if L.IsNumber(2) {
		idx := L.ToInteger(2)
		ret := slice.Index(idx - 1)
		GoToLua(L, ret.Type(), ret)
	} else {
		name := L.ToString(2)
		switch name {
		case "Slice":
			L.PushGoFunction(slice_slice)
		default:
			fmt.Println("unknown slice method")
		}
	}
	return 1
}
Exemplo n.º 9
0
func MessThingFindinsideMethod(state *lua.State, thing *Thing) int {
	state.PushGoFunction(func(state *lua.State) int {
		thing := checkThing(state, 1)
		text := state.CheckString(2)
		if text == "" {
			state.ArgError(2, "cannot find empty string")
		}

		otherThing := thing.FindInside(text)
		if otherThing == nil {
			return 0
		}
		pushValue(state, otherThing.Id)
		return 1
	})
	return 1
}
Exemplo n.º 10
0
Arquivo: luar.go Projeto: imvu/Tetra
func slice__ipairs(L *lua.State) int {
	s, _ := valueOfProxy(L, 1)
	n := s.Len()
	idx := -1
	iter := func(L *lua.State) int {
		idx++
		if idx == n {
			L.PushNil()
			return 1
		}
		GoToLua(L, nil, valueOf(idx+1), false) // report as 1-based index
		val := s.Index(idx)
		GoToLua(L, nil, val, false)
		return 2
	}
	L.PushGoFunction(iter)
	return 1
}
Exemplo n.º 11
0
Arquivo: luar.go Projeto: imvu/Tetra
func callGoMethod(L *lua.State, name string, st reflect.Value) {
	ret := st.MethodByName(name)
	if !ret.IsValid() {
		T := st.Type()
		// Could not resolve this method. Perhaps it's defined on the pointer?
		if T.Kind() != reflect.Ptr {
			if st.CanAddr() { // easy if we can get a pointer directly
				st = st.Addr()
			} else { // otherwise have to create and initialize one...
				VP := reflect.New(T)
				VP.Elem().Set(st)
				st = VP
			}
		}
		ret = st.MethodByName(name)
		assertValid(L, ret, st, name, "method")
	}
	L.PushGoFunction(GoLuaFunc(L, ret))
}
Exemplo n.º 12
0
Arquivo: luar.go Projeto: imvu/Tetra
func map__pairs(L *lua.State) int {
	m, _ := valueOfProxy(L, 1)
	keys := m.MapKeys()
	idx := -1
	n := m.Len()
	iter := func(L *lua.State) int {
		idx++
		if idx == n {
			L.PushNil()
			return 1
		}
		GoToLua(L, nil, keys[idx], false)
		val := m.MapIndex(keys[idx])
		GoToLua(L, nil, val, false)
		return 2
	}
	L.PushGoFunction(iter)
	return 1
}
Exemplo n.º 13
0
Arquivo: luar.go Projeto: 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()
}
Exemplo n.º 14
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
}
Exemplo n.º 15
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)
}
Exemplo n.º 16
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)
	}
}
Exemplo n.º 17
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)
		}
	}
}