mua.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "math/rand"
  6. "os"
  7. "strings"
  8. "time"
  9. )
  10. var reserved = map[string]int{
  11. "make": 2, "thing": 1, "print": 1, "read": 0, "add": 2,
  12. "sub": 2, "mul": 2, "div": 2, "mod": 2, "erase": 1,
  13. "isname": 1, "run": 1, "eq": 2, "gt": 2, "lt": 2,
  14. "and": 2, "or": 2, "not": 1, "if": 3, "isnumber": 1,
  15. "isword": 1, "islist": 1, "isbool": 1, "isempty": 1, "return": 1,
  16. "export": 1, "readlist": 0, "word": 2, "sentence": 2, "list": 2,
  17. "join": 2, "first": 1, "last": 1, "butfirst": 1, "butlast": 1,
  18. "random": 1, "int": 1, "sqrt": 1, "save": 1, "load": 1,
  19. "erall": 0, "poall": 0}
  20. type environ map[string]value
  21. type value struct {
  22. tp int
  23. num float64
  24. word string
  25. list []string
  26. param []string
  27. body []string
  28. env environ
  29. b bool
  30. }
  31. func interpret(scanner *scanProvider, envs []environ) (val value, returned bool) {
  32. stack, returned := []value{}, false
  33. for !returned && scanner.Scan() {
  34. // for _, v := range stack {
  35. // fmt.Println(toString(v))
  36. // }
  37. // fmt.Println()
  38. // fmt.Println(envs[0])
  39. // fmt.Println()
  40. s := scanner.Text()
  41. if s == "\n" {
  42. continue
  43. }
  44. if s[0] == ':' {
  45. leading := len(s) - len(strings.TrimLeft(s, ":"))
  46. val := toValue(value{word: `"` + s[leading:]}, envs[0])
  47. for i := 0; i < leading; i++ {
  48. val = toValue(opThing(val, envs), envs[0])
  49. }
  50. stack = append(stack, val)
  51. } else if s[0] == '[' && !scanner.isList {
  52. list, bracketCnt := []string{}, 0
  53. for {
  54. leading := len(s) - len(strings.TrimLeft(s, "["))
  55. trailing := len(s) - len(strings.TrimRight(s, "]"))
  56. escape := len(s) - len(strings.TrimRight(strings.TrimRight(s, "]"), `\`)) - trailing
  57. trailing -= escape & 1
  58. s = s[leading : len(s)-trailing]
  59. for i := 0; i < leading; i++ {
  60. list = append(list, "[")
  61. }
  62. if s != "" {
  63. list = append(list, s)
  64. }
  65. for i := 0; i < trailing; i++ {
  66. list = append(list, "]")
  67. }
  68. bracketCnt += leading - trailing
  69. if bracketCnt < 0 {
  70. panic(fmt.Errorf("list: %s", errUnmatchedBracket))
  71. }
  72. if bracketCnt == 0 {
  73. break
  74. }
  75. s = "\n"
  76. for s == "\n" && scanner.Scan() {
  77. s = scanner.Text()
  78. }
  79. if s == "\n" {
  80. panic(fmt.Errorf("list: %s", errUnmatchedBracket))
  81. }
  82. }
  83. stack = append(stack, value{word: strings.Join(list, " ")})
  84. } else {
  85. stack = append(stack, value{word: s})
  86. }
  87. for !returned {
  88. updated := false
  89. for i := len(stack) - 1; i >= 0; i-- {
  90. if !isName(value{word: `"` + stack[i].word}) {
  91. continue
  92. }
  93. paramCnt, ok := reserved[stack[i].word]
  94. if ok {
  95. if paramCnt == len(stack)-1-i {
  96. for j := i + 1; j < len(stack); j++ {
  97. stack[j] = toValue(stack[j], envs[0])
  98. }
  99. switch stack[i].word {
  100. case "make":
  101. stack[i] = opMake(stack[i+1], stack[i+2], envs)
  102. case "thing":
  103. stack[i] = opThing(stack[i+1], envs)
  104. case "print":
  105. stack[i] = opPrint(stack[i+1])
  106. case "read":
  107. stack[i] = opRead(scanner)
  108. case "add":
  109. stack[i] = opAdd(stack[i+1], stack[i+2])
  110. case "sub":
  111. stack[i] = opSub(stack[i+1], stack[i+2])
  112. case "mul":
  113. stack[i] = opMul(stack[i+1], stack[i+2])
  114. case "div":
  115. stack[i] = opDiv(stack[i+1], stack[i+2])
  116. case "mod":
  117. stack[i] = opMod(stack[i+1], stack[i+2])
  118. case "erase":
  119. stack[i] = opErase(stack[i+1], envs)
  120. case "isname":
  121. stack[i] = opIsName(stack[i+1], envs)
  122. case "run":
  123. stack[i], returned = opRun(stack[i+1], envs)
  124. case "eq":
  125. stack[i] = opEq(stack[i+1], stack[i+2])
  126. case "gt":
  127. stack[i] = opGt(stack[i+1], stack[i+2])
  128. case "lt":
  129. stack[i] = opLt(stack[i+1], stack[i+2])
  130. case "and":
  131. stack[i] = opAnd(stack[i+1], stack[i+2])
  132. case "or":
  133. stack[i] = opOr(stack[i+1], stack[i+2])
  134. case "not":
  135. stack[i] = opNot(stack[i+1])
  136. case "if":
  137. stack[i], returned = opIf(stack[i+1], stack[i+2], stack[i+3], envs)
  138. case "isnumber":
  139. stack[i] = opIsNumber(stack[i+1])
  140. case "isword":
  141. stack[i] = opIsWord(stack[i+1])
  142. case "islist":
  143. stack[i] = opIsList(stack[i+1])
  144. case "isbool":
  145. stack[i] = opIsBool(stack[i+1])
  146. case "isempty":
  147. stack[i] = opIsEmpty(stack[i+1])
  148. case "return":
  149. stack[i], returned = stack[i+1], true
  150. case "export":
  151. stack[i] = opExport(stack[i+1], envs)
  152. case "readlist":
  153. stack[i] = opReadList(scanner)
  154. case "word":
  155. stack[i] = opWord(stack[i+1], stack[i+2])
  156. case "sentence":
  157. stack[i] = opSentence(stack[i+1], stack[i+2])
  158. case "list":
  159. stack[i] = opList(stack[i+1], stack[i+2])
  160. case "join":
  161. stack[i] = opJoin(stack[i+1], stack[i+2])
  162. case "first":
  163. stack[i] = opFirst(stack[i+1])
  164. case "last":
  165. stack[i] = opLast(stack[i+1])
  166. case "butfirst":
  167. stack[i] = opButFirst(stack[i+1])
  168. case "butlast":
  169. stack[i] = opButLast(stack[i+1])
  170. case "random":
  171. stack[i] = opRandom(stack[i+1])
  172. case "int":
  173. stack[i] = opInt(stack[i+1])
  174. case "sqrt":
  175. stack[i] = opSqrt(stack[i+1])
  176. case "save":
  177. stack[i] = opSave(stack[i+1], envs[0])
  178. case "load":
  179. stack[i] = opLoad(stack[i+1], envs[0])
  180. case "erall":
  181. stack[i] = opErAll(envs[0])
  182. case "poall":
  183. stack[i] = opPoAll(envs[0])
  184. }
  185. stack = stack[:i+1]
  186. updated = true
  187. }
  188. break
  189. }
  190. val, _ := getValue(`"`+stack[i].word, envs)
  191. if val.param != nil {
  192. if len(val.param) == len(stack)-1-i {
  193. for j := i + 1; j < len(stack); j++ {
  194. stack[j] = toValue(stack[j], envs[0])
  195. }
  196. local := environ{stack[i].word: val}
  197. for j, name := range val.param {
  198. local[name] = stack[i+1+j]
  199. }
  200. stack[i], _ = opRun(value{tp: typeList, list: val.body}, []environ{local, val.env, envs[2]})
  201. stack = stack[:i+1]
  202. updated = true
  203. }
  204. break
  205. }
  206. panic(fmt.Errorf("func: %s (%s)", errFunctionExpected, stack[i].word))
  207. }
  208. if !updated {
  209. break
  210. }
  211. }
  212. }
  213. if len(stack) == 0 {
  214. val = value{tp: typeList, list: []string{}}
  215. } else {
  216. val = toValue(stack[len(stack)-1], envs[0])
  217. }
  218. return
  219. }
  220. func main() {
  221. rand.Seed(time.Now().UnixNano())
  222. env := map[string]value{"pi": {tp: typeNumber, num: 3.14159}}
  223. if len(os.Args) > 1 {
  224. file, err := os.Open(os.Args[1])
  225. if err != nil {
  226. panic(fmt.Errorf("script: %s (%s)", errFileError, os.Args[1]))
  227. }
  228. os.Stdin = file
  229. }
  230. scanner := bufio.NewScanner(os.Stdin)
  231. scanner.Split(splitFunc)
  232. interpret(&scanProvider{isList: false, scanner: scanner}, []environ{env, nil, env})
  233. }