github.com/mattn/anko@v0.1.10/anko.go (about) 1 // +build !appengine 2 3 package main 4 5 import ( 6 "bufio" 7 "flag" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "os" 12 "strings" 13 14 "github.com/mattn/anko/core" 15 "github.com/mattn/anko/env" 16 _ "github.com/mattn/anko/packages" 17 "github.com/mattn/anko/parser" 18 "github.com/mattn/anko/vm" 19 ) 20 21 const version = "0.1.8" 22 23 var ( 24 flagExecute string 25 file string 26 args []string 27 e *env.Env 28 ) 29 30 func main() { 31 var exitCode int 32 33 parseFlags() 34 setupEnv() 35 if flagExecute != "" || flag.NArg() > 0 { 36 exitCode = runNonInteractive() 37 } else { 38 exitCode = runInteractive() 39 } 40 41 os.Exit(exitCode) 42 } 43 44 func parseFlags() { 45 flagVersion := flag.Bool("v", false, "prints out the version and then exits") 46 flag.StringVar(&flagExecute, "e", "", "execute the Anko code") 47 flag.Parse() 48 49 if *flagVersion { 50 fmt.Println(version) 51 os.Exit(0) 52 } 53 54 if flagExecute != "" || flag.NArg() < 1 { 55 args = flag.Args() 56 return 57 } 58 59 file = flag.Arg(0) 60 args = flag.Args()[1:] 61 } 62 63 func setupEnv() { 64 e = env.NewEnv() 65 e.Define("args", args) 66 core.Import(e) 67 } 68 69 func runNonInteractive() int { 70 var source string 71 if flagExecute != "" { 72 source = flagExecute 73 } else { 74 sourceBytes, err := ioutil.ReadFile(file) 75 if err != nil { 76 fmt.Println("ReadFile error:", err) 77 return 2 78 } 79 source = string(sourceBytes) 80 } 81 82 _, err := vm.Execute(e, nil, source) 83 if err != nil { 84 fmt.Println("Execute error:", err) 85 return 4 86 } 87 88 return 0 89 } 90 91 func runInteractive() int { 92 var following bool 93 var source string 94 scanner := bufio.NewScanner(os.Stdin) 95 96 parser.EnableErrorVerbose() 97 98 for { 99 if following { 100 source += "\n" 101 fmt.Print(" ") 102 } else { 103 fmt.Print("> ") 104 } 105 106 if !scanner.Scan() { 107 break 108 } 109 source += scanner.Text() 110 if source == "" { 111 continue 112 } 113 if source == "quit()" { 114 break 115 } 116 117 stmts, err := parser.ParseSrc(source) 118 119 if e, ok := err.(*parser.Error); ok { 120 es := e.Error() 121 if strings.HasPrefix(es, "syntax error: unexpected") { 122 if strings.HasPrefix(es, "syntax error: unexpected $end,") { 123 following = true 124 continue 125 } 126 } else { 127 if e.Pos.Column == len(source) && !e.Fatal { 128 fmt.Fprintln(os.Stderr, e) 129 following = true 130 continue 131 } 132 if e.Error() == "unexpected EOF" { 133 following = true 134 continue 135 } 136 } 137 } 138 139 following = false 140 source = "" 141 var v interface{} 142 143 if err == nil { 144 v, err = vm.Run(e, nil, stmts) 145 } 146 if err != nil { 147 if e, ok := err.(*vm.Error); ok { 148 fmt.Fprintf(os.Stderr, "%d:%d %s\n", e.Pos.Line, e.Pos.Column, err) 149 } else if e, ok := err.(*parser.Error); ok { 150 fmt.Fprintf(os.Stderr, "%d:%d %s\n", e.Pos.Line, e.Pos.Column, err) 151 } else { 152 fmt.Fprintln(os.Stderr, err) 153 } 154 continue 155 } 156 157 fmt.Printf("%#v\n", v) 158 } 159 160 if err := scanner.Err(); err != nil { 161 if err != io.EOF { 162 fmt.Fprintln(os.Stderr, "ReadString error:", err) 163 return 12 164 } 165 } 166 167 return 0 168 }