github.com/yuin/gopher-lua@v1.1.2-0.20231212122839-2348fd042596/value.go (about)

     1  package lua
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  )
     8  
     9  type LValueType int
    10  
    11  const (
    12  	LTNil LValueType = iota
    13  	LTBool
    14  	LTNumber
    15  	LTString
    16  	LTFunction
    17  	LTUserData
    18  	LTThread
    19  	LTTable
    20  	LTChannel
    21  )
    22  
    23  var lValueNames = [9]string{"nil", "boolean", "number", "string", "function", "userdata", "thread", "table", "channel"}
    24  
    25  func (vt LValueType) String() string {
    26  	return lValueNames[int(vt)]
    27  }
    28  
    29  type LValue interface {
    30  	String() string
    31  	Type() LValueType
    32  }
    33  
    34  // LVIsFalse returns true if a given LValue is a nil or false otherwise false.
    35  func LVIsFalse(v LValue) bool { return v == LNil || v == LFalse }
    36  
    37  // LVIsFalse returns false if a given LValue is a nil or false otherwise true.
    38  func LVAsBool(v LValue) bool { return v != LNil && v != LFalse }
    39  
    40  // LVAsString returns string representation of a given LValue
    41  // if the LValue is a string or number, otherwise an empty string.
    42  func LVAsString(v LValue) string {
    43  	switch sn := v.(type) {
    44  	case LString, LNumber:
    45  		return sn.String()
    46  	default:
    47  		return ""
    48  	}
    49  }
    50  
    51  // LVCanConvToString returns true if a given LValue is a string or number
    52  // otherwise false.
    53  func LVCanConvToString(v LValue) bool {
    54  	switch v.(type) {
    55  	case LString, LNumber:
    56  		return true
    57  	default:
    58  		return false
    59  	}
    60  }
    61  
    62  // LVAsNumber tries to convert a given LValue to a number.
    63  func LVAsNumber(v LValue) LNumber {
    64  	switch lv := v.(type) {
    65  	case LNumber:
    66  		return lv
    67  	case LString:
    68  		if num, err := parseNumber(string(lv)); err == nil {
    69  			return num
    70  		}
    71  	}
    72  	return LNumber(0)
    73  }
    74  
    75  type LNilType struct{}
    76  
    77  func (nl *LNilType) String() string   { return "nil" }
    78  func (nl *LNilType) Type() LValueType { return LTNil }
    79  
    80  var LNil = LValue(&LNilType{})
    81  
    82  type LBool bool
    83  
    84  func (bl LBool) String() string {
    85  	if bool(bl) {
    86  		return "true"
    87  	}
    88  	return "false"
    89  }
    90  func (bl LBool) Type() LValueType { return LTBool }
    91  
    92  var LTrue = LBool(true)
    93  var LFalse = LBool(false)
    94  
    95  type LString string
    96  
    97  func (st LString) String() string   { return string(st) }
    98  func (st LString) Type() LValueType { return LTString }
    99  
   100  // fmt.Formatter interface
   101  func (st LString) Format(f fmt.State, c rune) {
   102  	switch c {
   103  	case 'd', 'i':
   104  		if nm, err := parseNumber(string(st)); err != nil {
   105  			defaultFormat(nm, f, 'd')
   106  		} else {
   107  			defaultFormat(string(st), f, 's')
   108  		}
   109  	default:
   110  		defaultFormat(string(st), f, c)
   111  	}
   112  }
   113  
   114  func (nm LNumber) String() string {
   115  	if isInteger(nm) {
   116  		return fmt.Sprint(int64(nm))
   117  	}
   118  	return fmt.Sprint(float64(nm))
   119  }
   120  
   121  func (nm LNumber) Type() LValueType { return LTNumber }
   122  
   123  // fmt.Formatter interface
   124  func (nm LNumber) Format(f fmt.State, c rune) {
   125  	switch c {
   126  	case 'q', 's':
   127  		defaultFormat(nm.String(), f, c)
   128  	case 'b', 'c', 'd', 'o', 'x', 'X', 'U':
   129  		defaultFormat(int64(nm), f, c)
   130  	case 'e', 'E', 'f', 'F', 'g', 'G':
   131  		defaultFormat(float64(nm), f, c)
   132  	case 'i':
   133  		defaultFormat(int64(nm), f, 'd')
   134  	default:
   135  		if isInteger(nm) {
   136  			defaultFormat(int64(nm), f, c)
   137  		} else {
   138  			defaultFormat(float64(nm), f, c)
   139  		}
   140  	}
   141  }
   142  
   143  type LTable struct {
   144  	Metatable LValue
   145  
   146  	array   []LValue
   147  	dict    map[LValue]LValue
   148  	strdict map[string]LValue
   149  	keys    []LValue
   150  	k2i     map[LValue]int
   151  }
   152  
   153  func (tb *LTable) String() string   { return fmt.Sprintf("table: %p", tb) }
   154  func (tb *LTable) Type() LValueType { return LTTable }
   155  
   156  type LFunction struct {
   157  	IsG       bool
   158  	Env       *LTable
   159  	Proto     *FunctionProto
   160  	GFunction LGFunction
   161  	Upvalues  []*Upvalue
   162  }
   163  type LGFunction func(*LState) int
   164  
   165  func (fn *LFunction) String() string   { return fmt.Sprintf("function: %p", fn) }
   166  func (fn *LFunction) Type() LValueType { return LTFunction }
   167  
   168  type Global struct {
   169  	MainThread    *LState
   170  	CurrentThread *LState
   171  	Registry      *LTable
   172  	Global        *LTable
   173  
   174  	builtinMts map[int]LValue
   175  	tempFiles  []*os.File
   176  	gccount    int32
   177  }
   178  
   179  type LState struct {
   180  	G       *Global
   181  	Parent  *LState
   182  	Env     *LTable
   183  	Panic   func(*LState)
   184  	Dead    bool
   185  	Options Options
   186  
   187  	stop         int32
   188  	reg          *registry
   189  	stack        callFrameStack
   190  	alloc        *allocator
   191  	currentFrame *callFrame
   192  	wrapped      bool
   193  	uvcache      *Upvalue
   194  	hasErrorFunc bool
   195  	mainLoop     func(*LState, *callFrame)
   196  	ctx          context.Context
   197  	ctxCancelFn  context.CancelFunc
   198  }
   199  
   200  func (ls *LState) String() string   { return fmt.Sprintf("thread: %p", ls) }
   201  func (ls *LState) Type() LValueType { return LTThread }
   202  
   203  type LUserData struct {
   204  	Value     interface{}
   205  	Env       *LTable
   206  	Metatable LValue
   207  }
   208  
   209  func (ud *LUserData) String() string   { return fmt.Sprintf("userdata: %p", ud) }
   210  func (ud *LUserData) Type() LValueType { return LTUserData }
   211  
   212  type LChannel chan LValue
   213  
   214  func (ch LChannel) String() string   { return fmt.Sprintf("channel: %p", ch) }
   215  func (ch LChannel) Type() LValueType { return LTChannel }