github.com/mattn/anko@v0.1.10/vm/vmStmt.go (about)

     1  package vm
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  
     8  	"github.com/mattn/anko/ast"
     9  	"github.com/mattn/anko/env"
    10  	"github.com/mattn/anko/parser"
    11  )
    12  
    13  // Execute parses script and executes in the specified environment.
    14  func Execute(env *env.Env, options *Options, script string) (interface{}, error) {
    15  	stmt, err := parser.ParseSrc(script)
    16  	if err != nil {
    17  		return nilValue, err
    18  	}
    19  
    20  	return RunContext(context.Background(), env, options, stmt)
    21  }
    22  
    23  // ExecuteContext parses script and executes in the specified environment with context.
    24  func ExecuteContext(ctx context.Context, env *env.Env, options *Options, script string) (interface{}, error) {
    25  	stmt, err := parser.ParseSrc(script)
    26  	if err != nil {
    27  		return nilValue, err
    28  	}
    29  
    30  	return RunContext(ctx, env, options, stmt)
    31  }
    32  
    33  // Run executes statement in the specified environment.
    34  func Run(env *env.Env, options *Options, stmt ast.Stmt) (interface{}, error) {
    35  	return RunContext(context.Background(), env, options, stmt)
    36  }
    37  
    38  // RunContext executes statement in the specified environment with context.
    39  func RunContext(ctx context.Context, env *env.Env, options *Options, stmt ast.Stmt) (interface{}, error) {
    40  	runInfo := runInfoStruct{ctx: ctx, env: env, options: options, stmt: stmt, rv: nilValue}
    41  	if runInfo.options == nil {
    42  		runInfo.options = &Options{}
    43  	}
    44  	runInfo.runSingleStmt()
    45  	if runInfo.err == ErrReturn {
    46  		runInfo.err = nil
    47  	}
    48  	return runInfo.rv.Interface(), runInfo.err
    49  }
    50  
    51  // runSingleStmt executes statement in the specified environment with context.
    52  func (runInfo *runInfoStruct) runSingleStmt() {
    53  	select {
    54  	case <-runInfo.ctx.Done():
    55  		runInfo.rv = nilValue
    56  		runInfo.err = ErrInterrupt
    57  		return
    58  	default:
    59  	}
    60  
    61  	switch stmt := runInfo.stmt.(type) {
    62  
    63  	// nil
    64  	case nil:
    65  
    66  	// StmtsStmt
    67  	case *ast.StmtsStmt:
    68  		for _, stmt := range stmt.Stmts {
    69  			switch stmt.(type) {
    70  			case *ast.BreakStmt:
    71  				runInfo.err = ErrBreak
    72  				return
    73  			case *ast.ContinueStmt:
    74  				runInfo.err = ErrContinue
    75  				return
    76  			case *ast.ReturnStmt:
    77  				runInfo.stmt = stmt
    78  				runInfo.runSingleStmt()
    79  				if runInfo.err != nil {
    80  					return
    81  				}
    82  				runInfo.err = ErrReturn
    83  				return
    84  			default:
    85  				runInfo.stmt = stmt
    86  				runInfo.runSingleStmt()
    87  				if runInfo.err != nil {
    88  					return
    89  				}
    90  			}
    91  		}
    92  
    93  	// ExprStmt
    94  	case *ast.ExprStmt:
    95  		runInfo.expr = stmt.Expr
    96  		runInfo.invokeExpr()
    97  
    98  	// VarStmt
    99  	case *ast.VarStmt:
   100  		// get right side expression values
   101  		rvs := make([]reflect.Value, len(stmt.Exprs))
   102  		var i int
   103  		for i, runInfo.expr = range stmt.Exprs {
   104  			runInfo.invokeExpr()
   105  			if runInfo.err != nil {
   106  				return
   107  			}
   108  			if env, ok := runInfo.rv.Interface().(*env.Env); ok {
   109  				rvs[i] = reflect.ValueOf(env.DeepCopy())
   110  			} else {
   111  				rvs[i] = runInfo.rv
   112  			}
   113  		}
   114  
   115  		if len(rvs) == 1 && len(stmt.Names) > 1 {
   116  			// only one right side value but many left side names
   117  			value := rvs[0]
   118  			if value.Kind() == reflect.Interface && !value.IsNil() {
   119  				value = value.Elem()
   120  			}
   121  			if (value.Kind() == reflect.Slice || value.Kind() == reflect.Array) && value.Len() > 0 {
   122  				// value is slice/array, add each value to left side names
   123  				for i := 0; i < value.Len() && i < len(stmt.Names); i++ {
   124  					runInfo.env.DefineValue(stmt.Names[i], value.Index(i))
   125  				}
   126  				// return last value of slice/array
   127  				runInfo.rv = value.Index(value.Len() - 1)
   128  				return
   129  			}
   130  		}
   131  
   132  		// define all names with right side values
   133  		for i = 0; i < len(rvs) && i < len(stmt.Names); i++ {
   134  			runInfo.env.DefineValue(stmt.Names[i], rvs[i])
   135  		}
   136  
   137  		// return last right side value
   138  		runInfo.rv = rvs[len(rvs)-1]
   139  
   140  	// LetsStmt
   141  	case *ast.LetsStmt:
   142  		// get right side expression values
   143  		rvs := make([]reflect.Value, len(stmt.RHSS))
   144  		var i int
   145  		for i, runInfo.expr = range stmt.RHSS {
   146  			runInfo.invokeExpr()
   147  			if runInfo.err != nil {
   148  				return
   149  			}
   150  			if env, ok := runInfo.rv.Interface().(*env.Env); ok {
   151  				rvs[i] = reflect.ValueOf(env.DeepCopy())
   152  			} else {
   153  				rvs[i] = runInfo.rv
   154  			}
   155  		}
   156  
   157  		if len(rvs) == 1 && len(stmt.LHSS) > 1 {
   158  			// only one right side value but many left side expressions
   159  			value := rvs[0]
   160  			if value.Kind() == reflect.Interface && !value.IsNil() {
   161  				value = value.Elem()
   162  			}
   163  			if (value.Kind() == reflect.Slice || value.Kind() == reflect.Array) && value.Len() > 0 {
   164  				// value is slice/array, add each value to left side expression
   165  				for i := 0; i < value.Len() && i < len(stmt.LHSS); i++ {
   166  					runInfo.rv = value.Index(i)
   167  					runInfo.expr = stmt.LHSS[i]
   168  					runInfo.invokeLetExpr()
   169  					if runInfo.err != nil {
   170  						return
   171  					}
   172  				}
   173  				// return last value of slice/array
   174  				runInfo.rv = value.Index(value.Len() - 1)
   175  				return
   176  			}
   177  		}
   178  
   179  		// invoke all left side expressions with right side values
   180  		for i = 0; i < len(rvs) && i < len(stmt.LHSS); i++ {
   181  			value := rvs[i]
   182  			if value.Kind() == reflect.Interface && !value.IsNil() {
   183  				value = value.Elem()
   184  			}
   185  			runInfo.rv = value
   186  			runInfo.expr = stmt.LHSS[i]
   187  			runInfo.invokeLetExpr()
   188  			if runInfo.err != nil {
   189  				return
   190  			}
   191  		}
   192  
   193  		// return last right side value
   194  		runInfo.rv = rvs[len(rvs)-1]
   195  
   196  	// LetMapItemStmt
   197  	case *ast.LetMapItemStmt:
   198  		runInfo.expr = stmt.RHS
   199  		runInfo.invokeExpr()
   200  		if runInfo.err != nil {
   201  			return
   202  		}
   203  		var rvs []reflect.Value
   204  		if isNil(runInfo.rv) {
   205  			rvs = []reflect.Value{nilValue, falseValue}
   206  		} else {
   207  			rvs = []reflect.Value{runInfo.rv, trueValue}
   208  		}
   209  		var i int
   210  		for i, runInfo.expr = range stmt.LHSS {
   211  			runInfo.rv = rvs[i]
   212  			if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
   213  				runInfo.rv = runInfo.rv.Elem()
   214  			}
   215  			runInfo.invokeLetExpr()
   216  			if runInfo.err != nil {
   217  				return
   218  			}
   219  		}
   220  		runInfo.rv = rvs[0]
   221  
   222  	// IfStmt
   223  	case *ast.IfStmt:
   224  		// if
   225  		runInfo.expr = stmt.If
   226  		runInfo.invokeExpr()
   227  		if runInfo.err != nil {
   228  			return
   229  		}
   230  
   231  		env := runInfo.env
   232  
   233  		if toBool(runInfo.rv) {
   234  			// then
   235  			runInfo.rv = nilValue
   236  			runInfo.stmt = stmt.Then
   237  			runInfo.env = env.NewEnv()
   238  			runInfo.runSingleStmt()
   239  			runInfo.env = env
   240  			return
   241  		}
   242  
   243  		for _, statement := range stmt.ElseIf {
   244  			elseIf := statement.(*ast.IfStmt)
   245  
   246  			// else if - if
   247  			runInfo.env = env.NewEnv()
   248  			runInfo.expr = elseIf.If
   249  			runInfo.invokeExpr()
   250  			if runInfo.err != nil {
   251  				runInfo.env = env
   252  				return
   253  			}
   254  
   255  			if !toBool(runInfo.rv) {
   256  				continue
   257  			}
   258  
   259  			// else if - then
   260  			runInfo.rv = nilValue
   261  			runInfo.stmt = elseIf.Then
   262  			runInfo.env = env.NewEnv()
   263  			runInfo.runSingleStmt()
   264  			runInfo.env = env
   265  			return
   266  		}
   267  
   268  		if stmt.Else != nil {
   269  			// else
   270  			runInfo.rv = nilValue
   271  			runInfo.stmt = stmt.Else
   272  			runInfo.env = env.NewEnv()
   273  			runInfo.runSingleStmt()
   274  		}
   275  
   276  		runInfo.env = env
   277  
   278  	// TryStmt
   279  	case *ast.TryStmt:
   280  		// only the try statement will ignore any error except ErrInterrupt
   281  		// all other parts will return the error
   282  
   283  		env := runInfo.env
   284  		runInfo.env = env.NewEnv()
   285  
   286  		runInfo.stmt = stmt.Try
   287  		runInfo.runSingleStmt()
   288  
   289  		if runInfo.err != nil {
   290  			if runInfo.err == ErrInterrupt {
   291  				runInfo.env = env
   292  				return
   293  			}
   294  
   295  			// Catch
   296  			runInfo.stmt = stmt.Catch
   297  			if stmt.Var != "" {
   298  				runInfo.env.DefineValue(stmt.Var, reflect.ValueOf(runInfo.err))
   299  			}
   300  			runInfo.err = nil
   301  			runInfo.runSingleStmt()
   302  			if runInfo.err != nil {
   303  				runInfo.env = env
   304  				return
   305  			}
   306  		}
   307  
   308  		if stmt.Finally != nil {
   309  			// Finally
   310  			runInfo.stmt = stmt.Finally
   311  			runInfo.runSingleStmt()
   312  		}
   313  
   314  		runInfo.env = env
   315  
   316  	// LoopStmt
   317  	case *ast.LoopStmt:
   318  		env := runInfo.env
   319  		runInfo.env = env.NewEnv()
   320  
   321  		for {
   322  			select {
   323  			case <-runInfo.ctx.Done():
   324  				runInfo.err = ErrInterrupt
   325  				runInfo.rv = nilValue
   326  				runInfo.env = env
   327  				return
   328  			default:
   329  			}
   330  
   331  			if stmt.Expr != nil {
   332  				runInfo.expr = stmt.Expr
   333  				runInfo.invokeExpr()
   334  				if runInfo.err != nil {
   335  					break
   336  				}
   337  				if !toBool(runInfo.rv) {
   338  					break
   339  				}
   340  			}
   341  
   342  			runInfo.stmt = stmt.Stmt
   343  			runInfo.runSingleStmt()
   344  			if runInfo.err != nil {
   345  				if runInfo.err == ErrContinue {
   346  					runInfo.err = nil
   347  					continue
   348  				}
   349  				if runInfo.err == ErrReturn {
   350  					runInfo.env = env
   351  					return
   352  				}
   353  				if runInfo.err == ErrBreak {
   354  					runInfo.err = nil
   355  				}
   356  				break
   357  			}
   358  		}
   359  
   360  		runInfo.rv = nilValue
   361  		runInfo.env = env
   362  
   363  	// ForStmt
   364  	case *ast.ForStmt:
   365  		runInfo.expr = stmt.Value
   366  		runInfo.invokeExpr()
   367  		value := runInfo.rv
   368  		if runInfo.err != nil {
   369  			return
   370  		}
   371  		if value.Kind() == reflect.Interface && !value.IsNil() {
   372  			value = value.Elem()
   373  		}
   374  
   375  		env := runInfo.env
   376  		runInfo.env = env.NewEnv()
   377  
   378  		switch value.Kind() {
   379  		case reflect.Slice, reflect.Array:
   380  			for i := 0; i < value.Len(); i++ {
   381  				select {
   382  				case <-runInfo.ctx.Done():
   383  					runInfo.err = ErrInterrupt
   384  					runInfo.rv = nilValue
   385  					runInfo.env = env
   386  					return
   387  				default:
   388  				}
   389  
   390  				iv := value.Index(i)
   391  				if iv.Kind() == reflect.Interface && !iv.IsNil() {
   392  					iv = iv.Elem()
   393  				}
   394  				if iv.Kind() == reflect.Ptr {
   395  					iv = iv.Elem()
   396  				}
   397  				runInfo.env.DefineValue(stmt.Vars[0], iv)
   398  
   399  				runInfo.stmt = stmt.Stmt
   400  				runInfo.runSingleStmt()
   401  				if runInfo.err != nil {
   402  					if runInfo.err == ErrContinue {
   403  						runInfo.err = nil
   404  						continue
   405  					}
   406  					if runInfo.err == ErrReturn {
   407  						runInfo.env = env
   408  						return
   409  					}
   410  					if runInfo.err == ErrBreak {
   411  						runInfo.err = nil
   412  					}
   413  					break
   414  				}
   415  			}
   416  			runInfo.rv = nilValue
   417  			runInfo.env = env
   418  
   419  		case reflect.Map:
   420  			keys := value.MapKeys()
   421  			for i := 0; i < len(keys); i++ {
   422  				select {
   423  				case <-runInfo.ctx.Done():
   424  					runInfo.err = ErrInterrupt
   425  					runInfo.rv = nilValue
   426  					runInfo.env = env
   427  					return
   428  				default:
   429  				}
   430  
   431  				runInfo.env.DefineValue(stmt.Vars[0], keys[i])
   432  
   433  				if len(stmt.Vars) > 1 {
   434  					runInfo.env.DefineValue(stmt.Vars[1], value.MapIndex(keys[i]))
   435  				}
   436  
   437  				runInfo.stmt = stmt.Stmt
   438  				runInfo.runSingleStmt()
   439  				if runInfo.err != nil {
   440  					if runInfo.err == ErrContinue {
   441  						runInfo.err = nil
   442  						continue
   443  					}
   444  					if runInfo.err == ErrReturn {
   445  						runInfo.env = env
   446  						return
   447  					}
   448  					if runInfo.err == ErrBreak {
   449  						runInfo.err = nil
   450  					}
   451  					break
   452  				}
   453  			}
   454  			runInfo.rv = nilValue
   455  			runInfo.env = env
   456  
   457  		case reflect.Chan:
   458  			var chosen int
   459  			var ok bool
   460  			for {
   461  				cases := []reflect.SelectCase{{
   462  					Dir:  reflect.SelectRecv,
   463  					Chan: reflect.ValueOf(runInfo.ctx.Done()),
   464  				}, {
   465  					Dir:  reflect.SelectRecv,
   466  					Chan: value,
   467  				}}
   468  				chosen, runInfo.rv, ok = reflect.Select(cases)
   469  				if chosen == 0 {
   470  					runInfo.err = ErrInterrupt
   471  					runInfo.rv = nilValue
   472  					break
   473  				}
   474  				if !ok {
   475  					break
   476  				}
   477  
   478  				if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
   479  					runInfo.rv = runInfo.rv.Elem()
   480  				}
   481  				if runInfo.rv.Kind() == reflect.Ptr {
   482  					runInfo.rv = runInfo.rv.Elem()
   483  				}
   484  
   485  				runInfo.env.DefineValue(stmt.Vars[0], runInfo.rv)
   486  
   487  				runInfo.stmt = stmt.Stmt
   488  				runInfo.runSingleStmt()
   489  				if runInfo.err != nil {
   490  					if runInfo.err == ErrContinue {
   491  						runInfo.err = nil
   492  						continue
   493  					}
   494  					if runInfo.err == ErrReturn {
   495  						runInfo.env = env
   496  						return
   497  					}
   498  					if runInfo.err == ErrBreak {
   499  						runInfo.err = nil
   500  					}
   501  					break
   502  				}
   503  			}
   504  			runInfo.rv = nilValue
   505  			runInfo.env = env
   506  
   507  		default:
   508  			runInfo.err = newStringError(stmt, "for cannot loop over type "+value.Kind().String())
   509  			runInfo.rv = nilValue
   510  			runInfo.env = env
   511  		}
   512  
   513  	// CForStmt
   514  	case *ast.CForStmt:
   515  		env := runInfo.env
   516  		runInfo.env = env.NewEnv()
   517  
   518  		if stmt.Stmt1 != nil {
   519  			runInfo.stmt = stmt.Stmt1
   520  			runInfo.runSingleStmt()
   521  			if runInfo.err != nil {
   522  				runInfo.env = env
   523  				return
   524  			}
   525  		}
   526  
   527  		for {
   528  			select {
   529  			case <-runInfo.ctx.Done():
   530  				runInfo.err = ErrInterrupt
   531  				runInfo.rv = nilValue
   532  				runInfo.env = env
   533  				return
   534  			default:
   535  			}
   536  
   537  			if stmt.Expr2 != nil {
   538  				runInfo.expr = stmt.Expr2
   539  				runInfo.invokeExpr()
   540  				if runInfo.err != nil {
   541  					break
   542  				}
   543  				if !toBool(runInfo.rv) {
   544  					break
   545  				}
   546  			}
   547  
   548  			runInfo.stmt = stmt.Stmt
   549  			runInfo.runSingleStmt()
   550  			if runInfo.err == ErrContinue {
   551  				runInfo.err = nil
   552  			}
   553  			if runInfo.err != nil {
   554  				if runInfo.err == ErrReturn {
   555  					runInfo.env = env
   556  					return
   557  				}
   558  				if runInfo.err == ErrBreak {
   559  					runInfo.err = nil
   560  				}
   561  				break
   562  			}
   563  
   564  			if stmt.Expr3 != nil {
   565  				runInfo.expr = stmt.Expr3
   566  				runInfo.invokeExpr()
   567  				if runInfo.err != nil {
   568  					break
   569  				}
   570  			}
   571  		}
   572  		runInfo.rv = nilValue
   573  		runInfo.env = env
   574  
   575  	// ReturnStmt
   576  	case *ast.ReturnStmt:
   577  		switch len(stmt.Exprs) {
   578  		case 0:
   579  			runInfo.rv = nilValue
   580  			return
   581  		case 1:
   582  			runInfo.expr = stmt.Exprs[0]
   583  			runInfo.invokeExpr()
   584  			return
   585  		}
   586  		rvs := make([]interface{}, len(stmt.Exprs))
   587  		var i int
   588  		for i, runInfo.expr = range stmt.Exprs {
   589  			runInfo.invokeExpr()
   590  			if runInfo.err != nil {
   591  				return
   592  			}
   593  			rvs[i] = runInfo.rv.Interface()
   594  		}
   595  		runInfo.rv = reflect.ValueOf(rvs)
   596  
   597  	// ThrowStmt
   598  	case *ast.ThrowStmt:
   599  		runInfo.expr = stmt.Expr
   600  		runInfo.invokeExpr()
   601  		if runInfo.err != nil {
   602  			return
   603  		}
   604  		runInfo.err = newStringError(stmt, fmt.Sprint(runInfo.rv.Interface()))
   605  
   606  	// ModuleStmt
   607  	case *ast.ModuleStmt:
   608  		e := runInfo.env
   609  		runInfo.env, runInfo.err = e.NewModule(stmt.Name)
   610  		if runInfo.err != nil {
   611  			return
   612  		}
   613  		runInfo.stmt = stmt.Stmt
   614  		runInfo.runSingleStmt()
   615  		runInfo.env = e
   616  		if runInfo.err != nil {
   617  			return
   618  		}
   619  		runInfo.rv = nilValue
   620  
   621  	// SwitchStmt
   622  	case *ast.SwitchStmt:
   623  		env := runInfo.env
   624  		runInfo.env = env.NewEnv()
   625  
   626  		runInfo.expr = stmt.Expr
   627  		runInfo.invokeExpr()
   628  		if runInfo.err != nil {
   629  			runInfo.env = env
   630  			return
   631  		}
   632  		value := runInfo.rv
   633  
   634  		for _, switchCaseStmt := range stmt.Cases {
   635  			caseStmt := switchCaseStmt.(*ast.SwitchCaseStmt)
   636  			for _, runInfo.expr = range caseStmt.Exprs {
   637  				runInfo.invokeExpr()
   638  				if runInfo.err != nil {
   639  					runInfo.env = env
   640  					return
   641  				}
   642  				if equal(runInfo.rv, value) {
   643  					runInfo.stmt = caseStmt.Stmt
   644  					runInfo.runSingleStmt()
   645  					runInfo.env = env
   646  					return
   647  				}
   648  			}
   649  		}
   650  
   651  		if stmt.Default == nil {
   652  			runInfo.rv = nilValue
   653  		} else {
   654  			runInfo.stmt = stmt.Default
   655  			runInfo.runSingleStmt()
   656  		}
   657  
   658  		runInfo.env = env
   659  
   660  	// GoroutineStmt
   661  	case *ast.GoroutineStmt:
   662  		runInfo.expr = stmt.Expr
   663  		runInfo.invokeExpr()
   664  
   665  	// DeleteStmt
   666  	case *ast.DeleteStmt:
   667  		runInfo.expr = stmt.Item
   668  		runInfo.invokeExpr()
   669  		if runInfo.err != nil {
   670  			return
   671  		}
   672  		item := runInfo.rv
   673  
   674  		if stmt.Key != nil {
   675  			runInfo.expr = stmt.Key
   676  			runInfo.invokeExpr()
   677  			if runInfo.err != nil {
   678  				return
   679  			}
   680  		}
   681  
   682  		if item.Kind() == reflect.Interface && !item.IsNil() {
   683  			item = item.Elem()
   684  		}
   685  
   686  		switch item.Kind() {
   687  		case reflect.String:
   688  			if stmt.Key != nil && runInfo.rv.Kind() == reflect.Bool && runInfo.rv.Bool() {
   689  				runInfo.env.DeleteGlobal(item.String())
   690  				runInfo.rv = nilValue
   691  				return
   692  			}
   693  			runInfo.env.Delete(item.String())
   694  			runInfo.rv = nilValue
   695  
   696  		case reflect.Map:
   697  			if stmt.Key == nil {
   698  				runInfo.err = newStringError(stmt, "second argument to delete cannot be nil for map")
   699  				runInfo.rv = nilValue
   700  				return
   701  			}
   702  			if item.IsNil() {
   703  				runInfo.rv = nilValue
   704  				return
   705  			}
   706  			runInfo.rv, runInfo.err = convertReflectValueToType(runInfo.rv, item.Type().Key())
   707  			if runInfo.err != nil {
   708  				runInfo.err = newStringError(stmt, "cannot use type "+item.Type().Key().String()+" as type "+runInfo.rv.Type().String()+" in delete")
   709  				runInfo.rv = nilValue
   710  				return
   711  			}
   712  			item.SetMapIndex(runInfo.rv, reflect.Value{})
   713  			runInfo.rv = nilValue
   714  		default:
   715  			runInfo.err = newStringError(stmt, "first argument to delete cannot be type "+item.Kind().String())
   716  			runInfo.rv = nilValue
   717  		}
   718  
   719  	// CloseStmt
   720  	case *ast.CloseStmt:
   721  		runInfo.expr = stmt.Expr
   722  		runInfo.invokeExpr()
   723  		if runInfo.err != nil {
   724  			return
   725  		}
   726  		if runInfo.rv.Kind() == reflect.Chan {
   727  			runInfo.rv.Close()
   728  			runInfo.rv = nilValue
   729  			return
   730  		}
   731  		runInfo.err = newStringError(stmt, "type cannot be "+runInfo.rv.Kind().String()+" for close")
   732  		runInfo.rv = nilValue
   733  
   734  	// ChanStmt
   735  	case *ast.ChanStmt:
   736  		runInfo.expr = stmt.RHS
   737  		runInfo.invokeExpr()
   738  		if runInfo.err != nil {
   739  			return
   740  		}
   741  		if runInfo.rv.Kind() == reflect.Interface && !runInfo.rv.IsNil() {
   742  			runInfo.rv = runInfo.rv.Elem()
   743  		}
   744  
   745  		if runInfo.rv.Kind() != reflect.Chan {
   746  			// rhs is not channel
   747  			runInfo.err = newStringError(stmt, "receive from non-chan type "+runInfo.rv.Kind().String())
   748  			runInfo.rv = nilValue
   749  			return
   750  		}
   751  
   752  		// rhs is channel
   753  		// receive from rhs channel
   754  		rhs := runInfo.rv
   755  		cases := []reflect.SelectCase{{
   756  			Dir:  reflect.SelectRecv,
   757  			Chan: reflect.ValueOf(runInfo.ctx.Done()),
   758  		}, {
   759  			Dir:  reflect.SelectRecv,
   760  			Chan: rhs,
   761  		}}
   762  		var chosen int
   763  		var ok bool
   764  		chosen, runInfo.rv, ok = reflect.Select(cases)
   765  		if chosen == 0 {
   766  			runInfo.err = ErrInterrupt
   767  			runInfo.rv = nilValue
   768  			return
   769  		}
   770  
   771  		rhs = runInfo.rv // store rv in rhs temporarily
   772  
   773  		if stmt.OkExpr != nil {
   774  			// set ok to OkExpr
   775  			if ok {
   776  				runInfo.rv = trueValue
   777  			} else {
   778  				runInfo.rv = falseValue
   779  			}
   780  			runInfo.expr = stmt.OkExpr
   781  			runInfo.invokeLetExpr()
   782  			// TODO: ok to ignore error?
   783  		}
   784  
   785  		if ok {
   786  			// set rv to lhs
   787  			runInfo.rv = rhs
   788  			runInfo.expr = stmt.LHS
   789  			runInfo.invokeLetExpr()
   790  			if runInfo.err != nil {
   791  				return
   792  			}
   793  		} else {
   794  			runInfo.rv = nilValue
   795  		}
   796  
   797  	// default
   798  	default:
   799  		runInfo.err = newStringError(stmt, "unknown statement")
   800  		runInfo.rv = nilValue
   801  	}
   802  
   803  }