diff --git a/pkg/obilua/lua.go b/pkg/obilua/lua.go index 34700b3..354f9a0 100644 --- a/pkg/obilua/lua.go +++ b/pkg/obilua/lua.go @@ -81,6 +81,8 @@ func LuaWorker(proto *lua.FunctionProto) obiseq.SeqWorker { switch val := s.(type) { case *obiseq.BioSequence: return obiseq.BioSequenceSlice{val}, err + case *obiseq.BioSequenceSlice: + return *val, err default: return nil, fmt.Errorf("worker function doesn't return the correct type") } diff --git a/pkg/obilua/lua_push_interface.go b/pkg/obilua/lua_push_interface.go index a5092c6..39e338d 100644 --- a/pkg/obilua/lua_push_interface.go +++ b/pkg/obilua/lua_push_interface.go @@ -146,25 +146,6 @@ func pushMapStringFloat64ToLua(L *lua.LState, m map[string]float64) { L.Push(luaTable) } -// pushSliceIntToLua creates a new Lua table and sets the elements of a Go slice in the Lua table. Then, it pushes the Lua table onto the stack. -// -// L *lua.LState, slice []int -// None -func pushSliceIntToLua(L *lua.LState, slice []int) { - // Create a new Lua table - luaTable := L.NewTable() - - // Iterate over the Go slice and set the elements in the Lua table - for _, value := range slice { - // Append the value to the Lua table - // Lua is 1-indexed, so we use the length of the table + 1 as the next index - luaTable.Append(lua.LNumber(value)) - } - - // Push the Lua table onto the stack - L.Push(luaTable) -} - func pushSliceNumericToLua[T float64 | int | byte](L *lua.LState, slice []T) { // Create a new Lua table luaTable := L.NewTable() @@ -215,21 +196,3 @@ func pushSliceBoolToLua(L *lua.LState, slice []bool) { // Push the Lua table onto the stack L.Push(luaTable) } - -// pushSliceFloat64ToLua creates a new Lua table and pushes it onto the stack. -// -// L *lua.LState - the Lua state -// slice []float64 - the Go slice to be inserted into the Lua table -func pushSliceFloat64ToLua(L *lua.LState, slice []float64) { - // Create a new Lua table - luaTable := L.NewTable() - - // Iterate over the Go slice and insert each float64 into the Lua table - for _, value := range slice { - // Lua is 1-indexed, so we append the value to the Lua table - luaTable.Append(lua.LNumber(value)) - } - - // Push the Lua table onto the stack - L.Push(luaTable) -} diff --git a/pkg/obilua/obiseq.go b/pkg/obilua/obiseq.go index e89ebf5..d99c634 100644 --- a/pkg/obilua/obiseq.go +++ b/pkg/obilua/obiseq.go @@ -7,6 +7,7 @@ import ( func RegisterObiSeq(luaState *lua.LState) { registerBioSequenceType(luaState) + registerBioSequenceSliceType(luaState) } const luaBioSequenceTypeName = "BioSequence" diff --git a/pkg/obilua/obiseqslice.go b/pkg/obilua/obiseqslice.go new file mode 100644 index 0000000..15dd3b2 --- /dev/null +++ b/pkg/obilua/obiseqslice.go @@ -0,0 +1,107 @@ +package obilua + +import ( + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq" + lua "github.com/yuin/gopher-lua" +) + +const luaBioSequenceSliceTypeName = "BioSequenceSlice" + +func registerBioSequenceSliceType(luaState *lua.LState) { + bioSequenceSliceType := luaState.NewTypeMetatable(luaBioSequenceSliceTypeName) + luaState.SetGlobal(luaBioSequenceSliceTypeName, bioSequenceSliceType) + luaState.SetField(bioSequenceSliceType, "new", luaState.NewFunction(newObiSeqSlice)) + + luaState.SetField(bioSequenceSliceType, "__index", + luaState.SetFuncs(luaState.NewTable(), + bioSequenceSliceMethods)) +} + +func obiseqslice2Lua(interpreter *lua.LState, + seqslice *obiseq.BioSequenceSlice) lua.LValue { + ud := interpreter.NewUserData() + ud.Value = seqslice + interpreter.SetMetatable(ud, interpreter.GetTypeMetatable(luaBioSequenceSliceTypeName)) + + return ud +} + +func newObiSeqSlice(luaState *lua.LState) int { + seqslice := obiseq.NewBioSequenceSlice() + luaState.Push(obiseqslice2Lua(luaState, seqslice)) + return 1 +} + +var bioSequenceSliceMethods = map[string]lua.LGFunction{ + "push": bioSequenceSlicePush, + "pop": bioSequenceSlicePop, + "sequence": bioSequenceSliceGetSetSequence, + "len": bioSequenceSliceGetLength, +} + +func checkBioSequenceSlice(L *lua.LState) *obiseq.BioSequenceSlice { + ud := L.CheckUserData(1) + if v, ok := ud.Value.(*obiseq.BioSequenceSlice); ok { + return v + } + L.ArgError(1, "obiseq.BioSequenceSlice expected") + return nil +} + +func bioSequenceSliceGetLength(luaState *lua.LState) int { + s := checkBioSequenceSlice(luaState) + luaState.Push(lua.LNumber(s.Len())) + return 1 +} + +func bioSequenceSliceGetSetSequence(luaState *lua.LState) int { + s := checkBioSequenceSlice(luaState) + index := luaState.CheckInt(2) + + if index > s.Len() || index < 0 { + luaState.RaiseError("BioSequenceSlice index out of range") + return 0 + } + + if luaState.GetTop() == 3 { + ud := luaState.CheckUserData(3) + if v, ok := ud.Value.(*obiseq.BioSequence); ok { + (*s)[index] = v + return 0 + } + luaState.ArgError(1, "obiseq.BioSequenceSlice expected") + return 0 + } + + value := obiseq2Lua(luaState, (*s)[index]) + luaState.Push(value) + + return 1 +} + +func bioSequenceSlicePush(luaState *lua.LState) int { + s := checkBioSequenceSlice(luaState) + + ud := luaState.CheckUserData(2) + if v, ok := ud.Value.(*obiseq.BioSequence); ok { + (*s) = append((*s), v) + return 0 + } + + luaState.ArgError(1, "obiseq.BioSequenceSlice expected") + return 0 +} + +func bioSequenceSlicePop(luaState *lua.LState) int { + s := checkBioSequenceSlice(luaState) + if len(*s) == 0 { + return 0 + } + + seq := (*s)[len(*s)-1] + (*s) = (*s)[0 : len(*s)-1] + value := obiseq2Lua(luaState, seq) + luaState.Push(value) + return 1 + +}