fork(1) download
  1. local translators = { }
  2.  
  3. local function translate(expr)
  4. return translators[expr.expr_type](expr)
  5. end
  6.  
  7. function translators.var(expr)
  8. return { text = expr.name, locals = { } }
  9. end
  10.  
  11. function translators.abs(expr)
  12. local param = expr.param
  13. local body = translate(expr.body)
  14. local text = "function(" .. param .. ")\n"
  15. for i, local_ in ipairs(body.locals) do
  16. text = text .. local_
  17. end
  18. text = text .. "return " .. body.text .. "\nend"
  19. return { text = text, locals = { } }
  20. end
  21.  
  22. function translators.app(expr)
  23. local fn = translate(expr.fn)
  24. local arg = translate(expr.arg)
  25. local text = "(" .. fn.text .. ")(" .. arg.text .. ")"
  26. local locals = { }
  27. for i, local_ in ipairs(fn.locals) do
  28. table.insert(locals, local_)
  29. end
  30. for i, local_ in ipairs(arg.locals) do
  31. table.insert(locals, local_)
  32. end
  33. return { text = text, locals = locals }
  34. end
  35.  
  36. function translators.let(expr)
  37. local value = translate(expr.value)
  38. local body = translate(expr.body)
  39. local local_ = "local " .. expr.name .. " = " .. value.text .. "\n"
  40. local locals = { }
  41. table.insert(locals, local_)
  42. for i, local_ in ipairs(value.locals) do
  43. table.insert(locals, local_)
  44. end
  45. for i, local_ in ipairs(body.locals) do
  46. table.insert(locals, local_)
  47. end
  48. return { text = body.text, locals = locals }
  49. end
  50.  
  51. function translators.str(expr)
  52. return { text = string.format("%q", expr.value), locals = { } }
  53. end
  54.  
  55. local optimizers = { }
  56.  
  57. local function optimize(expr)
  58. return optimizers[expr.expr_type](expr)
  59. end
  60.  
  61. function optimizers.var(expr)
  62. return expr
  63. end
  64.  
  65. function optimizers.abs(expr)
  66. return {
  67. expr_type = "abs",
  68. param = expr.param,
  69. body = optimize(expr.body),
  70. }
  71. end
  72.  
  73. function optimizers.app(expr)
  74. if expr.fn.expr_type == "abs" then
  75. return optimize({
  76. expr_type = "let",
  77. name = expr.fn.param,
  78. value = optimize(expr.arg),
  79. body = optimize(expr.fn.body),
  80. })
  81. else
  82. return {
  83. expr_type = "app",
  84. fn = optimize(expr.fn),
  85. arg = optimize(expr.arg),
  86. }
  87. end
  88. end
  89.  
  90. function optimizers.let(expr)
  91. return {
  92. expr_type = "let",
  93. name = expr.name,
  94. value = optimize(expr.value),
  95. body = optimize(expr.body),
  96. }
  97. end
  98.  
  99. function optimizers.str(expr)
  100. return expr
  101. end
  102.  
  103. local expr = {
  104. expr_type = "abs",
  105. param = "_",
  106. body = {
  107. expr_type = "app",
  108. fn = {
  109. expr_type = "abs",
  110. param = "x",
  111. body = {
  112. expr_type = "app",
  113. fn = {
  114. expr_type = "abs",
  115. param = "y",
  116. body = { expr_type = "var", name = "y" },
  117. },
  118. arg = { expr_type = "var", name = "x" },
  119. },
  120. },
  121. arg = { expr_type = "str", value = "Hello, world!" },
  122. },
  123. }
  124.  
  125. print("-- unoptimized")
  126. print(translate(expr).text)
  127.  
  128. print("-- optimized")
  129. print(translate(optimize(expr)).text)
  130.  
Success #stdin #stdout 0s 2836KB
stdin
Standard input is empty
stdout
-- unoptimized
function(_)
return (function(x)
return (function(y)
return y
end)(x)
end)("Hello, world!")
end
-- optimized
function(_)
local x = "Hello, world!"
local y = x
return y
end