Skip to content

Commit

Permalink
Implement string.dump
Browse files Browse the repository at this point in the history
  • Loading branch information
zombiezen committed Jan 22, 2025
1 parent c7fc7f4 commit 15c7053
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
27 changes: 26 additions & 1 deletion internal/lua/lua.go
Original file line number Diff line number Diff line change
Expand Up @@ -1763,6 +1763,27 @@ func (l *State) Load(r io.ByteScanner, chunkName Source, mode string) (err error
return nil
}

// Dump marshals the function at the top of the stack into a binary chunk.
// If stripDebug is true,
// the binary representation may not include all debug information about the function,
// to save space.
func (l *State) Dump(stripDebug bool) ([]byte, error) {
if l.Top() < 1 {
return nil, errMissingArguments
}

l.init()
top := l.stack[len(l.stack)-1]
f, ok := top.(luaFunction)
if !ok {
if valueType(top) == TypeFunction {
return nil, errors.New("cannot dump a Go function")
}
return nil, fmt.Errorf("cannot dump a %s", l.typeName(top))
}
return f.proto.MarshalBinary()
}

// Next pops a key from the stack,
// and pushes a key–value pair from the table at the given index,
// the “next” pair after the given key.
Expand Down Expand Up @@ -1992,7 +2013,11 @@ const typeNameMetafield = "__name"
func (l *State) typeName(v value) string {
switch v := v.(type) {
case *table:
if s, ok := v.get(stringValue{s: typeNameMetafield}).(stringValue); ok {
if s, ok := v.meta.get(stringValue{s: typeNameMetafield}).(stringValue); ok {
return s.s
}
case *userdata:
if s, ok := v.meta.get(stringValue{s: typeNameMetafield}).(stringValue); ok {
return s.s
}
}
Expand Down
20 changes: 17 additions & 3 deletions internal/lua/stringlib.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ const StringLibraryName = "string"
// [string manipulation library]: https://www.lua.org/manual/5.4/manual.html#6.4
func OpenString(ctx context.Context, l *State) (int, error) {
NewLib(l, map[string]Function{
"byte": stringByte,
"char": stringChar,
// "dump": stringDump,
"byte": stringByte,
"char": stringChar,
"dump": stringDump,
"find": stringFind,
"format": stringFormat,
"gmatch": stringGMatch,
Expand Down Expand Up @@ -144,6 +144,20 @@ func stringChar(ctx context.Context, l *State) (int, error) {
return 1, nil
}

func stringDump(ctx context.Context, l *State) (int, error) {
stripDebug := l.ToBoolean(2)
if got, want := l.Type(1), TypeFunction; got != want {
return 0, NewTypeError(l, 1, want.String())
}
l.SetTop(1)
chunk, err := l.Dump(stripDebug)
if err != nil {
return 0, err
}
l.PushString(string(chunk))
return 1, nil
}

func stringFind(ctx context.Context, l *State) (int, error) {
s, err := CheckString(l, 1)
if err != nil {
Expand Down

0 comments on commit 15c7053

Please sign in to comment.