function.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. package transpiler
  2. import "fmt"
  3. import "strings"
  4. import "../parser"
  5. import "../parser/syntax"
  6. var FunctionMap = map[string]TransFunction {
  7. // function = f_sync
  8. "function": TranspileFirstChild,
  9. // f_sync = @function name Call paralist_strict! ->! type! body!
  10. "f_sync": func (tree Tree, ptr int) string {
  11. // the rule name "f_sync" is depended by OO_Map["method_implemented"]
  12. // the rule name "f_sync" is also depended by MethodTable()
  13. var children = Children(tree, ptr)
  14. var name_ptr = children["name"]
  15. var params_ptr = children["paralist_strict"]
  16. var parameters = Transpile(tree, params_ptr)
  17. var type_ptr = children["type"]
  18. var value_type = Transpile(tree, type_ptr)
  19. var body_ptr = children["body"]
  20. var desc = Desc (
  21. GetWholeContent(tree, name_ptr),
  22. GetWholeContent(tree, params_ptr),
  23. GetWholeContent(tree, type_ptr),
  24. )
  25. return Function (
  26. tree, body_ptr, F_Sync,
  27. desc, parameters, value_type,
  28. )
  29. },
  30. // lambda = lambda_block | lambda_inline
  31. "lambda": TranspileFirstChild,
  32. // lambda_block = @lambda paralist_block ret_lambda body!
  33. "lambda_block": func (tree Tree, ptr int) string {
  34. var children = Children(tree, ptr)
  35. var paralist_ptr = children["paralist_block"]
  36. var parameters = Transpile(tree, paralist_ptr)
  37. var ret_ptr = children["ret_lambda"]
  38. var value_type = Transpile(tree, ret_ptr)
  39. var body_ptr = children["body"]
  40. var value_type_desc string
  41. if value_type == G(T_ANY) {
  42. value_type_desc = "Object"
  43. } else {
  44. var t = string(GetWholeContent(tree, ret_ptr))
  45. t = strings.TrimPrefix(t, "->")
  46. t = strings.TrimLeft(t, " ")
  47. value_type_desc = t
  48. }
  49. var desc = Desc (
  50. []rune("lambda"),
  51. GetWholeContent(tree, paralist_ptr),
  52. []rune(value_type_desc),
  53. )
  54. return Function (
  55. tree, body_ptr, F_Sync,
  56. desc, parameters, value_type,
  57. )
  58. },
  59. // ret_lambda? = -> type | ->
  60. "ret_lambda": func (tree Tree, ptr int) string {
  61. if NotEmpty(tree, ptr) {
  62. var children = Children(tree, ptr)
  63. var type_ptr, type_specified = children["type"]
  64. if type_specified {
  65. return Transpile(tree, type_ptr)
  66. } else {
  67. return G(T_ANY)
  68. }
  69. } else {
  70. return G(T_ANY)
  71. }
  72. },
  73. // lambda_inline = .{ paralist_inline expr! }!
  74. "lambda_inline": func (tree Tree, ptr int) string {
  75. var children = Children(tree, ptr)
  76. var l_ptr = children["paralist_inline"]
  77. var parameters string
  78. var desc string
  79. if NotEmpty(tree, l_ptr) {
  80. parameters = Transpile(tree, l_ptr)
  81. var l_children = Children(tree, l_ptr)
  82. desc = Desc (
  83. []rune("lambda"),
  84. GetWholeContent(tree, l_children["namelist"]),
  85. []rune("Object"),
  86. )
  87. } else {
  88. var names = SearchDotParameters(tree, ptr)
  89. parameters = UntypedParameters(names)
  90. desc = Desc (
  91. []rune("lambda"),
  92. []rune(strings.Join(names, ", ")),
  93. []rune("Object"),
  94. )
  95. }
  96. var expr = Transpile(tree, children["expr"])
  97. var raw = BareFunction(fmt.Sprintf("return %v;", expr))
  98. var proto = fmt.Sprintf (
  99. "{ parameters: %v, value_type: %v }",
  100. parameters, G(T_ANY),
  101. )
  102. return fmt.Sprintf (
  103. "%v(%v, %v, %v, %v)",
  104. L_WRAP, proto, "null", desc, raw,
  105. )
  106. },
  107. // iife = invoke | iterator | promise | async_iterator
  108. "iife": TranspileFirstChild,
  109. // invoke = @invoke body
  110. "invoke": func (tree Tree, ptr int) string {
  111. var children = Children(tree, ptr)
  112. var body_ptr = children["body"]
  113. var desc = Desc([]rune("IIFE"), []rune("()"), []rune("Object"))
  114. var f = Function(tree, body_ptr, F_Sync, desc, "[]", G(T_ANY))
  115. var file = GetFileName(tree)
  116. var row, col = GetRowColInfo(tree, ptr)
  117. return fmt.Sprintf("%v(%v, [], %v, %v, %v)", G(CALL), f, file, row, col)
  118. },
  119. // promise = @promise body
  120. "promise": func (tree Tree, ptr int) string {
  121. var children = Children(tree, ptr)
  122. var body_ptr = children["body"]
  123. var desc = Desc([]rune("IIFE"), []rune("()"), []rune("Promise"))
  124. var f = Function(tree, body_ptr, F_Async, desc, "[]", G(T_PROMISE))
  125. var file = GetFileName(tree)
  126. var row, col = GetRowColInfo(tree, ptr)
  127. return fmt.Sprintf("%v(%v, [], %v, %v, %v)", G(CALL), f, file, row, col)
  128. },
  129. // iterator = @iterator body
  130. "iterator": func (tree Tree, ptr int) string {
  131. var children = Children(tree, ptr)
  132. var body_ptr = children["body"]
  133. var desc = Desc([]rune("IIFE"), []rune("()"), []rune("Iterator"))
  134. var f = Function(tree, body_ptr, F_Generator, desc, "[]", G(T_ITERATOR))
  135. var file = GetFileName(tree)
  136. var row, col = GetRowColInfo(tree, ptr)
  137. return fmt.Sprintf("%v(%v, [], %v, %v, %v)", G(CALL), f, file, row, col)
  138. },
  139. // async_iterator = @async @iterator body!
  140. "async_iterator": func (tree Tree, ptr int) string {
  141. var children = Children(tree, ptr)
  142. var body_ptr = children["body"]
  143. var desc = Desc([]rune("IIFE"), []rune("()"), []rune("AsyncIterator"))
  144. var f = Function (
  145. tree, body_ptr, F_AsyncGenerator, desc, "[]", G(T_ASYNC_ITERATOR),
  146. )
  147. var file = GetFileName(tree)
  148. var row, col = GetRowColInfo(tree, ptr)
  149. return fmt.Sprintf("%v(%v, [], %v, %v, %v)", G(CALL), f, file, row, col)
  150. },
  151. // body = { static_commands commands mock_hook handle_hook }!
  152. "body": func (tree Tree, ptr int) string {
  153. // note: the rule name "body" is depended by CommandMap["block"]
  154. var children = Children(tree, ptr)
  155. // mock_hook? = ... @mock name! { commands }
  156. var mock_ptr = children["mock_hook"]
  157. var should_mock = false
  158. var mock_commands_ptr = -1
  159. if NotEmpty(tree, mock_ptr) {
  160. var children = Children(tree, mock_ptr)
  161. var name_ptr = children["name"]
  162. var name = string(GetTokenContent(tree, name_ptr))
  163. for _, mocked := range tree.Mock {
  164. if name == mocked {
  165. should_mock = true
  166. mock_commands_ptr = children["commands"]
  167. break
  168. }
  169. }
  170. }
  171. // commands? = command commands
  172. var commands_ptr = children["commands"]
  173. if should_mock {
  174. commands_ptr = mock_commands_ptr
  175. }
  176. var commands = Commands(tree, commands_ptr, true)
  177. var handle_ptr = children["handle_hook"]
  178. if NotEmpty(tree, handle_ptr) {
  179. var catch_and_finally = Transpile(tree, handle_ptr)
  180. var buf strings.Builder
  181. fmt.Fprintf(&buf, "let %v = {}; ", ERROR_DUMP)
  182. buf.WriteString("try { ")
  183. buf.WriteString(commands)
  184. buf.WriteString(" } ")
  185. buf.WriteString(catch_and_finally)
  186. fmt.Fprintf(&buf, " return %v;", G(T_VOID))
  187. return buf.String()
  188. } else {
  189. return commands
  190. }
  191. },
  192. // handle_hook? = ... @handle name { handle_cmds }! finally
  193. "handle_hook": func (tree Tree, ptr int) string {
  194. // note: the rule name "handle_hook" is depended by CommandMap["block"]
  195. var children = Children(tree, ptr)
  196. var error_name = Transpile(tree, children["name"])
  197. var buf strings.Builder
  198. fmt.Fprintf(&buf, "catch (%v) { ", H_HOOK_ERROR)
  199. fmt.Fprintf (
  200. &buf, "let %v = %v.%v(%v); ",
  201. H_HOOK_SCOPE, RUNTIME, R_NEW_SCOPE, SCOPE,
  202. )
  203. WriteHelpers(&buf, H_HOOK_SCOPE)
  204. fmt.Fprintf(&buf, "%v(%v); ", G(ENTER_H_HOOK), H_HOOK_ERROR)
  205. fmt.Fprintf(&buf, "%v(%v, %v); ", L_VAR_DECL, error_name, H_HOOK_ERROR)
  206. buf.WriteString(Transpile(tree, children["handle_cmds"]))
  207. fmt.Fprintf(&buf, " %v(%v); ", G(EXIT_H_HOOK), H_HOOK_ERROR)
  208. buf.WriteString("}")
  209. var finally_ptr = children["finally"]
  210. if NotEmpty(tree, finally_ptr) {
  211. fmt.Fprintf(
  212. &buf, " finally { %v };",
  213. Transpile(tree, finally_ptr),
  214. )
  215. } else {
  216. buf.WriteString(";")
  217. }
  218. return buf.String()
  219. },
  220. // finally? = @finally { commands }
  221. "finally": func (tree Tree, ptr int) string {
  222. var children = Children(tree, ptr)
  223. return Commands(tree, children["commands"], false)
  224. },
  225. // handle_cmds? = handle_cmd handle_cmds
  226. "handle_cmds": func (tree Tree, ptr int) string {
  227. var cmds = FlatSubTree(tree, ptr, "handle_cmd", "handle_cmds")
  228. var buf strings.Builder
  229. for _, cmd := range cmds {
  230. buf.WriteString(Transpile(tree, cmd))
  231. buf.WriteString("; ")
  232. }
  233. return buf.String()
  234. },
  235. // handle_cmd = unless | failed | command
  236. "handle_cmd": TranspileFirstChild,
  237. // unless = @unless name unless_para { commands }
  238. "unless": func (tree Tree, ptr int) string {
  239. var children = Children(tree, ptr)
  240. var name = Transpile(tree, children["name"])
  241. var params = Transpile(tree, children["unless_para"])
  242. var file = GetFileName(tree)
  243. var row, col = GetRowColInfo(tree, ptr)
  244. var buf strings.Builder
  245. fmt.Fprintf (
  246. &buf, "if (%v.%v === '%v' && %v.%v === %v)",
  247. ERROR_DUMP, DUMP_TYPE, DUMP_ENSURE, ERROR_DUMP, DUMP_NAME, name,
  248. )
  249. buf.WriteString(" { ")
  250. buf.WriteString(G(CALL))
  251. buf.WriteString("(")
  252. WriteList(&buf, []string {
  253. G(INJECT_E_ARGS),
  254. fmt.Sprintf("[%v, %v, %v]", H_HOOK_SCOPE, params, ERROR_DUMP),
  255. file, row, col,
  256. })
  257. buf.WriteString(");")
  258. buf.WriteString(Commands(tree, children["commands"], false))
  259. buf.WriteString(" }")
  260. return buf.String()
  261. },
  262. // unless_para? = Call ( namelist )
  263. "unless_para": func (tree Tree, ptr int) string {
  264. if NotEmpty(tree, ptr) {
  265. return Transpile(tree, Children(tree, ptr)["namelist"])
  266. } else {
  267. return "[]"
  268. }
  269. },
  270. // failed = @failed opt_to name { commands }
  271. "failed": func (tree Tree, ptr int) string {
  272. var children = Children(tree, ptr)
  273. var name = Transpile(tree, children["name"])
  274. var buf strings.Builder
  275. fmt.Fprintf (
  276. &buf, "if (%v.%v === '%v' && %v.%v === %v)",
  277. ERROR_DUMP, DUMP_TYPE, DUMP_TRY, ERROR_DUMP, DUMP_NAME, name,
  278. )
  279. buf.WriteString(" { ")
  280. buf.WriteString(Commands(tree, children["commands"], false))
  281. buf.WriteString(" }")
  282. return buf.String()
  283. },
  284. // paralist_strict = ( ) | ( typed_list! )!
  285. "paralist_strict": func (tree Tree, ptr int) string {
  286. var children = Children(tree, ptr)
  287. var list, exists = children["typed_list"]
  288. if exists {
  289. return Transpile(tree, list)
  290. } else {
  291. return "[]"
  292. }
  293. },
  294. // paralist_block? = name | Call paralist
  295. "paralist_block": func (tree Tree, ptr int) string {
  296. if NotEmpty(tree, ptr) {
  297. var children = Children(tree, ptr)
  298. var name_ptr, only_name = children["name"]
  299. if only_name {
  300. var name = Transpile(tree, name_ptr)
  301. return fmt.Sprintf("[{ name: %v, type: %v }]", name, G(T_ANY))
  302. } else {
  303. return Transpile(tree, children["paralist"])
  304. }
  305. } else {
  306. return "[]"
  307. }
  308. },
  309. // paralist = ( ) | ( namelist ) | ( typed_list! )!
  310. "paralist": func (tree Tree, ptr int) string {
  311. var children = Children(tree, ptr)
  312. var namelist_ptr, is_namelist = children["namelist"]
  313. var typed_list_ptr, is_typed_list = children["typed_list"]
  314. if is_namelist {
  315. return UntypedParameterList(tree, namelist_ptr)
  316. } else if is_typed_list {
  317. return Transpile(tree, typed_list_ptr)
  318. } else {
  319. return "[]"
  320. }
  321. },
  322. // paralist_inline? = namelist -->
  323. "paralist_inline": func (tree Tree, ptr int) string {
  324. if NotEmpty(tree, ptr) {
  325. var children = Children(tree, ptr)
  326. var l_ptr = children["namelist"]
  327. return UntypedParameterList(tree, l_ptr)
  328. } else {
  329. panic("trying to transpile empty paralist_inline")
  330. }
  331. },
  332. // typed_list = typed_list_item typed_list_tail
  333. "typed_list": func (tree Tree, ptr int) string {
  334. var l = FlatSubTree(tree, ptr, "typed_list_item", "typed_list_tail")
  335. var occurred = make(map[string]bool)
  336. var buf strings.Builder
  337. buf.WriteRune('[')
  338. for i, item_ptr := range l {
  339. var item_children = Children(tree, item_ptr)
  340. var name = Transpile(tree, item_children["name"])
  341. if occurred[name] {
  342. parser.Error (
  343. tree, item_ptr, fmt.Sprintf (
  344. "duplicate parameter %v",
  345. name,
  346. ),
  347. )
  348. }
  349. occurred[name] = true
  350. buf.WriteString(Transpile(tree, item_ptr))
  351. if i != len(l)-1 {
  352. buf.WriteString(",")
  353. }
  354. }
  355. buf.WriteRune(']')
  356. return buf.String()
  357. },
  358. // typed_list_item = name :! type!
  359. "typed_list_item": func (tree Tree, ptr int) string {
  360. var children = Children(tree, ptr)
  361. var name = Transpile(tree, children["name"])
  362. var type_ = Transpile(tree, children["type"])
  363. return fmt.Sprintf("{ name: %v, type: %v }", name, type_)
  364. },
  365. // operator_defs? = operator_def operator_defs
  366. "operator_defs": func (tree Tree, ptr int) string {
  367. if Empty(tree, ptr) { return "{}" }
  368. var parent = tree.Nodes[ptr].Parent
  369. var parent_id = tree.Nodes[parent].Part.Id
  370. var is_schema bool
  371. if parent_id == syntax.Name2Id["schema_config"] {
  372. is_schema = true
  373. } else if parent_id == syntax.Name2Id["class_opt"] {
  374. is_schema = false
  375. } else {
  376. panic("impossible branch")
  377. }
  378. var def_ptrs = FlatSubTree(tree, ptr, "operator_def", "operator_defs")
  379. var defined = make(map[string]bool)
  380. var buf strings.Builder
  381. buf.WriteString("{ ")
  382. for i, def_ptr := range def_ptrs {
  383. // operator_def = @operator general_op operator_def_fun
  384. var children = Children(tree, def_ptr)
  385. var op_ptr = children["general_op"]
  386. var op_name, can_redef = GetGeneralOperatorName(tree, op_ptr)
  387. if !can_redef {
  388. parser.Error (
  389. tree, def_ptr, fmt.Sprintf (
  390. "cannot overload non-redefinable operator %v",
  391. op_name,
  392. ),
  393. )
  394. }
  395. if is_schema && op_name == "copy" {
  396. parser.Error (
  397. tree, def_ptr,
  398. "cannot overload copy operator on struct",
  399. )
  400. }
  401. if defined[op_name] {
  402. parser.Error (
  403. tree, def_ptr, fmt.Sprintf (
  404. "duplicate definition of operator %v",
  405. op_name,
  406. ),
  407. )
  408. }
  409. defined[op_name] = true
  410. var op_escaped = EscapeRawString([]rune(op_name))
  411. var op_fun = Transpile(tree, children["operator_def_fun"])
  412. fmt.Fprintf(&buf, "%v: %v", op_escaped, op_fun)
  413. if i != len(def_ptrs)-1 {
  414. buf.WriteString(", ")
  415. }
  416. }
  417. buf.WriteString(" }")
  418. return buf.String()
  419. },
  420. // operator_def_fun = (! namelist! )! opt_arrow body!
  421. "operator_def_fun": func (tree Tree, ptr int) string {
  422. var children = Children(tree, ptr)
  423. var namelist_ptr = children["namelist"]
  424. var body_ptr = children["body"]
  425. var parameters = UntypedParameterList(tree, namelist_ptr)
  426. var desc = Desc (
  427. []rune("redefined_operator"),
  428. GetWholeContent(tree, namelist_ptr),
  429. []rune("Object"),
  430. )
  431. return Function(tree, body_ptr, F_Sync, desc, parameters, G(T_ANY))
  432. },
  433. }