github.com/dfcfw/lua@v0.0.0-20230325031207-0cc7ffb7b8b9/luar/array.go (about)

     1  package luar
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/dfcfw/lua"
     7  )
     8  
     9  func arrayIndex(L *lua.LState) int {
    10  	ref, mt := check(L, 1)
    11  	ref = reflect.Indirect(ref)
    12  	key := L.CheckAny(2)
    13  
    14  	switch converted := key.(type) {
    15  	case lua.LNumber:
    16  		index := int(converted)
    17  		if index < 1 || index > ref.Len() {
    18  			L.ArgError(2, "index out of range")
    19  		}
    20  		val := ref.Index(index - 1)
    21  		if (val.Kind() == reflect.Struct || val.Kind() == reflect.Array) && val.CanAddr() {
    22  			val = val.Addr()
    23  		}
    24  		L.Push(New(L, val.Interface()))
    25  	case lua.LString:
    26  		if fn := mt.method(string(converted)); fn != nil {
    27  			L.Push(fn)
    28  			return 1
    29  		}
    30  		return 0
    31  	default:
    32  		L.ArgError(2, "must be a number or string")
    33  	}
    34  	return 1
    35  }
    36  
    37  func arrayPtrIndex(L *lua.LState) int {
    38  	ref, mt := check(L, 1)
    39  	ref = ref.Elem()
    40  	key := L.CheckAny(2)
    41  
    42  	switch converted := key.(type) {
    43  	case lua.LNumber:
    44  		index := int(converted)
    45  		if index < 1 || index > ref.Len() {
    46  			L.ArgError(2, "index out of range")
    47  		}
    48  		val := ref.Index(index - 1)
    49  		if (val.Kind() == reflect.Struct || val.Kind() == reflect.Array) && val.CanAddr() {
    50  			val = val.Addr()
    51  		}
    52  		L.Push(New(L, val.Interface()))
    53  	case lua.LString:
    54  		if fn := mt.method(string(converted)); fn != nil {
    55  			L.Push(fn)
    56  			return 1
    57  		}
    58  
    59  		mt = MT(L, ref.Interface())
    60  		if fn := mt.method(string(converted)); fn != nil {
    61  			L.Push(fn)
    62  			return 1
    63  		}
    64  
    65  		return 0
    66  	default:
    67  		L.ArgError(2, "must be a number or string")
    68  	}
    69  	return 1
    70  }
    71  
    72  func arrayPtrNewIndex(L *lua.LState) int {
    73  	ref, _ := check(L, 1)
    74  	ref = ref.Elem()
    75  
    76  	index := L.CheckInt(2)
    77  	value := L.CheckAny(3)
    78  	if index < 1 || index > ref.Len() {
    79  		L.ArgError(2, "index out of range")
    80  	}
    81  	hint := ref.Type().Elem()
    82  	val, err := lValueToReflect(L, value, hint, nil)
    83  	if err != nil {
    84  		L.ArgError(3, err.Error())
    85  	}
    86  	ref.Index(index - 1).Set(val)
    87  	return 0
    88  }
    89  
    90  func arrayLen(L *lua.LState) int {
    91  	ref, _ := check(L, 1)
    92  	ref = reflect.Indirect(ref)
    93  
    94  	L.Push(lua.LNumber(ref.Len()))
    95  	return 1
    96  }
    97  
    98  func arrayCall(L *lua.LState) int {
    99  	ref, _ := check(L, 1)
   100  	ref = reflect.Indirect(ref)
   101  
   102  	i := 0
   103  	fn := func(L *lua.LState) int {
   104  		if i >= ref.Len() {
   105  			return 0
   106  		}
   107  		item := ref.Index(i).Interface()
   108  		L.Push(lua.LNumber(i + 1))
   109  		L.Push(New(L, item))
   110  		i++
   111  		return 2
   112  	}
   113  
   114  	L.Push(L.NewFunction(fn))
   115  	return 1
   116  }
   117  
   118  func arrayEq(L *lua.LState) int {
   119  	ref1, _ := check(L, 1)
   120  	ref2, _ := check(L, 2)
   121  
   122  	L.Push(lua.LBool(ref1.Interface() == ref2.Interface()))
   123  	return 1
   124  }