anko.go 2.8 KB

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