github.com/mattn/anko@v0.1.10/vm/vmOperator.go (about) 1 package vm 2 3 import ( 4 "reflect" 5 "strings" 6 7 "github.com/mattn/anko/ast" 8 ) 9 10 // invokeOperator evaluates one Operator. 11 func (runInfo *runInfoStruct) invokeOperator() { 12 switch operator := runInfo.operator.(type) { 13 14 // BinaryOperator 15 case *ast.BinaryOperator: 16 runInfo.expr = operator.LHS 17 runInfo.invokeExpr() 18 if runInfo.err != nil { 19 return 20 } 21 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 22 runInfo.rv = runInfo.rv.Elem() 23 } 24 25 switch operator.Operator { 26 case "||": 27 if toBool(runInfo.rv) { 28 runInfo.rv = trueValue 29 return 30 } 31 case "&&": 32 if !toBool(runInfo.rv) { 33 runInfo.rv = falseValue 34 return 35 } 36 default: 37 runInfo.err = newStringError(operator, "unknown operator") 38 runInfo.rv = nilValue 39 return 40 } 41 42 runInfo.expr = operator.RHS 43 runInfo.invokeExpr() 44 if runInfo.err != nil { 45 return 46 } 47 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 48 runInfo.rv = runInfo.rv.Elem() 49 } 50 51 if toBool(runInfo.rv) { 52 runInfo.rv = trueValue 53 } else { 54 runInfo.rv = falseValue 55 } 56 57 // ComparisonOperator 58 case *ast.ComparisonOperator: 59 runInfo.expr = operator.LHS 60 runInfo.invokeExpr() 61 if runInfo.err != nil { 62 return 63 } 64 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 65 runInfo.rv = runInfo.rv.Elem() 66 } 67 lhsV := runInfo.rv 68 69 runInfo.expr = operator.RHS 70 runInfo.invokeExpr() 71 if runInfo.err != nil { 72 return 73 } 74 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 75 runInfo.rv = runInfo.rv.Elem() 76 } 77 78 switch operator.Operator { 79 case "==": 80 runInfo.rv = reflect.ValueOf(equal(lhsV, runInfo.rv)) 81 case "!=": 82 runInfo.rv = reflect.ValueOf(!equal(lhsV, runInfo.rv)) 83 case "<": 84 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) < toFloat64(runInfo.rv)) 85 case "<=": 86 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) <= toFloat64(runInfo.rv)) 87 case ">": 88 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) > toFloat64(runInfo.rv)) 89 case ">=": 90 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) >= toFloat64(runInfo.rv)) 91 default: 92 runInfo.err = newStringError(operator, "unknown operator") 93 runInfo.rv = nilValue 94 } 95 96 // AddOperator 97 case *ast.AddOperator: 98 runInfo.expr = operator.LHS 99 runInfo.invokeExpr() 100 if runInfo.err != nil { 101 return 102 } 103 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 104 runInfo.rv = runInfo.rv.Elem() 105 } 106 lhsV := runInfo.rv 107 108 runInfo.expr = operator.RHS 109 runInfo.invokeExpr() 110 if runInfo.err != nil { 111 return 112 } 113 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 114 runInfo.rv = runInfo.rv.Elem() 115 } 116 117 switch operator.Operator { 118 case "+": 119 lhsKind := lhsV.Kind() 120 rhsKind := runInfo.rv.Kind() 121 122 if lhsKind == reflect.Slice || lhsKind == reflect.Array { 123 if rhsKind == reflect.Slice || rhsKind == reflect.Array { 124 // append slice to slice 125 runInfo.rv, runInfo.err = appendSlice(operator, lhsV, runInfo.rv) 126 return 127 } 128 // try to append rhs non-slice to lhs slice 129 runInfo.rv, runInfo.err = convertReflectValueToType(runInfo.rv, lhsV.Type().Elem()) 130 if runInfo.err != nil { 131 runInfo.err = newStringError(operator, "invalid type conversion") 132 runInfo.rv = nilValue 133 return 134 } 135 runInfo.rv = reflect.Append(lhsV, runInfo.rv) 136 return 137 } 138 if rhsKind == reflect.Slice || rhsKind == reflect.Array { 139 // can not append rhs slice to lhs non-slice 140 runInfo.err = newStringError(operator, "invalid type conversion") 141 runInfo.rv = nilValue 142 return 143 } 144 145 kind := precedenceOfKinds(lhsKind, rhsKind) 146 switch kind { 147 case reflect.String: 148 runInfo.rv = reflect.ValueOf(toString(lhsV) + toString(runInfo.rv)) 149 case reflect.Float64, reflect.Float32: 150 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) + toFloat64(runInfo.rv)) 151 default: 152 runInfo.rv = reflect.ValueOf(toInt64(lhsV) + toInt64(runInfo.rv)) 153 } 154 155 case "-": 156 switch lhsV.Kind() { 157 case reflect.Float64, reflect.Float32: 158 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) - toFloat64(runInfo.rv)) 159 return 160 } 161 switch runInfo.rv.Kind() { 162 case reflect.Float64, reflect.Float32: 163 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) - toFloat64(runInfo.rv)) 164 default: 165 runInfo.rv = reflect.ValueOf(toInt64(lhsV) - toInt64(runInfo.rv)) 166 } 167 168 case "|": 169 runInfo.rv = reflect.ValueOf(toInt64(lhsV) | toInt64(runInfo.rv)) 170 default: 171 runInfo.err = newStringError(operator, "unknown operator") 172 runInfo.rv = nilValue 173 } 174 175 // MultiplyOperator 176 case *ast.MultiplyOperator: 177 runInfo.expr = operator.LHS 178 runInfo.invokeExpr() 179 if runInfo.err != nil { 180 return 181 } 182 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 183 runInfo.rv = runInfo.rv.Elem() 184 } 185 lhsV := runInfo.rv 186 187 runInfo.expr = operator.RHS 188 runInfo.invokeExpr() 189 if runInfo.err != nil { 190 return 191 } 192 if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() { 193 runInfo.rv = runInfo.rv.Elem() 194 } 195 196 switch operator.Operator { 197 case "*": 198 if lhsV.Kind() == reflect.String && (runInfo.rv.Kind() == reflect.Int || runInfo.rv.Kind() == reflect.Int32 || runInfo.rv.Kind() == reflect.Int64) { 199 runInfo.rv = reflect.ValueOf(strings.Repeat(toString(lhsV), int(toInt64(runInfo.rv)))) 200 return 201 } 202 if lhsV.Kind() == reflect.Float64 || runInfo.rv.Kind() == reflect.Float64 { 203 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) * toFloat64(runInfo.rv)) 204 return 205 } 206 runInfo.rv = reflect.ValueOf(toInt64(lhsV) * toInt64(runInfo.rv)) 207 case "/": 208 runInfo.rv = reflect.ValueOf(toFloat64(lhsV) / toFloat64(runInfo.rv)) 209 case "%": 210 runInfo.rv = reflect.ValueOf(toInt64(lhsV) % toInt64(runInfo.rv)) 211 case ">>": 212 runInfo.rv = reflect.ValueOf(toInt64(lhsV) >> uint64(toInt64(runInfo.rv))) 213 case "<<": 214 runInfo.rv = reflect.ValueOf(toInt64(lhsV) << uint64(toInt64(runInfo.rv))) 215 case "&": 216 runInfo.rv = reflect.ValueOf(toInt64(lhsV) & toInt64(runInfo.rv)) 217 218 default: 219 runInfo.err = newStringError(operator, "unknown operator") 220 runInfo.rv = nilValue 221 } 222 223 default: 224 runInfo.err = newStringError(operator, "unknown operator") 225 runInfo.rv = nilValue 226 227 } 228 }