literal.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package transpiler
  2. import "fmt"
  3. import "strings"
  4. import "../parser"
  5. import "../parser/syntax"
  6. var LiteralMap = map[string]TransFunction {
  7. // literal = primitive | adv_literal
  8. "literal": TranspileFirstChild,
  9. // adv_literal = comp | type_literal | list | hash | brace
  10. "adv_literal": TranspileFirstChild,
  11. // brace = when | iife | struct
  12. "brace": TranspileFirstChild,
  13. // when = @when {! branch_list }!
  14. "when": func (tree Tree, ptr int) string {
  15. var children = Children(tree, ptr)
  16. return fmt.Sprintf (
  17. "((function(){ %v })())",
  18. BranchList (
  19. tree, children["branch_list"],
  20. CondBranch, G(WHEN_FAILED),
  21. ),
  22. )
  23. },
  24. // match = @match expr {! branch_list }!
  25. "match": func (tree Tree, ptr int) string {
  26. var children = Children(tree, ptr)
  27. var declare_target = fmt.Sprintf (
  28. "let %v = %v;",
  29. MATCH_TARGET, Transpile(tree, children["expr"]),
  30. )
  31. return fmt.Sprintf (
  32. "((function(){ %v %v })())",
  33. declare_target,
  34. BranchList (
  35. tree, children["branch_list"],
  36. MatchBranch, G(MATCH_FAILED),
  37. ),
  38. )
  39. },
  40. // observer = @observer body
  41. "observer": func (tree Tree, ptr int) string {
  42. var children = Children(tree, ptr)
  43. var body_ptr = children["body"]
  44. var desc = Desc([]rune("observer"), []rune("()"), []rune("Object"))
  45. var f = Function(tree, body_ptr, F_Sync, desc, "[]", G(T_ANY))
  46. return fmt.Sprintf("%v(%v)", G(C_OBSERVER), f)
  47. },
  48. // tree = _tree tree_node! | @tree { tree_node! }!
  49. "tree": func (tree Tree, ptr int) string {
  50. var children = Children(tree, ptr)
  51. return Transpile(tree, children["tree_node"])
  52. },
  53. // tree_node = type { node_props node_children }!
  54. "tree_node": func (tree Tree, ptr int) string {
  55. var children = Children(tree, ptr)
  56. var inflater = Transpile(tree, children["type"])
  57. var node_props = Transpile(tree, children["node_props"])
  58. var node_children = Transpile(tree, children["node_children"])
  59. var file = GetFileName(tree)
  60. var row, col = GetRowColInfo(tree, ptr)
  61. return fmt.Sprintf (
  62. "%v(%v, [%v, %v, %v], %v, %v, %v)",
  63. G(CALL), G(C_TREE_NODE), inflater, node_props, node_children,
  64. file, row, col,
  65. )
  66. },
  67. // node_props? = node_prop node_props
  68. "node_props": func (tree Tree, ptr int) string {
  69. if Empty(tree, ptr) { return "{}" }
  70. var prop_ptrs = FlatSubTree(tree, ptr, "node_prop", "node_props")
  71. var occurred = make(map[string]bool)
  72. var buf strings.Builder
  73. buf.WriteString("{ ")
  74. for i, prop_ptr := range prop_ptrs {
  75. // node_prop = name = expr! | string = expr!
  76. var children = Children(tree, prop_ptr)
  77. var name_ptr, has_name = children["name"]
  78. var name string
  79. // note: see comments in LiteralMap["hash"]
  80. if has_name {
  81. name = Transpile(tree, name_ptr)
  82. } else {
  83. name = Transpile(tree, children["string"])
  84. }
  85. if occurred[name] {
  86. parser.Error (
  87. tree, prop_ptr,
  88. fmt.Sprintf (
  89. "duplicate prop %v",
  90. name,
  91. ),
  92. )
  93. }
  94. occurred[name] = true
  95. var value = Transpile(tree, children["expr"])
  96. fmt.Fprintf(&buf, "%v: %v", name, value)
  97. if i != len(prop_ptrs)-1 {
  98. buf.WriteString(", ")
  99. }
  100. }
  101. buf.WriteString(" }")
  102. return buf.String()
  103. },
  104. // node_children? = node_child node_children
  105. "node_children": func (tree Tree, ptr int) string {
  106. if Empty(tree, ptr) { return "[]" }
  107. return TranspileSubTree(tree, ptr, "node_child", "node_children")
  108. },
  109. // node_child = tree_node | = expr
  110. "node_child": TranspileLastChild,
  111. // hash = { } | { hash_item! hash_tail }!
  112. "hash": func (tree Tree, ptr int) string {
  113. if tree.Nodes[ptr].Length == 2 {
  114. return "{}"
  115. }
  116. var items = FlatSubTree(tree, ptr, "hash_item", "hash_tail")
  117. var names = make(map[string]bool)
  118. var buf strings.Builder
  119. buf.WriteString("{ ")
  120. for i, item := range items {
  121. // hash_item = name :! expr! | string :! expr! | :: name!
  122. var children = Children(tree, item)
  123. var name_ptr, has_name = children["name"]
  124. var expr_ptr, has_expr = children["expr"]
  125. var name string
  126. if has_name {
  127. name = Transpile(tree, name_ptr)
  128. } else {
  129. name = Transpile(tree, children["string"])
  130. }
  131. var _, exists = names[name]
  132. if exists {
  133. // this check requires `Transpile(tree, name_ptr)`
  134. // and `Transpile(tree, children["string"])`
  135. // using the same quotes, which is promised by EscapeRawString()
  136. parser.Error (
  137. tree, item,
  138. fmt.Sprintf (
  139. "duplicate hash key %v",
  140. name,
  141. ),
  142. )
  143. }
  144. names[name] = true
  145. var expr string
  146. if has_expr {
  147. expr = Transpile(tree, expr_ptr)
  148. } else {
  149. expr = VarLookup(tree, name_ptr)
  150. }
  151. fmt.Fprintf(&buf, "%v: %v", name, expr)
  152. if i != len(items)-1 {
  153. buf.WriteString(", ")
  154. }
  155. }
  156. buf.WriteString(" }")
  157. return buf.String()
  158. },
  159. // list = [ ] | [ list_item! list_tail ]!
  160. "list": func (tree Tree, ptr int) string {
  161. if tree.Nodes[ptr].Length == 2 {
  162. return "[]"
  163. } else {
  164. return TranspileSubTree(tree, ptr, "list_item", "list_tail")
  165. }
  166. },
  167. // list_item = expr
  168. "list_item": TranspileFirstChild,
  169. // comp = .[ comp_rule! ]! | [ comp_rule ]!
  170. "comp": func (tree Tree, ptr int) string {
  171. var children = Children(tree, ptr)
  172. var _, is_iterator = children[".["]
  173. var rule = Transpile(tree, children["comp_rule"])
  174. var file = GetFileName(tree)
  175. var row, col = GetRowColInfo(tree, ptr)
  176. var f string
  177. if is_iterator {
  178. f = G(ITER_COMP)
  179. } else {
  180. f = G(LIST_COMP)
  181. }
  182. return fmt.Sprintf (
  183. "%v(%v, [%v], %v, %v, %v)",
  184. G(CALL), f, rule, file, row, col,
  185. )
  186. },
  187. // comp_rule = expr _bar1 in_list! opt_filters
  188. "comp_rule": func (tree Tree, ptr int) string {
  189. var children = Children(tree, ptr)
  190. var val_expr = Transpile(tree, children["expr"])
  191. var list_ptr = children["in_list"]
  192. // in_list = in_item in_list_tail
  193. var item_ptrs = FlatSubTree(tree, list_ptr, "in_item", "in_list_tail")
  194. var names = make([]string, 0, 10)
  195. var occurred = make(map[string]bool)
  196. var iterators = make([]string, 0, 10)
  197. for _, item_ptr := range item_ptrs {
  198. // in_item = name @in expr
  199. var item_children = Children(tree, item_ptr)
  200. var name = string(GetTokenContent(tree, item_children["name"]))
  201. var expr = Transpile(tree, item_children["expr"])
  202. if occurred[name] {
  203. parser.Error (
  204. tree, item_ptr, fmt.Sprintf (
  205. `duplicate parameter "%v"`,
  206. name,
  207. ),
  208. )
  209. }
  210. occurred[name] = true
  211. names = append(names, name)
  212. iterators = append(iterators, expr)
  213. }
  214. var parameters = UntypedParameters(names)
  215. var proto = fmt.Sprintf (
  216. "{ parameters: %v, value_type: %v }",
  217. parameters, G(T_ANY),
  218. )
  219. var val_raw = BareFunction(fmt.Sprintf("return %v;", val_expr))
  220. var val_desc = EscapeRawString([]rune("comprehension.value_function"))
  221. var val = fmt.Sprintf (
  222. "%v(%v, %v, %v, %v)",
  223. L_WRAP, proto, "null", val_desc, val_raw,
  224. )
  225. var iterator_list = fmt.Sprintf (
  226. "[%v]", strings.Join(iterators, ", "),
  227. )
  228. var filter_expr = Transpile(tree, children["opt_filters"])
  229. var filter_raw = BareFunction(fmt.Sprintf("return %v;", filter_expr))
  230. var filter_desc = EscapeRawString([]rune("comprehension.filter"))
  231. var filter = fmt.Sprintf (
  232. "%v(%v, %v, %v, %v)",
  233. L_WRAP, proto, "null", filter_desc, filter_raw,
  234. )
  235. return fmt.Sprintf("%v, %v, %v", val, iterator_list, filter)
  236. },
  237. // opt_filters? = , exprlist
  238. "opt_filters": func (tree Tree, ptr int) string {
  239. if NotEmpty(tree, ptr) {
  240. var children = Children(tree, ptr)
  241. return Filters(tree, children["exprlist"])
  242. } else {
  243. return "true"
  244. }
  245. },
  246. // struct = type struct_hash
  247. "struct": func (tree Tree, ptr int) string {
  248. var file = GetFileName(tree)
  249. var row, col = GetRowColInfo(tree, ptr)
  250. var children = Children(tree, ptr)
  251. var type_ = Transpile(tree, children["type"])
  252. var hash = Transpile(tree, children["struct_hash"])
  253. return fmt.Sprintf (
  254. "%v(%v, [%v, %v], %v, %v, %v)",
  255. G(CALL), G(C_STRUCT), type_, hash, file, row, col,
  256. )
  257. },
  258. // struct_hash = { } | { struct_hash_item struct_hash_tail }!
  259. "struct_hash": func (tree Tree, ptr int) string {
  260. if tree.Nodes[ptr].Length == 2 {
  261. return "{}"
  262. }
  263. var item_ptrs = FlatSubTree (
  264. tree, ptr, "struct_hash_item", "struct_hash_tail",
  265. )
  266. var names = make(map[string]bool)
  267. var buf strings.Builder
  268. buf.WriteString("{ ")
  269. for i, item_ptr := range item_ptrs {
  270. // struct_hash_item = name : expr! | :: name!
  271. var children = Children(tree, item_ptr)
  272. var name_ptr = children["name"]
  273. var name = Transpile(tree, name_ptr)
  274. var expr_ptr, has_expr = children["expr"]
  275. var _, exists = names[name]
  276. if exists {
  277. parser.Error (
  278. tree, item_ptr, fmt.Sprintf (
  279. "duplicate struct field %v",
  280. name,
  281. ),
  282. )
  283. }
  284. names[name] = true
  285. var expr string
  286. if has_expr {
  287. expr = Transpile(tree, expr_ptr)
  288. } else {
  289. expr = VarLookup(tree, name_ptr)
  290. }
  291. fmt.Fprintf(&buf, "%v: %v", name, expr)
  292. if i != len(item_ptrs)-1 {
  293. buf.WriteString(", ")
  294. }
  295. }
  296. buf.WriteString(" }")
  297. return buf.String()
  298. },
  299. // primitive = string | number | bool
  300. "primitive": TranspileFirstChild,
  301. // string = String
  302. "string": func (tree Tree, ptr int) string {
  303. var MulId = syntax.Name2Id["MulStr"]
  304. var child = tree.Nodes[tree.Nodes[ptr].Children[0]]
  305. var content = GetTokenContent(tree, ptr)
  306. var trimed []rune
  307. if child.Part.Id == MulId {
  308. trimed = content[3:len(content)-3]
  309. } else {
  310. trimed = content[1:len(content)-1]
  311. }
  312. return EscapeRawString(trimed)
  313. },
  314. // number = Hex | Exp | Dec | Int
  315. "number": func (tree Tree, ptr int) string {
  316. return string(GetTokenContent(tree, ptr))
  317. },
  318. // bool = @true | @false
  319. "bool": func (tree Tree, ptr int) string {
  320. var child_ptr = tree.Nodes[ptr].Children[0]
  321. if tree.Nodes[child_ptr].Part.Id == syntax.Name2Id["@true"] {
  322. return "true"
  323. } else {
  324. return "false"
  325. }
  326. },
  327. }