123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772 |
- package vm
- import (
- "reflect"
- "github.com/mattn/anko/ast"
- "github.com/mattn/anko/env"
- )
- // invokeExpr evaluates one expression.
- func (runInfo *runInfoStruct) invokeExpr() {
- switch expr := runInfo.expr.(type) {
- // OpExpr
- case *ast.OpExpr:
- runInfo.operator = expr.Op
- runInfo.invokeOperator()
- // IdentExpr
- case *ast.IdentExpr:
- runInfo.rv, runInfo.err = runInfo.env.GetValue(expr.Lit)
- if runInfo.err != nil {
- runInfo.err = newError(expr, runInfo.err)
- }
- // LiteralExpr
- case *ast.LiteralExpr:
- runInfo.rv = expr.Literal
- // ArrayExpr
- case *ast.ArrayExpr:
- if expr.TypeData == nil {
- slice := make([]interface{}, len(expr.Exprs))
- var i int
- for i, runInfo.expr = range expr.Exprs {
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- slice[i] = runInfo.rv.Interface()
- }
- runInfo.rv = reflect.ValueOf(slice)
- return
- }
- t := makeType(runInfo, expr.TypeData)
- if runInfo.err != nil {
- runInfo.rv = nilValue
- return
- }
- if t == nil {
- runInfo.err = newStringError(expr, "cannot make type nil")
- runInfo.rv = nilValue
- return
- }
- slice := reflect.MakeSlice(t, len(expr.Exprs), len(expr.Exprs))
- var i int
- valueType := t.Elem()
- for i, runInfo.expr = range expr.Exprs {
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- runInfo.rv, runInfo.err = convertReflectValueToType(runInfo.rv, valueType)
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "cannot use type "+runInfo.rv.Type().String()+" as type "+valueType.String()+" as slice value")
- runInfo.rv = nilValue
- return
- }
- slice.Index(i).Set(runInfo.rv)
- }
- runInfo.rv = slice
- // MapExpr
- case *ast.MapExpr:
- if expr.TypeData == nil {
- var i int
- var key reflect.Value
- m := make(map[interface{}]interface{}, len(expr.Keys))
- for i, runInfo.expr = range expr.Keys {
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- key = runInfo.rv
- runInfo.expr = expr.Values[i]
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- m[key.Interface()] = runInfo.rv.Interface()
- }
- runInfo.rv = reflect.ValueOf(m)
- return
- }
- t := makeType(runInfo, expr.TypeData)
- if runInfo.err != nil {
- runInfo.rv = nilValue
- return
- }
- if t == nil {
- runInfo.err = newStringError(expr, "cannot make type nil")
- runInfo.rv = nilValue
- return
- }
- runInfo.rv, runInfo.err = makeValue(t)
- if runInfo.err != nil {
- runInfo.rv = nilValue
- return
- }
- var i int
- var key reflect.Value
- m := runInfo.rv
- keyType := t.Key()
- valueType := t.Elem()
- for i, runInfo.expr = range expr.Keys {
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- key, runInfo.err = convertReflectValueToType(runInfo.rv, keyType)
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "cannot use type "+key.Type().String()+" as type "+keyType.String()+" as map key")
- runInfo.rv = nilValue
- return
- }
- runInfo.expr = expr.Values[i]
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- runInfo.rv, runInfo.err = convertReflectValueToType(runInfo.rv, valueType)
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "cannot use type "+runInfo.rv.Type().String()+" as type "+valueType.String()+" as map value")
- runInfo.rv = nilValue
- return
- }
- m.SetMapIndex(key, runInfo.rv)
- }
- runInfo.rv = m
- // DerefExpr
- case *ast.DerefExpr:
- runInfo.expr = expr.Expr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.Kind() != reflect.Ptr {
- runInfo.err = newStringError(expr.Expr, "cannot deference non-pointer")
- runInfo.rv = nilValue
- return
- }
- runInfo.rv = runInfo.rv.Elem()
- // AddrExpr
- case *ast.AddrExpr:
- runInfo.expr = expr.Expr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.CanAddr() {
- runInfo.rv = runInfo.rv.Addr()
- } else {
- i := runInfo.rv.Interface()
- runInfo.rv = reflect.ValueOf(&i)
- }
- // UnaryExpr
- case *ast.UnaryExpr:
- runInfo.expr = expr.Expr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- switch expr.Operator {
- case "-":
- switch runInfo.rv.Kind() {
- case reflect.Int64:
- runInfo.rv = reflect.ValueOf(-runInfo.rv.Int())
- case reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int, reflect.Bool:
- runInfo.rv = reflect.ValueOf(-toInt64(runInfo.rv))
- case reflect.Float64:
- runInfo.rv = reflect.ValueOf(-runInfo.rv.Float())
- default:
- runInfo.rv = reflect.ValueOf(-toFloat64(runInfo.rv))
- }
- case "^":
- runInfo.rv = reflect.ValueOf(^toInt64(runInfo.rv))
- case "!":
- if toBool(runInfo.rv) {
- runInfo.rv = falseValue
- } else {
- runInfo.rv = trueValue
- }
- default:
- runInfo.err = newStringError(expr, "unknown operator")
- runInfo.rv = nilValue
- }
- // ParenExpr
- case *ast.ParenExpr:
- runInfo.expr = expr.SubExpr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- // MemberExpr
- case *ast.MemberExpr:
- runInfo.expr = expr.Expr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
- runInfo.rv = runInfo.rv.Elem()
- }
- if env, ok := runInfo.rv.Interface().(*env.Env); ok {
- runInfo.rv, runInfo.err = env.GetValue(expr.Name)
- if runInfo.err != nil {
- runInfo.err = newError(expr, runInfo.err)
- runInfo.rv = nilValue
- }
- return
- }
- value := runInfo.rv.MethodByName(expr.Name)
- if value.IsValid() {
- runInfo.rv = value
- return
- }
- if runInfo.rv.Kind() == reflect.Ptr {
- runInfo.rv = runInfo.rv.Elem()
- }
- switch runInfo.rv.Kind() {
- case reflect.Struct:
- field, found := runInfo.rv.Type().FieldByName(expr.Name)
- if found {
- runInfo.rv = runInfo.rv.FieldByIndex(field.Index)
- return
- }
- if runInfo.rv.CanAddr() {
- runInfo.rv = runInfo.rv.Addr()
- method, found := runInfo.rv.Type().MethodByName(expr.Name)
- if found {
- runInfo.rv = runInfo.rv.Method(method.Index)
- return
- }
- } else {
- // Check wether method with pointer receiver is defined,
- // if yes, invoke it in the copied instance
- method, found := reflect.PtrTo(runInfo.rv.Type()).MethodByName(expr.Name)
- if found {
- // Create pointer value to given struct type which were passed by value
- cv := reflect.New(runInfo.rv.Type())
- cv.Elem().Set(runInfo.rv)
- runInfo.rv = cv.Method(method.Index)
- return
- }
- }
- runInfo.err = newStringError(expr, "no member named '"+expr.Name+"' for struct")
- runInfo.rv = nilValue
- case reflect.Map:
- runInfo.rv = getMapIndex(reflect.ValueOf(expr.Name), runInfo.rv)
- default:
- runInfo.err = newStringError(expr, "type "+runInfo.rv.Kind().String()+" does not support member operation")
- runInfo.rv = nilValue
- }
- // ItemExpr
- case *ast.ItemExpr:
- runInfo.expr = expr.Item
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- item := runInfo.rv
- runInfo.expr = expr.Index
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if item.Kind() == reflect.Interface && !item.IsNil() {
- item = item.Elem()
- }
- switch item.Kind() {
- case reflect.String, reflect.Slice, reflect.Array:
- var index int
- index, runInfo.err = tryToInt(runInfo.rv)
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "index must be a number")
- runInfo.rv = nilValue
- return
- }
- if index < 0 || index >= item.Len() {
- runInfo.err = newStringError(expr, "index out of range")
- runInfo.rv = nilValue
- return
- }
- if item.Kind() != reflect.String {
- runInfo.rv = item.Index(index)
- } else {
- // String
- runInfo.rv = item.Index(index).Convert(stringType)
- }
- case reflect.Map:
- runInfo.rv = getMapIndex(runInfo.rv, item)
- default:
- runInfo.err = newStringError(expr, "type "+item.Kind().String()+" does not support index operation")
- runInfo.rv = nilValue
- }
- // SliceExpr
- case *ast.SliceExpr:
- runInfo.expr = expr.Item
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- item := runInfo.rv
- if item.Kind() == reflect.Interface && !item.IsNil() {
- item = item.Elem()
- }
- switch item.Kind() {
- case reflect.String, reflect.Slice, reflect.Array:
- var beginIndex int
- endIndex := item.Len()
- if expr.Begin != nil {
- runInfo.expr = expr.Begin
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- beginIndex, runInfo.err = tryToInt(runInfo.rv)
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "index must be a number")
- runInfo.rv = nilValue
- return
- }
- // (0 <= low) <= high <= len(a)
- if beginIndex < 0 {
- runInfo.err = newStringError(expr, "index out of range")
- runInfo.rv = nilValue
- return
- }
- }
- if expr.End != nil {
- runInfo.expr = expr.End
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- endIndex, runInfo.err = tryToInt(runInfo.rv)
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "index must be a number")
- runInfo.rv = nilValue
- return
- }
- // 0 <= low <= (high <= len(a))
- if endIndex > item.Len() {
- runInfo.err = newStringError(expr, "index out of range")
- runInfo.rv = nilValue
- return
- }
- }
- // 0 <= (low <= high) <= len(a)
- if beginIndex > endIndex {
- runInfo.err = newStringError(expr, "index out of range")
- runInfo.rv = nilValue
- return
- }
- if item.Kind() == reflect.String {
- if expr.Cap != nil {
- runInfo.err = newStringError(expr, "type string does not support cap")
- runInfo.rv = nilValue
- return
- }
- runInfo.rv = item.Slice(beginIndex, endIndex)
- return
- }
- sliceCap := item.Cap()
- if expr.Cap != nil {
- runInfo.expr = expr.Cap
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- sliceCap, runInfo.err = tryToInt(runInfo.rv)
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "cap must be a number")
- runInfo.rv = nilValue
- return
- }
- // 0 <= low <= (high <= max <= cap(a))
- if sliceCap < endIndex || sliceCap > item.Cap() {
- runInfo.err = newStringError(expr, "cap out of range")
- runInfo.rv = nilValue
- return
- }
- }
- runInfo.rv = item.Slice3(beginIndex, endIndex, sliceCap)
- default:
- runInfo.err = newStringError(expr, "type "+item.Kind().String()+" does not support slice operation")
- runInfo.rv = nilValue
- }
- // LetsExpr
- case *ast.LetsExpr:
- var i int
- for i, runInfo.expr = range expr.RHSS {
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
- runInfo.rv = runInfo.rv.Elem()
- }
- if i < len(expr.LHSS) {
- runInfo.expr = expr.LHSS[i]
- runInfo.invokeLetExpr()
- if runInfo.err != nil {
- return
- }
- }
- }
- // TernaryOpExpr
- case *ast.TernaryOpExpr:
- runInfo.expr = expr.Expr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if toBool(runInfo.rv) {
- runInfo.expr = expr.LHS
- } else {
- runInfo.expr = expr.RHS
- }
- runInfo.invokeExpr()
- // NilCoalescingOpExpr
- case *ast.NilCoalescingOpExpr:
- // if left side has no error and is not nil, returns left side
- // otherwise returns right side
- runInfo.expr = expr.LHS
- runInfo.invokeExpr()
- if runInfo.err == nil {
- if !isNil(runInfo.rv) {
- return
- }
- } else {
- runInfo.err = nil
- }
- runInfo.expr = expr.RHS
- runInfo.invokeExpr()
- // LenExpr
- case *ast.LenExpr:
- runInfo.expr = expr.Expr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
- runInfo.rv = runInfo.rv.Elem()
- }
- switch runInfo.rv.Kind() {
- case reflect.Slice, reflect.Array, reflect.Map, reflect.String, reflect.Chan:
- runInfo.rv = reflect.ValueOf(int64(runInfo.rv.Len()))
- default:
- runInfo.err = newStringError(expr, "type "+runInfo.rv.Kind().String()+" does not support len operation")
- runInfo.rv = nilValue
- }
- // ImportExpr
- case *ast.ImportExpr:
- runInfo.expr = expr.Name
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- runInfo.rv, runInfo.err = convertReflectValueToType(runInfo.rv, stringType)
- if runInfo.err != nil {
- runInfo.rv = nilValue
- return
- }
- name := runInfo.rv.String()
- runInfo.rv = nilValue
- methods, ok := env.Packages[name]
- if !ok {
- runInfo.err = newStringError(expr, "package not found: "+name)
- return
- }
- var err error
- pack := runInfo.env.NewEnv()
- for methodName, methodValue := range methods {
- err = pack.DefineValue(methodName, methodValue)
- if err != nil {
- runInfo.err = newStringError(expr, "import DefineValue error: "+err.Error())
- return
- }
- }
- types, ok := env.PackageTypes[name]
- if ok {
- for typeName, typeValue := range types {
- err = pack.DefineReflectType(typeName, typeValue)
- if err != nil {
- runInfo.err = newStringError(expr, "import DefineReflectType error: "+err.Error())
- return
- }
- }
- }
- runInfo.rv = reflect.ValueOf(pack)
- // MakeExpr
- case *ast.MakeExpr:
- t := makeType(runInfo, expr.TypeData)
- if runInfo.err != nil {
- runInfo.rv = nilValue
- return
- }
- if t == nil {
- runInfo.err = newStringError(expr, "cannot make type nil")
- runInfo.rv = nilValue
- return
- }
- switch expr.TypeData.Kind {
- case ast.TypeSlice:
- aLen := 0
- if expr.LenExpr != nil {
- runInfo.expr = expr.LenExpr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- aLen = toInt(runInfo.rv)
- }
- cap := aLen
- if expr.CapExpr != nil {
- runInfo.expr = expr.CapExpr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- cap = toInt(runInfo.rv)
- }
- if aLen > cap {
- runInfo.err = newStringError(expr, "make slice len > cap")
- runInfo.rv = nilValue
- return
- }
- runInfo.rv = reflect.MakeSlice(t, aLen, cap)
- return
- case ast.TypeChan:
- aLen := 0
- if expr.LenExpr != nil {
- runInfo.expr = expr.LenExpr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- aLen = toInt(runInfo.rv)
- }
- runInfo.rv = reflect.MakeChan(t, aLen)
- return
- }
- runInfo.rv, runInfo.err = makeValue(t)
- // MakeTypeExpr
- case *ast.MakeTypeExpr:
- runInfo.expr = expr.Type
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- // if expr.Name has a dot in it, it should give a syntax error, so no needs to check err
- runInfo.env.DefineReflectType(expr.Name, runInfo.rv.Type())
- runInfo.rv = reflect.ValueOf(runInfo.rv.Type())
- // ChanExpr
- case *ast.ChanExpr:
- runInfo.expr = expr.RHS
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
- runInfo.rv = runInfo.rv.Elem()
- }
- var lhs reflect.Value
- rhs := runInfo.rv
- if expr.LHS == nil {
- // lhs is nil
- if rhs.Kind() != reflect.Chan {
- // rhs is not channel
- runInfo.err = newStringError(expr, "receive from non-chan type "+rhs.Kind().String())
- runInfo.rv = nilValue
- return
- }
- } else {
- // lhs is not nil
- runInfo.expr = expr.LHS
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
- runInfo.rv = runInfo.rv.Elem()
- }
- if runInfo.rv.Kind() != reflect.Chan {
- // lhs is not channel
- // lhs <- chan rhs or lhs <- rhs
- runInfo.err = newStringError(expr, "send to non-chan type "+runInfo.rv.Kind().String())
- runInfo.rv = nilValue
- return
- }
- lhs = runInfo.rv
- }
- var chosen int
- var ok bool
- if rhs.Kind() == reflect.Chan {
- // rhs is channel
- // receive from rhs channel
- cases := []reflect.SelectCase{{
- Dir: reflect.SelectRecv,
- Chan: reflect.ValueOf(runInfo.ctx.Done()),
- }, {
- Dir: reflect.SelectRecv,
- Chan: rhs,
- }}
- chosen, runInfo.rv, ok = reflect.Select(cases)
- if chosen == 0 {
- runInfo.err = ErrInterrupt
- runInfo.rv = nilValue
- return
- }
- if !ok {
- runInfo.rv = nilValue
- return
- }
- rhs = runInfo.rv
- }
- if expr.LHS == nil {
- // <- chan rhs is receive
- return
- }
- // chan lhs <- chan rhs is receive & send
- // or
- // chan lhs <- rhs is send
- runInfo.rv = nilValue
- rhs, runInfo.err = convertReflectValueToType(rhs, lhs.Type().Elem())
- if runInfo.err != nil {
- runInfo.err = newStringError(expr, "cannot use type "+rhs.Type().String()+" as type "+lhs.Type().Elem().String()+" to send to chan")
- return
- }
- // send rhs to lhs channel
- cases := []reflect.SelectCase{{
- Dir: reflect.SelectRecv,
- Chan: reflect.ValueOf(runInfo.ctx.Done()),
- }, {
- Dir: reflect.SelectSend,
- Chan: lhs,
- Send: rhs,
- }}
- if !runInfo.options.Debug {
- // captures panic
- defer recoverFunc(runInfo)
- }
- chosen, _, _ = reflect.Select(cases)
- if chosen == 0 {
- runInfo.err = ErrInterrupt
- }
- // FuncExpr
- case *ast.FuncExpr:
- runInfo.expr = expr
- runInfo.funcExpr()
- // AnonCallExpr
- case *ast.AnonCallExpr:
- runInfo.expr = expr
- runInfo.anonCallExpr()
- // CallExpr
- case *ast.CallExpr:
- runInfo.expr = expr
- runInfo.callExpr()
- // IncludeExpr
- case *ast.IncludeExpr:
- runInfo.expr = expr.ItemExpr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- itemExpr := runInfo.rv
- runInfo.expr = expr.ListExpr
- runInfo.invokeExpr()
- if runInfo.err != nil {
- return
- }
- if runInfo.rv.Kind() != reflect.Slice && runInfo.rv.Kind() != reflect.Array {
- runInfo.err = newStringError(expr, "second argument must be slice or array; but have "+runInfo.rv.Kind().String())
- runInfo.rv = nilValue
- return
- }
- for i := 0; i < runInfo.rv.Len(); i++ {
- if equal(itemExpr, runInfo.rv.Index(i)) {
- runInfo.rv = trueValue
- return
- }
- }
- runInfo.rv = falseValue
- default:
- runInfo.err = newStringError(expr, "unknown expression")
- runInfo.rv = nilValue
- }
- }
|