toolkit.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. package transpiler
  2. import "fmt"
  3. import "strings"
  4. import "../parser"
  5. import "../parser/syntax"
  6. type FunType int
  7. const (
  8. F_Sync FunType = iota
  9. F_Async
  10. F_Generator
  11. F_AsyncGenerator
  12. )
  13. func LazyValueWrapper (expr string) string {
  14. return fmt.Sprintf("(() => (%v))", expr)
  15. }
  16. func VarLookup (tree Tree, ptr int) string {
  17. var file = GetFileName(tree)
  18. var row, col = GetRowColInfo(tree, ptr)
  19. return fmt.Sprintf (
  20. "%v(%v, [%v], %v, %v, %v)",
  21. G(CALL), L_VAR_LOOKUP,
  22. EscapeRawString(GetTokenContent(tree, ptr)), file, row, col,
  23. )
  24. }
  25. func EscapeRawString (raw []rune) string {
  26. // example: ['a', '"', 'b', 'c', '\', 'n'] -> `"a\"bc\\n"`
  27. // Containers["hash"] requires this function to be consistent when
  28. // checking duplicate keys.
  29. var buf strings.Builder
  30. buf.WriteRune('"')
  31. for _, char := range raw {
  32. if char == '\\' {
  33. buf.WriteString(`\\`)
  34. } else if char == '"' {
  35. buf.WriteString(`\"`)
  36. } else if char == '\n' {
  37. buf.WriteString(`\n`)
  38. } else {
  39. buf.WriteRune(char)
  40. }
  41. }
  42. buf.WriteRune('"')
  43. return buf.String()
  44. }
  45. func NotEmpty (tree Tree, ptr int) bool {
  46. return tree.Nodes[ptr].Length > 0
  47. }
  48. func Empty (tree Tree, ptr int) bool {
  49. return !NotEmpty(tree, ptr)
  50. }
  51. func FlatSubTree (tree Tree, ptr int, extract string, next string) []int {
  52. var sequence = make([]int, 0)
  53. for NotEmpty(tree, ptr) {
  54. var children = Children(tree, ptr)
  55. var extract_ptr, exists = children[extract]
  56. if !exists { panic("cannot extract part " + next) }
  57. sequence = append(sequence, extract_ptr)
  58. ptr, exists = children[next]
  59. if !exists { panic("next part " + next + " not found") }
  60. }
  61. return sequence
  62. }
  63. func TranspileSubTree (tree Tree, ptr int, item string, next string) string {
  64. var item_ptrs = FlatSubTree(tree, ptr, item, next)
  65. var buf strings.Builder
  66. buf.WriteRune('[')
  67. for i, item_ptr := range item_ptrs {
  68. buf.WriteString(Transpile(tree, item_ptr))
  69. if i != len(item_ptrs)-1 {
  70. buf.WriteString(", ")
  71. }
  72. }
  73. buf.WriteRune(']')
  74. return buf.String()
  75. }
  76. func GetTokenContent (tree Tree, ptr int) []rune {
  77. var node = &tree.Nodes[ptr]
  78. if node.Part.Partype == syntax.Recursive {
  79. node = &tree.Nodes[node.Children[0]]
  80. }
  81. if node.Part.Partype != syntax.MatchToken {
  82. panic("trying to get token content of non-token node")
  83. }
  84. return tree.Tokens[node.Pos].Content
  85. }
  86. func GetWholeContent (tree Tree, ptr int) []rune {
  87. if NotEmpty(tree, ptr) {
  88. var pos = tree.Nodes[ptr].Pos
  89. var amount = tree.Nodes[ptr].Amount
  90. var begin_token = tree.Tokens[pos]
  91. var end_token = tree.Tokens[pos+amount-1]
  92. return tree.Code[begin_token.Pos : end_token.Pos+len(end_token.Content)]
  93. } else {
  94. return []rune("")
  95. }
  96. }
  97. func GetOperatorInfo (tree Tree, ptr int) syntax.Operator {
  98. var Id = tree.Nodes[ptr].Part.Id
  99. var OpId = syntax.Name2Id["operator"]
  100. var SopId = syntax.Name2Id["set_op"]
  101. if Id != OpId && Id != SopId {
  102. panic("unable to get operator info of non-operator")
  103. }
  104. var group_ptr = tree.Nodes[ptr].Children[0]
  105. var group = &tree.Nodes[group_ptr]
  106. var token_node = &tree.Nodes[group.Children[0]]
  107. var op_id = token_node.Part.Id
  108. var info, exists = syntax.Id2Operator[op_id]
  109. if !exists {
  110. panic("undefined operator " + syntax.Id2Name[op_id])
  111. }
  112. return info
  113. }
  114. func GetGeneralOperatorName (tree Tree, ptr int) (string, bool) {
  115. var Id = tree.Nodes[ptr].Part.Id
  116. if Id != syntax.Name2Id["general_op"] {
  117. panic("invalid usage of GetGeneralOperatorName()")
  118. }
  119. // general_op = operator | unary
  120. var children = Children(tree, ptr)
  121. var infix, is_infix = children["operator"]
  122. if is_infix {
  123. var info = GetOperatorInfo(tree, infix)
  124. return strings.TrimPrefix(info.Match, "@"), info.CanRedef
  125. } else {
  126. var unary = children["unary"]
  127. var group = tree.Nodes[unary].Children[0]
  128. var child = tree.Nodes[group].Children[0]
  129. var match = syntax.Id2Name[tree.Nodes[child].Part.Id]
  130. var can_redef = false
  131. for _, redefinable := range syntax.RedefinableOperators {
  132. if match == redefinable {
  133. can_redef = true
  134. break
  135. }
  136. }
  137. return strings.TrimPrefix(match, "@"), can_redef
  138. }
  139. }
  140. func WriteHelpers (buf *strings.Builder, scope_name string) {
  141. fmt.Fprintf (
  142. buf,
  143. "let {%v,%v,%v,%v,%v,%v,%v,%v,%v,%v,%v,%v,%v,%v} = %v.%v(%v); ",
  144. L_METHOD_CALL, L_VAR_LOOKUP, L_VAR_DECL, L_VAR_RESET,
  145. L_ADD_FUN, L_OP_MOUNT, L_OP_PUSH, L_STATIC_SCOPE, L_WRAP,
  146. L_IMPORT_VAR, L_IMPORT_MOD, L_IMPORT_ALL, L_MATCH,
  147. L_GLOBAL_HELPERS,
  148. RUNTIME, R_GET_HELPERS, scope_name,
  149. )
  150. }
  151. func BareFunction (content string) string {
  152. var buf strings.Builder
  153. fmt.Fprintf(&buf, "(function (%v) { ", SCOPE)
  154. WriteHelpers(&buf, SCOPE)
  155. buf.WriteString(content)
  156. buf.WriteString(" })")
  157. return buf.String()
  158. }
  159. func BareAsyncFunction (content string) string {
  160. var buf strings.Builder
  161. fmt.Fprintf(&buf, "(async function (%v) { ", SCOPE)
  162. WriteHelpers(&buf, SCOPE)
  163. buf.WriteString(content)
  164. buf.WriteString(" })")
  165. return buf.String()
  166. }
  167. func BareGenerator (content string) string {
  168. var buf strings.Builder
  169. fmt.Fprintf(&buf, "(function* (%v) { ", SCOPE)
  170. WriteHelpers(&buf, SCOPE)
  171. buf.WriteString(content)
  172. buf.WriteString(" })")
  173. return buf.String()
  174. }
  175. func BareAsyncGenerator (content string) string {
  176. var buf strings.Builder
  177. fmt.Fprintf(&buf, "(async function* (%v) { ", SCOPE)
  178. WriteHelpers(&buf, SCOPE)
  179. buf.WriteString(content)
  180. buf.WriteString(" })")
  181. return buf.String()
  182. }
  183. func Commands (tree Tree, ptr int, add_return bool) string {
  184. var commands = FlatSubTree(tree, ptr, "command", "commands")
  185. var ReturnId = syntax.Name2Id["cmd_return"]
  186. var has_return = false
  187. var prev_row = -1
  188. var buf strings.Builder
  189. for i, command := range commands {
  190. if !has_return {
  191. var group = tree.Nodes[command].Children[0]
  192. if group == 0 { panic("invalid command") }
  193. var real = tree.Nodes[group].Children[0]
  194. if real == 0 { panic("invalid command") }
  195. if tree.Nodes[real].Part.Id == ReturnId {
  196. has_return = true
  197. }
  198. }
  199. var node = &tree.Nodes[command]
  200. var token = tree.Tokens[node.Pos]
  201. var row = tree.Info[token.Pos].Row
  202. if row == prev_row && !tree.Semi[node.Pos] {
  203. parser.Error(tree, command, "semicolon expected")
  204. }
  205. prev_row = row
  206. buf.WriteString(Transpile(tree, command))
  207. if i != len(commands)-1 {
  208. buf.WriteString("; ")
  209. } else {
  210. buf.WriteString(";")
  211. }
  212. }
  213. if add_return && !has_return {
  214. // return Void
  215. fmt.Fprintf(&buf, " return %v;", G(T_VOID))
  216. }
  217. return buf.String()
  218. }
  219. func Function (
  220. tree Tree, body_ptr int, fun_type FunType,
  221. desc string, parameters string, value_type string,
  222. ) string {
  223. var body = Transpile(tree, body_ptr)
  224. var body_children = Children(tree, body_ptr)
  225. // static_commands? = @static { commands }
  226. var static_ptr = body_children["static_commands"]
  227. var static_scope = "null"
  228. if NotEmpty(tree, static_ptr) {
  229. var parent_ptr = tree.Nodes[body_ptr].Parent
  230. var parent_name = syntax.Id2Name[tree.Nodes[parent_ptr].Part.Id]
  231. if parent_name == "method" || parent_name == "method_implemented" {
  232. parser.Error (
  233. tree, static_ptr,
  234. "static block is not available in method definition",
  235. )
  236. }
  237. var static_commands_ptr = Children(tree, static_ptr)["commands"]
  238. var static_commands = Commands(tree, static_commands_ptr, true)
  239. var static_executor = BareFunction(static_commands)
  240. static_scope = fmt.Sprintf("%v(%v)", L_STATIC_SCOPE, static_executor)
  241. }
  242. var raw string
  243. switch fun_type {
  244. case F_Sync:
  245. raw = BareFunction(body)
  246. case F_Async:
  247. raw = BareAsyncFunction(body)
  248. case F_Generator:
  249. raw = BareGenerator(body)
  250. case F_AsyncGenerator:
  251. raw = BareAsyncGenerator(body)
  252. default:
  253. panic("invalid FunType")
  254. }
  255. return fmt.Sprintf(
  256. "%v(%v, %v, %v, %v)",
  257. L_WRAP,
  258. fmt.Sprintf(
  259. "{ parameters: %v, value_type: %v }",
  260. parameters, value_type,
  261. ),
  262. static_scope, desc, raw,
  263. )
  264. }
  265. func InitFunction (tree Tree, ptr int, name []rune) string {
  266. var children = Children(tree, ptr)
  267. var params_ptr = children["paralist_strict"]
  268. var parameters = Transpile(tree, params_ptr)
  269. var body_ptr = children["body"]
  270. var desc = Desc (
  271. name,
  272. GetWholeContent(tree, params_ptr),
  273. []rune("Instance"),
  274. )
  275. return Function (
  276. tree, body_ptr, F_Sync,
  277. desc, parameters, G(T_INSTANCE),
  278. )
  279. }
  280. func Desc (name []rune, parameters []rune, value_type []rune) string {
  281. var desc_buf = make([]rune, 0, 120)
  282. desc_buf = append(desc_buf, name...)
  283. desc_buf = append(desc_buf, ' ')
  284. if len(parameters) == 0 || parameters[0] != '(' {
  285. desc_buf = append(desc_buf, '(')
  286. }
  287. desc_buf = append(desc_buf, parameters...)
  288. if len(parameters) == 0 || parameters[len(parameters)-1] != ')' {
  289. desc_buf = append(desc_buf, ')')
  290. }
  291. desc_buf = append(desc_buf, []rune(" -> ")...)
  292. desc_buf = append(desc_buf, value_type...)
  293. return EscapeRawString(desc_buf)
  294. }
  295. func SearchDotParameters (tree Tree, search_root int) []string {
  296. var names = make([]string, 0, 25)
  297. var DotParaId = syntax.Name2Id["dot_para"]
  298. var LambdaId = syntax.Name2Id["lambda"]
  299. var IIFE_Id = syntax.Name2Id["iife"]
  300. var do_search func(int)
  301. do_search = func (ptr int) {
  302. var node = &tree.Nodes[ptr]
  303. var id = node.Part.Id
  304. if (id == LambdaId || id == IIFE_Id) && ptr != search_root {
  305. return
  306. } else if id == DotParaId {
  307. // dot_para = . Name
  308. var children = Children(tree, ptr)
  309. var name = GetTokenContent(tree, children["Name"])
  310. names = append(names, string(name))
  311. }
  312. for i := 0; i < node.Length; i++ {
  313. var child = node.Children[i]
  314. do_search(child)
  315. }
  316. }
  317. do_search(search_root)
  318. var name_set = make(map[string]bool)
  319. var normalized = make([]string, 0, 10)
  320. for _, name := range names {
  321. var _, exists = name_set[name]
  322. if !exists {
  323. name_set[name] = true
  324. normalized = append(normalized, name)
  325. }
  326. }
  327. return normalized
  328. }
  329. func UntypedParameters (names []string) string {
  330. var buf strings.Builder
  331. buf.WriteRune('[')
  332. for i, name := range names {
  333. fmt.Fprintf (
  334. &buf, "{ name: %v, type: %v }",
  335. EscapeRawString([]rune(name)),
  336. G(T_ANY),
  337. )
  338. if i != len(names)-1 {
  339. buf.WriteString(", ")
  340. }
  341. }
  342. buf.WriteRune(']')
  343. return buf.String()
  344. }
  345. func TypedParameterList (tree Tree, namelist_ptr int, type_ string) string {
  346. var name_ptrs = FlatSubTree(tree, namelist_ptr, "name", "namelist_tail")
  347. var occurred = make(map[string]bool)
  348. var buf strings.Builder
  349. buf.WriteRune('[')
  350. for i, name_ptr := range name_ptrs {
  351. var name = Transpile(tree, name_ptr)
  352. if occurred[name] {
  353. parser.Error (
  354. tree, name_ptr, fmt.Sprintf (
  355. "duplicate parameter %v",
  356. name,
  357. ),
  358. )
  359. }
  360. occurred[name] = true
  361. fmt.Fprintf(&buf, "{ name: %v, type: %v }", name, type_)
  362. if i != len(name_ptrs)-1 {
  363. buf.WriteString(", ")
  364. }
  365. }
  366. buf.WriteRune(']')
  367. return buf.String()
  368. }
  369. func UntypedParameterList (tree Tree, namelist_ptr int) string {
  370. return TypedParameterList(tree, namelist_ptr, G(T_ANY))
  371. }
  372. func GenericParameters (tree Tree, gp_ptr int, name []rune) (string, string) {
  373. var GpId = syntax.Name2Id["generic_params"]
  374. if tree.Nodes[gp_ptr].Part.Id != GpId || !NotEmpty(tree, gp_ptr) {
  375. panic("invalid usage of GenericParameters()")
  376. }
  377. var children = Children(tree, gp_ptr)
  378. var parameters string
  379. var desc string
  380. var typed_ptr, exists = children["typed_list"]
  381. if exists {
  382. parameters = Transpile(tree, typed_ptr)
  383. desc = Desc(name, GetWholeContent(tree, typed_ptr), []rune("Type"))
  384. } else {
  385. var l_ptr = children["namelist"]
  386. parameters = TypedParameterList(tree, l_ptr, G(T_TYPE))
  387. desc = Desc(name, GetWholeContent(tree, l_ptr), []rune("Type"))
  388. }
  389. return parameters, desc
  390. }
  391. func TypeTemplate (tree Tree, gp_ptr int, name_ptr int, expr string) string {
  392. var name_raw = GetTokenContent(tree, name_ptr)
  393. var parameters, desc = GenericParameters(tree, gp_ptr, name_raw)
  394. var raw = BareFunction(fmt.Sprintf("return %v;", expr))
  395. var proto = fmt.Sprintf (
  396. "{ parameters: %v, value_type: %v }",
  397. parameters, G(T_TYPE),
  398. )
  399. var f = fmt.Sprintf (
  400. "%v(%v, %v, %v, %v)",
  401. L_WRAP, proto, "null", desc, raw,
  402. )
  403. return fmt.Sprintf("%v(%v)", G(C_TEMPLATE), f)
  404. }
  405. func FieldList (tree Tree, ptr int) (string, string, string) {
  406. var FieldListId = syntax.Name2Id["field_list"]
  407. if tree.Nodes[ptr].Part.Id != FieldListId {
  408. panic("invalid usage of FieldList()")
  409. }
  410. var names = make([]string, 0, 16)
  411. var types = make([]string, 0, 16)
  412. var defaults = make([]string, 0, 16)
  413. var contains = make([]string, 0, 16)
  414. var names_hash = make(map[string]bool)
  415. // field_list = field field_list_tail
  416. var field_ptrs = FlatSubTree(tree, ptr, "field", "field_list_tail")
  417. for _, field_ptr := range field_ptrs {
  418. // field = name : type! field_default | @fields @of type!
  419. var children = Children(tree, field_ptr)
  420. var name_ptr, has_name = children["name"]
  421. if !has_name {
  422. contains = append(contains, Transpile(tree, children["type"]))
  423. continue
  424. }
  425. var name = Transpile(tree, name_ptr)
  426. var type_ = Transpile(tree, children["type"])
  427. var _, exists = names_hash[name]
  428. if exists {
  429. parser.Error (
  430. tree, field_ptr, fmt.Sprintf (
  431. "duplicate schema field %v",
  432. name,
  433. ),
  434. )
  435. }
  436. names_hash[name] = true
  437. var default_ string
  438. var default_ptr = children["field_default"]
  439. if NotEmpty(tree, default_ptr) {
  440. // field_default? = = expr
  441. default_ = TranspileLastChild(tree, default_ptr)
  442. } else {
  443. default_ = ""
  444. }
  445. names = append(names, name)
  446. types = append(types, type_)
  447. defaults = append(defaults, default_)
  448. }
  449. var field_items = make([]string, 0, 16)
  450. var default_items = make([]string, 0, 16)
  451. for i := 0; i < len(names); i++ {
  452. var field_item = fmt.Sprintf("%v: %v", names[i], types[i])
  453. field_items = append(field_items, field_item)
  454. if defaults[i] != "" {
  455. var default_item = fmt.Sprintf("%v: %v", names[i], defaults[i])
  456. default_items = append(default_items, default_item)
  457. }
  458. }
  459. var t = fmt.Sprintf("{ %v }", strings.Join(field_items, ", "))
  460. var d = fmt.Sprintf("{ %v }", strings.Join(default_items, ", "))
  461. var c = fmt.Sprintf("[%v]", strings.Join(contains, ", "))
  462. return t, d, c
  463. }
  464. func MethodTable (tree Tree, ptr int, extract string, next string) string {
  465. if NotEmpty(tree, ptr) {
  466. // argument 'extract' can be "method" or "pf"
  467. // note: the rule name "method" is depended by Function()
  468. var method_ptrs = FlatSubTree(tree, ptr, extract, next)
  469. var buf strings.Builder
  470. for i, method_ptr := range method_ptrs {
  471. var children = Children(tree, method_ptr)
  472. var name = Transpile(tree, children["name"])
  473. // call another rule function here
  474. var method = TransMapByName["f_sync"](tree, method_ptr)
  475. fmt.Fprintf(&buf, "{ name: %v, f: %v }", name, method)
  476. if i != len(method_ptrs)-1 {
  477. buf.WriteString(", ")
  478. }
  479. }
  480. return fmt.Sprintf("[ %v ]", buf.String())
  481. } else {
  482. return "[]"
  483. }
  484. }
  485. func Filters (tree Tree, exprlist_ptr int) string {
  486. var ExprListId = syntax.Name2Id["exprlist"]
  487. if tree.Nodes[exprlist_ptr].Part.Id != ExprListId {
  488. panic("invalid usage of Filters()")
  489. }
  490. var file = GetFileName(tree)
  491. var expr_ptrs = FlatSubTree(tree, exprlist_ptr, "expr", "exprlist_tail")
  492. var buf strings.Builder
  493. buf.WriteRune('(')
  494. for i, expr_ptr := range expr_ptrs {
  495. var row, col = GetRowColInfo(tree, expr_ptr)
  496. fmt.Fprintf (
  497. &buf, "%v(%v, [%v], %v, %v, %v)",
  498. G(CALL), G(REQ_BOOL), Transpile(tree, expr_ptr), file, row, col,
  499. )
  500. if i != len(expr_ptrs)-1 {
  501. buf.WriteString(" && ")
  502. }
  503. }
  504. buf.WriteRune(')')
  505. return buf.String()
  506. }
  507. func WriteList (buf *strings.Builder, strlist []string) {
  508. for i, item := range strlist {
  509. buf.WriteString(item)
  510. if i != len(strlist)-1 {
  511. buf.WriteString(", ")
  512. }
  513. }
  514. }
  515. func GetKey (tree Tree, ptr int) (string, string) {
  516. if tree.Nodes[ptr].Part.Id != syntax.Name2Id["get"] {
  517. panic("invalid usage of GetKey()")
  518. }
  519. // get = get_expr | get_name
  520. var params = Children(tree, tree.Nodes[ptr].Children[0])
  521. // get_expr = Get [ expr! ]! nil_flag
  522. // get_name = Get . name! nil_flag
  523. var nil_flag = Transpile(tree, params["nil_flag"])
  524. var _, is_get_expr = params["expr"]
  525. if is_get_expr {
  526. return Transpile(tree, params["expr"]), nil_flag
  527. } else {
  528. return Transpile(tree, params["name"]), nil_flag
  529. }
  530. }
  531. func CondBranch (cond string, file string, row string, col string) string {
  532. return cond
  533. }
  534. func MatchBranch (raw string, file string, row string, col string) string {
  535. var T = fmt.Sprintf (
  536. "%v(%v, [%v], %v, %v, %v)",
  537. G(CALL), G(REQ_TYPE), raw,
  538. file, row, col,
  539. )
  540. return fmt.Sprintf (
  541. "%v(%v(%v), [%v, %v], %v, %v, %v)",
  542. G(CALL), G(OPERATOR), "\"is\"", MATCH_TARGET, T,
  543. file, row, col,
  544. )
  545. }
  546. func Cases (
  547. tree Tree, ptr int, f func(string,string,string,string)string,
  548. ) string {
  549. // cases = case more_cases
  550. if tree.Nodes[ptr].Part.Id != syntax.Name2Id["cases"] {
  551. panic("invalid usage of Cases()")
  552. }
  553. var file = GetFileName(tree)
  554. var row, col = GetRowColInfo(tree, ptr)
  555. var case_ptrs = FlatSubTree(tree, ptr, "case", "more_cases")
  556. var buf strings.Builder
  557. buf.WriteString("if (false) { void(0) }")
  558. for _, case_ptr := range case_ptrs {
  559. // case = @otherwise block! | expr! block!
  560. var children = Children(tree, case_ptr)
  561. var _, is_default = children["@otherwise"]
  562. if is_default {
  563. var block = Transpile(tree, children["block"])
  564. fmt.Fprintf(&buf, " else if(true) %v", block)
  565. } else {
  566. var expr_ptr = children["expr"]
  567. var file = GetFileName(tree)
  568. var row, col = GetRowColInfo(tree, expr_ptr)
  569. var condition = f(Transpile(tree, expr_ptr), file, row, col)
  570. var block = Transpile(tree, children["block"])
  571. fmt.Fprintf (
  572. &buf, " else if (%v(%v, [%v], %v, %v, %v)) %v",
  573. G(CALL), G(REQ_BOOL), condition, file, row, col, block,
  574. )
  575. }
  576. }
  577. fmt.Fprintf (
  578. &buf, " else { %v(%v, [], %v, %v, %v) }",
  579. G(CALL), G(SWITCH_FAILED), file, row, col,
  580. )
  581. return buf.String()
  582. }
  583. func BranchList (
  584. tree Tree, ptr int, f func(string,string,string,string)string, err string,
  585. ) string {
  586. // branch_list = branch! branch_list_tail
  587. if tree.Nodes[ptr].Part.Id != syntax.Name2Id["branch_list"] {
  588. panic("invalid usage of BranchList()")
  589. }
  590. var file = GetFileName(tree)
  591. var row, col = GetRowColInfo(tree, ptr)
  592. var item_ptrs = FlatSubTree(tree, ptr, "branch", "branch_list_tail")
  593. var buf strings.Builder
  594. buf.WriteString("if (false) { void(0) }")
  595. for _, item_ptr := range item_ptrs {
  596. // branch = @otherwise :! expr! | expr! :! expr!
  597. var row, col = GetRowColInfo(tree, item_ptr)
  598. var children = Children(tree, item_ptr)
  599. var condition string
  600. var _, is_otherwise = children["@otherwise"]
  601. if is_otherwise {
  602. condition = "true"
  603. } else {
  604. condition = f(TranspileFirstChild(tree, item_ptr), file, row, col)
  605. }
  606. var value = TranspileLastChild(tree, item_ptr)
  607. var condition_bool = fmt.Sprintf (
  608. "%v(%v, [%v], %v, %v, %v)",
  609. G(CALL), G(REQ_BOOL), condition, file, row, col,
  610. )
  611. fmt.Fprintf (
  612. &buf, " else if (%v) { return %v }",
  613. condition_bool, value,
  614. )
  615. }
  616. fmt.Fprintf (
  617. &buf, " else { %v(%v, [], %v, %v, %v) }",
  618. G(CALL), err, file, row, col,
  619. )
  620. return buf.String()
  621. }
  622. func SubPatternList (tree Tree, ptr int, use_index bool) string {
  623. if tree.Nodes[ptr].Part.Id != syntax.Name2Id["sub_pattern_list"] {
  624. panic("invalid usage of SubPatternList()")
  625. }
  626. var TranspileExtract = func (ptr int, default_ string) string {
  627. // extract? = : name | : ( expr )!
  628. if Empty(tree, ptr) {
  629. if default_ == "" {
  630. parser.Error(tree, ptr, "colon expected")
  631. }
  632. return default_
  633. }
  634. var children = Children(tree, ptr)
  635. var expr_ptr, is_expr = children["expr"]
  636. if is_expr {
  637. return Transpile(tree, expr_ptr)
  638. } else {
  639. return Transpile(tree, children["name"])
  640. }
  641. }
  642. // sub_pattern_list = sub_pattern sub_pattern_list_tail
  643. var sub_ptrs = FlatSubTree (
  644. tree, ptr, "sub_pattern", "sub_pattern_list_tail",
  645. )
  646. var buf strings.Builder
  647. buf.WriteRune('[')
  648. for i, sub_ptr := range sub_ptrs {
  649. // sub_pattern = @_ | name nil_flag extract | pattern extract
  650. var children = Children(tree, sub_ptr)
  651. var _, is_empty = children["@_"]
  652. if is_empty {
  653. fmt.Fprintf (
  654. &buf,
  655. "{ is_final: true, ignore: true, %v }",
  656. "extract: null, target: '', allow_nil: false",
  657. )
  658. if i != len(sub_ptrs)-1 {
  659. buf.WriteString(", ")
  660. }
  661. continue
  662. }
  663. var nested_ptr, is_nested = children["pattern"]
  664. if is_nested {
  665. var default_ string
  666. if use_index {
  667. default_ = fmt.Sprintf("%v", i)
  668. } else {
  669. default_ = ""
  670. }
  671. var extract = TranspileExtract(children["extract"], default_)
  672. var nested = Transpile(tree, nested_ptr)
  673. fmt.Fprintf (
  674. &buf, "Object.assign(%v, { extract: %v })",
  675. nested, extract,
  676. )
  677. } else {
  678. var target = Transpile(tree, children["name"])
  679. var default_ string
  680. if use_index {
  681. default_ = fmt.Sprintf("%v", i)
  682. } else {
  683. default_ = Transpile(tree, children["name"])
  684. }
  685. var allow_nil = Transpile(tree, children["nil_flag"])
  686. var extract = TranspileExtract(children["extract"], default_)
  687. fmt.Fprintf (
  688. &buf,
  689. "{ %v, extract: %v, target: %v, allow_nil: %v }",
  690. "is_final: true, ignore: false", extract, target, allow_nil,
  691. )
  692. }
  693. if i != len(sub_ptrs)-1 {
  694. buf.WriteString(", ")
  695. }
  696. }
  697. buf.WriteRune(']')
  698. return buf.String()
  699. }
  700. func ReduceExpression (operators []syntax.Operator) [][3]int {
  701. /**
  702. * Reduce Expression using the Shunting Yard Algorithm
  703. *
  704. * N = the number of operators
  705. * input = [1, -1, 2, -2, ..., (N-1), -(N-1), N, 0]
  706. * (positive: operand, negative: operator, 0: pusher)
  707. * output = index stack of operands (pos: operand, neg: reduced_operand)
  708. * temp = index stack of operators
  709. * reduced = [[operand1, operand2, operator], ...]
  710. */
  711. var pusher = syntax.Operator { Priority: -1, Assoc: syntax.Left }
  712. var N = len(operators)
  713. var input = make([]int, 0, 2*N+1+1)
  714. var output = make([]int, 0, N+1)
  715. var temp = make([]int, 0, N+1)
  716. var reduced = make([][3]int, 0, N)
  717. /* Initialize the Input */
  718. for i := 0; i <= N; i++ {
  719. // add operand index (incremented by 1)
  720. input = append(input, i+1)
  721. if i < N {
  722. // add operator index (incremented by 1 and negated)
  723. input = append(input, -(i+1))
  724. }
  725. }
  726. // add pusher
  727. input = append(input, 0)
  728. /* Read the Input */
  729. for _, I := range input {
  730. if I > 0 {
  731. // positive index => operand, push it to output stack
  732. var operand_index = I-1
  733. output = append(output, operand_index)
  734. } else {
  735. // non-positive index => operator
  736. // this index will be -1 if I == 0 (operator is pusher)
  737. var operator_index = -I-1
  738. // read the operator stack
  739. for len(temp) > 0 {
  740. // there is an operator on the operator stack
  741. var this *syntax.Operator
  742. if operator_index >= 0 {
  743. // index is non-negative => normal operator
  744. this = &operators[operator_index]
  745. } else {
  746. // index is -1 => pusher
  747. this = &pusher
  748. }
  749. // get the dumped operator on the top of the stack
  750. var dumped_op_index = temp[len(temp)-1]
  751. var dumped = operators[dumped_op_index]
  752. // determine if we should reduce output by the dumped operator
  753. var should_reduce bool
  754. if (this.Assoc == syntax.Left) {
  755. should_reduce = dumped.Priority >= this.Priority
  756. } else {
  757. should_reduce = dumped.Priority > this.Priority
  758. }
  759. if should_reduce {
  760. // reduce the output stack
  761. temp = temp[0:len(temp)-1]
  762. var operand1 = output[len(output)-2]
  763. var operand2 = output[len(output)-1]
  764. output = output[0:len(output)-2]
  765. reduced = append(reduced, [3]int {
  766. operand1, operand2, dumped_op_index,
  767. })
  768. var reduced_index = len(reduced)-1
  769. output = append(output, -(reduced_index+1))
  770. } else {
  771. // important: if we should not reduce, exit the loop
  772. break
  773. }
  774. }
  775. // push the current operator to the operator stack
  776. temp = append(temp, operator_index)
  777. }
  778. }
  779. /* Return the Result */
  780. return reduced
  781. }