github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/internal/errors/errors.go (about) 1 package errors 2 3 import ( 4 "fmt" 5 6 "github.com/hirochachacha/plua/object" 7 ) 8 9 func NaNIndexError() *object.RuntimeError { 10 return object.NewRuntimeError("table index is nan") 11 } 12 13 func NilIndexError() *object.RuntimeError { 14 return object.NewRuntimeError("table index is nil") 15 } 16 17 func StackOverflowError() *object.RuntimeError { 18 return object.NewRuntimeError("Go stack overflow") 19 } 20 21 func InvalidByteCodeError() *object.RuntimeError { 22 return object.NewRuntimeError("malformed bytecode detected") 23 } 24 25 func ForLoopError(elem string) *object.RuntimeError { 26 return object.NewRuntimeError(fmt.Sprintf("'for' %s value must be a number", elem)) 27 } 28 29 func typeName(th object.Thread, arg object.Value) string { 30 if mt := th.GetMetatable(arg); mt != nil { 31 if name := mt.Get(object.TM_NAME); name != nil { 32 if name, ok := name.(object.String); ok { 33 return string(name) 34 } 35 if _, ok := arg.(object.LightUserdata); ok { 36 return "light userdata" 37 } 38 return object.ToType(arg).String() 39 } 40 } 41 if _, ok := arg.(object.LightUserdata); ok { 42 return "light userdata" 43 } 44 return object.ToType(arg).String() 45 } 46 47 func TypeError(th object.Thread, op string, x object.Value) *object.RuntimeError { 48 return object.NewRuntimeError(fmt.Sprintf("attempt to %s a %s value%s", op, typeName(th, x), varinfo(th, x))) 49 } 50 51 func CallError(th object.Thread, fn object.Value) *object.RuntimeError { 52 return TypeError(th, "call", fn) 53 } 54 55 func IndexError(th object.Thread, t object.Value) *object.RuntimeError { 56 return TypeError(th, "index", t) 57 } 58 59 func UnaryError(th object.Thread, tag object.Value, x object.Value) *object.RuntimeError { 60 switch tag { 61 case object.TM_LEN: 62 return LengthError(th, x) 63 case object.TM_UNM: 64 return UnaryMinusError(th, x) 65 case object.TM_BNOT: 66 return BinaryNotError(th, x) 67 default: 68 panic("unreachable") 69 } 70 } 71 72 func BinaryError(th object.Thread, tag object.Value, x, y object.Value) *object.RuntimeError { 73 switch tag { 74 case object.TM_ADD, object.TM_SUB, object.TM_MUL, object.TM_MOD, object.TM_POW, object.TM_DIV: 75 return ArithError(th, x, y) 76 case object.TM_IDIV, object.TM_BAND, object.TM_BOR, object.TM_BXOR, object.TM_SHL, object.TM_SHR: 77 return BitwiseError(th, x, y) 78 case object.TM_CONCAT: 79 return ConcatError(th, x, y) 80 default: 81 panic("unreachable") 82 } 83 } 84 85 func LengthError(th object.Thread, x object.Value) *object.RuntimeError { 86 return TypeError(th, "get length of", x) 87 } 88 89 func UnaryMinusError(th object.Thread, x object.Value) *object.RuntimeError { 90 return TypeError(th, "negate", x) 91 } 92 93 func BinaryNotError(th object.Thread, x object.Value) *object.RuntimeError { 94 if _, ok := object.ToNumber(x); ok { 95 return object.NewRuntimeError(fmt.Sprintf("number%s has no integer representation", varinfo(th, x))) 96 } 97 return TypeError(th, "bitwise negation on", x) 98 } 99 100 func CompareError(th object.Thread, x, y object.Value) *object.RuntimeError { 101 t1 := typeName(th, x) 102 t2 := typeName(th, y) 103 104 if t1 == t2 { 105 return object.NewRuntimeError(fmt.Sprintf("attempt to compare two %s values", t1)) 106 } 107 108 return object.NewRuntimeError(fmt.Sprintf("attempt to compare %s with %s", t1, t2)) 109 } 110 111 func ArithError(th object.Thread, x, y object.Value) *object.RuntimeError { 112 if _, ok := object.ToNumber(x); ok { 113 return TypeError(th, "perform arithmetic on", y) 114 } 115 return TypeError(th, "perform arithmetic on", x) 116 } 117 118 func BitwiseError(th object.Thread, x, y object.Value) *object.RuntimeError { 119 if _, ok := object.ToInteger(x); ok { 120 if _, ok := object.ToNumber(y); ok { 121 return object.NewRuntimeError(fmt.Sprintf("number%s has no integer representation", varinfo(th, y))) 122 } 123 return TypeError(th, "perform bitwise operation on", y) 124 } 125 if _, ok := object.ToNumber(x); ok { 126 return object.NewRuntimeError(fmt.Sprintf("number%s has no integer representation", varinfo(th, x))) 127 } 128 return TypeError(th, "perform bitwise operation on", x) 129 } 130 131 func ConcatError(th object.Thread, x, y object.Value) *object.RuntimeError { 132 if _, ok := object.ToString(x); ok { 133 return TypeError(th, "concatenate", y) 134 } 135 return TypeError(th, "concatenate", x) 136 } 137 138 func varinfo(th object.Thread, x object.Value) string { 139 // TODO? INCOMPATIBLE 140 // Current implementation uses value instead of pointer everywhere. 141 // So there is no way to identify two object is exactly same. 142 // That's why I can't implement this. 143 return "" 144 }