std.qi 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. func head(l): return l[0]
  2. func tail(l): return slice(l, 1)
  3. func min(x, y): x < y? x: y
  4. func max(x, y): x > y? x: y
  5. func reverse(x) {
  6. if type(x) !in ("list", "string", "bytes")
  7. throw "expected first argument to be: list, string or bytes, but got: " + type(x)
  8. var r = []
  9. for var i = len(x)-1; i >= 0; i--
  10. list_push(r, x[i])
  11. if type(x) == "string"
  12. return list_join(r)
  13. elif type(x) == "bytes"
  14. return bytes(r)
  15. return r
  16. }
  17. set_pseudomethod("list.reverse", reverse)
  18. set_pseudomethod("string.reverse", reverse)
  19. set_pseudomethod("bytes.reverse", reverse)
  20. func range(f) {
  21. var t, s
  22. if len(arguments) >= 3 {
  23. t = arguments[1]
  24. s = arguments[2]
  25. } elif len(arguments) >= 2 {
  26. t = arguments[1]
  27. s = 1
  28. } else {
  29. t = f
  30. f = 0
  31. s = 1
  32. }
  33. if type(f) != "number"
  34. throw "expected first argument to be: number, but got: " + type(f)
  35. if type(t) != "number"
  36. throw "expected second argument to be: number, but got: " + type(t)
  37. if type(s) != "number"
  38. throw "expected third argument to be: number, but got: " + type(s)
  39. if f > t
  40. return reverse(range(t, f, s))
  41. var r = []
  42. for var i = f; i < t; i += s
  43. list_push(r, i)
  44. return r
  45. }
  46. let SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2
  47. func frewind(file)
  48. return file.rewind()
  49. func file_read(filename) {
  50. let file = fopen(filename, "r")
  51. defer fclose(file)
  52. return str(fread(file, -1))
  53. }
  54. func file_write(filename, data) {
  55. let file = fopen(filename, "w")
  56. defer fclose(file)
  57. fwrite(file, bytes(data))
  58. }
  59. func is_defined(name) {
  60. if type(name) != "string"
  61. throw "expected first argument to be: string, but got: " + type(name)
  62. inline `qi_bool b = qi_find(state, qi_get(state, "name")->value.string) != NULL`
  63. inline `return qi_make_boolean(state, b)`
  64. }
  65. func is_table(a) {
  66. inline `return qi_make_boolean(state, qi_get(state, "a")->type == QI_TABLE)`
  67. }
  68. func list_remove(l, x, first=false) {
  69. if type(l) != "list"
  70. throw "expected first argument to be: list, but got: " + type(l)
  71. repeat:
  72. for var i = 0; i < len(l); i++
  73. if l[i] == x {
  74. list_delete(l, i)
  75. if first
  76. break
  77. goto repeat
  78. }
  79. }
  80. set_pseudomethod("list.remove", list_remove)
  81. func list_join(l) {
  82. if type(l) != "list"
  83. throw "expected first argumient to be: list, but got: " + type(l)
  84. var r = ""
  85. var s
  86. if len(arguments) == 1
  87. s = ""
  88. else
  89. s = arguments[1]
  90. if type(s) != "string"
  91. throw "expected second argument to be: string, but got: " + type(s)
  92. var first = true
  93. for var x of l {
  94. if type(x) != "string"
  95. throw "expected sequence item to be: string, but got: " + type(x)
  96. if s != "" && !first
  97. r += s
  98. r += x
  99. first = false
  100. }
  101. return r
  102. }
  103. set_pseudomethod("list.join", list_join)
  104. func list_pop_at(l, i) {
  105. if type(l) != "list"
  106. throw "expected first argument to be: list, but got: " + type(l)
  107. if type(i) != "number"
  108. throw "expected second argument to be: number, but got: " + type(i)
  109. var x = l[i]
  110. list_delete(l, i)
  111. return x
  112. }
  113. set_pseudomethod("list.popAt", list_pop_at)
  114. func __cmp(x, y): x > y? 1: x < y? -1: 0
  115. func list_sort(l, cmp=__cmp) {
  116. if type(l) != "list"
  117. throw "expected first argument to be: list, but got: " + type(l)
  118. if type(cmp) != "function"
  119. throw "expected second argument to be: function, but got: " + type(cmp)
  120. if len(l) == 0
  121. return l
  122. var z = len(l)
  123. for var i = 0; i < z - 1; i++
  124. for var j = 0; j < z - 1 - i; j++
  125. if cmp(l[j], l[j+1]) > 0 {
  126. let tmp = l[j]
  127. l[j] = l[j+1]
  128. l[j+1] = tmp
  129. }
  130. return l
  131. }
  132. func list_sorted(l, cmp=__cmp) {
  133. l = list_copy(l)
  134. return list_sort(l, cmp)
  135. }
  136. set_pseudomethod("list.sort", list_sort)
  137. set_pseudomethod("list.sorted", list_sorted)
  138. func list_shift(l) {
  139. if type(l) != "list"
  140. throw "expected first argument to be: list, but got: " + type(l)
  141. if is_empty(l)
  142. throw "shift from empty list"
  143. var a = l[0]
  144. list_delete(l, 0)
  145. return a
  146. }
  147. func list_unshift(l, x) {
  148. list_insert(l, 0, x)
  149. }
  150. set_pseudomethod("list.shift", list_shift)
  151. set_pseudomethod("list.unshift", list_unshift)
  152. func slice(l) {
  153. if type(l) !in ("list", "string", "bytes", "ustr")
  154. throw "expected first argument to be: list, string, bytes or ustr, but got: " + type(l)
  155. var r = []
  156. if len(arguments) == 2 {
  157. var f = arguments[1]
  158. if type(f) != "number"
  159. throw "expected second argument to be: number, but got: " + type(f)
  160. if f < 0
  161. f += len(l)
  162. for var i = f; i < len(l); i++
  163. list_push(r, l[i])
  164. } elif len(arguments) == 3 {
  165. var f = arguments[1], t = arguments[2]
  166. if type(f) != "number"
  167. throw "expected second argument to be: number, but got: " + type(f)
  168. if type(t) != "number"
  169. throw "expected third argument to be: number, but got: " + type(t)
  170. if f < 0
  171. f += len(l)
  172. if t < 0
  173. t += len(l)
  174. for var i = f; i < len(l) && i <= t; i++
  175. list_push(r, l[i])
  176. }
  177. if type(l) == "string"
  178. return list_join(r)
  179. elif type(l) == "bytes"
  180. return bytes(r)
  181. elif type(l) == "ustr"
  182. return ustr(r)
  183. return r
  184. }
  185. set_pseudomethod("list.slice", slice)
  186. set_pseudomethod("string.slice", slice)
  187. set_pseudomethod("bytes.slice", slice)
  188. let __slice = slice;
  189. func str_startswith(s, p) {
  190. if type(s) != "string"
  191. throw "expected first argument to be: string, but got: " + type(s)
  192. if len(s) < len(p)
  193. return false
  194. return slice(s, 0, len(p)-1) == p
  195. }
  196. set_pseudomethod("string.startsWith", str_startswith)
  197. func str_endswith(s, p) {
  198. if type(s) != "string"
  199. throw "expected first argument to be: string, but got: " + type(s)
  200. if len(s) < len(p)
  201. return false
  202. return slice(s, len(s) - len(p)) == p
  203. }
  204. set_pseudomethod("string.endsWith", str_endswith)
  205. func str_split(s) {
  206. if len(arguments) == 1 || arguments[1] == ""
  207. return list(s)
  208. if type(s) != "string"
  209. throw "expected first argument to be:!string, but got: " + type(s)
  210. var r = []
  211. var d = arguments[1]
  212. if type(d) != "string"
  213. throw "expected second argument to be: string, but got: " + type(s)
  214. var t = ""
  215. for var i = 0; i < len(s); i++ {
  216. if slice(s, i, i+len(d)-1) == d {
  217. list_push(r, t)
  218. t = ""
  219. i += len(d)-1
  220. continue
  221. }
  222. t += s[i]
  223. }
  224. if t != ""
  225. list_push(r, t)
  226. return r
  227. }
  228. set_pseudomethod("string.split", str_split)
  229. func str_replace(s, w, b) {
  230. if type(s) != "string"
  231. throw "expected first argument to be: string, but got: " + type(s)
  232. if type(w) != "string"
  233. throw "expected second argument to be: string, but got: " + type(w)
  234. if type(b) != "string"
  235. throw "expected third argument to be: string, but got: " + type(b)
  236. var r = ""
  237. for var i = 0; i < len(s); i++ {
  238. if slice(s, i, i+len(w)-1) == w {
  239. r += b
  240. i += len(w)-1
  241. continue
  242. }
  243. r += s[i]
  244. }
  245. return r
  246. }
  247. set_pseudomethod("string.replace", str_replace)
  248. func table_keys(t) {
  249. if type(t) != "table"
  250. throw "expected first argument to be: table, but got: " + type(t)
  251. var r = []
  252. for var k of t
  253. list_push(r, k)
  254. return r
  255. }
  256. set_pseudomethod("table.keys", table_keys)
  257. func table_values(t) {
  258. if type(t) != "table"
  259. throw "expected first argument to be: table, but got: " + type(t)
  260. var r = []
  261. for var k of t
  262. list_push(r, t[k])
  263. return r
  264. }
  265. set_pseudomethod("table.values", table_values)
  266. func reduce(f, xs) {
  267. if type(f) != "function"
  268. throw "expected first argument to be: function, but got: " + type(f)
  269. if type(xs) !in ("list", "tuple", "string", "bytes")
  270. throw "expected second argument to be: list, tuple, string or bytes, but got: " + type(xs)
  271. if len(xs) == 0
  272. throw "cannot reduce empty list"
  273. r = xs[0]
  274. for var x of slice(xs, 1)
  275. r = f(r, x)
  276. if type(xs) == "tuple"
  277. return tuple(r)
  278. elif type(xs) == "string"
  279. return list_join(r)
  280. elif type(xs) == "bytes"
  281. return bytes(r)
  282. return r
  283. }
  284. set_pseudomethod("list.reduce", func (xs, f): reduce(f, xs))
  285. set_pseudomethod("tuple.reduce", func (xs, f): reduce(f, xs))
  286. set_pseudomethod("string.reduce", func (xs, f): reduce(f, xs))
  287. set_pseudomethod("bytes.reduce", func (xs, f): reduce(f, xs))
  288. func sum(xs)
  289. return reduce(func (x, y): x + y, xs)
  290. set_pseudomethod("list.sum", sum)
  291. set_pseudomethod("tuple.sum", sum)
  292. func product(xs)
  293. return reduce(func (x, y): x * y, xs)
  294. set_pseudomethod("list.product", product)
  295. set_pseudomethod("tuple.product", product)
  296. func all(l): reduce(func (x, y): x && y, l)
  297. set_pseudomethod("list.all", all)
  298. set_pseudomethod("tuple.all", all)
  299. func any(l): reduce(func (x, y): x || y, l)
  300. set_pseudomethod("list.any", any)
  301. set_pseudomethod("tuple.any", any)
  302. func map(f, xs) {
  303. if type(f) != "function"
  304. throw "expected first argument to be: function, but got: " + type(f)
  305. if type(xs) !in ("list", "tuple", "string", "bytes")
  306. throw "expected second argument to be: list, tuple, string or bytes, but got: " + type(xs)
  307. if len(xs) == 0
  308. return xs
  309. var r = []
  310. for var x of xs
  311. list_push(r, f(x))
  312. if type(xs) == "tuple"
  313. return tuple(r)
  314. elif type(xs) == "string"
  315. return list_join(r)
  316. elif type(xs) == "bytes"
  317. return bytes(r)
  318. return r
  319. }
  320. set_pseudomethod("list.map", func (xs, f): map(f, xs))
  321. set_pseudomethod("tuple.map", func (xs, f): map(f, xs))
  322. set_pseudomethod("string.map", func (xs, f): map(f, xs))
  323. set_pseudomethod("bytes.map", func (xs, f): map(f, xs))
  324. func filter(f, xs) {
  325. if type(f) != "function"
  326. throw "expected first argument to be: function, but got: " + type(f)
  327. if type(xs) !in ("list", "tuple", "string", "bytes")
  328. throw "expected second argument to be: list, tuple, string or bytes, but got: " + type(xs)
  329. if len(xs) == 0
  330. return xs
  331. var r = []
  332. for var x of xs
  333. if f(x)
  334. list_push(r, x)
  335. if type(xs) == "tuple"
  336. return tuple(r)
  337. elif type(xs) == "string"
  338. return list_join(r)
  339. elif type(xs) == "bytes"
  340. return bytes(r)
  341. return r
  342. }
  343. set_pseudomethod("list.filter", func (xs, f): filter(f, xs))
  344. set_pseudomethod("tuple.filter", func (xs, f): filter(f, xs))
  345. set_pseudomethod("string.filter", func (xs, f): filter(f, xs))
  346. set_pseudomethod("bytes.filter", func (xs, f): filter(f, xs))
  347. func str_index(s, w) {
  348. if s == "" || w == ""
  349. return -1
  350. if type(s) != "string"
  351. throw "expected first argument to be: string, but got: " + type(s)
  352. if type(w) != "string"
  353. throw "expected second argument to be: string, but got: " + type(w)
  354. for var i = 0; i < len(s); i++
  355. if len(w) == 1 && s[i] == w
  356. return i
  357. elif slice(s, i, i+len(w)-1) == w
  358. return i
  359. return -1
  360. }
  361. set_pseudomethod("string.index", str_index)
  362. func str_lstrip(s, cs=" \t\n\r\x0b\x0c") {
  363. if type(s) != "string"
  364. throw "expected first argument to be: string, but got: " + type(s)
  365. if type(cs) != "string"
  366. throw "expected second argument to be: string, but got: " + type(cs)
  367. if s == ""
  368. return s
  369. var i
  370. for i = 0; s[i] in cs && i < len(s); i++
  371. pass
  372. return slice(s, i)
  373. }
  374. set_pseudomethod("string.lstrip", str_lstrip)
  375. func str_rstrip(s, cs=" \t\n\r\x0b\x0c") {
  376. if type(s) != "string"
  377. throw "expected first argument to be: string, but got: " + type(s)
  378. if type(cs) != "string"
  379. throw "expected second argument to be: string, but got: " + type(cs)
  380. if s == ""
  381. return s
  382. var k, i
  383. for k = 0, i = len(s)-1; s[i] in cs && i >= 0; k++
  384. i--
  385. return slice(s, 0, len(s)-k-1)
  386. }
  387. set_pseudomethod("string.rstrip", str_rstrip)
  388. func str_strip(s, cs=" \t\n\r\x0b\x0c") {
  389. if type(s) != "string"
  390. throw "expected first argument to be: string, but got: " + type(s)
  391. if type(cs) != "string"
  392. throw "expected second argument to be: string, but got: " + type(cs)
  393. return str_lstrip(str_rstrip(s, cs), cs)
  394. }
  395. set_pseudomethod("string.strip", str_strip)
  396. func zip() {
  397. if !arguments
  398. return []
  399. var l = map(len, arguments)
  400. l = reduce(min, l)
  401. var r = []
  402. for var i = 0; i < l; i++ {
  403. var t = []
  404. for var xs of arguments
  405. list_push(t, xs[i])
  406. list_push(r, t)
  407. }
  408. return r
  409. }
  410. func enumerate(l)
  411. if type(l) == "table"
  412. return zip(table_keys(l), table_values(l))
  413. else
  414. return zip(range(len(l)), l)
  415. func str_toupper(s) {
  416. if type(s) != "string"
  417. throw "expected first argument to be: string, but got: " + type(c)
  418. return map(func (c): c >= 'a' && c <= 'z'? chr(ord(c) - 32): c, s)
  419. }
  420. set_pseudomethod("string.toupper", str_toupper)
  421. func str_tolower(s) {
  422. if type(s) != "string"
  423. throw "expected first argument to be: string, but got: " + type(c)
  424. return map(func (c): c >= 'A' && c <= 'Z'? chr(ord(c) + 32): c, s)
  425. }
  426. set_pseudomethod("string.tolower", str_tolower)
  427. func Object(t, p=nil, o={}): return p !is nil? set_meta_table(p, get_meta_table(p) + t): set_meta_table(o, t)
  428. func is_object(o): return has_meta_table(o)
  429. func __class_wrapper(n, p, t, mt, st): return Object({
  430. "t": t,
  431. "mt": mt,
  432. "super": p,
  433. "__type": func (this) use (n): return n,
  434. "__str": func (this) use (n): return "<class " + n + ">",
  435. "__call": func (this, pargs) use (n, p) {
  436. var t = {}
  437. var mt = { "__type": func (this) use (n): n }
  438. if p {
  439. var i = 0
  440. while i < len(p) {
  441. t += p[i].t
  442. mt += p[i].mt
  443. i += 1
  444. }
  445. }
  446. t += this.t
  447. mt += this.mt
  448. mt.super = this.super
  449. var obj = set_meta_table(t, mt)
  450. if "constructor" in mt
  451. func_call(mt.constructor, [obj] + pargs)
  452. return obj
  453. }
  454. }, nil, st)
  455. func format(s) {
  456. if type(s) != "string"
  457. throw "expected first argument to be: string, but got: " + type(s)
  458. var r = ""
  459. var n = 1
  460. for var i = 0; i < len(s); i++
  461. switch s[i] {
  462. case '_'
  463. if i+1 < len(s) && s[i+1] == '_' {
  464. r += '_'
  465. i++
  466. continue
  467. }
  468. r += repr(arguments[n++])
  469. break
  470. default
  471. r += s[i]
  472. }
  473. return r
  474. }
  475. set_pseudomethod("string.format", format)
  476. func formatl(s, l) {
  477. if type(s) != "string"
  478. throw "expected first argument to be: string, but got: " + type(s)
  479. if type(l) != "list"
  480. throw "expected second argument to be: list, but got: " + type(l)
  481. return func_call(str_format, [s] + l)
  482. }
  483. set_pseudomethod("string.formatl", formatl)
  484. func formatd(s, t) {
  485. if type(s) != "string"
  486. throw "expected first argument to be: string, but got: " + type(s)
  487. var r = ""
  488. var n = 1
  489. for var i = 0; i < len(s); i++
  490. switch s[i] {
  491. case '{'
  492. if i+1 < len(s) && s[i+1] == '{' {
  493. r += '{'
  494. i++
  495. continue
  496. }
  497. var k = ''
  498. i++
  499. for i < len(s) && s[i] != '}'
  500. k += s[i++]
  501. if i >= len(s) || s[i] != '}'
  502. throw "unmatched { in format specifier"
  503. if !k
  504. throw "empty format key"
  505. r += repr(t[k])
  506. break
  507. default
  508. r += s[i]
  509. }
  510. return r
  511. }
  512. set_pseudomethod("string.formatd", formatd)
  513. func getch() return chr(fgetc(STDIN))
  514. func putch(c) fputc(STDOUT, c)
  515. func getline()
  516. return fgets(STDIN, 256)
  517. func input() {
  518. if len(arguments) > 0
  519. func_call(print, arguments)
  520. return str_rstrip(getline(), "\n\r")
  521. }
  522. func open(path, mode="r"): fopen(path, mode)
  523. set_pseudomethod("file.__enter", func () {})
  524. set_pseudomethod("file.__leave", func (f): fclose(f))
  525. set_pseudomethod("file.close", fclose)
  526. set_pseudomethod("file.flush", fflush)
  527. set_pseudomethod("file.seek", fseek)
  528. set_pseudomethod("file.getc", fgetc)
  529. set_pseudomethod("file.putc", fputc)
  530. set_pseudomethod("file.gets", fgets)
  531. set_pseudomethod("file.puts", fputs)
  532. set_pseudomethod("file.tell", ftell)
  533. set_pseudomethod("reference.deref", deref)
  534. set_pseudomethod("reference.set", ref_set)
  535. class Error {
  536. msg = nil
  537. constructor (this, msg=nil) {
  538. this.msg = msg
  539. }
  540. __str (this): this.msg is nil? type(this): type(this) + ": " + this.msg
  541. }
  542. class AssertionError(Error)
  543. func assert(cond, msg=AssertionError())
  544. if !cond
  545. throw msg
  546. class ListIterator {
  547. constructor(this, l) {
  548. this.l = list(l)
  549. this.i = 0
  550. this.z = len(this.l)
  551. }
  552. __str(this): "<ListIterator>"
  553. __begin(this) {
  554. this.i = 0
  555. return this
  556. }
  557. __next(this) {
  558. if this.i < this.z
  559. return this.l[this.i++]
  560. }
  561. __end(this): this.i >= this.z
  562. }
  563. class OrderedTable {
  564. __data__ = nil
  565. constructor (this, v=nil) {
  566. this.__data__ = []
  567. if v !is nil {
  568. v = table(v)
  569. for var k of v
  570. this[k] = v[k]
  571. }
  572. }
  573. __type (this): "orderedtable"
  574. stringify (this, tempstack=[]) {
  575. if this in tempstack
  576. return "OrderedTable({...})"
  577. tempstack.push(this)
  578. var buf = "OrderedTable({"
  579. var f = true
  580. for var [k, v] of this.__data__ {
  581. if f
  582. f = false
  583. else buf += ", "
  584. k = k.replace(`\`, `\\`).replace(`"`, `\"`)
  585. if type(v) is "orderedtable"
  586. v = v.stringify(tempstack)
  587. buf += f`"${k}": ${v}`
  588. }
  589. buf += "})"
  590. return buf
  591. }
  592. __str (this) {
  593. return this.stringify([])
  594. }
  595. keys (this) {
  596. let keys = []
  597. for var [k, _] of this.__data__
  598. keys.push(k)
  599. return keys
  600. }
  601. values (this) {
  602. let values = []
  603. for var [_, v] of this.__data__
  604. values.push(v)
  605. return values
  606. }
  607. delete (this, k) {
  608. del this[k]
  609. }
  610. copy (this) {
  611. return OrderedTable(this.__data__)
  612. }
  613. get (this, k, d=nil) {
  614. k = str(k)
  615. for var [ok, v] of this.__data__
  616. if ok == k
  617. return v
  618. return d
  619. }
  620. __iter (this): ListIterator(this.keys())
  621. __len (this): len(this.__data__)
  622. __in (this, k) {
  623. k = str(k)
  624. for var [ok, _] of this.__data__
  625. if ok == k
  626. return true
  627. return false
  628. }
  629. __del (this, k) {
  630. k = str(k)
  631. for var [i, ok] of zip(range(len(this)), this.keys())
  632. if ok == k {
  633. del this.__data__[i]
  634. return
  635. }
  636. throw "no such key: " + k
  637. }
  638. __index (this, k) {
  639. k = str(k)
  640. for var [ok, v] of this.__data__
  641. if ok == k
  642. return v
  643. throw "no such key: " + k
  644. }
  645. __index_set (this, k, v) {
  646. k = str(k)
  647. for var [i, ok] of zip(range(len(this)), this.keys())
  648. if ok == k {
  649. this.__data__[i] = (ok, v)
  650. return
  651. }
  652. this.__data__.push((k, v))
  653. }
  654. }