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  }