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 }