Skip to content

Commit 319ac9d

Browse files
committed
Improve toNumber, fix protect
1 parent 5672259 commit 319ac9d

File tree

10 files changed

+54
-22
lines changed

10 files changed

+54
-22
lines changed

base.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ var baseLibrary = []RegistryFunction{
256256
}},
257257
{"type", func(l *State) int {
258258
CheckAny(l, 1)
259-
PushString(l, TypeName(l, 1))
259+
PushString(l, TypeNameOf(l, 1))
260260
return 1
261261
}},
262262
{"xpcall", func(l *State) int {

debug.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func (l *State) orderError(left, right value) {
5353
}
5454

5555
func (l *State) arithError(v1, v2 value) {
56-
if _, ok := toNumber(v1); !ok {
56+
if _, ok := l.toNumber(v1); !ok {
5757
v2 = v1
5858
}
5959
l.typeError(v2, "perform arithmetic on")

libs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ func OpenLibraries(l *State) {
55
{"_G", BaseOpen},
66
{"package", PackageOpen},
77
{"math", MathOpen},
8+
{"string", StringOpen},
89
}
910
for _, lib := range libs {
1011
Require(l, lib.Name, lib.Function, true)

lua.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ func IsGoFunction(l *State, index int) bool {
568568
//
569569
// http://www.lua.org/manual/5.2/manual.html#lua_isnumber
570570
func IsNumber(l *State, index int) bool {
571-
_, ok := toNumber(l.indexToValue(index))
571+
_, ok := l.toNumber(l.indexToValue(index))
572572
return ok
573573
}
574574

@@ -654,7 +654,7 @@ func Compare(l *State, index1, index2 int, op ComparisonOperator) bool {
654654
//
655655
// http://www.lua.org/manual/5.2/manual.html#lua_tointegerx
656656
func ToInteger(l *State, index int) (int, bool) {
657-
if n, ok := toNumber(l.indexToValue(index)); ok {
657+
if n, ok := l.toNumber(l.indexToValue(index)); ok {
658658
return int(n), true
659659
}
660660
return 0, false
@@ -672,7 +672,7 @@ func ToInteger(l *State, index int) (int, bool) {
672672
//
673673
// http://www.lua.org/manual/5.2/manual.html#lua_tounsignedx
674674
func ToUnsigned(l *State, index int) (uint, bool) {
675-
if n, ok := toNumber(l.indexToValue(index)); ok {
675+
if n, ok := l.toNumber(l.indexToValue(index)); ok {
676676
const supUnsigned = float64(^uint(0)) + 1
677677
return uint(n - math.Floor(n/supUnsigned)*supUnsigned), true
678678
}
@@ -1256,7 +1256,7 @@ func TypeName(l *State, t Type) string { return typeNames[t+1] }
12561256
// If the operation failed, the second return value will be false.
12571257
//
12581258
// http://www.lua.org/manual/5.2/manual.html#lua_tonumberx
1259-
func ToNumber(l *State, index int) (float64, bool) { return toNumber(l.indexToValue(index)) }
1259+
func ToNumber(l *State, index int) (float64, bool) { return l.toNumber(l.indexToValue(index)) }
12601260

12611261
// ToBoolean converts the Lua value at `index` to a Go boolean. Like all
12621262
// tests in Lua, the only true values are `true` booleans and `nil`.

math_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,17 @@ package lua
33
import "testing"
44

55
func TestMath(t *testing.T) {
6+
t.Skip()
67
l := NewState()
78
OpenLibraries(l)
8-
LoadString(l, "print(math.abs(-math.pi))")
9+
// SetHooker(l, func(state *State, ar *Debug) {
10+
// ci := state.callInfo.(*luaCallInfo)
11+
// printStack(state.stack[ci.base():state.top])
12+
// println(ci.code[ci.savedPC].String())
13+
// p := state.stack[ci.function()].(*luaClosure).prototype
14+
// println(p.source, p.lineInfo[ci.savedPC])
15+
// }, MaskCount, 1)
16+
// LoadString(l, "print(math.abs(-math.pi))")
17+
LoadFile(l, "fixtures/math.lua", "text")
918
Call(l, 0, 0)
1019
}

parser_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func load(l *State, t *testing.T, fileName string) *luaClosure {
1818
func TestParser(t *testing.T) {
1919
l := NewState()
2020
OpenLibraries(l)
21-
// SetHook(l, func(state *State, ar *Debug) {
21+
// SetHooker(l, func(state *State, ar *Debug) {
2222
// printStack(state.stack[state.callInfo.(*luaCallInfo).base():state.top])
2323
// println(state.callInfo.(*luaCallInfo).code[state.callInfo.(*luaCallInfo).savedPC].String())
2424
// }, MaskCount, 1)

scanner_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func TestScanner(t *testing.T) {
3535
{"0x0.1E", []token{{t: tkNumber, n: 0.1171875}}},
3636
{"0xA23p-4", []token{{t: tkNumber, n: 162.1875}}},
3737
{"0X1.921FB54442D18P+1", []token{{t: tkNumber, n: 3.141592653589793}}},
38+
{" -0xa ", []token{{t: '-'}, {t: tkNumber, n: 10.0}}},
3839
}
3940
for i, v := range tests {
4041
testScanner(t, i, v.source, v.tokens)

stack.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,8 @@ func (l *State) throw(errorCode error) {
409409
}
410410
}
411411

412-
func (l *State) protect(f func()) error {
412+
func (l *State) protect(f func()) (err error) {
413413
nestedGoCallCount, protectFunction := l.nestedGoCallCount, l.protectFunction
414-
var err error
415414
l.protectFunction = func() {
416415
if e := recover(); e != nil {
417416
err = e.(error)

types.go

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"reflect"
77
"runtime"
88
"strconv"
9+
"strings"
910
)
1011

1112
type value interface{}
@@ -132,16 +133,37 @@ func arith(op Operator, v1, v2 float64) float64 {
132133
panic(fmt.Sprintf("not an arithmetic op code (%d)", op))
133134
}
134135

135-
func toNumber(r value) (float64, bool) {
136-
if v, ok := r.(float64); ok {
137-
return v, true
136+
func (l *State) parseNumber(s string) (float64, bool) {
137+
scanner := scanner{l: l, r: strings.NewReader(s)}
138+
t := scanner.scan()
139+
if t.t == '-' {
140+
if t := scanner.scan(); t.t == tkNumber {
141+
return -t.n, true
142+
}
143+
} else if t.t == tkNumber {
144+
return t.n, true
138145
}
139-
if s, ok := r.(string); ok {
140-
if v, err := strconv.ParseFloat(s, 64); err == nil { // TODO handle hexadecimal floats
146+
return 0.0, false
147+
}
148+
149+
func (l *State) toNumber(r value) (v float64, ok bool) {
150+
if v, ok = r.(float64); ok {
151+
return
152+
}
153+
var s string
154+
if s, ok = r.(string); ok {
155+
s = strings.TrimSpace(s)
156+
if v, err := strconv.ParseFloat(s, 64); err == nil {
141157
return v, true
142158
}
159+
if err := l.protectedCall(func() { v, ok = l.parseNumber(s) }, l.top, l.errorFunction); err == nil {
160+
return
161+
} else {
162+
l.pop() // Remove error message from the stack.
163+
ok = false
164+
}
143165
}
144-
return 0.0, false
166+
return
145167
}
146168

147169
func numberToString(f float64) string {

vm.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
)
88

99
func (l *State) arith(rb, rc value, op tm) value {
10-
b, bok := toNumber(rb)
11-
c, cok := toNumber(rc)
10+
b, bok := l.toNumber(rb)
11+
c, cok := l.toNumber(rc)
1212
if bok && cok {
1313
return arith(Operator(op-tmAdd)+OpAdd, b, c)
1414
} else if result, ok := l.callBinaryTagMethod(rb, rc, op); ok {
@@ -485,11 +485,11 @@ func (l *State) execute() {
485485
}
486486
case opForPrep:
487487
a := i.a()
488-
if init, ok := toNumber(frame[a+0]); !ok {
488+
if init, ok := l.toNumber(frame[a+0]); !ok {
489489
l.runtimeError("'for' initial value must be a number")
490-
} else if limit, ok := toNumber(frame[a+1]); !ok {
490+
} else if limit, ok := l.toNumber(frame[a+1]); !ok {
491491
l.runtimeError("'for' limit must be a number")
492-
} else if step, ok := toNumber(frame[a+2]); !ok {
492+
} else if step, ok := l.toNumber(frame[a+2]); !ok {
493493
l.runtimeError("'for' step must be a number")
494494
} else {
495495
frame[a+0], frame[a+1], frame[a+2] = init-step, limit, step
@@ -518,7 +518,7 @@ func (l *State) execute() {
518518
c = expectNext(opExtraArg).ax()
519519
}
520520
h := frame[a].(*table)
521-
start := c - 1*listItemsPerFlush
521+
start := (c - 1) * listItemsPerFlush
522522
last := start + n
523523
if last > cap(h.array) {
524524
h.extendArray(last)

0 commit comments

Comments
 (0)