Skip to content

Commit

Permalink
updated tests and auxlib
Browse files Browse the repository at this point in the history
  • Loading branch information
fibonacci1729 committed Nov 2, 2018
1 parent 841f5d7 commit 0bd2b80
Show file tree
Hide file tree
Showing 51 changed files with 4,296 additions and 6,678 deletions.
173 changes: 150 additions & 23 deletions lua/access.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
package lua

import "fmt"

var _ = fmt.Println

// CheckUserData checks whether the function argument arg is a userdata of the type
// metaType (see NewMetaTable) and returns the userdata address (see ToUserData).
//
// See https://www.lua.org/manual/5.3/manual.html#luaL_checkudata
func (state *State) CheckUserData(index int, metaType string) (data interface{}) {
if data = state.TestUserData(index, metaType); data == nil {
typeError(state, index, metaType)
}
return
}

// TestUserData is equivalent to CheckUserData, except that, when the test fails, it
// returns nil instead of raising an error.
//
// See https://www.lua.org/manual/5.3/manual.html#luaL_testudata
func (state *State) TestUserData(index int, metaType string) (data interface{}) {
if data = state.ToUserData(index); data != nil {
if state.GetMetaTableAt(index) {
state.GetMetaTable(metaType)
if !state.RawEqual(-1, -2) {
data = nil
}
state.PopN(2)
}
}
return
}

// CheckType checks whether the function argument at index has type typ.
//
// See https://www.lua.org/manual/5.3/manual.html#luaL_checktype
func (state *State) CheckType(index int, typ Type) {
if state.TypeAt(index) != typ {
typeError(state, index, typ)
typeError(state, index, typ.String())
}
}

