Exemple #1
1
// 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()
}
Exemple #2
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
}
Exemple #3
0
func (p *Plugin) apiProcessNew(l *lua.State) int {
	callback := luar.NewLuaObject(l, 1)
	command := l.ToString(2)

	args := make([]string, l.GetTop()-2)
	for i := 3; i <= l.GetTop(); i++ {
		args[i-3] = l.ToString(i)
	}

	proc := &process{
		cmd: exec.Command(command, args...),
	}

	go func() {
		var str string
		bytes, err := proc.cmd.Output()
		if err == nil {
			if bytes != nil {
				str = string(bytes)
			}
			p.callValue(callback, proc.cmd.ProcessState.Success(), str)
		} else {
			p.callValue(callback, false, "")
		}
		callback.Close()
	}()

	obj := luar.NewLuaObjectFromValue(l, proc)
	obj.Push()
	obj.Close()
	return 1
}
Exemple #4
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 #5
0
// ProxyMethod pushes the proxy method on the stack.
//
// Argument: proxy
//
// Returns: method (function)
func ProxyMethod(L *lua.State) int {
	if !isValueProxy(L, 1) {
		L.PushNil()
		return 1
	}
	v, _ := valueOfProxy(L, 1)
	name := L.ToString(2)
	pushGoMethod(L, name, v)
	return 1
}
Exemple #6
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
}
Exemple #7
0
// 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)
	}
}
Exemple #8
0
func struct__newindex(L *lua.State) int {
	st, t := valueOfProxy(L, 1)
	name := L.ToString(2)
	if t.Kind() == reflect.Ptr {
		st = st.Elem()
	}
	field := st.FieldByName(name)
	val := LuaToGo(L, field.Type(), 3)
	field.Set(valueOf(val))
	return 0
}
Exemple #9
0
func LuaIntRmColumn(L *lua.State) int {
	luaAssertArgnum(L, 1, "rmcolumn()")
	name := L.ToString(1)
	entry := GetEntryFromLua(L, CURSOR, "rmcolumn()")
	entry.RemoveColumn(name)
	tl := GetTasklistFromLua(L)
	if !tl.luaFlags.cursorCloned {
		tl.luaFlags.cursorEdited = true
	}
	return 0
}
Exemple #10
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()
}
Exemple #11
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)
	}
}
Exemple #12
0
func LuaIntPriorityQuery(L *lua.State) int {
	luaAssertArgnum(L, 1, "priorityq()")

	priority := L.ToString(1)

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

	tl.luaState.PushGoStruct(&SimpleExpr{":priority", "=", priority, nil, ParsePriority(priority), ""})

	return 1
}
Exemple #13
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)
}
Exemple #14
0
func struct__index(L *lua.State) int {
	st, t := valueOfProxy(L, 1)
	name := L.ToString(2)
	est := st
	if t.Kind() == reflect.Ptr {
		est = st.Elem()
	}
	ret := est.FieldByName(name)
	if !ret.IsValid() { // no such field, try for method?
		callGoMethod(L, name, st)
	} else {
		GoToLua(L, ret.Type(), ret)
	}
	return 1
}
Exemple #15
0
func struct__newindex(L *lua.State) int {
	st, t := valueOfProxy(L, 1)
	name := L.ToString(2)
	if t.Kind() == reflect.Ptr {
		st = st.Elem()
	}
	field := st.FieldByName(name)
	assertValid(L, field, st, name, "field")
	val := luaToGoValue(L, field.Type(), 3)
	if isPointerToPrimitive(field) {
		field.Elem().Set(val)
	} else {
		field.Set(val)
	}
	return 0
}
Exemple #16
0
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
}
Exemple #17
0
func LuaIntParseDateTime(L *lua.State) int {
	luaAssertArgnum(L, 1, "parsedatetime()")

	L.CheckStack(1)

	input := L.ToString(-1)
	tl := GetTasklistFromLua(L)

	out, _ := ParseDateTime(input, tl.GetTimezone())

	if out != nil {
		L.PushInteger(int64(out.Unix()))
	} else {
		L.PushInteger(0)
	}

	return 1
}
Exemple #18
0
// 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()
}
Exemple #19
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
}
Exemple #20
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
}
Exemple #21
0
func LuaIntSearch(L *lua.State) int {
	if (L.GetTop() < 1) || (L.GetTop() > 2) {
		panic(errors.New("Wrong number of arguments to search()"))
		return 0
	}

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

	if !tl.luaFlags.freeCursor {
		panic(errors.New("search() function only available on a free cursor"))
		return 0
	}

	query := L.ToString(1)
	var luaClausable Clausable = nil
	if L.GetTop() == 2 {
		luaClausable = GetQueryObject(tl, 2)
	}

	theselect, _, _, _, _, _, _, perr := tl.ParseSearch(query, luaClausable)
	Must(perr)

	entries, serr := tl.Retrieve(theselect, "", false)
	Must(serr)

	Logf(INFO, "Searching from lua interface <%s> clausable: <%v> yields %d results\n", query, luaClausable, len(entries))

	r := []string{}
	for _, entry := range entries {
		r = append(r, entry.Id())
	}

	PushStringVec(L, r)
	return 1
}
Exemple #22
0
func LuaIntSplit(L *lua.State) int {
	if L.GetTop() < 2 {
		panic(errors.New("Wrong number of arguments to split()"))
		return 0
	}

	instr := L.ToString(1)
	sepstr := L.ToString(2)

	n := -1

	if L.GetTop() == 3 {
		n = L.ToInteger(3)
	}

	if L.GetTop() > 3 {
		panic(errors.New("Wrong number of arguments to split()"))
		return 0
	}

	PushStringVec(L, strings.SplitN(instr, sepstr, n))

	return 1
}
Exemple #23
0
func LuaIntVisit(L *lua.State) int {
	L.CheckStack(1)
	tl := GetTasklistFromLua(L)
	luaAssertNotFreeCursor(tl, "visit()")
	id := L.ToString(1)
	Logf(DEBUG, "Lua visiting: <%s>\n", id)
	var error interface{} = nil

	{
		defer func() {
			if rerr := recover(); rerr != nil {
				error = rerr
			}
		}()
		cursor := tl.Get(id)
		tl.SetEntryInLua(CURSOR, cursor)
	}

	if error != nil {
		tl.SetEntryInLua(CURSOR, nil)
	}

	return 0
}
Exemple #24
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
}
Exemple #25
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
}
Exemple #26
0
// 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
}
Exemple #27
0
func interface__index(L *lua.State) int {
	st, _ := valueOfProxy(L, 1)
	name := L.ToString(2)
	callGoMethod(L, name, st)
	return 1
}
Exemple #28
0
// 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))
}
Exemple #29
0
// function that lua will call before aborting.
// we override this because normally lua longjmps,
// but that breaks go's defer/panic. so we just panic.
func LuaAtPanic(L *lua.State) int {
	panic(errors.New(L.ToString(-1)))
	return 0
}
Exemple #30
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
}