Skip to content

Commit

Permalink
Fix varargs calling
Browse files Browse the repository at this point in the history
  • Loading branch information
zombiezen committed Dec 16, 2024
1 parent 470dad1 commit a0ea228
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
10 changes: 8 additions & 2 deletions internal/mylua/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -926,10 +926,16 @@ func (l *State) exec() (err error) {
*ra = *rb
}
case luacode.OpCall:
numArguments := int(i.ArgB())
numArguments := int(i.ArgB()) - 1
numResults := int(i.ArgC()) - 1
// TODO(soon): Validate ArgA.
l.setTop(frame.registerStart() + int(i.ArgA()) + 1 + numArguments)
functionIndex := frame.registerStart() + int(i.ArgA())
if numArguments < 0 {
// Varargs: read from top.
numArguments = len(l.stack) - (functionIndex + 1)
} else {
l.setTop(functionIndex + 1 + numArguments)
}
isLua, err := l.prepareCall(numArguments, numResults)
if err != nil {
return err
Expand Down
41 changes: 41 additions & 0 deletions internal/mylua/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,47 @@ func TestVM(t *testing.T) {
}
})

t.Run("Vararg", func(t *testing.T) {
state := new(State)
defer func() {
if err := state.Close(); err != nil {
t.Error("Close:", err)
}
}()

var got []int64
state.PushClosure(0, func(state *State) (int, error) {
for i := range state.Top() {
n, ok := state.ToInteger(1 + i)
if !ok {
t.Errorf("emit arg %d is a %v", len(got)+1, state.Type(1))
}
got = append(got, n)
}
return 0, nil
})
if err := state.SetGlobal("emit", 0); err != nil {
t.Fatal(err)
}

const source = `local function passthru(...)` + "\n" +
`return ...` + "\n" +
`end` + "\n" +
// Not returning, because that would be a tail call.
`emit(passthru(123, 456, 789))` + "\n"
if err := state.Load(strings.NewReader(source), luacode.Source(source), "t"); err != nil {
t.Fatal(err)
}
if err := state.Call(0, 0, 0); err != nil {
t.Fatal(err)
}

want := []int64{123, 456, 789}
if !slices.Equal(want, got) {
t.Errorf("emit arguments = %v; want %v", got, want)
}
})

t.Run("TBC", func(t *testing.T) {
state := new(State)
defer func() {
Expand Down

0 comments on commit a0ea228

Please sign in to comment.