Expand All @@ -16,7 +48,7 @@ func (state *State) CheckType(index int, typ Type) {
func (state *State) CheckNumber(index int) float64 {
f64, ok := state.TryFloat(index)
if !ok {
typeError(state, index, NumberType)
typeError(state, index, "number")
}
return f64
}
Expand All @@ -29,7 +61,7 @@ func (state *State) CheckNumber(index int) float64 {
func (state *State) CheckString(index int) string {
str, ok := state.TryString(index)
if !ok {
typeError(state, index, StringType)
typeError(state, index, "string")
}
return str
}
Expand Down Expand Up @@ -63,7 +95,7 @@ func (state *State) CheckAny(index int) {
//
// See https://www.lua.org/manual/5.3/manual.html#pdf-optstring
func (state *State) OptString(index int, optStr string) string {
if state.IsNoneOrNil(index) {
if state.TypeAt(index) == NoneType {
return optStr
}
return state.CheckString(index)
Expand All @@ -74,7 +106,7 @@ func (state *State) OptString(index int, optStr string) string {
//
// See https://www.lua.org/manual/5.3/manual.html#luaL_optnumber
func (state *State) OptNumber(index int, optNum float64) float64 {
if state.IsNoneOrNil(index) {
if state.TypeAt(index) == NoneType {
return optNum
}
return state.CheckNumber(index)
Expand All @@ -87,12 +119,72 @@ func (state *State) OptNumber(index int, optNum float64) float64 {
//
// See https://www.lua.org/manual/5.3/manual.html#luaL_optinteger
func (state *State) OptInt(index int, optInt int64) int64 {
if state.TypeAt(index) != IntType {
if state.TypeAt(index) == NoneType {
return optInt
}
return state.CheckInt(index)
}

// ToUserData returns the value at the given index if type userdata. Otherwise, returns nil.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_touserdata
func (state *State) ToUserData(index int) interface{} {
if udata, ok := state.get(index).(*Object); ok {
return udata.data
}
return nil
}

// ToStringMeta converts any Lua value at the given index to a C string in a reasonable format. The resulting
// string is pushed onto the stack and also returned by the function. If len is not NULL, the function also
// sets *len with the string length.
//
// If the value has a metatable with a __tostring field, then luaL_tolstring calls the corresponding
// metamethod with the value as argument, and uses the result of the call as its result.
//
// See https://www.lua.org/manual/5.3/manual.html#luaL_tolstring
func (state *State) ToStringMeta(index int) string {
if state.CallMeta(index, "__tostring") {
s, ok := state.TryString(-1)
if ok {
return s
}
panic(fmt.Errorf("'__tostring' must return a string"))
} else {
switch kind := state.TypeAt(index); kind {
case NumberType:
if state.IsInt(index) {
state.Push(fmt.Sprintf("%d", state.ToInt(index)))
} else {
state.Push(fmt.Sprintf("%.14g", state.ToNumber(index)))
}
case StringType:
state.PushIndex(index)
case BoolType:
state.Push(state.ToBool(index))
case NilType:
state.Push("nil")
default:
// TODO: check __name metafield
state.Push(fmt.Sprintf("%s: %p", kind, state.get(index)))
}
}
return state.ToString(-1)
}

// ToNumber converts the Lua value at the given index to a Number. The Lua value must be a number or a string
// convertible to a number (see §3.4.3); otherwise, otherwise, returns 0.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_tonumber
func (state *State) ToNumber(index int) float64 {
f64, ok := state.TryFloat(index)
if !ok {
return 0
}
state.set(index, Float(f64))
return f64
}

// ToString converts the Lua value at the given index to a Go string. The Lua value must be a string
// or a number; otherwise, the function returns ("", false). If the value is a number, then ToString
// also changes the actual value in the stack to a string. (This change confuses Next(...) when ToString
Expand All @@ -101,18 +193,8 @@ func (state *State) OptInt(index int, optInt int64) int64 {
// ToString returns a copy of the string inside the Lua state.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_tolstring
// func (state *State) ToString(index int) (string, bool) {
func (state *State) ToString(index int) string {
val := state.get(index)
if meta := state.metafield(val, "__tostring"); !IsNone(meta) {
if cls, ok := meta.(*Closure); ok {
state.frame().push(cls)
state.frame().push(val)
state.Call(1, 1)
val = state.frame().pop()
}
}
s, ok := toString(val)
s, ok := toString(state.get(index))
if ok {
state.set(index, String(s))
}
Expand All @@ -125,9 +207,10 @@ func (state *State) ToString(index int) string {
// See https://www.lua.org/manual/5.3/manual.html#lua_tointeger
func (state *State) ToInt(index int) int64 {
i64, ok := state.TryInt(index)
if ok {
state.set(index, Int(i64))
if !ok {
return 0
}
state.set(index, Int(i64))
return i64
}

Expand All @@ -148,9 +231,9 @@ func (state *State) ToBool(index int) bool {
// otherwise, the function returns nil.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_tothread
func (state *State) ToThread(index int) *Thread {
func (state *State) ToThread(index int) *State {
if v, ok := state.get(index).(*Thread); ok {
return v
return v.State
}
return nil
}
Expand All @@ -162,11 +245,20 @@ func (state *State) IsThread(index int) bool {
return state.TypeAt(index) == ThreadType
}

// IsString returns true if the value at the given index is a string or a number (which is
// always convertible to a string); otherwise, returns false.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_isstring
func (state *State) IsString(index int) bool {
t := state.TypeAt(index)
return t == StringType || t == NumberType
}

// IsNumber returns true if the value at the given index is a number or a string
// convertible to a number, and false otherwise.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_isnumber
func (state *State) IsNumber(index int) bool { return state.TypeAt(index) == FloatType || state.IsInt(index) }
func (state *State) IsNumber(index int) bool { _, ok := state.TryNumber(index); return ok }

// IsNoneOrNil returns true if the given index is not valid or if the value at this index is nil and
// false otherwise.
Expand All @@ -184,12 +276,47 @@ func (state *State) IsNone(index int) bool { return state.TypeAt(index) == NoneT
// See https://www.lua.org/manual/5.3/manual.html#lua_isnil
func (state *State) IsNil(index int) bool { return state.TypeAt(index) == NilType }

// Returns true if the value at the given index is a boolean; otherwise falsse.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_isboolean
func (state *State) IsBool(index int) bool { return state.TypeAt(index) == BoolType }

// IsFunc returns true if the value at the given index is a function (either Go or Lua);
// otherwise returns false.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_isfunction
func (state *State) IsFunc(index int) bool { return state.TypeAt(index) == FuncType }

// IsGoFunc returns true if the value at the given index is a Go function;
// otherwise returns false.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_iscfunction
func (state *State) IsGoFunc(index int) bool {
cls, ok := state.get(index).(*Closure)
return ok && !cls.isLua()
}

// IsFloat returns true if the value at the given index is an float
// (that is, the value is a number and is represented as a float),
// and false otherwise.
func (state *State) IsFloat(index int) bool { return IsFloat(state.get(index)) }

// IsInt returns true if the value at the given index is an integer
// (that is, the value is a number and is represented as an integer),
// and false otherwise.
//
// See https://www.lua.org/manual/5.3/manual.html#lua_isinteger
func (state *State) IsInt(index int) bool { return state.TypeAt(index) == IntType }
func (state *State) IsInt(index int) bool { return IsInt(state.get(index)) }

func (state *State) TryNumber(index int) (Number, bool) {
if v, ok := toInteger(state.get(index)); ok {
return v, ok
}
if v, ok := toFloat(state.get(index)); ok {
return v, ok
}
return nil, false
}

func (state *State) TryString(index int) (string, bool) {
return toString(state.get(index))
Expand Down
Loading

0 comments on commit 0bd2b80

Please sign in to comment.