command.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. package transpiler
  2. import "fmt"
  3. import "strings"
  4. import "../parser"
  5. import "../parser/syntax"
  6. var CommandMap = map[string]TransFunction {
  7. // command = cmd_group1 | cmd_group2 | cmd_group3
  8. "command": TranspileFirstChild,
  9. // cmd_group1 = cmd_flow | cmd_pause | cmd_err | cmd_return
  10. "cmd_group1": TranspileFirstChild,
  11. // cmd_group2 = cmd_module | cmd_scope | cmd_def
  12. "cmd_group2": TranspileFirstChild,
  13. // cmd_group3 = cmd_pass | cmd_set | cmd_exec
  14. "cmd_group3": TranspileFirstChild,
  15. // cmd_def = function | schema | enum | class | interface
  16. "cmd_def": func (tree Tree, ptr int) string {
  17. var children = Children(tree, ptr)
  18. var fun_ptr, is_fun = children["function"]
  19. fun_ptr = tree.Nodes[fun_ptr].Children[0]
  20. if is_fun {
  21. var f = Transpile(tree, fun_ptr)
  22. var f_children = Children(tree, fun_ptr)
  23. var name = Transpile(tree, f_children["name"])
  24. var file = GetFileName(tree)
  25. var row, col = GetRowColInfo(tree, ptr)
  26. return fmt.Sprintf(
  27. "%v(%v, [%v, %v], %v, %v, %v)",
  28. G(CALL), L_ADD_FUN, name, f, file, row, col,
  29. )
  30. } else {
  31. return TranspileFirstChild(tree, ptr)
  32. }
  33. },
  34. // cmd_exec = expr
  35. "cmd_exec": TranspileFirstChild,
  36. // cmd_return = @return Void | @return expr
  37. "cmd_return": func (tree Tree, ptr int) string {
  38. var children = Children(tree, ptr)
  39. var expr, exists = children["expr"]
  40. if exists {
  41. return fmt.Sprintf("return %v", Transpile(tree, expr))
  42. } else {
  43. return fmt.Sprintf("return %v", G(T_VOID))
  44. }
  45. },
  46. // cmd_scope = cmd_let | cmd_var | cmd_reset
  47. "cmd_scope": TranspileFirstChild,
  48. // cmd_let = @let name var_type = expr | @let pattern = expr
  49. "cmd_let": func (tree Tree, ptr int) string {
  50. var file = GetFileName(tree)
  51. var row, col = GetRowColInfo(tree, ptr)
  52. var children = Children(tree, ptr)
  53. var value = Transpile(tree, children["expr"])
  54. var pattern_ptr, use_pattern = children["pattern"]
  55. if use_pattern {
  56. var pattern = Transpile(tree, pattern_ptr)
  57. return fmt.Sprintf (
  58. "%v(%v, [%v, %v, %v], %v, %v, %v)",
  59. G(CALL), L_MATCH, "true", pattern, value, file, row, col,
  60. )
  61. }
  62. var name = Transpile(tree, children["name"])
  63. var T = Transpile(tree, children["var_type"])
  64. return fmt.Sprintf(
  65. "%v(%v, [%v, %v, true, %v], %v, %v, %v)",
  66. G(CALL), L_VAR_DECL, name, value, T, file, row, col,
  67. )
  68. },
  69. // cmd_type = @type name = @singleton | @type name generic_params = expr
  70. "cmd_type": func (tree Tree, ptr int) string {
  71. var file = GetFileName(tree)
  72. var row, col = GetRowColInfo(tree, ptr)
  73. var children = Children(tree, ptr)
  74. var name_ptr = children["name"]
  75. var _, is_singleton = children["@singleton"]
  76. if is_singleton {
  77. var name = Transpile(tree, name_ptr)
  78. var singleton = fmt.Sprintf (
  79. "%v(%v)", G(C_SINGLETON), name,
  80. )
  81. return fmt.Sprintf(
  82. "%v(%v, [%v, %v, true, %v], %v, %v, %v)",
  83. G(CALL), L_VAR_DECL, name, singleton, G(T_TYPE),
  84. file, row, col,
  85. )
  86. }
  87. var gp_ptr = children["generic_params"]
  88. var name = Transpile(tree, name_ptr)
  89. var expr = Transpile(tree, children["expr"])
  90. var value string
  91. if NotEmpty(tree, gp_ptr) {
  92. value = TypeTemplate(tree, gp_ptr, name_ptr, expr)
  93. } else {
  94. value = expr
  95. }
  96. return fmt.Sprintf(
  97. "%v(%v, [%v, %v, true, %v], %v, %v, %v)",
  98. G(CALL), L_VAR_DECL, name, value, G(T_TYPE), file, row, col,
  99. )
  100. },
  101. // cmd_var = @var name var_type = expr | @var pattern = expr
  102. "cmd_var": func (tree Tree, ptr int) string {
  103. var file = GetFileName(tree)
  104. var row, col = GetRowColInfo(tree, ptr)
  105. var children = Children(tree, ptr)
  106. var value = Transpile(tree, children["expr"])
  107. var pattern_ptr, use_pattern = children["pattern"]
  108. if use_pattern {
  109. var pattern = Transpile(tree, pattern_ptr)
  110. return fmt.Sprintf (
  111. "%v(%v, [%v, %v, %v], %v, %v, %v)",
  112. G(CALL), L_MATCH, "false", pattern, value, file, row, col,
  113. )
  114. }
  115. var name = Transpile(tree, children["name"])
  116. var T = Transpile(tree, children["var_type"])
  117. return fmt.Sprintf (
  118. "%v(%v, [%v, %v, false, %v], %v, %v, %v)",
  119. G(CALL), L_VAR_DECL, name, value, T, file, row, col,
  120. )
  121. },
  122. // pattern = pattern_key | pattern_index
  123. "pattern": TranspileFirstChild,
  124. // pattern_key = { sub_pattern_list! }! nil_flag
  125. "pattern_key": func (tree Tree, ptr int) string {
  126. var children = Children(tree, ptr)
  127. var allow_nil = Transpile(tree, children["nil_flag"])
  128. var items = SubPatternList(tree, children["sub_pattern_list"], false)
  129. return fmt.Sprintf (
  130. "{ is_final: false, extract: null, allow_nil: %v, items: %v }",
  131. allow_nil, items,
  132. )
  133. },
  134. // pattern_index = [ sub_pattern_list! ]! nil_flag
  135. "pattern_index": func (tree Tree, ptr int) string {
  136. var children = Children(tree, ptr)
  137. var allow_nil = Transpile(tree, children["nil_flag"])
  138. var items = SubPatternList(tree, children["sub_pattern_list"], true)
  139. return fmt.Sprintf (
  140. "{ is_final: false, extract: null, allow_nil: %v, items: %v }",
  141. allow_nil, items,
  142. )
  143. },
  144. // cmd_pause = cmd_yield | cmd_async_for | cmd_await
  145. "cmd_pause": TranspileFirstChild,
  146. // cmd_yield = @yield name var_type = expr! | @yield expr!
  147. "cmd_yield": func (tree Tree, ptr int) string {
  148. var children = Children(tree, ptr)
  149. var name_ptr, is_decl = children["name"]
  150. var T_ptr = children["var_type"]
  151. var value = Transpile(tree, children["expr"])
  152. if is_decl {
  153. var name = Transpile(tree, name_ptr)
  154. var T = Transpile(tree, T_ptr)
  155. var file = GetFileName(tree)
  156. var row, col = GetRowColInfo(tree, ptr)
  157. return fmt.Sprintf(
  158. "%v(%v, [%v, (yield %v), false, %v], %v, %v, %v)",
  159. G(CALL), L_VAR_DECL, name, value, T, file, row, col,
  160. )
  161. } else {
  162. return fmt.Sprintf("((yield %v), %v)", value, G(T_VOID))
  163. }
  164. },
  165. // cmd_await = @await name var_type = expr! | @await expr!
  166. "cmd_await": func (tree Tree, ptr int) string {
  167. var children = Children(tree, ptr)
  168. var name_ptr, is_decl = children["name"]
  169. var T_ptr = children["var_type"]
  170. var expr = Transpile(tree, children["expr"])
  171. var file = GetFileName(tree)
  172. var row, col = GetRowColInfo(tree, ptr)
  173. var await = fmt.Sprintf (
  174. "(await %v(%v, [%v], %v, %v, %v))",
  175. G(CALL), G(REQ_PROMISE), expr, file, row, col,
  176. )
  177. if is_decl {
  178. var name = Transpile(tree, name_ptr)
  179. var T = Transpile(tree, T_ptr)
  180. return fmt.Sprintf (
  181. "%v(%v, [%v, %v, false, %v], %v, %v, %v)",
  182. G(CALL), L_VAR_DECL, name, await, T, file, row, col,
  183. )
  184. } else {
  185. return fmt.Sprintf("(%v, %v)", await, G(T_VOID))
  186. }
  187. },
  188. // cmd_reset = @reset name = expr
  189. "cmd_reset": func (tree Tree, ptr int) string {
  190. var file = GetFileName(tree)
  191. var row, col = GetRowColInfo(tree, ptr)
  192. var children = Children(tree, ptr)
  193. var name_ptr = children["name"]
  194. var name = Transpile(tree, name_ptr)
  195. var value = Transpile(tree, children["expr"])
  196. var op_ptr = children["set_op"]
  197. if NotEmpty(tree, op_ptr) {
  198. value = fmt.Sprintf(
  199. "%v(%v, [%v, %v], %v, %v, %v)",
  200. G(CALL),
  201. Transpile(tree, op_ptr),
  202. VarLookup(tree, name_ptr),
  203. value, file, row, col,
  204. )
  205. }
  206. return fmt.Sprintf(
  207. "%v(%v, [%v, %v], %v, %v, %v)",
  208. G(CALL), L_VAR_RESET, name, value, file, row, col,
  209. )
  210. },
  211. "set_op": func (tree Tree, ptr int) string {
  212. return TransMapByName["operator"](tree, ptr)
  213. },
  214. // var_type? = : type
  215. "var_type": func (tree Tree, ptr int) string {
  216. if NotEmpty(tree, ptr) {
  217. return TranspileLastChild(tree, ptr)
  218. } else {
  219. return G(T_ANY)
  220. }
  221. },
  222. // cmd_set = @set left_val = expr
  223. "cmd_set": func (tree Tree, ptr int) string {
  224. var file = GetFileName(tree)
  225. var children = Children(tree, ptr)
  226. var value = Transpile(tree, children["expr"])
  227. // left_val = operand_base gets!
  228. var left_ptr = children["left_val"]
  229. var left = Children(tree, left_ptr)
  230. var base = Transpile(tree, left["operand_base"])
  231. var gets = FlatSubTree(tree, left["gets"], "get", "gets")
  232. var real_gets = gets[0:len(gets)-1]
  233. var tail = gets[len(gets)-1]
  234. var t = base
  235. for _, get := range real_gets {
  236. // get_expr = Get [ expr! ]! nil_flag
  237. // get_name = Get . name! nil_flag
  238. var row, col = GetRowColInfo(tree, get)
  239. var key, nil_flag = GetKey(tree, get)
  240. t = fmt.Sprintf(
  241. "%v(%v, %v, %v, %v, %v, %v)",
  242. G(GET), t, key, nil_flag, file, row, col,
  243. )
  244. }
  245. var object = t
  246. var row, col = GetRowColInfo(tree, ptr)
  247. var set_key, _ = GetKey(tree, tail)
  248. var op_ptr = children["set_op"]
  249. if NotEmpty(tree, op_ptr) {
  250. var operator = Transpile(tree, op_ptr)
  251. var previous = fmt.Sprintf(
  252. "%v(%v, %v, %v, %v, %v, %v)",
  253. G(GET), object, set_key, "false", file, row, col,
  254. )
  255. value = fmt.Sprintf(
  256. "%v(%v, [%v, %v], %v, %v, %v)",
  257. G(CALL), operator, previous, value, file, row, col,
  258. )
  259. }
  260. return fmt.Sprintf(
  261. "%v(%v, [%v, %v, %v], %v, %v, %v)",
  262. G(CALL), G(SET), object, set_key, value, file, row, col,
  263. )
  264. },
  265. // cmd_flow = cmd_if | cmd_switch | cmd_while | cmd_for | cmd_loop_ctrl
  266. "cmd_flow": TranspileFirstChild,
  267. // block = { commands }!
  268. "block": func (tree Tree, ptr int) string {
  269. var children = Children(tree, ptr)
  270. var commands = Commands(tree, children["commands"], false)
  271. var BodyId = syntax.Name2Id["body"]
  272. var BlockId = syntax.Name2Id["block"]
  273. var HandleId = syntax.Name2Id["handle_hook"]
  274. var ForId = syntax.Name2Id["cmd_for"]
  275. var AsyncForId = syntax.Name2Id["cmd_async_for"]
  276. var depth = 0
  277. var node = &tree.Nodes[ptr]
  278. for node.Part.Id != BodyId && node.Part.Id != HandleId {
  279. if node.Part.Id == BlockId {
  280. depth += 1
  281. }
  282. if node.Parent < 0 {
  283. break
  284. }
  285. node = &tree.Nodes[node.Parent]
  286. }
  287. var upper string
  288. if depth-1 > 0 {
  289. upper = fmt.Sprintf("%v%v", SCOPE, depth-1)
  290. } else {
  291. if node.Part.Id == HandleId {
  292. upper = H_HOOK_SCOPE
  293. } else {
  294. upper = SCOPE
  295. }
  296. }
  297. var current = fmt.Sprintf("%v%v", SCOPE, depth)
  298. var buf strings.Builder
  299. buf.WriteString("{ ")
  300. fmt.Fprintf(
  301. &buf, "let %v = %v.%v(%v); ",
  302. current, RUNTIME, R_NEW_SCOPE, upper,
  303. )
  304. WriteHelpers(&buf, current)
  305. var parent_node = tree.Nodes[tree.Nodes[ptr].Parent]
  306. var parent_part_id = parent_node.Part.Id
  307. if parent_part_id == ForId || parent_part_id == AsyncForId {
  308. fmt.Fprintf (
  309. &buf, "if (l.key) { %v(l.key, I.key) }; ",
  310. L_VAR_DECL,
  311. )
  312. fmt.Fprintf (
  313. &buf, "if (l.value) { %v(l.value, I.value) }; ",
  314. L_VAR_DECL,
  315. )
  316. }
  317. buf.WriteString(commands)
  318. buf.WriteString(" }")
  319. return buf.String()
  320. },
  321. // cmd_if = @if expr! block! elifs else
  322. "cmd_if": func (tree Tree, ptr int) string {
  323. var children = Children(tree, ptr)
  324. var expr_ptr = children["expr"]
  325. var condition = Transpile(tree, expr_ptr)
  326. var file = GetFileName(tree)
  327. var row, col = GetRowColInfo(tree, expr_ptr)
  328. var block = Transpile(tree, children["block"])
  329. var elifs = Transpile(tree, children["elifs"])
  330. var else_ = Transpile(tree, children["else"])
  331. return fmt.Sprintf (
  332. "if (%v(%v, [%v], %v, %v, %v)) %v%v%v",
  333. G(CALL), G(REQ_BOOL), condition, file, row, col,
  334. block, elifs, else_,
  335. )
  336. },
  337. // elifs? = elif elifs
  338. "elifs": func (tree Tree, ptr int) string {
  339. var elif_ptrs = FlatSubTree(tree, ptr, "elif", "elifs")
  340. var buf strings.Builder
  341. for _, elif_ptr := range elif_ptrs {
  342. buf.WriteString(Transpile(tree, elif_ptr))
  343. }
  344. return buf.String()
  345. },
  346. // elif = @else @if expr! block! | @elif expr! block!
  347. "elif": func (tree Tree, ptr int) string {
  348. var children = Children(tree, ptr)
  349. var expr_ptr = children["expr"]
  350. var condition = Transpile(tree, expr_ptr)
  351. var file = GetFileName(tree)
  352. var row, col = GetRowColInfo(tree, expr_ptr)
  353. var block = Transpile(tree, children["block"])
  354. return fmt.Sprintf(
  355. " else if (%v(%v, [%v], %v, %v, %v)) %v",
  356. G(CALL), G(REQ_BOOL), condition, file, row, col, block,
  357. )
  358. },
  359. // else? = @else block!
  360. "else": func (tree Tree, ptr int) string {
  361. if NotEmpty(tree, ptr) {
  362. var children = Children(tree, ptr)
  363. var block = Transpile(tree, children["block"])
  364. return fmt.Sprintf(" else %v", block)
  365. } else {
  366. return ""
  367. }
  368. },
  369. // cmd_switch = switch_if | switch_match
  370. "cmd_switch": TranspileFirstChild,
  371. // switch_if = @switch @if { cases! }!
  372. "switch_if": func (tree Tree, ptr int) string {
  373. var children = Children(tree, ptr)
  374. return Cases(tree, children["cases"], CondBranch)
  375. },
  376. // switch_match = @switch @match expr {! cases! }!
  377. "switch_match": func (tree Tree, ptr int) string {
  378. var children = Children(tree, ptr)
  379. var declare_target = fmt.Sprintf (
  380. "let %v = %v;",
  381. MATCH_TARGET, Transpile(tree, children["expr"]),
  382. )
  383. return fmt.Sprintf (
  384. "{ %v %v }",
  385. declare_target,
  386. Cases(tree, children["cases"], MatchBranch),
  387. )
  388. },
  389. // cmd_for = @for for_params! @in expr! block!
  390. "cmd_for": func (tree Tree, ptr int) string {
  391. // note: rule name "cmd_for" is depended by CommandMap["block"]
  392. var file = GetFileName(tree)
  393. var row, col = GetRowColInfo(tree, ptr)
  394. var children = Children(tree, ptr)
  395. var params_ptr = children["for_params"]
  396. var params = Transpile(tree, params_ptr)
  397. var expr = Transpile(tree, children["expr"])
  398. var block = Transpile(tree, children["block"])
  399. var c = tree.Nodes[params_ptr].Children[0]
  400. var params_type = syntax.Id2Name[tree.Nodes[c].Part.Id]
  401. var loop_type string
  402. switch params_type {
  403. case "for_params_list":
  404. loop_type = G(FOR_LOOP_ITER)
  405. case "for_params_hash":
  406. loop_type = G(FOR_LOOP_ENUM)
  407. case "for_params_value":
  408. loop_type = G(FOR_LOOP_VALUE)
  409. default:
  410. panic("impossible switch branch")
  411. }
  412. return fmt.Sprintf (
  413. "for (let I of %v(%v, [%v], %v, %v, %v)) { %v %v; }",
  414. G(CALL), loop_type, expr, file, row, col, params, block,
  415. )
  416. },
  417. // cmd_async_for = @await name @in expr! block!
  418. "cmd_async_for": func (tree Tree, ptr int) string {
  419. var children = Children(tree, ptr)
  420. var item_name = Transpile(tree, children["name"])
  421. var expr = Transpile(tree, children["expr"])
  422. var block = Transpile(tree, children["block"])
  423. var params = fmt.Sprintf("let l = { value: %v };", item_name)
  424. var file = GetFileName(tree)
  425. var row, col = GetRowColInfo(tree, ptr)
  426. return fmt.Sprintf (
  427. "for await (let I of %v(%v, [%v], %v, %v, %v)) { %v %v; }",
  428. G(CALL), G(FOR_LOOP_ASYNC), expr, file, row, col, params, block,
  429. )
  430. },
  431. // for_params = for_params_list | for_params_hash | for_params_value
  432. "for_params": TranspileFirstChild,
  433. // for_params_list = for_value [ for_index! ]!
  434. "for_params_list": func (tree Tree, ptr int) string {
  435. var children = Children(tree, ptr)
  436. var value = Transpile(tree, children["for_value"])
  437. var key = Transpile(tree, children["for_index"])
  438. if key == value {
  439. parser.Error (
  440. tree, ptr, fmt.Sprintf (
  441. "duplicate parameter name %v in for statement",
  442. key,
  443. ),
  444. )
  445. }
  446. return fmt.Sprintf("let l = { key: %v, value: %v };", key, value)
  447. },
  448. // for_params_hash = { for_key :! for_value! }!
  449. "for_params_hash": func (tree Tree, ptr int) string {
  450. var children = Children(tree, ptr)
  451. var key = Transpile(tree, children["for_key"])
  452. var value = Transpile(tree, children["for_value"])
  453. return fmt.Sprintf("let l = { key: %v, value: %v };", key, value)
  454. },
  455. // for_params_value = for_value
  456. "for_params_value": func (tree Tree, ptr int) string {
  457. var children = Children(tree, ptr)
  458. var value = Transpile(tree, children["for_value"])
  459. return fmt.Sprintf("let l = { value: %v };", value)
  460. },
  461. // for_value = name
  462. "for_value": TranspileFirstChild,
  463. // for_index = name
  464. "for_index": TranspileFirstChild,
  465. // for_key = name
  466. "for_key": TranspileFirstChild,
  467. // cmd_while = @while expr! block!
  468. "cmd_while": func (tree Tree, ptr int) string {
  469. var children = Children(tree, ptr)
  470. var expr_ptr = children["expr"]
  471. var condition = Transpile(tree, expr_ptr)
  472. var file = GetFileName(tree)
  473. var row, col = GetRowColInfo(tree, expr_ptr)
  474. var block = Transpile(tree, children["block"])
  475. return fmt.Sprintf (
  476. "while (%v(%v, [%v], %v, %v, %v)) %v",
  477. G(CALL), G(REQ_BOOL), condition, file, row, col, block,
  478. )
  479. },
  480. // cmd_loop_ctrl = @break | @continue
  481. "cmd_loop_ctrl": func (tree Tree, ptr int) string {
  482. var child_ptr = tree.Nodes[ptr].Children[0]
  483. var id = tree.Nodes[child_ptr].Part.Id
  484. var name = syntax.Id2Name[id]
  485. if name == "@break" {
  486. return "break"
  487. } else if name == "@continue" {
  488. return "continue"
  489. } else {
  490. panic("impossible branch")
  491. }
  492. },
  493. // cmd_err = cmd_throw | cmd_assert | cmd_ensure | cmd_try | cmd_panic
  494. "cmd_err": TranspileFirstChild,
  495. // cmd_throw = @throw expr!
  496. "cmd_throw": func (tree Tree, ptr int) string {
  497. var expr = TranspileLastChild(tree, ptr)
  498. var file = GetFileName(tree)
  499. var row, col = GetRowColInfo(tree, ptr)
  500. return fmt.Sprintf (
  501. "%v(%v, [%v], %v, %v, %v)",
  502. G(CALL), G(THROW), expr, file, row, col,
  503. )
  504. },
  505. // cmd_assert = @assert expr!
  506. "cmd_assert": func (tree Tree, ptr int) string {
  507. var expr = TranspileLastChild(tree, ptr)
  508. var file = GetFileName(tree)
  509. var row, col = GetRowColInfo(tree, ptr)
  510. return fmt.Sprintf (
  511. "%v(%v, [%v], %v, %v, %v)",
  512. G(CALL), G(ASSERT), expr, file, row, col,
  513. )
  514. },
  515. // cmd_panic = @panic expr!
  516. "cmd_panic": func (tree Tree, ptr int) string {
  517. var expr = TranspileLastChild(tree, ptr)
  518. var file = GetFileName(tree)
  519. var row, col = GetRowColInfo(tree, ptr)
  520. return fmt.Sprintf (
  521. "%v(%v, [%v], %v, %v, %v)",
  522. G(CALL), G(PANIC), expr, file, row, col,
  523. )
  524. },
  525. // cmd_ensure = @ensure name! ensure_args { expr! }!
  526. "cmd_ensure": func (tree Tree, ptr int) string {
  527. var children = Children(tree, ptr)
  528. var name = Transpile(tree, children["name"])
  529. var args = Transpile(tree, children["ensure_args"])
  530. var expr_ptr = children["expr"]
  531. var expr = Transpile(tree, expr_ptr)
  532. var file = GetFileName(tree)
  533. var row, col = GetRowColInfo(tree, ptr)
  534. var e_row, e_col = GetRowColInfo(tree, expr_ptr)
  535. return fmt.Sprintf (
  536. "if (!(%v(%v, [%v], %v, %v, %v))) " +
  537. "{ %v(%v, %v, %v, %v, %v, %v) }",
  538. G(CALL), G(REQ_BOOL), expr, file, e_row, e_col,
  539. G(ENSURE_FAILED), ERROR_DUMP, name, args, file, row, col,
  540. )
  541. },
  542. // ensure_args? = Call ( exprlist )
  543. "ensure_args": func (tree Tree, ptr int) string {
  544. if NotEmpty(tree, ptr) {
  545. var children = Children(tree, ptr)
  546. var exprlist = Transpile(tree, children["exprlist"])
  547. return fmt.Sprintf("[%v]", exprlist)
  548. } else {
  549. return "[]"
  550. }
  551. },
  552. // cmd_try = @try opt_to name { commands }!
  553. "cmd_try": func (tree Tree, ptr int) string {
  554. var children = Children(tree, ptr)
  555. var name = Transpile(tree, children["name"])
  556. var commands = Commands(tree, children["commands"], false)
  557. return fmt.Sprintf(
  558. "try { %v } catch (%v) { %v(%v, %v, %v) }",
  559. commands, TRY_ERROR, G(TRY_FAILED), ERROR_DUMP, TRY_ERROR, name,
  560. )
  561. },
  562. // cmd_pass = @do @nothing
  563. "cmd_pass": func (tree Tree, ptr int) string {
  564. return G(T_VOID)
  565. },
  566. // cmd_module = cmd_import
  567. "cmd_module": TranspileFirstChild,
  568. // cmd_import = import_all | import_names | import_module
  569. "cmd_import": TranspileFirstChild,
  570. // import_names = @import as_list @from name
  571. "import_names": func (tree Tree, ptr int) string {
  572. var children = Children(tree, ptr)
  573. var module_name = Transpile(tree, children["name"])
  574. var configs = Transpile(tree, children["as_list"])
  575. var file = GetFileName(tree)
  576. var row, col = GetRowColInfo(tree, ptr)
  577. return fmt.Sprintf (
  578. "%v(%v, [%v, %v], %v, %v, %v)",
  579. G(CALL), L_IMPORT_VAR, module_name, configs, file, row, col,
  580. )
  581. },
  582. // import_module = @import as_item
  583. "import_module": func (tree Tree, ptr int) string {
  584. var config = TranspileLastChild(tree, ptr)
  585. var file = GetFileName(tree)
  586. var row, col = GetRowColInfo(tree, ptr)
  587. return fmt.Sprintf (
  588. "%v(%v, [%v], %v, %v, %v)",
  589. G(CALL), L_IMPORT_MOD, config, file, row, col,
  590. )
  591. },
  592. // import_all = @import * @from name
  593. "import_all": func (tree Tree, ptr int) string {
  594. var name = TranspileLastChild(tree, ptr)
  595. var file = GetFileName(tree)
  596. var row, col = GetRowColInfo(tree, ptr)
  597. return fmt.Sprintf (
  598. "%v(%v, [%v], %v, %v, %v)",
  599. G(CALL), L_IMPORT_ALL, name, file, row, col,
  600. )
  601. },
  602. // as_list = as_item as_list_tail
  603. "as_list": func (tree Tree, ptr int) string {
  604. return TranspileSubTree(tree, ptr, "as_item", "as_list_tail")
  605. },
  606. // as_item = name @as name! | name
  607. "as_item": func (tree Tree, ptr int) string {
  608. var children = Children(tree, ptr)
  609. var _, has_alias = children["@as"]
  610. if has_alias {
  611. var name = TranspileFirstChild(tree, ptr)
  612. var alias = TranspileLastChild(tree, ptr)
  613. return fmt.Sprintf("[%v, %v]", name, alias)
  614. } else {
  615. var name = TranspileFirstChild(tree, ptr)
  616. return fmt.Sprintf("[%v, %v]", name, name)
  617. }
  618. },
  619. }