gen.lua 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. return function(ast, out)
  2. local function compile(chu)
  3. if chu.type == "chunk" then
  4. if chu.toplevel then
  5. for k, import in pairs(chu.imports) do
  6. out("local %s = require(%q)\n", import[#import], table.concat(import, "."))
  7. end
  8. for k, var in pairs(chu.vars) do
  9. out("local %s\n", k)
  10. end
  11. for k, expr in pairs(chu.vars) do
  12. if expr then
  13. out("%s=", k)
  14. compile(expr)
  15. out(";")
  16. end
  17. end
  18. for k, t in pairs(chu.types) do
  19. out("local %s={}%s.__index=%s;setmetatable(%s, %s)", k, k, k, k, k)
  20. for _, m in pairs(t.members) do
  21. if m.type == "field" then
  22. -- Do nothing.
  23. elseif m.type == "static" then
  24. out("%s.%s=", k, m.name)
  25. compile(m.value)
  26. out(";")
  27. else
  28. error("Invalid AST")
  29. end
  30. end
  31. end
  32. out("return{")
  33. for k,v in pairs(chu.vars) do
  34. out("%s=%s,", k, k)
  35. end
  36. for k,v in pairs(chu.types) do
  37. out("%s=%s,", k, k)
  38. end
  39. out("}")
  40. else
  41. for k, stmt in ipairs(chu.stmts) do
  42. compile(stmt)
  43. if stmt.type == 'call' then
  44. out(";") --Safety delimiter.
  45. end
  46. end
  47. end
  48. elseif chu.type == "function" then
  49. out("function(%s%s)", chu.is_constructor and "_," or "", table.concat(chu.args, ","))
  50. if SAFE_MODE then
  51. for k, argname in pairs(chu.args) do
  52. local et = chu.et.args[k]
  53. if et then
  54. local checks = {}
  55. if et.type == 'integer' or et.type == 'number' or et.type == 'string' or et.type == 'boolean' then
  56. if et.type == 'integer' then
  57. table.insert(checks, 'type(' .. argname .. ')=="number"')
  58. table.insert(checks, argname .. '%1==0')
  59. else
  60. table.insert(checks, 'type(' .. argname .. ')=="'..et.type..'"')
  61. end
  62. elseif et.type == 'list' then
  63. table.insert(checks, 'type(' .. argname .. ')=="table"')
  64. end
  65. if #checks > 0 then
  66. out("assert(%s, %q);", table.concat(checks, " and "), string.format("Invalid argument %q", argname))
  67. end
  68. end
  69. end
  70. end
  71. if chu.is_constructor then
  72. out("local self=setmetatable({}, %s);", chu.et.ret.name)
  73. end
  74. compile(chu.chunk)
  75. if chu.is_constructor then
  76. out("return self;")
  77. end
  78. out("end")
  79. elseif chu.type == "let" then
  80. out("local %s", chu.var.name)
  81. if chu.expr then
  82. out("=")
  83. compile(chu.expr)
  84. end
  85. out(";")
  86. elseif chu.type == "num" then
  87. out("%g", chu.value)
  88. elseif chu.type == "var" then
  89. out("%s", chu.which.name)
  90. elseif chu.type == "binop" then
  91. local paren
  92. paren = chu.a.type == "binop" and chu.a.level > chu.level
  93. if paren then out("(") end
  94. compile(chu.a)
  95. if paren then out(")") end
  96. local op = chu.op
  97. if op == "**" then
  98. op = "^"
  99. elseif op == "/" and (not chu.a.et or chu.a.et.type == 'integer') and (not chu.b.et or chu.b.et.type == 'integer') then
  100. op = "//"
  101. end
  102. out("%s", op)
  103. paren = chu.b.type == "binop" and chu.b.level > chu.level
  104. if paren then out("(") end
  105. compile(chu.b)
  106. if paren then out(")") end
  107. elseif chu.type == "lengthof" then
  108. out("#(")
  109. compile(chu.sub)
  110. out(")")
  111. elseif chu.type == "dot" then
  112. compile(chu.a)
  113. out("%s%s", chu.colon and ":" or ".", chu.b)
  114. elseif chu.type == "index" then
  115. out("(")
  116. compile(chu.what)
  117. out(")[")
  118. compile(chu.idx)
  119. out("]")
  120. elseif chu.type == "call" then
  121. local guard = chu.type == 'binop'
  122. if guard then
  123. out("(")
  124. end
  125. compile(chu.what)
  126. if guard then
  127. out(")")
  128. end
  129. out("(")
  130. for k, v in pairs(chu.args) do
  131. compile(v)
  132. if k < #chu.args then
  133. out(",")
  134. end
  135. end
  136. out(")")
  137. elseif chu.type == "dict" then
  138. out("{")
  139. for k, v in pairs(chu.mappings) do
  140. out("[")
  141. compile(k)
  142. out("]=")
  143. compile(v)
  144. out(",")
  145. end
  146. out("}")
  147. elseif chu.type == "list" then
  148. out("{")
  149. for k, v in pairs(chu.values) do
  150. out("[%i]=", k)
  151. compile(v)
  152. out(",")
  153. end
  154. out("}")
  155. elseif chu.type == "string" then
  156. out("%q", chu.value)
  157. elseif chu.type == "null" then
  158. out("nil")
  159. elseif chu.type == "return" then
  160. out("return ")
  161. compile(chu.expr)
  162. out(";")
  163. elseif chu.type == "if" then
  164. out("if ")
  165. compile(chu[1].pred)
  166. out(" then ")
  167. compile(chu[1].chu)
  168. for i = 2, #chu do
  169. out("elseif ")
  170. compile(chu[i].pred)
  171. out("then ")
  172. compile(chu[i].chu)
  173. end
  174. if chu.elsa then
  175. out("else ")
  176. compile(chu.elsa)
  177. end
  178. out("end;")
  179. elseif chu.type == "fori" then
  180. out("for " .. chu.varname .. "=")
  181. compile(chu.from)
  182. out(",")
  183. compile(chu.to)
  184. out("-1 do ")
  185. compile(chu.chu)
  186. out("end ")
  187. elseif chu.type == "loop" then
  188. out("while true do ")
  189. compile(chu.chu)
  190. out("end ")
  191. elseif chu.type == "break" then
  192. out("break ")
  193. elseif chu.type == "noop" then
  194. elseif chu.type == "exprstat" then
  195. compile(chu.expr)
  196. out(";")
  197. elseif chu.type == "assign" then
  198. compile(chu.dest)
  199. out("=")
  200. compile(chu.src)
  201. out(";")
  202. else
  203. error(string.format("Invalid AST node (type %q)", chu.type))
  204. end
  205. end
  206. return compile(ast)
  207. end