github.com/HaHadaxigua/yaegi@v1.0.1/interp/interp.go (about)

     1  package interp
     2  
     3  import (
     4  	"bufio"
     5  	"context"
     6  	"errors"
     7  	"flag"
     8  	"fmt"
     9  	"go/build"
    10  	"go/constant"
    11  	"go/scanner"
    12  	"go/token"
    13  	"io"
    14  	"io/fs"
    15  	"log"
    16  	"math/bits"
    17  	"os"
    18  	"os/signal"
    19  	"path"
    20  	"path/filepath"
    21  	"reflect"
    22  	"runtime"
    23  	"runtime/debug"
    24  	"strconv"
    25  	"strings"
    26  	"sync"
    27  	"sync/atomic"
    28  )
    29  
    30  // Interpreter node structure for AST and CFG.
    31  type node struct {
    32  	debug  *nodeDebugData // debug info
    33  	child  []*node        // child subtrees (AST)
    34  	anc    *node          // ancestor (AST)
    35  	start  *node          // entry point in subtree (CFG)
    36  	tnext  *node          // true branch successor (CFG)
    37  	fnext  *node          // false branch successor (CFG)
    38  	interp *Interpreter   // interpreter context
    39  	frame  *frame         // frame pointer used for closures only (TODO: suppress this)
    40  	index  int64          // node index (dot display)
    41  	findex int            // index of value in frame or frame size (func def, type def)
    42  	level  int            // number of frame indirections to access value
    43  	nleft  int            // number of children in left part (assign) or indicates preceding type (compositeLit)
    44  	nright int            // number of children in right part (assign)
    45  	kind   nkind          // kind of node
    46  	pos    token.Pos      // position in source code, relative to fset
    47  	sym    *symbol        // associated symbol
    48  	typ    *itype         // type of value in frame, or nil
    49  	recv   *receiver      // method receiver node for call, or nil
    50  	types  []reflect.Type // frame types, used by function literals only
    51  	scope  *scope         // frame scope
    52  	action action         // action
    53  	exec   bltn           // generated function to execute
    54  	gen    bltnGenerator  // generator function to produce above bltn
    55  	val    interface{}    // static generic value (CFG execution)
    56  	rval   reflect.Value  // reflection value to let runtime access interpreter (CFG)
    57  	ident  string         // set if node is a var or func
    58  	meta   interface{}    // meta stores meta information between gta runs, like errors
    59  }
    60  
    61  func (n *node) shouldBreak() bool {
    62  	if n == nil || n.debug == nil {
    63  		return false
    64  	}
    65  
    66  	if n.debug.breakOnLine || n.debug.breakOnCall {
    67  		return true
    68  	}
    69  
    70  	return false
    71  }
    72  
    73  func (n *node) setProgram(p *Program) {
    74  	if n.debug == nil {
    75  		n.debug = new(nodeDebugData)
    76  	}
    77  	n.debug.program = p
    78  }
    79  
    80  func (n *node) setBreakOnCall(v bool) {
    81  	if n.debug == nil {
    82  		if !v {
    83  			return
    84  		}
    85  		n.debug = new(nodeDebugData)
    86  	}
    87  	n.debug.breakOnCall = v
    88  }
    89  
    90  func (n *node) setBreakOnLine(v bool) {
    91  	if n.debug == nil {
    92  		if !v {
    93  			return
    94  		}
    95  		n.debug = new(nodeDebugData)
    96  	}
    97  	n.debug.breakOnLine = v
    98  }
    99  
   100  // receiver stores method receiver object access path.
   101  type receiver struct {
   102  	node  *node         // receiver value for alias and struct types
   103  	val   reflect.Value // receiver value for interface type and value type
   104  	index []int         // path in receiver value for interface or value type
   105  }
   106  
   107  // frame contains values for the current execution level (a function context).
   108  type frame struct {
   109  	// id is an atomic counter used for cancellation, only accessed
   110  	// via newFrame/runid/setrunid/clone.
   111  	// Located at start of struct to ensure proper aligment.
   112  	id uint64
   113  
   114  	debug *frameDebugData
   115  
   116  	root *frame          // global space
   117  	anc  *frame          // ancestor frame (caller space)
   118  	data []reflect.Value // values
   119  
   120  	mutex     sync.RWMutex
   121  	deferred  [][]reflect.Value  // defer stack
   122  	recovered interface{}        // to handle panic recover
   123  	done      reflect.SelectCase // for cancellation of channel operations
   124  }
   125  
   126  func newFrame(anc *frame, length int, id uint64) *frame {
   127  	f := &frame{
   128  		anc:  anc,
   129  		data: make([]reflect.Value, length),
   130  		id:   id,
   131  	}
   132  	if anc == nil {
   133  		f.root = f
   134  	} else {
   135  		f.done = anc.done
   136  		f.root = anc.root
   137  	}
   138  	return f
   139  }
   140  
   141  func (f *frame) runid() uint64      { return atomic.LoadUint64(&f.id) }
   142  func (f *frame) setrunid(id uint64) { atomic.StoreUint64(&f.id, id) }
   143  func (f *frame) clone(fork bool) *frame {
   144  	f.mutex.RLock()
   145  	defer f.mutex.RUnlock()
   146  	nf := &frame{
   147  		anc:       f.anc,
   148  		root:      f.root,
   149  		deferred:  f.deferred,
   150  		recovered: f.recovered,
   151  		id:        f.runid(),
   152  		done:      f.done,
   153  		debug:     f.debug,
   154  	}
   155  	if fork {
   156  		nf.data = make([]reflect.Value, len(f.data))
   157  		copy(nf.data, f.data)
   158  	} else {
   159  		nf.data = f.data
   160  	}
   161  	return nf
   162  }
   163  
   164  // Exports stores the map of binary packages per package path.
   165  // The package path is the path joined from the import path and the package name
   166  // as specified in source files by the "package" statement.
   167  type Exports map[string]map[string]reflect.Value
   168  
   169  // imports stores the map of source packages per package path.
   170  type imports map[string]map[string]*symbol
   171  
   172  // opt stores interpreter options.
   173  type opt struct {
   174  	// dotCmd is the command to process the dot graph produced when astDot and/or
   175  	// cfgDot is enabled. It defaults to 'dot -Tdot -o <filename>.dot'.
   176  	dotCmd       string
   177  	context      build.Context     // build context: GOPATH, build constraints
   178  	stdin        io.Reader         // standard input
   179  	stdout       io.Writer         // standard output
   180  	stderr       io.Writer         // standard error
   181  	args         []string          // cmdline args
   182  	env          map[string]string // environment of interpreter, entries in form of "key=value"
   183  	filesystem   fs.FS             // filesystem containing sources
   184  	astDot       bool              // display AST graph (debug)
   185  	cfgDot       bool              // display CFG graph (debug)
   186  	noRun        bool              // compile, but do not run
   187  	fastChan     bool              // disable cancellable chan operations
   188  	specialStdio bool              // allows os.Stdin, os.Stdout, os.Stderr to not be file descriptors
   189  	unrestricted bool              // allow use of non sandboxed symbols
   190  }
   191  
   192  // Interpreter contains global resources and state.
   193  type Interpreter struct {
   194  	// id is an atomic counter counter used for run cancellation,
   195  	// only accessed via runid/stop
   196  	// Located at start of struct to ensure proper alignment on 32 bit
   197  	// architectures.
   198  	id uint64
   199  
   200  	// nindex is a node number incremented for each new node.
   201  	// It is used for debug (AST and CFG graphs). As it is atomically
   202  	// incremented, keep it aligned on 64 bits boundary.
   203  	nindex int64
   204  
   205  	name string // name of the input source file (or main)
   206  
   207  	opt                                         // user settable options
   208  	cancelChan bool                             // enables cancellable chan operations
   209  	fset       *token.FileSet                   // fileset to locate node in source code
   210  	binPkg     Exports                          // binary packages used in interpreter, indexed by path
   211  	rdir       map[string]bool                  // for src import cycle detection
   212  	mapTypes   map[reflect.Value][]reflect.Type // special interfaces mapping for wrappers
   213  
   214  	mutex    sync.RWMutex
   215  	frame    *frame            // program data storage during execution
   216  	universe *scope            // interpreter global level scope
   217  	scopes   map[string]*scope // package level scopes, indexed by import path
   218  	srcPkg   imports           // source packages used in interpreter, indexed by path
   219  	pkgNames map[string]string // package names, indexed by import path
   220  	done     chan struct{}     // for cancellation of channel operations
   221  	roots    []*node
   222  
   223  	hooks *hooks // symbol hooks
   224  
   225  	debugger *Debugger
   226  }
   227  
   228  const (
   229  	mainID     = "main"
   230  	selfPrefix = "github.com/traefik/yaegi"
   231  	selfPath   = selfPrefix + "/interp/interp"
   232  	// DefaultSourceName is the name used by default when the name of the input
   233  	// source file has not been specified for an Eval.
   234  	// TODO(mpl): something even more special as a name?
   235  	DefaultSourceName = "_.go"
   236  
   237  	// Test is the value to pass to EvalPath to activate evaluation of test functions.
   238  	Test = false
   239  	// NoTest is the value to pass to EvalPath to skip evaluation of test functions.
   240  	NoTest = true
   241  )
   242  
   243  // Self points to the current interpreter if accessed from within itself, or is nil.
   244  var Self *Interpreter
   245  
   246  // Symbols exposes interpreter values.
   247  var Symbols = Exports{
   248  	selfPath: map[string]reflect.Value{
   249  		"New": reflect.ValueOf(New),
   250  
   251  		"Interpreter": reflect.ValueOf((*Interpreter)(nil)),
   252  		"Options":     reflect.ValueOf((*Options)(nil)),
   253  		"Panic":       reflect.ValueOf((*Panic)(nil)),
   254  	},
   255  }
   256  
   257  func init() { Symbols[selfPath]["Symbols"] = reflect.ValueOf(Symbols) }
   258  
   259  // _error is a wrapper of error interface type.
   260  type _error struct {
   261  	IValue interface{}
   262  	WError func() string
   263  }
   264  
   265  func (w _error) Error() string { return w.WError() }
   266  
   267  // Panic is an error recovered from a panic call in interpreted code.
   268  type Panic struct {
   269  	// Value is the recovered value of a call to panic.
   270  	Value interface{}
   271  
   272  	// Callers is the call stack obtained from the recover call.
   273  	// It may be used as the parameter to runtime.CallersFrames.
   274  	Callers []uintptr
   275  
   276  	// Stack is the call stack buffer for debug.
   277  	Stack []byte
   278  }
   279  
   280  // TODO: Capture interpreter stack frames also and remove
   281  // fmt.Fprintln(n.interp.stderr, oNode.cfgErrorf("panic")) in runCfg.
   282  
   283  func (e Panic) Error() string { return fmt.Sprint(e.Value) }
   284  
   285  // Walk traverses AST n in depth first order, call cbin function
   286  // at node entry and cbout function at node exit.
   287  func (n *node) Walk(in func(n *node) bool, out func(n *node)) {
   288  	if in != nil && !in(n) {
   289  		return
   290  	}
   291  	for _, child := range n.child {
   292  		child.Walk(in, out)
   293  	}
   294  	if out != nil {
   295  		out(n)
   296  	}
   297  }
   298  
   299  // Options are the interpreter options.
   300  type Options struct {
   301  	// GoPath sets GOPATH for the interpreter.
   302  	GoPath string
   303  
   304  	// BuildTags sets build constraints for the interpreter.
   305  	BuildTags []string
   306  
   307  	// Standard input, output and error streams.
   308  	// They default to os.Stdin, os.Stdout and os.Stderr respectively.
   309  	Stdin          io.Reader
   310  	Stdout, Stderr io.Writer
   311  
   312  	// Cmdline args, defaults to os.Args.
   313  	Args []string
   314  
   315  	// Environment of interpreter. Entries are in the form "key=values".
   316  	Env []string
   317  
   318  	// SourcecodeFilesystem is where the _sourcecode_ is loaded from and does
   319  	// NOT affect the filesystem of scripts when they run.
   320  	// It can be any fs.FS compliant filesystem (e.g. embed.FS, or fstest.MapFS for testing)
   321  	// See example/fs/fs_test.go for an example.
   322  	SourcecodeFilesystem fs.FS
   323  
   324  	// Unrestricted allows to run non sandboxed stdlib symbols such as os/exec and environment
   325  	Unrestricted bool
   326  }
   327  
   328  // New returns a new interpreter.
   329  func New(options Options) *Interpreter {
   330  	i := Interpreter{
   331  		opt:      opt{context: build.Default, filesystem: &realFS{}, env: map[string]string{}},
   332  		frame:    newFrame(nil, 0, 0),
   333  		fset:     token.NewFileSet(),
   334  		universe: initUniverse(),
   335  		scopes:   map[string]*scope{},
   336  		binPkg:   Exports{"": map[string]reflect.Value{"_error": reflect.ValueOf((*_error)(nil))}},
   337  		mapTypes: map[reflect.Value][]reflect.Type{},
   338  		srcPkg:   imports{},
   339  		pkgNames: map[string]string{},
   340  		rdir:     map[string]bool{},
   341  		hooks:    &hooks{},
   342  	}
   343  
   344  	if i.opt.stdin = options.Stdin; i.opt.stdin == nil {
   345  		i.opt.stdin = os.Stdin
   346  	}
   347  
   348  	if i.opt.stdout = options.Stdout; i.opt.stdout == nil {
   349  		i.opt.stdout = os.Stdout
   350  	}
   351  
   352  	if i.opt.stderr = options.Stderr; i.opt.stderr == nil {
   353  		i.opt.stderr = os.Stderr
   354  	}
   355  
   356  	if i.opt.args = options.Args; i.opt.args == nil {
   357  		i.opt.args = os.Args
   358  	}
   359  
   360  	// unrestricted allows to use non sandboxed stdlib symbols and env.
   361  	if options.Unrestricted {
   362  		i.opt.unrestricted = true
   363  	} else {
   364  		for _, e := range options.Env {
   365  			a := strings.SplitN(e, "=", 2)
   366  			if len(a) == 2 {
   367  				i.opt.env[a[0]] = a[1]
   368  			} else {
   369  				i.opt.env[a[0]] = ""
   370  			}
   371  		}
   372  	}
   373  
   374  	if options.SourcecodeFilesystem != nil {
   375  		i.opt.filesystem = options.SourcecodeFilesystem
   376  	}
   377  
   378  	i.opt.context.GOPATH = options.GoPath
   379  	if len(options.BuildTags) > 0 {
   380  		i.opt.context.BuildTags = options.BuildTags
   381  	}
   382  
   383  	// astDot activates AST graph display for the interpreter
   384  	i.opt.astDot, _ = strconv.ParseBool(os.Getenv("YAEGI_AST_DOT"))
   385  
   386  	// cfgDot activates CFG graph display for the interpreter
   387  	i.opt.cfgDot, _ = strconv.ParseBool(os.Getenv("YAEGI_CFG_DOT"))
   388  
   389  	// dotCmd defines how to process the dot code generated whenever astDot and/or
   390  	// cfgDot is enabled. It defaults to 'dot -Tdot -o<filename>.dot' where filename
   391  	// is context dependent.
   392  	i.opt.dotCmd = os.Getenv("YAEGI_DOT_CMD")
   393  
   394  	// noRun disables the execution (but not the compilation) in the interpreter
   395  	i.opt.noRun, _ = strconv.ParseBool(os.Getenv("YAEGI_NO_RUN"))
   396  
   397  	// fastChan disables the cancellable version of channel operations in evalWithContext
   398  	i.opt.fastChan, _ = strconv.ParseBool(os.Getenv("YAEGI_FAST_CHAN"))
   399  
   400  	// specialStdio allows to assign directly io.Writer and io.Reader to os.Stdxxx,
   401  	// even if they are not file descriptors.
   402  	i.opt.specialStdio, _ = strconv.ParseBool(os.Getenv("YAEGI_SPECIAL_STDIO"))
   403  
   404  	return &i
   405  }
   406  
   407  const (
   408  	bltnAppend  = "append"
   409  	bltnCap     = "cap"
   410  	bltnClose   = "close"
   411  	bltnComplex = "complex"
   412  	bltnImag    = "imag"
   413  	bltnCopy    = "copy"
   414  	bltnDelete  = "delete"
   415  	bltnLen     = "len"
   416  	bltnMake    = "make"
   417  	bltnNew     = "new"
   418  	bltnPanic   = "panic"
   419  	bltnPrint   = "print"
   420  	bltnPrintln = "println"
   421  	bltnReal    = "real"
   422  	bltnRecover = "recover"
   423  )
   424  
   425  func initUniverse() *scope {
   426  	sc := &scope{global: true, sym: map[string]*symbol{
   427  		// predefined Go types
   428  		"bool":        {kind: typeSym, typ: &itype{cat: boolT, name: "bool", str: "bool"}},
   429  		"byte":        {kind: typeSym, typ: &itype{cat: uint8T, name: "uint8", str: "uint8"}},
   430  		"complex64":   {kind: typeSym, typ: &itype{cat: complex64T, name: "complex64", str: "complex64"}},
   431  		"complex128":  {kind: typeSym, typ: &itype{cat: complex128T, name: "complex128", str: "complex128"}},
   432  		"error":       {kind: typeSym, typ: &itype{cat: errorT, name: "error", str: "error"}},
   433  		"float32":     {kind: typeSym, typ: &itype{cat: float32T, name: "float32", str: "float32"}},
   434  		"float64":     {kind: typeSym, typ: &itype{cat: float64T, name: "float64", str: "float64"}},
   435  		"int":         {kind: typeSym, typ: &itype{cat: intT, name: "int", str: "int"}},
   436  		"int8":        {kind: typeSym, typ: &itype{cat: int8T, name: "int8", str: "int8"}},
   437  		"int16":       {kind: typeSym, typ: &itype{cat: int16T, name: "int16", str: "int16"}},
   438  		"int32":       {kind: typeSym, typ: &itype{cat: int32T, name: "int32", str: "int32"}},
   439  		"int64":       {kind: typeSym, typ: &itype{cat: int64T, name: "int64", str: "int64"}},
   440  		"interface{}": {kind: typeSym, typ: &itype{cat: interfaceT, str: "interface{}"}},
   441  		"rune":        {kind: typeSym, typ: &itype{cat: int32T, name: "int32", str: "int32"}},
   442  		"string":      {kind: typeSym, typ: &itype{cat: stringT, name: "string", str: "string"}},
   443  		"uint":        {kind: typeSym, typ: &itype{cat: uintT, name: "uint", str: "uint"}},
   444  		"uint8":       {kind: typeSym, typ: &itype{cat: uint8T, name: "uint8", str: "uint8"}},
   445  		"uint16":      {kind: typeSym, typ: &itype{cat: uint16T, name: "uint16", str: "uint16"}},
   446  		"uint32":      {kind: typeSym, typ: &itype{cat: uint32T, name: "uint32", str: "uint32"}},
   447  		"uint64":      {kind: typeSym, typ: &itype{cat: uint64T, name: "uint64", str: "uint64"}},
   448  		"uintptr":     {kind: typeSym, typ: &itype{cat: uintptrT, name: "uintptr", str: "uintptr"}},
   449  
   450  		// predefined Go constants
   451  		"false": {kind: constSym, typ: untypedBool(), rval: reflect.ValueOf(false)},
   452  		"true":  {kind: constSym, typ: untypedBool(), rval: reflect.ValueOf(true)},
   453  		"iota":  {kind: constSym, typ: untypedInt()},
   454  
   455  		// predefined Go zero value
   456  		"nil": {typ: &itype{cat: nilT, untyped: true, str: "nil"}},
   457  
   458  		// predefined Go builtins
   459  		bltnAppend:  {kind: bltnSym, builtin: _append},
   460  		bltnCap:     {kind: bltnSym, builtin: _cap},
   461  		bltnClose:   {kind: bltnSym, builtin: _close},
   462  		bltnComplex: {kind: bltnSym, builtin: _complex},
   463  		bltnImag:    {kind: bltnSym, builtin: _imag},
   464  		bltnCopy:    {kind: bltnSym, builtin: _copy},
   465  		bltnDelete:  {kind: bltnSym, builtin: _delete},
   466  		bltnLen:     {kind: bltnSym, builtin: _len},
   467  		bltnMake:    {kind: bltnSym, builtin: _make},
   468  		bltnNew:     {kind: bltnSym, builtin: _new},
   469  		bltnPanic:   {kind: bltnSym, builtin: _panic},
   470  		bltnPrint:   {kind: bltnSym, builtin: _print},
   471  		bltnPrintln: {kind: bltnSym, builtin: _println},
   472  		bltnReal:    {kind: bltnSym, builtin: _real},
   473  		bltnRecover: {kind: bltnSym, builtin: _recover},
   474  	}}
   475  	return sc
   476  }
   477  
   478  // resizeFrame resizes the global frame of interpreter.
   479  func (interp *Interpreter) resizeFrame() {
   480  	l := len(interp.universe.types)
   481  	b := len(interp.frame.data)
   482  	if l-b <= 0 {
   483  		return
   484  	}
   485  	data := make([]reflect.Value, l)
   486  	copy(data, interp.frame.data)
   487  	for j, t := range interp.universe.types[b:] {
   488  		data[b+j] = reflect.New(t).Elem()
   489  	}
   490  	interp.frame.data = data
   491  }
   492  
   493  // Eval evaluates Go code represented as a string. Eval returns the last result
   494  // computed by the interpreter, and a non nil error in case of failure.
   495  func (interp *Interpreter) Eval(src string) (res reflect.Value, err error) {
   496  	return interp.eval(src, "", true)
   497  }
   498  
   499  // EvalPath evaluates Go code located at path and returns the last result computed
   500  // by the interpreter, and a non nil error in case of failure.
   501  // The main function of the main package is executed if present.
   502  func (interp *Interpreter) EvalPath(path string) (res reflect.Value, err error) {
   503  	if !isFile(interp.opt.filesystem, path) {
   504  		_, err := interp.importSrc(mainID, path, NoTest)
   505  		return res, err
   506  	}
   507  
   508  	b, err := fs.ReadFile(interp.filesystem, path)
   509  	if err != nil {
   510  		return res, err
   511  	}
   512  	return interp.eval(string(b), path, false)
   513  }
   514  
   515  // EvalPathWithContext evaluates Go code located at path and returns the last
   516  // result computed by the interpreter, and a non nil error in case of failure.
   517  // The main function of the main package is executed if present.
   518  func (interp *Interpreter) EvalPathWithContext(ctx context.Context, path string) (res reflect.Value, err error) {
   519  	interp.mutex.Lock()
   520  	interp.done = make(chan struct{})
   521  	interp.cancelChan = !interp.opt.fastChan
   522  	interp.mutex.Unlock()
   523  
   524  	done := make(chan struct{})
   525  	go func() {
   526  		defer close(done)
   527  		res, err = interp.EvalPath(path)
   528  	}()
   529  
   530  	select {
   531  	case <-ctx.Done():
   532  		interp.stop()
   533  		return reflect.Value{}, ctx.Err()
   534  	case <-done:
   535  	}
   536  	return res, err
   537  }
   538  
   539  // EvalTest evaluates Go code located at path, including test files with "_test.go" suffix.
   540  // A non nil error is returned in case of failure.
   541  // The main function, test functions and benchmark functions are internally compiled but not
   542  // executed. Test functions can be retrieved using the Symbol() method.
   543  func (interp *Interpreter) EvalTest(path string) error {
   544  	_, err := interp.importSrc(mainID, path, Test)
   545  	return err
   546  }
   547  
   548  // Symbols returns a map of interpreter exported symbol values for the given
   549  // import path. If the argument is the empty string, all known symbols are
   550  // returned.
   551  func (interp *Interpreter) Symbols(importPath string) Exports {
   552  	m := map[string]map[string]reflect.Value{}
   553  	interp.mutex.RLock()
   554  	defer interp.mutex.RUnlock()
   555  
   556  	for k, v := range interp.srcPkg {
   557  		if importPath != "" && k != importPath {
   558  			continue
   559  		}
   560  		syms := map[string]reflect.Value{}
   561  		for n, s := range v {
   562  			if !canExport(n) {
   563  				// Skip private non-exported symbols.
   564  				continue
   565  			}
   566  			switch s.kind {
   567  			case constSym:
   568  				syms[n] = s.rval
   569  			case funcSym:
   570  				syms[n] = genFunctionWrapper(s.node)(interp.frame)
   571  			case varSym:
   572  				syms[n] = interp.frame.data[s.index]
   573  			case typeSym:
   574  				syms[n] = reflect.New(s.typ.TypeOf())
   575  			}
   576  		}
   577  
   578  		if len(syms) > 0 {
   579  			m[k] = syms
   580  		}
   581  
   582  		if importPath != "" {
   583  			return m
   584  		}
   585  	}
   586  
   587  	if importPath != "" && len(m) > 0 {
   588  		return m
   589  	}
   590  
   591  	for k, v := range interp.binPkg {
   592  		if importPath != "" && k != importPath {
   593  			continue
   594  		}
   595  		m[k] = v
   596  		if importPath != "" {
   597  			return m
   598  		}
   599  	}
   600  
   601  	return m
   602  }
   603  
   604  func isFile(filesystem fs.FS, path string) bool {
   605  	fi, err := fs.Stat(filesystem, path)
   606  	return err == nil && fi.Mode().IsRegular()
   607  }
   608  
   609  func (interp *Interpreter) eval(src, name string, inc bool) (res reflect.Value, err error) {
   610  	prog, err := interp.compileSrc(src, name, inc)
   611  	if err != nil {
   612  		return res, err
   613  	}
   614  
   615  	if interp.noRun {
   616  		return res, err
   617  	}
   618  
   619  	return interp.Execute(prog)
   620  }
   621  
   622  // EvalWithContext evaluates Go code represented as a string. It returns
   623  // a map on current interpreted package exported symbols.
   624  func (interp *Interpreter) EvalWithContext(ctx context.Context, src string) (reflect.Value, error) {
   625  	var v reflect.Value
   626  	var err error
   627  
   628  	interp.mutex.Lock()
   629  	interp.done = make(chan struct{})
   630  	interp.cancelChan = !interp.opt.fastChan
   631  	interp.mutex.Unlock()
   632  
   633  	done := make(chan struct{})
   634  	go func() {
   635  		defer func() {
   636  			if r := recover(); r != nil {
   637  				var pc [64]uintptr
   638  				n := runtime.Callers(1, pc[:])
   639  				err = Panic{Value: r, Callers: pc[:n], Stack: debug.Stack()}
   640  			}
   641  			close(done)
   642  		}()
   643  		v, err = interp.Eval(src)
   644  	}()
   645  
   646  	select {
   647  	case <-ctx.Done():
   648  		interp.stop()
   649  		return reflect.Value{}, ctx.Err()
   650  	case <-done:
   651  	}
   652  	return v, err
   653  }
   654  
   655  // stop sends a semaphore to all running frames and closes the chan
   656  // operation short circuit channel. stop may only be called once per
   657  // invocation of EvalWithContext.
   658  func (interp *Interpreter) stop() {
   659  	atomic.AddUint64(&interp.id, 1)
   660  	close(interp.done)
   661  }
   662  
   663  func (interp *Interpreter) runid() uint64 { return atomic.LoadUint64(&interp.id) }
   664  
   665  // getWrapper returns the wrapper type of the corresponding interface, or nil if not found.
   666  func (interp *Interpreter) getWrapper(t reflect.Type) reflect.Type {
   667  	if p, ok := interp.binPkg[t.PkgPath()]; ok {
   668  		return p["_"+t.Name()].Type().Elem()
   669  	}
   670  	return nil
   671  }
   672  
   673  // Use loads binary runtime symbols in the interpreter context so
   674  // they can be used in interpreted code.
   675  func (interp *Interpreter) Use(values Exports) error {
   676  	for k, v := range values {
   677  		importPath := path.Dir(k)
   678  		packageName := path.Base(k)
   679  
   680  		if k == "." && v["MapTypes"].IsValid() {
   681  			// Use mapping for special interface wrappers.
   682  			for kk, vv := range v["MapTypes"].Interface().(map[reflect.Value][]reflect.Type) {
   683  				interp.mapTypes[kk] = vv
   684  			}
   685  			continue
   686  		}
   687  
   688  		if importPath == "." {
   689  			return fmt.Errorf("export path %[1]q is missing a package name; did you mean '%[1]s/%[1]s'?", k)
   690  		}
   691  
   692  		if importPath == selfPrefix {
   693  			interp.hooks.Parse(v)
   694  			continue
   695  		}
   696  
   697  		if interp.binPkg[importPath] == nil {
   698  			interp.binPkg[importPath] = make(map[string]reflect.Value)
   699  			interp.pkgNames[importPath] = packageName
   700  		}
   701  
   702  		for s, sym := range v {
   703  			interp.binPkg[importPath][s] = sym
   704  		}
   705  		if k == selfPath {
   706  			interp.binPkg[importPath]["Self"] = reflect.ValueOf(interp)
   707  		}
   708  	}
   709  
   710  	// Checks if input values correspond to stdlib packages by looking for one
   711  	// well known stdlib package path.
   712  	if _, ok := values["fmt/fmt"]; ok {
   713  		fixStdlib(interp)
   714  	}
   715  	return nil
   716  }
   717  
   718  // fixStdlib redefines interpreter stdlib symbols to use the standard input,
   719  // output and errror assigned to the interpreter. The changes are limited to
   720  // the interpreter only.
   721  // Note that it is possible to escape the virtualized stdio by
   722  // read/write directly to file descriptors 0, 1, 2.
   723  func fixStdlib(interp *Interpreter) {
   724  	p := interp.binPkg["fmt"]
   725  	if p == nil {
   726  		return
   727  	}
   728  
   729  	stdin, stdout, stderr := interp.stdin, interp.stdout, interp.stderr
   730  
   731  	p["Print"] = reflect.ValueOf(func(a ...interface{}) (n int, err error) { return fmt.Fprint(stdout, a...) })
   732  	p["Printf"] = reflect.ValueOf(func(f string, a ...interface{}) (n int, err error) { return fmt.Fprintf(stdout, f, a...) })
   733  	p["Println"] = reflect.ValueOf(func(a ...interface{}) (n int, err error) { return fmt.Fprintln(stdout, a...) })
   734  
   735  	p["Scan"] = reflect.ValueOf(func(a ...interface{}) (n int, err error) { return fmt.Fscan(stdin, a...) })
   736  	p["Scanf"] = reflect.ValueOf(func(f string, a ...interface{}) (n int, err error) { return fmt.Fscanf(stdin, f, a...) })
   737  	p["Scanln"] = reflect.ValueOf(func(a ...interface{}) (n int, err error) { return fmt.Fscanln(stdin, a...) })
   738  
   739  	// Update mapTypes to virtualized symbols as well.
   740  	interp.mapTypes[p["Print"]] = interp.mapTypes[reflect.ValueOf(fmt.Print)]
   741  	interp.mapTypes[p["Printf"]] = interp.mapTypes[reflect.ValueOf(fmt.Printf)]
   742  	interp.mapTypes[p["Println"]] = interp.mapTypes[reflect.ValueOf(fmt.Println)]
   743  	interp.mapTypes[p["Scan"]] = interp.mapTypes[reflect.ValueOf(fmt.Scan)]
   744  	interp.mapTypes[p["Scanf"]] = interp.mapTypes[reflect.ValueOf(fmt.Scanf)]
   745  	interp.mapTypes[p["Scanln"]] = interp.mapTypes[reflect.ValueOf(fmt.Scanln)]
   746  
   747  	if p = interp.binPkg["flag"]; p != nil {
   748  		c := flag.NewFlagSet(os.Args[0], flag.PanicOnError)
   749  		c.SetOutput(stderr)
   750  		p["CommandLine"] = reflect.ValueOf(&c).Elem()
   751  	}
   752  
   753  	if p = interp.binPkg["log"]; p != nil {
   754  		l := log.New(stderr, "", log.LstdFlags)
   755  		// Restrict Fatal symbols to panic instead of exit.
   756  		p["Fatal"] = reflect.ValueOf(l.Panic)
   757  		p["Fatalf"] = reflect.ValueOf(l.Panicf)
   758  		p["Fatalln"] = reflect.ValueOf(l.Panicln)
   759  
   760  		p["Flags"] = reflect.ValueOf(l.Flags)
   761  		p["Output"] = reflect.ValueOf(l.Output)
   762  		p["Panic"] = reflect.ValueOf(l.Panic)
   763  		p["Panicf"] = reflect.ValueOf(l.Panicf)
   764  		p["Panicln"] = reflect.ValueOf(l.Panicln)
   765  		p["Prefix"] = reflect.ValueOf(l.Prefix)
   766  		p["Print"] = reflect.ValueOf(l.Print)
   767  		p["Printf"] = reflect.ValueOf(l.Printf)
   768  		p["Println"] = reflect.ValueOf(l.Println)
   769  		p["SetFlags"] = reflect.ValueOf(l.SetFlags)
   770  		p["SetOutput"] = reflect.ValueOf(l.SetOutput)
   771  		p["SetPrefix"] = reflect.ValueOf(l.SetPrefix)
   772  		p["Writer"] = reflect.ValueOf(l.Writer)
   773  
   774  		// Update mapTypes to virtualized symbols as well.
   775  		interp.mapTypes[p["Print"]] = interp.mapTypes[reflect.ValueOf(log.Print)]
   776  		interp.mapTypes[p["Printf"]] = interp.mapTypes[reflect.ValueOf(log.Printf)]
   777  		interp.mapTypes[p["Println"]] = interp.mapTypes[reflect.ValueOf(log.Println)]
   778  		interp.mapTypes[p["Panic"]] = interp.mapTypes[reflect.ValueOf(log.Panic)]
   779  		interp.mapTypes[p["Panicf"]] = interp.mapTypes[reflect.ValueOf(log.Panicf)]
   780  		interp.mapTypes[p["Panicln"]] = interp.mapTypes[reflect.ValueOf(log.Panicln)]
   781  	}
   782  
   783  	if p = interp.binPkg["os"]; p != nil {
   784  		p["Args"] = reflect.ValueOf(&interp.args).Elem()
   785  		if interp.specialStdio {
   786  			// Inherit streams from interpreter even if they do not have a file descriptor.
   787  			p["Stdin"] = reflect.ValueOf(&stdin).Elem()
   788  			p["Stdout"] = reflect.ValueOf(&stdout).Elem()
   789  			p["Stderr"] = reflect.ValueOf(&stderr).Elem()
   790  		} else {
   791  			// Inherits streams from interpreter only if they have a file descriptor and preserve original type.
   792  			if s, ok := stdin.(*os.File); ok {
   793  				p["Stdin"] = reflect.ValueOf(&s).Elem()
   794  			}
   795  			if s, ok := stdout.(*os.File); ok {
   796  				p["Stdout"] = reflect.ValueOf(&s).Elem()
   797  			}
   798  			if s, ok := stderr.(*os.File); ok {
   799  				p["Stderr"] = reflect.ValueOf(&s).Elem()
   800  			}
   801  		}
   802  		if !interp.unrestricted {
   803  			// In restricted mode, scripts can only access to a passed virtualized env, and can not write the real one.
   804  			getenv := func(key string) string { return interp.env[key] }
   805  			p["Clearenv"] = reflect.ValueOf(func() { interp.env = map[string]string{} })
   806  			p["ExpandEnv"] = reflect.ValueOf(func(s string) string { return os.Expand(s, getenv) })
   807  			p["Getenv"] = reflect.ValueOf(getenv)
   808  			p["LookupEnv"] = reflect.ValueOf(func(key string) (s string, ok bool) { s, ok = interp.env[key]; return })
   809  			p["Setenv"] = reflect.ValueOf(func(key, value string) error { interp.env[key] = value; return nil })
   810  			p["Unsetenv"] = reflect.ValueOf(func(key string) error { delete(interp.env, key); return nil })
   811  			p["Environ"] = reflect.ValueOf(func() (a []string) {
   812  				for k, v := range interp.env {
   813  					a = append(a, k+"="+v)
   814  				}
   815  				return
   816  			})
   817  		}
   818  	}
   819  
   820  	if p = interp.binPkg["math/bits"]; p != nil {
   821  		// Do not trust extracted value maybe from another arch.
   822  		p["UintSize"] = reflect.ValueOf(constant.MakeInt64(bits.UintSize))
   823  	}
   824  }
   825  
   826  // ignoreScannerError returns true if the error from Go scanner can be safely ignored
   827  // to let the caller grab one more line before retrying to parse its input.
   828  func ignoreScannerError(e *scanner.Error, s string) bool {
   829  	msg := e.Msg
   830  	if strings.HasSuffix(msg, "found 'EOF'") {
   831  		return true
   832  	}
   833  	if msg == "raw string literal not terminated" {
   834  		return true
   835  	}
   836  	if strings.HasPrefix(msg, "expected operand, found '}'") && !strings.HasSuffix(s, "}") {
   837  		return true
   838  	}
   839  	return false
   840  }
   841  
   842  // ImportUsed automatically imports pre-compiled packages included by Use().
   843  // This is mainly useful for REPLs, or single command lines. In case of an ambiguous default
   844  // package name, for example "rand" for crypto/rand and math/rand, the package name is
   845  // constructed by replacing the last "/" by a "_", producing crypto_rand and math_rand.
   846  // ImportUsed should not be called more than once, and not after a first Eval, as it may
   847  // rename packages.
   848  func (interp *Interpreter) ImportUsed() {
   849  	sc := interp.universe
   850  	for k := range interp.binPkg {
   851  		// By construction, the package name is the last path element of the key.
   852  		name := path.Base(k)
   853  		if sym, ok := sc.sym[name]; ok {
   854  			// Handle collision by renaming old and new entries.
   855  			name2 := key2name(fixKey(sym.typ.path))
   856  			sc.sym[name2] = sym
   857  			if name2 != name {
   858  				delete(sc.sym, name)
   859  			}
   860  			name = key2name(fixKey(k))
   861  		}
   862  		sc.sym[name] = &symbol{kind: pkgSym, typ: &itype{cat: binPkgT, path: k, scope: sc}}
   863  	}
   864  }
   865  
   866  func key2name(name string) string {
   867  	return filepath.Join(name, DefaultSourceName)
   868  }
   869  
   870  func fixKey(k string) string {
   871  	i := strings.LastIndex(k, "/")
   872  	if i >= 0 {
   873  		k = k[:i] + "_" + k[i+1:]
   874  	}
   875  	return k
   876  }
   877  
   878  // REPL performs a Read-Eval-Print-Loop on input reader.
   879  // Results are printed to the output writer of the Interpreter, provided as option
   880  // at creation time. Errors are printed to the similarly defined errors writer.
   881  // The last interpreter result value and error are returned.
   882  func (interp *Interpreter) REPL() (reflect.Value, error) {
   883  	in, out, errs := interp.stdin, interp.stdout, interp.stderr
   884  	ctx, cancel := context.WithCancel(context.Background())
   885  	end := make(chan struct{})     // channel to terminate the REPL
   886  	sig := make(chan os.Signal, 1) // channel to trap interrupt signal (Ctrl-C)
   887  	lines := make(chan string)     // channel to read REPL input lines
   888  	prompt := getPrompt(in, out)   // prompt activated on tty like IO stream
   889  	s := bufio.NewScanner(in)      // read input stream line by line
   890  	var v reflect.Value            // result value from eval
   891  	var err error                  // error from eval
   892  	src := ""                      // source string to evaluate
   893  
   894  	signal.Notify(sig, os.Interrupt)
   895  	defer signal.Stop(sig)
   896  	prompt(v)
   897  
   898  	go func() {
   899  		defer close(end)
   900  		for s.Scan() {
   901  			lines <- s.Text()
   902  		}
   903  		if e := s.Err(); e != nil {
   904  			fmt.Fprintln(errs, e)
   905  		}
   906  	}()
   907  
   908  	go func() {
   909  		for {
   910  			select {
   911  			case <-sig:
   912  				cancel()
   913  				lines <- ""
   914  			case <-end:
   915  				return
   916  			}
   917  		}
   918  	}()
   919  
   920  	for {
   921  		var line string
   922  
   923  		select {
   924  		case <-end:
   925  			cancel()
   926  			return v, err
   927  		case line = <-lines:
   928  			src += line + "\n"
   929  		}
   930  
   931  		v, err = interp.EvalWithContext(ctx, src)
   932  		if err != nil {
   933  			switch e := err.(type) {
   934  			case scanner.ErrorList:
   935  				if len(e) > 0 && ignoreScannerError(e[0], line) {
   936  					continue
   937  				}
   938  				fmt.Fprintln(errs, strings.TrimPrefix(e[0].Error(), DefaultSourceName+":"))
   939  			case Panic:
   940  				fmt.Fprintln(errs, e.Value)
   941  				fmt.Fprintln(errs, string(e.Stack))
   942  			default:
   943  				fmt.Fprintln(errs, err)
   944  			}
   945  		}
   946  		if errors.Is(err, context.Canceled) {
   947  			ctx, cancel = context.WithCancel(context.Background())
   948  		}
   949  		src = ""
   950  		prompt(v)
   951  	}
   952  }
   953  
   954  func doPrompt(out io.Writer) func(v reflect.Value) {
   955  	return func(v reflect.Value) {
   956  		if v.IsValid() {
   957  			fmt.Fprintln(out, ":", v)
   958  		}
   959  		fmt.Fprint(out, "> ")
   960  	}
   961  }
   962  
   963  // getPrompt returns a function which prints a prompt only if input is a terminal.
   964  func getPrompt(in io.Reader, out io.Writer) func(reflect.Value) {
   965  	forcePrompt, _ := strconv.ParseBool(os.Getenv("YAEGI_PROMPT"))
   966  	if forcePrompt {
   967  		return doPrompt(out)
   968  	}
   969  	s, ok := in.(interface{ Stat() (os.FileInfo, error) })
   970  	if !ok {
   971  		return func(reflect.Value) {}
   972  	}
   973  	stat, err := s.Stat()
   974  	if err == nil && stat.Mode()&os.ModeCharDevice != 0 {
   975  		return doPrompt(out)
   976  	}
   977  	return func(reflect.Value) {}
   978  }