wmc.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. import os
  2. import os.path
  3. import sys
  4. import lark
  5. GRAMMAR = r"""
  6. start: toplevel+
  7. ?toplevel: include
  8. | funcdef
  9. | arrdec ";"
  10. | vardec ";"
  11. | varinit ";"
  12. | arrinit ";"
  13. | asm ";"
  14. include: "#" "include" FILENAME
  15. FILENAME: "<" /.+/ ">"
  16. funcdef: NAME "(" params ")" block
  17. varinit: NAME
  18. arrinit: NAME "[" INTEGER "]"
  19. vardec: NAME "=" expr
  20. arrdec: NAME "[" expr "]" ("=" expr)?
  21. params:
  22. | NAME ("," NAME)*
  23. block: "{" op* "}"
  24. asm: "asm" "(" STRING+ ")"
  25. ?op: block
  26. | label
  27. | goto ";"
  28. | vardec ";"
  29. | arrdec ";"
  30. | varinit ";"
  31. | arrinit ";"
  32. | inc ";"
  33. | dec ";"
  34. | rinc ";"
  35. | rdec ";"
  36. | asm ";"
  37. | funcall ";"
  38. | if
  39. | while
  40. | for
  41. | return ";"
  42. label: NAME ":"
  43. goto: "goto" NAME
  44. if: "if" "(" expr ")" op ("else" op)?
  45. while: "while" "(" expr ")" op
  46. for: "for" "(" vardec ";" expr ";" (inc|dec|vardec|funcall) ")" op
  47. return: "return" expr
  48. inc: NAME "++"
  49. dec: NAME "--"
  50. rinc: "++" NAME
  51. rdec: "--" NAME
  52. funcall: NAME "(" args ")"
  53. args:
  54. | [expr ("," expr)*]
  55. ?expr: op1
  56. ?op1: op2
  57. | vardec
  58. | op1 "==" op1 -> equals
  59. | op1 "!=" op1 -> not_equals
  60. | op1 "+" op2 -> plus
  61. | op1 "-" op2 -> minus
  62. ?op2: op3
  63. | op2 "*" op2 -> times
  64. | op2 "/" op3 -> divide
  65. | op2 "%" op3 -> modulo
  66. | op2 "<" op3 -> less
  67. | op2 ">" op3 -> greater
  68. | op2 "<=" op3 -> less_or_equals
  69. | op2 ">=" op3 -> greater_or_equals
  70. ?op3: op4
  71. | op3 "**" op4 -> raise
  72. ?op4: op5
  73. | op4 "||" op4 -> or
  74. | op4 "&&" op4 -> and
  75. | "!" atom -> not
  76. | "*" atom -> deref
  77. ?op5: atom
  78. | op5 "[" op1 "]" -> index
  79. ?atom: "(" op1 ")"
  80. | NAME
  81. | INTEGER
  82. | FLOAT
  83. | CHAR
  84. | STRING
  85. | "-" atom -> negate
  86. | array
  87. | funcall
  88. | inc
  89. | dec
  90. | rinc
  91. | rdec
  92. array: "{" atom ("," atom)* "}"
  93. NAME: /[A-Za-z_][a-zA-Z0-9_]*/
  94. INTEGER: /[0-9]+/
  95. FLOAT: /[0-9]+\.[0-9]+/
  96. CHAR: /'(.|(\\.))'/
  97. _STRING_INNER: /(.|\n)*?/
  98. _STRING_ESC_INNER: _STRING_INNER /(?<!\\)(\\\\)*?/
  99. STRING: "\"" _STRING_ESC_INNER "\""
  100. IG: /[ \t\r\n]+/
  101. COM: /\/\*(.|\!)*\*\//
  102. %ignore IG
  103. %ignore COM
  104. """
  105. def parse_escape(s):
  106. return bytes(s, "utf-8").decode("unicode_escape")
  107. class Buffer:
  108. def __init__(self, *init):
  109. self.buffer = list(init)
  110. def emit(self, asm, *args):
  111. if type(asm) is list:
  112. self.buffer.extend(asm)
  113. elif type(asm) is Buffer:
  114. self.buffer.extend(asm.buffer)
  115. else:
  116. self.buffer.append(asm.format(*args))
  117. def generate(self):
  118. return "\n".join(self.buffer)
  119. def __add__(self, other):
  120. if type(other) is Buffer:
  121. return Buffer(
  122. *self.buffer + other.buffer
  123. )
  124. raise TypeError
  125. class Scope:
  126. def __init__(self):
  127. self.scopes = []
  128. self.ndx = 0
  129. self.names = set()
  130. def new(self):
  131. self.scopes.append((self.ndx, {}, {}))
  132. self.ndx += 1
  133. def leave(self):
  134. self.scopes.pop()
  135. def add_label(self, name):
  136. renamed = f"__{self.scopes[-1][0]}l_{name}"
  137. self.scopes[-1][2][name] = renamed
  138. return renamed
  139. def get_label(self, name):
  140. if name not in self.scopes[-1][2]:
  141. raise Exception(f"Undeclared label: '{name}`.")
  142. return self.scopes[-1][2][name]
  143. def is_local(self, name):
  144. return name in self.scopes[-1][1]
  145. def insert(self, name):
  146. renamed = f"__{self.scopes[-1][0]}_{name}"
  147. self.scopes[-1][1][name] = renamed
  148. self.names.add(renamed)
  149. return renamed
  150. def find(self, name):
  151. for _, scope, _ in self.scopes[::-1]:
  152. if name in scope:
  153. return scope[name]
  154. raise Exception(f"Undeclared identifier: '{name}`.")
  155. def __contains__(self, name):
  156. for _, scope, _ in self.scopes[::-1]:
  157. if name in scope:
  158. return True
  159. return False
  160. def __getitem__(self, name):
  161. if name in self:
  162. return self.find(name)
  163. return self.insert(name)
  164. def __iter__(self):
  165. for _, scope, _ in self.scopes[::-1]:
  166. for name in scope:
  167. yield (name, scope[name])
  168. @property
  169. def is_toplevel(self):
  170. return self.scopes[-1][0] == 0
  171. class Func:
  172. def __init__(self, argc, params):
  173. self.argc = argc
  174. self.params = params
  175. class WMC:
  176. def __init__(self):
  177. self.funcs = {}
  178. self.used_symbols = {}
  179. self.where = "toplevel"
  180. self.scope = Scope()
  181. self.scope.new()
  182. self.compiled_funcs = {}
  183. self.arrays_buffer = Buffer()
  184. self.init_buffer = Buffer()
  185. self.buffer = Buffer(
  186. "jw __main",
  187. "pop Y",
  188. "mov 80 _dirBuf",
  189. "mov Y _dirBuf+1",
  190. "dir _dirBuf",
  191. "hlt",
  192. "_dirBuf:0*4",
  193. )
  194. self.label_ndx = 0
  195. self.included_files = set()
  196. self.parser = lark.Lark(GRAMMAR)
  197. def record_usage(self, name):
  198. if name in self.used_symbols:
  199. self.used_symbols[name].add(self.where)
  200. else:
  201. self.used_symbols[name] = set([self.where])
  202. def is_used(self, name):
  203. if name in ("main", "toplevel"):
  204. return True
  205. if name not in self.used_symbols:
  206. return False
  207. for other in self.used_symbols[name]:
  208. if other == name:
  209. continue
  210. if self.is_used(other):
  211. return True
  212. return False
  213. def make_label(self):
  214. name = f"__{self.label_ndx}l"
  215. self.label_ndx += 1
  216. return name
  217. def make_array(self, value):
  218. name = self.make_label()
  219. self.arrays_buffer.emit(
  220. "{}:{}",
  221. name, value
  222. )
  223. return name
  224. def compile_literal(self, node):
  225. if type(node) is lark.Token:
  226. if node.type == "NAME":
  227. value = self.scope.find(node.value)
  228. self.record_usage(value)
  229. return value
  230. elif node.type in ("INTEGER", "FLOAT"):
  231. return node.value
  232. elif node.type == "CHAR":
  233. return str(ord(parse_escape(node.value[1:-1])))
  234. elif node.type == "STRING":
  235. value = parse_escape(node.value[1:-1])
  236. value = map(ord, value)
  237. value = map(str, value)
  238. value = " ".join(value)
  239. value += " 0"
  240. return value
  241. elif node.data == "array":
  242. value = []
  243. for child in node.children:
  244. value.append(
  245. self.compile_literal(child)
  246. )
  247. return " ".join(value)
  248. raise Exception(f"Not implemented: {node}")
  249. def compile_unary_expr(self, node, *ops):
  250. buffer = Buffer()
  251. buffer.emit(
  252. self.compile_expr(
  253. node.children[0]
  254. )
  255. )
  256. for op in ops:
  257. buffer.emit(op)
  258. return buffer
  259. def compile_binary_expr(self, node):
  260. buffer = Buffer()
  261. buffer.emit(
  262. self.compile_expr(
  263. node.children[0]
  264. )
  265. )
  266. buffer.emit('push Y')
  267. buffer.emit(
  268. self.compile_expr(
  269. node.children[1]
  270. )
  271. )
  272. buffer.emit('push Y')
  273. buffer.emit('pop X')
  274. buffer.emit('pop Y')
  275. return buffer
  276. def compile_compare_expr(self, node, *ops, true='1', false='0'):
  277. buffer = Buffer()
  278. ret_label = self.make_label()
  279. exit_label = self.make_label()
  280. buffer.emit(
  281. self.compile_binary_expr(
  282. node
  283. )
  284. )
  285. for op in ops:
  286. buffer.emit(
  287. op,
  288. ret_label
  289. )
  290. buffer.emit(
  291. "mov {} Y",
  292. false
  293. )
  294. buffer.emit(
  295. "jmp {}",
  296. exit_label
  297. )
  298. buffer.emit(
  299. "{}:",
  300. ret_label
  301. )
  302. buffer.emit(
  303. "mov {} Y",
  304. true
  305. )
  306. buffer.emit(
  307. "{}:",
  308. exit_label
  309. )
  310. return buffer
  311. def compile_expr(self, node):
  312. buffer = Buffer()
  313. if type(node) is lark.Token:
  314. if node.type == "NAME":
  315. buffer.emit(
  316. "mov {} Y",
  317. self.compile_literal(node)
  318. )
  319. elif node.type in ("INTEGER", "FLOAT"):
  320. buffer.emit(
  321. "mov {} Y",
  322. self.compile_literal(node)
  323. )
  324. elif node.type == "CHAR":
  325. buffer.emit(
  326. "mov {} Y",
  327. self.compile_literal(node)
  328. )
  329. elif node.type == "STRING":
  330. buffer.emit(
  331. "ld {} Y",
  332. self.make_array(
  333. self.compile_literal(node)
  334. )
  335. )
  336. else:
  337. raise Exception(f"Not implemented: {node}")
  338. elif node.data == "equals":
  339. buffer.emit(
  340. self.compile_compare_expr(
  341. node,
  342. "sblez X Y !",
  343. "nbnz Y {}",
  344. true='1',
  345. false='0'
  346. )
  347. )
  348. elif node.data == "not_equals":
  349. buffer.emit(
  350. self.compile_compare_expr(
  351. node,
  352. "sblez X Y !",
  353. "nbnz Y {}",
  354. true='0',
  355. false='1'
  356. )
  357. )
  358. elif node.data == "plus":
  359. buffer.emit(
  360. self.compile_binary_expr(
  361. node
  362. )
  363. )
  364. buffer.emit(
  365. "ablez X Y !"
  366. )
  367. elif node.data == "minus":
  368. buffer.emit(
  369. self.compile_binary_expr(
  370. node
  371. )
  372. )
  373. buffer.emit(
  374. "sblez X Y !"
  375. )
  376. elif node.data == "times":
  377. buffer.emit(
  378. self.compile_binary_expr(
  379. node
  380. )
  381. )
  382. buffer.emit(
  383. "mbnz X Y !"
  384. )
  385. elif node.data == "divide":
  386. buffer.emit(
  387. self.compile_binary_expr(
  388. node
  389. )
  390. )
  391. buffer.emit(
  392. "vblz X Y !"
  393. )
  394. elif node.data == "modulo":
  395. buffer.emit(
  396. self.compile_binary_expr(
  397. node
  398. )
  399. )
  400. buffer.emit(
  401. "modbz X Y !"
  402. )
  403. elif node.data == "raise":
  404. buffer.emit(
  405. self.compile_binary_expr(
  406. node
  407. )
  408. )
  409. buffer.emit(
  410. "mov 12 _dirBuf"
  411. )
  412. buffer.emit(
  413. "mov X _dirBuf+1"
  414. )
  415. buffer.emit(
  416. "mov Y _dirBuf+2"
  417. )
  418. buffer.emit(
  419. "dir _dirBuf"
  420. )
  421. buffer.emit(
  422. "mov _dirBuf+2 Y"
  423. )
  424. elif node.data == "or":
  425. true_label = self.make_label()
  426. exit_label = self.make_label()
  427. buffer.emit(
  428. self.compile_expr(
  429. node.children[0]
  430. )
  431. )
  432. buffer.emit(
  433. "nbnz Y !"
  434. )
  435. buffer.emit(
  436. "nbnz Y {}",
  437. true_label
  438. )
  439. buffer.emit(
  440. self.compile_expr(
  441. node.children[1]
  442. )
  443. )
  444. buffer.emit(
  445. "jmp {}",
  446. exit_label
  447. )
  448. buffer.emit(
  449. "{}:",
  450. true_label
  451. )
  452. buffer.emit(
  453. "mov 1 Y"
  454. )
  455. buffer.emit(
  456. "{}:",
  457. exit_label
  458. )
  459. elif node.data == "and":
  460. false_label = self.make_label()
  461. exit_label = self.make_label()
  462. buffer.emit(
  463. self.compile_expr(
  464. node.children[0]
  465. )
  466. )
  467. buffer.emit(
  468. "nbnz Y {}",
  469. false_label
  470. )
  471. buffer.emit(
  472. self.compile_expr(
  473. node.children[1]
  474. )
  475. )
  476. buffer.emit(
  477. "jmp {}",
  478. exit_label
  479. )
  480. buffer.emit(
  481. "{}:",
  482. false_label
  483. )
  484. buffer.emit(
  485. "mov 0 Y"
  486. )
  487. buffer.emit(
  488. "{}:",
  489. exit_label
  490. )
  491. elif node.data == "less":
  492. buffer.emit(
  493. self.compile_compare_expr(
  494. node,
  495. "inc Y",
  496. "sblez X Y {}"
  497. )
  498. )
  499. elif node.data == "greater":
  500. buffer.emit(
  501. self.compile_compare_expr(
  502. node,
  503. "dec Y",
  504. "sblez X Y {}",
  505. true='0',
  506. false='1'
  507. )
  508. )
  509. elif node.data == "less_or_equals":
  510. buffer.emit(
  511. self.compile_compare_expr(
  512. node,
  513. "sblez X Y {}"
  514. )
  515. )
  516. elif node.data == "greater_or_equals":
  517. buffer.emit(
  518. self.compile_compare_expr(
  519. node,
  520. "inc Y",
  521. "sblez X Y {}",
  522. true='0',
  523. false='1'
  524. )
  525. )
  526. elif node.data == "not":
  527. buffer.emit(
  528. self.compile_unary_expr(
  529. node,
  530. "nbnz Y !"
  531. )
  532. )
  533. elif node.data == "deref":
  534. buffer.emit(
  535. self.compile_unary_expr(
  536. node,
  537. "la Y Y"
  538. )
  539. )
  540. elif node.data == "index":
  541. buffer.emit(
  542. self.compile_binary_expr(
  543. node
  544. )
  545. )
  546. buffer.emit(
  547. "ablez X Y !"
  548. )
  549. buffer.emit(
  550. "la Y Y"
  551. )
  552. elif node.data == "negate":
  553. buffer.emit(
  554. self.compile_unary_expr(
  555. node,
  556. "mov Y X",
  557. "sblez X Y !",
  558. "sblez X Y !",
  559. )
  560. )
  561. elif node.data == "array":
  562. buffer.emit(
  563. "ld {} Y",
  564. self.make_array(
  565. self.compile_literal(node)
  566. )
  567. )
  568. elif node.data == "inc":
  569. name = self.scope[node.children[0].value]
  570. self.record_usage(name)
  571. buffer.emit(
  572. "mov {} Y",
  573. name
  574. )
  575. buffer.emit(
  576. "inc {}",
  577. name
  578. )
  579. elif node.data == "dec":
  580. name = self.scope[node.children[0].value]
  581. self.record_usage(name)
  582. buffer.emit(
  583. "mov {} Y"
  584. )
  585. buffer.emit(
  586. "dec {}",
  587. name
  588. )
  589. elif node.data == "rinc":
  590. name = self.scope[node.children[0].value]
  591. self.record_usage(name)
  592. buffer.emit(
  593. "inc {}",
  594. name
  595. )
  596. buffer.emit(
  597. "mov {} Y",
  598. name
  599. )
  600. elif node.data == "rdec":
  601. name = self.scope[node.children[0].value]
  602. self.record_usage(name)
  603. buffer.emit(
  604. "dec {}",
  605. name
  606. )
  607. buffer.emit(
  608. "mov {} Y"
  609. )
  610. elif node.data == "funcall":
  611. buffer.emit(
  612. self.compile_funcall(node, dest='Y')
  613. )
  614. else:
  615. raise Exception(f"Not implemented: {node}")
  616. return buffer
  617. def compile_funcall(self, node, dest='Y'):
  618. buffer = Buffer()
  619. name = node.children[0].value
  620. if name not in self.funcs:
  621. raise Exception(f"Call to an undeclared function: '{name}`.")
  622. if self.funcs[name].argc != len(node.children[1].children):
  623. raise Exception(f"Function '{name}` expects {self.funcs[name].argc} arguments, but got {node.children[1].children}.")
  624. for arg in node.children[1].children[::-1]:
  625. buffer.emit(
  626. self.compile_expr(arg)
  627. )
  628. buffer.emit(
  629. "push Y"
  630. )
  631. buffer.emit(
  632. "jw __{}",
  633. name
  634. )
  635. buffer.emit(
  636. "pop {}",
  637. dest
  638. )
  639. self.record_usage(name)
  640. return buffer
  641. def compile_asm(self, node):
  642. buffer = Buffer()
  643. table = {}
  644. for name, renamed in self.scope:
  645. table[name] = renamed
  646. for child in node.children:
  647. value = parse_escape(child.value[1:-1])
  648. for name in table:
  649. if f"{{{name}}}" in value:
  650. self.record_usage(table[name])
  651. try:
  652. value = value.format(
  653. **table
  654. )
  655. except:
  656. raise Exception("Malformed asm directive.")
  657. buffer.emit(value)
  658. return buffer
  659. def compile_arrdec(self, node):
  660. buffer = Buffer()
  661. name = node.children[0].value
  662. if name in self.scope and len(node.children) == 3: # Index assignment.
  663. name = self.scope.find(name)
  664. self.record_usage(name)
  665. buffer.emit(
  666. self.compile_expr(
  667. node.children[1]
  668. )
  669. )
  670. buffer.emit(
  671. "mov {} X",
  672. name
  673. )
  674. buffer.emit(
  675. "ablez X Y !"
  676. )
  677. buffer.emit(
  678. "push Y"
  679. )
  680. buffer.emit(
  681. self.compile_expr(
  682. node.children[2]
  683. )
  684. )
  685. buffer.emit(
  686. "pop X"
  687. )
  688. buffer.emit(
  689. "str Y X"
  690. )
  691. return buffer
  692. if not self.scope.is_toplevel and self.scope.is_local(name):
  693. raise Exception(f"Duplicated declaration of a local variable: '{node.children[0].value}`.")
  694. name = self.scope[name]
  695. self.record_usage(name)
  696. count = int(node.children[1].value)
  697. if count <= 0:
  698. raise Exception(f"Illegal array declaration '{node.children[0].value}`: array size should be >0, but it is {count}.")
  699. if len(node.children) == 3:
  700. value = self.compile_literal(node.children[2])
  701. size = len(value.split(" ")) # Dirty.
  702. if size < count:
  703. value += f" 0*{count-size}"
  704. elif size != count:
  705. raise Exception(f"Illegal array declaration '{node.children[0].value}`: value size is {size}, but expected {count}.")
  706. buffer.emit(
  707. "ld {} Y",
  708. self.make_array(value)
  709. )
  710. else:
  711. buffer.emit(
  712. "ld {} Y",
  713. self.make_array(f"0*{count}")
  714. )
  715. buffer.emit(
  716. "mov Y {}",
  717. name
  718. )
  719. return buffer
  720. def compile_op(self, node):
  721. buffer = Buffer()
  722. if node.data == "block":
  723. buffer.emit(
  724. self.compile_block(
  725. node
  726. )
  727. )
  728. elif node.data == "label":
  729. buffer.emit(
  730. "{}:",
  731. self.scope.get_label(node.children[0].value)
  732. )
  733. elif node.data == "goto":
  734. buffer.emit(
  735. "jmp {}",
  736. self.scope.get_label(node.children[0].value)
  737. )
  738. elif node.data == "varinit":
  739. name = node.children[0].value
  740. if self.scope.is_local(name):
  741. raise Exception(f"Duplicated declaration of a local variable: '{name}`.")
  742. self.scope.insert(name)
  743. elif node.data == "vardec":
  744. name = self.scope[node.children[0].value]
  745. self.record_usage(name)
  746. buffer.emit(
  747. self.compile_expr(node.children[1])
  748. )
  749. buffer.emit(
  750. "mov Y {}",
  751. name
  752. )
  753. elif node.data in ("arrdec", "arrinit"):
  754. buffer.emit(
  755. self.compile_arrdec(node)
  756. )
  757. elif node.data in ("inc", "rinc"):
  758. name = self.scope[node.children[0].value]
  759. self.record_usage(name)
  760. buffer.emit(
  761. "inc {}",
  762. name
  763. )
  764. elif node.data == ("dec", "rdec"):
  765. name = self.scope[node.children[0].value]
  766. self.record_usage(name)
  767. buffer.emit(
  768. "dec {}",
  769. name
  770. )
  771. elif node.data == "funcall":
  772. buffer.emit(
  773. self.compile_funcall(node, dest='ZZ')
  774. )
  775. elif node.data == "return":
  776. buffer.emit(
  777. self.compile_expr(
  778. node.children[0]
  779. )
  780. )
  781. buffer.emit("push Y")
  782. buffer.emit("ret")
  783. elif node.data == "asm":
  784. buffer.emit(
  785. self.compile_asm(node)
  786. )
  787. elif node.data == "if":
  788. else_label = self.make_label()
  789. exit_label = self.make_label()
  790. buffer.emit(
  791. self.compile_expr(
  792. node.children[0]
  793. )
  794. )
  795. buffer.emit(
  796. "nbnz Y {}",
  797. else_label
  798. )
  799. buffer.emit(
  800. self.compile_op(
  801. node.children[1]
  802. )
  803. )
  804. buffer.emit(
  805. "jmp {}",
  806. exit_label
  807. )
  808. buffer.emit(
  809. "{}:",
  810. else_label
  811. )
  812. if len(node.children) == 3:
  813. buffer.emit(
  814. self.compile_op(
  815. node.children[2]
  816. )
  817. )
  818. buffer.emit(
  819. "{}:",
  820. exit_label
  821. )
  822. elif node.data == "while":
  823. loop_label = self.make_label()
  824. exit_label = self.make_label()
  825. buffer.emit(
  826. "{}:",
  827. loop_label
  828. )
  829. buffer.emit(
  830. self.compile_expr(
  831. node.children[0]
  832. )
  833. )
  834. buffer.emit(
  835. "nbnz Y {}",
  836. exit_label
  837. )
  838. buffer.emit(
  839. self.compile_op(
  840. node.children[1]
  841. )
  842. )
  843. buffer.emit(
  844. "jmp {}",
  845. loop_label
  846. )
  847. buffer.emit(
  848. "{}:",
  849. exit_label
  850. )
  851. elif node.data == "for":
  852. loop_label = self.make_label()
  853. exit_label = self.make_label()
  854. self.scope.new()
  855. buffer.emit(
  856. self.compile_op(
  857. node.children[0]
  858. )
  859. )
  860. buffer.emit(
  861. "{}:",
  862. loop_label
  863. )
  864. buffer.emit(
  865. self.compile_expr(
  866. node.children[1]
  867. )
  868. )
  869. buffer.emit(
  870. "nbnz Y {}",
  871. exit_label
  872. )
  873. buffer.emit(
  874. self.compile_op(
  875. node.children[3]
  876. )
  877. )
  878. buffer.emit(
  879. self.compile_op(
  880. node.children[2]
  881. )
  882. )
  883. self.scope.leave()
  884. buffer.emit(
  885. "jmp {}",
  886. loop_label
  887. )
  888. buffer.emit(
  889. "{}:",
  890. exit_label
  891. )
  892. else:
  893. raise Exception(f"Not implemented: {node}")
  894. return buffer
  895. def collect_labels(self, node):
  896. for child in node.children:
  897. if child.data == "label":
  898. self.scope.add_label(child.children[0].value)
  899. def compile_block(self, node, *prepend_names, scope=True):
  900. if scope:
  901. self.scope.new()
  902. for name in prepend_names:
  903. self.scope.insert(name)
  904. buffer = Buffer()
  905. self.collect_labels(node)
  906. for child in node.children:
  907. buffer.emit(
  908. self.compile_op(child)
  909. )
  910. if scope:
  911. self.scope.leave()
  912. return buffer
  913. def compile_toplevel(self, node):
  914. buffer = Buffer()
  915. if node.data == "funcdef":
  916. name = node.children[0].value
  917. params = self.funcs[name].params
  918. buffer.emit("__{}:", name)
  919. for param in params:
  920. buffer.emit(
  921. "pop __{}_{}",
  922. self.scope.ndx, param
  923. )
  924. self.where = name
  925. buffer.emit(
  926. self.compile_block(
  927. node.children[2],
  928. *params
  929. )
  930. )
  931. buffer.emit(
  932. "push Z"
  933. )
  934. buffer.emit(
  935. "ret"
  936. )
  937. elif node.data == "vardec":
  938. name = node.children[0].value
  939. self.init_buffer.emit(
  940. self.compile_expr(node.children[1])
  941. )
  942. self.init_buffer.emit(
  943. "mov Y __0_{}",
  944. name
  945. )
  946. self.record_usage(f"__0__{name}")
  947. elif node.data in ("arrdec", "arrinit"):
  948. self.init_buffer.emit(
  949. self.compile_arrdec(node)
  950. )
  951. elif node.data == "asm":
  952. buffer.emit(
  953. self.compile_asm(node)
  954. )
  955. elif node.data == "include":
  956. filename = node.children[0].value[1:-1]
  957. if not os.path.isfile(filename):
  958. filename = os.path.join(os.getenv("WC_I"), filename)
  959. if not os.path.isfile(filename):
  960. raise Exception(f"No such file: '{os.path.basename(filename)}`.")
  961. if filename not in self.included_files:
  962. with open(filename, "r") as f:
  963. self.compile_program(f.read())
  964. self.included_files.add(filename)
  965. elif node.data == "varinit":
  966. pass
  967. else:
  968. raise Exception(f"Not implemented: {node}")
  969. return buffer
  970. def collect_toplevel(self, ast):
  971. for node in ast.children:
  972. if node.data == "funcdef":
  973. name = node.children[0].value
  974. if name in self.funcs:
  975. raise Exception(f"Duplicated function declaration: '{name}`.")
  976. self.funcs[name] = Func(
  977. len(node.children[1].children),
  978. tuple(map(lambda t: t.value, node.children[1].children))
  979. )
  980. elif node.data in ("varinit", "vardec", "arrinit", "arrdec"):
  981. name = node.children[0].value
  982. if name in self.scope:
  983. raise Exception(f"Duplicated top-level variable declaration: '{name}`.")
  984. self.scope.insert(name) # Because we're at the top-level rn.
  985. def compile_program(self, text):
  986. ast = self.parser.parse(text)
  987. #print(ast.pretty())
  988. self.collect_toplevel(ast)
  989. for node in ast.children:
  990. buffer = self.compile_toplevel(node)
  991. if node.data == "funcdef":
  992. self.compiled_funcs[node.children[0].value] = buffer
  993. else:
  994. self.buffer.emit(buffer)
  995. def compile(self, text):
  996. self.compile_program(text)
  997. for name in self.compiled_funcs:
  998. if self.is_used(name):
  999. self.buffer.emit(self.compiled_funcs[name])
  1000. for param in self.funcs[name].params:
  1001. self.record_usage(param)
  1002. self.buffer = self.init_buffer + self.buffer + self.arrays_buffer
  1003. for name in self.scope.names:
  1004. if self.is_used(name):
  1005. self.buffer.emit(
  1006. "{}:0", name
  1007. )
  1008. if "main" not in self.funcs:
  1009. raise Exception("Missing 'main` function.")
  1010. return self.buffer.generate() + "\n"
  1011. wmc = WMC()
  1012. try:
  1013. if len(sys.argv) == 3:
  1014. with open(sys.argv[1], "r") as fin:
  1015. with open(sys.argv[2], "w") as fout:
  1016. fout.write(wmc.compile(fin.read()))
  1017. else:
  1018. sys.stdout.write(wmc.compile(sys.stdin.read()))
  1019. except Exception as e:
  1020. #__import__('traceback').print_exc()
  1021. print(e)
  1022. sys.exit(1)