github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/internal/arith/table.go (about) 1 package arith 2 3 import ( 4 "github.com/hirochachacha/plua/internal/errors" 5 "github.com/hirochachacha/plua/internal/version" 6 "github.com/hirochachacha/plua/object" 7 ) 8 9 func CallGettable(th object.Thread, t, key object.Value) (object.Value, *object.RuntimeError) { 10 for i := 0; i < version.MAX_TAG_LOOP; i++ { 11 var tm object.Value 12 if tab, ok := t.(object.Table); ok { 13 val := tab.Get(key) 14 if val != nil { 15 return val, nil 16 } 17 tm = gettm(tab.Metatable(), object.TM_INDEX) 18 if tm == nil { 19 return nil, nil 20 } 21 } else { 22 tm = gettmbyobj(th, t, object.TM_INDEX) 23 } 24 25 if tm == nil { 26 return nil, errors.IndexError(th, t) 27 } 28 29 if isFunction(tm) { 30 return calltm(th, tm, t, key) 31 } 32 33 t = tm 34 } 35 36 return nil, object.NewRuntimeError("gettable chain too long; possible loop") 37 } 38 39 func CallSettable(th object.Thread, t, key, val object.Value) *object.RuntimeError { 40 for i := 0; i < version.MAX_TAG_LOOP; i++ { 41 var tm object.Value 42 if tab, ok := t.(object.Table); ok { 43 tm = gettm(tab.Metatable(), object.TM_NEWINDEX) 44 if tm == nil || tab.Get(key) != nil { 45 if key == nil { 46 return errors.NilIndexError() 47 } 48 49 if object.IsNaN(key) { 50 return errors.NaNIndexError() 51 } 52 53 tab.Set(key, val) 54 55 return nil 56 } 57 } else { 58 tm = gettmbyobj(th, t, object.TM_NEWINDEX) 59 } 60 61 if tm == nil { 62 return errors.IndexError(th, t) 63 } 64 65 if isFunction(tm) { 66 _, err := calltm(th, tm, t, key, val) 67 return err 68 } 69 70 t = tm 71 } 72 73 return object.NewRuntimeError("settable chain too long; possible loop") 74 } 75 76 func isFunction(val object.Value) bool { 77 return object.ToType(val) == object.TFUNCTION 78 }