mua.go 6.9 KB

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