Skip to content

Commit

Permalink
Implement math and string libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
zombiezen committed Jan 16, 2025
1 parent 7990a49 commit 62a6761
Show file tree
Hide file tree
Showing 8 changed files with 2,551 additions and 32 deletions.
37 changes: 27 additions & 10 deletions internal/lua/auxlib.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,9 @@ func ToString(l *State, idx int) (string, sets.Set[string], error) {
case TypeString:
s, _ := l.ToString(idx)
return s, l.StringContext(idx), nil
case TypeBoolean:
if l.ToBoolean(idx) {
return "true", nil, nil
} else {
return "false", nil, nil
}
case TypeNil:
return "nil", nil, nil
case TypeBoolean, TypeNil:
k, _ := ToConstant(l, idx)
return k.String(), nil, nil
default:
var kind string
var sctx sets.Set[string]
Expand All @@ -117,6 +112,28 @@ func ToString(l *State, idx int) (string, sets.Set[string], error) {
}
}

// ToConstant converts the nil, boolean, number, or string at the given index
// to a [luacode.Value].
func ToConstant(l *State, idx int) (_ luacode.Value, ok bool) {
switch l.Type(idx) {
case TypeNumber:
if i, ok := l.ToInteger(idx); ok {
return luacode.IntegerValue(i), true
}
n, _ := l.ToNumber(idx)
return luacode.FloatValue(n), true
case TypeString:
s, _ := l.ToString(idx)
return luacode.StringValue(s), true
case TypeBoolean:
return luacode.BoolValue(l.ToBoolean(idx)), true
case TypeNil:
return luacode.Value{}, true
default:
return luacode.Value{}, false
}
}

// CheckString checks whether the function argument arg is a string
// and returns this string.
// This function uses [State.ToString] to get its result,
Expand Down Expand Up @@ -399,11 +416,11 @@ func OpenLibraries(l *State) error {
}{
{GName, NewOpenBase(nil)},
{TableLibraryName, OpenTable},
{StringLibraryName, OpenString},
{MathLibraryName, NewOpenMath(nil)},
// {IOLibraryName, NewIOLibrary().OpenLibrary},
// {OSLibraryName, NewOSLibrary().OpenLibrary},
// {StringLibraryName, OpenString},
// {UTF8LibraryName, OpenUTF8},
// {MathLibraryName, NewOpenMath(nil)},
// {DebugLibraryName, OpenDebug},
// {PackageLibraryName, OpenPackage},
}
Expand Down
1 change: 1 addition & 0 deletions internal/lua/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ However, there are some differences:
- The “__gc” (finalizer) metamethod is never called.
Use “__close” instead, as the semantics are well-defined.
- Weak tables (i.e. the “__mode” metafield) are not supported.
- The “string” library has differences; see [OpenString] for more details.
[Lua C API]: https://www.lua.org/manual/5.4/manual.html#4
[auxiliary library]: https://www.lua.org/manual/5.4/manual.html#5
Expand Down
40 changes: 40 additions & 0 deletions internal/lua/lua_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"errors"
"io"
"math"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
Expand Down Expand Up @@ -705,6 +707,44 @@ func TestRotate(t *testing.T) {
}
}

func TestSuite(t *testing.T) {
names := []string{
"math",
"strings",
}

for _, name := range names {
t.Run(strings.ToUpper(name[:1])+name[1:], func(t *testing.T) {
l := new(State)
defer func() {
if err := l.Close(); err != nil {
t.Error("Close:", err)
}
}()
if err := OpenLibraries(l); err != nil {
t.Fatal(err)
}
l.PushBoolean(true)
if err := l.SetGlobal("_port", 0); err != nil {
t.Fatal(err)
}

sourcePath := filepath.Join("testdata", "testsuite", name+".lua")
sourceData, err := os.ReadFile(sourcePath)
if err != nil {
t.Fatal(err)
}
err = l.Load(bytes.NewReader(sourceData), FilenameSource(sourcePath), "t")
if err != nil {
t.Fatal(err)
}
if err := l.Call(0, 0, 0); err != nil {
t.Fatal(err)
}
})
}
}

func BenchmarkExec(b *testing.B) {
state := new(State)
defer func() {
Expand Down
Loading

0 comments on commit 62a6761

Please sign in to comment.