github.com/traefik/yaegi@v0.15.1/cmd/yaegi/yaegi.go (about) 1 /* 2 Yaegi interprets Go programs. 3 4 Yaegi reads Go language programs from standard input, string 5 parameters or files and run them. 6 7 If invoked with no arguments, it processes the standard input in 8 a Read-Eval-Print-Loop. A prompt is displayed if standard input is 9 a terminal. 10 11 File Mode 12 13 In file mode, as in a standard Go compiler, source files are read entirely 14 before being parsed, then evaluated. It allows to handle forward 15 declarations and to have package code split in multiple source files. 16 17 Go specifications fully apply in this mode. 18 19 All files are interpreted in file mode except the initial file if it 20 starts with "#!" characters (the shebang pattern to allow executable 21 scripts), for example "#!/usr/bin/env yaegi". In that case, the initial 22 file is interpreted in REPL mode. 23 24 REPL mode 25 26 In REPL mode, the interpreter parses the code incrementally. As soon 27 as a statement is complete, it evaluates it. This makes the interpreter 28 suitable for interactive command line and scripts. 29 30 Go specifications apply with the following differences: 31 32 All local and global declarations (const, var, type, func) are allowed, 33 including in short form, except that all identifiers must be defined 34 before use (as declarations inside a standard Go function). 35 36 The statements are evaluated in the global space, within an implicit 37 "main" package. 38 39 It is not necessary to have a package statement, or a main function in 40 REPL mode. Import statements for preloaded binary packages can also 41 be avoided (i.e. all the standard library except the few packages 42 where default names collide, as "math/rand" and "crypto/rand", for which 43 an explicit import is still necessary). 44 45 Note that the source packages are always interpreted in file mode, 46 even if imported from REPL. 47 48 The following extract is a valid executable script: 49 50 #!/usr/bin/env yaegi 51 helloHandler := func(w http.ResponseWriter, req *http.Request) { 52 io.WriteString(w, "Hello, world!\n") 53 } 54 http.HandleFunc("/hello", helloHandler) 55 log.Fatal(http.ListenAndServe(":8080", nil)) 56 57 Example of a one liner: 58 59 $ yaegi -e 'println(reflect.TypeOf(fmt.Print))' 60 61 Options: 62 -e string 63 evaluate the string and return. 64 -i 65 start an interactive REPL after file execution. 66 -syscall 67 include syscall symbols. 68 -tags tag,list 69 a comma-separated list of build tags to consider satisfied during 70 the interpretation. 71 -unsafe 72 include unsafe symbols. 73 74 Environment variables: 75 YAEGI_SYSCALL=1 76 Include syscall symbols (same as -syscall flag). 77 YAEGI_UNRESTRICTED=1 78 Include unrestricted symbols (same as -unrestricted flag). 79 YAEGI_UNSAFE=1 80 Include unsafe symbols (same as -unsafe flag). 81 YAEGI_PROMPT=1 82 Force enable the printing of the REPL prompt and the result of last instruction, 83 even if stdin is not a terminal. 84 YAEGI_AST_DOT=1 85 Generate and display graphviz dot of AST with dotty(1) 86 YAEGI_CFG_DOT=1 87 Generate and display graphviz dot of CFG with dotty(1) 88 YAEGI_DOT_CMD='dot -Tsvg -ofoo.svg' 89 Defines how to process the dot code generated whenever YAEGI_AST_DOT and/or 90 YAEGI_CFG_DOT is enabled. If any of YAEGI_AST_DOT or YAEGI_CFG_DOT is set, 91 but YAEGI_DOT_CMD is not defined, the default is to write to a .dot file 92 next to the Go source file. 93 */ 94 package main 95 96 import ( 97 "errors" 98 "flag" 99 "fmt" 100 "log" 101 "os" 102 103 "github.com/traefik/yaegi/interp" 104 ) 105 106 const ( 107 Extract = "extract" 108 Help = "help" 109 Run = "run" 110 Test = "test" 111 Version = "version" 112 ) 113 114 var version = "devel" // This may be overwritten at build time. 115 116 func main() { 117 var cmd string 118 var err error 119 var exitCode int 120 121 log.SetFlags(log.Lshortfile) // Ease debugging. 122 123 if len(os.Args) > 1 { 124 cmd = os.Args[1] 125 } 126 127 switch cmd { 128 case Extract: 129 err = extractCmd(os.Args[2:]) 130 case Help, "-h", "--help": 131 err = help(os.Args[2:]) 132 case Run: 133 err = run(os.Args[2:]) 134 case Test: 135 err = test(os.Args[2:]) 136 case Version: 137 fmt.Println(version) 138 default: 139 // If no command is given, fallback to default "run" command. 140 // This allows scripts starting with "#!/usr/bin/env yaegi", 141 // as passing more than 1 argument to #! executable may be not supported 142 // on all platforms. 143 cmd = Run 144 err = run(os.Args[1:]) 145 } 146 147 if err != nil && !errors.Is(err, flag.ErrHelp) { 148 fmt.Fprintln(os.Stderr, fmt.Errorf("%s: %w", cmd, err)) 149 if p, ok := err.(interp.Panic); ok { 150 fmt.Fprintln(os.Stderr, string(p.Stack)) 151 } 152 exitCode = 1 153 } 154 os.Exit(exitCode) 155 }