local translators = { }
local function translate( expr)
return translators[ expr. expr_type] ( expr)
end
function translators. var( expr)
return { text = expr. name, locals = { } }
end
function translators. abs ( expr)
local param = expr. param
local body = translate( expr. body)
local text = "function(" .. param .. ")\n "
for i, local_ in ipairs ( body. locals) do
text = text .. local_
end
text = text .. "return " .. body. text .. "\n end"
return { text = text, locals = { } }
end
function translators. app( expr)
local fn = translate( expr. fn)
local arg = translate( expr. arg)
local text = "(" .. fn. text .. ")(" .. arg. text .. ")"
local locals = { }
for i, local_ in ipairs ( fn. locals) do
table.insert ( locals, local_)
end
for i, local_ in ipairs ( arg. locals) do
table.insert ( locals, local_)
end
return { text = text, locals = locals }
end
function translators. let( expr)
local value = translate( expr. value)
local body = translate( expr. body)
local local_ = "local " .. expr. name .. " = " .. value. text .. "\n "
local locals = { }
table.insert ( locals, local_)
for i, local_ in ipairs ( value. locals) do
table.insert ( locals, local_)
end
for i, local_ in ipairs ( body. locals) do
table.insert ( locals, local_)
end
return { text = body. text, locals = locals }
end
function translators. str( expr)
return { text = string.format ( "%q" , expr. value) , locals = { } }
end
local optimizers = { }
local function optimize( expr)
return optimizers[ expr. expr_type] ( expr)
end
function optimizers. var( expr)
return expr
end
function optimizers. abs ( expr)
return {
expr_type = "abs" ,
param = expr. param,
body = optimize( expr. body) ,
}
end
function optimizers. app( expr)
if expr. fn. expr_type == "abs" then
return optimize( {
expr_type = "let" ,
name = expr. fn. param,
value = optimize( expr. arg) ,
body = optimize( expr. fn. body) ,
} )
else
return {
expr_type = "app" ,
fn = optimize( expr. fn) ,
arg = optimize( expr. arg) ,
}
end
end
function optimizers. let( expr)
return {
expr_type = "let" ,
name = expr. name,
value = optimize( expr. value) ,
body = optimize( expr. body) ,
}
end
function optimizers. str( expr)
return expr
end
local expr = {
expr_type = "abs" ,
param = "_" ,
body = {
expr_type = "app" ,
fn = {
expr_type = "abs" ,
param = "x" ,
body = {
expr_type = "app" ,
fn = {
expr_type = "abs" ,
param = "y" ,
body = { expr_type = "var" , name = "y" } ,
} ,
arg = { expr_type = "var" , name = "x" } ,
} ,
} ,
arg = { expr_type = "str" , value = "Hello, world!" } ,
} ,
}
print ( "-- unoptimized" )
print ( translate( expr) . text)
print ( "-- optimized" )
print ( translate( optimize( expr) ) . text)
bG9jYWwgdHJhbnNsYXRvcnMgPSB7IH0KCmxvY2FsIGZ1bmN0aW9uIHRyYW5zbGF0ZShleHByKQoJcmV0dXJuIHRyYW5zbGF0b3JzW2V4cHIuZXhwcl90eXBlXShleHByKQplbmQKCmZ1bmN0aW9uIHRyYW5zbGF0b3JzLnZhcihleHByKQoJcmV0dXJuIHsgdGV4dCA9IGV4cHIubmFtZSwgbG9jYWxzID0geyB9IH0KZW5kCgpmdW5jdGlvbiB0cmFuc2xhdG9ycy5hYnMoZXhwcikKCWxvY2FsIHBhcmFtID0gZXhwci5wYXJhbQoJbG9jYWwgYm9keSA9IHRyYW5zbGF0ZShleHByLmJvZHkpCglsb2NhbCB0ZXh0ID0gImZ1bmN0aW9uKCIgLi4gcGFyYW0gLi4gIilcbiIKCWZvciBpLCBsb2NhbF8gaW4gaXBhaXJzKGJvZHkubG9jYWxzKSBkbwoJCXRleHQgPSB0ZXh0IC4uIGxvY2FsXwoJZW5kCgl0ZXh0ID0gdGV4dCAuLiAicmV0dXJuICIgLi4gYm9keS50ZXh0IC4uICJcbmVuZCIKCXJldHVybiB7IHRleHQgPSB0ZXh0LCBsb2NhbHMgPSB7IH0gfQplbmQKCmZ1bmN0aW9uIHRyYW5zbGF0b3JzLmFwcChleHByKQoJbG9jYWwgZm4gPSB0cmFuc2xhdGUoZXhwci5mbikKCWxvY2FsIGFyZyA9IHRyYW5zbGF0ZShleHByLmFyZykKCWxvY2FsIHRleHQgPSAiKCIgLi4gZm4udGV4dCAuLiAiKSgiIC4uIGFyZy50ZXh0IC4uICIpIgoJbG9jYWwgbG9jYWxzID0geyB9Cglmb3IgaSwgbG9jYWxfIGluIGlwYWlycyhmbi5sb2NhbHMpIGRvCgkJdGFibGUuaW5zZXJ0KGxvY2FscywgbG9jYWxfKQoJZW5kCglmb3IgaSwgbG9jYWxfIGluIGlwYWlycyhhcmcubG9jYWxzKSBkbwoJCXRhYmxlLmluc2VydChsb2NhbHMsIGxvY2FsXykKCWVuZAoJcmV0dXJuIHsgdGV4dCA9IHRleHQsIGxvY2FscyA9IGxvY2FscyB9CmVuZAoKZnVuY3Rpb24gdHJhbnNsYXRvcnMubGV0KGV4cHIpCglsb2NhbCB2YWx1ZSA9IHRyYW5zbGF0ZShleHByLnZhbHVlKQoJbG9jYWwgYm9keSA9IHRyYW5zbGF0ZShleHByLmJvZHkpCglsb2NhbCBsb2NhbF8gPSAibG9jYWwgIiAuLiBleHByLm5hbWUgLi4gIiA9ICIgLi4gdmFsdWUudGV4dCAuLiAiXG4iCglsb2NhbCBsb2NhbHMgPSB7IH0KCXRhYmxlLmluc2VydChsb2NhbHMsIGxvY2FsXykKCWZvciBpLCBsb2NhbF8gaW4gaXBhaXJzKHZhbHVlLmxvY2FscykgZG8KCQl0YWJsZS5pbnNlcnQobG9jYWxzLCBsb2NhbF8pCgllbmQKCWZvciBpLCBsb2NhbF8gaW4gaXBhaXJzKGJvZHkubG9jYWxzKSBkbwoJCXRhYmxlLmluc2VydChsb2NhbHMsIGxvY2FsXykKCWVuZAoJcmV0dXJuIHsgdGV4dCA9IGJvZHkudGV4dCwgbG9jYWxzID0gbG9jYWxzIH0KZW5kCgpmdW5jdGlvbiB0cmFuc2xhdG9ycy5zdHIoZXhwcikKCXJldHVybiB7IHRleHQgPSBzdHJpbmcuZm9ybWF0KCIlcSIsIGV4cHIudmFsdWUpLCBsb2NhbHMgPSB7IH0gfQplbmQKCmxvY2FsIG9wdGltaXplcnMgPSB7IH0KCmxvY2FsIGZ1bmN0aW9uIG9wdGltaXplKGV4cHIpCglyZXR1cm4gb3B0aW1pemVyc1tleHByLmV4cHJfdHlwZV0oZXhwcikKZW5kCgpmdW5jdGlvbiBvcHRpbWl6ZXJzLnZhcihleHByKQoJcmV0dXJuIGV4cHIKZW5kCgpmdW5jdGlvbiBvcHRpbWl6ZXJzLmFicyhleHByKQoJcmV0dXJuIHsKCQlleHByX3R5cGUgPSAiYWJzIiwKCQlwYXJhbSA9IGV4cHIucGFyYW0sCgkJYm9keSA9IG9wdGltaXplKGV4cHIuYm9keSksCgl9CmVuZAoKZnVuY3Rpb24gb3B0aW1pemVycy5hcHAoZXhwcikKCWlmIGV4cHIuZm4uZXhwcl90eXBlID09ICJhYnMiIHRoZW4KCQlyZXR1cm4gb3B0aW1pemUoewoJCQlleHByX3R5cGUgPSAibGV0IiwKCQkJbmFtZSA9IGV4cHIuZm4ucGFyYW0sCgkJCXZhbHVlID0gb3B0aW1pemUoZXhwci5hcmcpLAoJCQlib2R5ID0gb3B0aW1pemUoZXhwci5mbi5ib2R5KSwKCQl9KQoJZWxzZQoJCXJldHVybiB7CgkJCWV4cHJfdHlwZSA9ICJhcHAiLAoJCQlmbiA9IG9wdGltaXplKGV4cHIuZm4pLAoJCQlhcmcgPSBvcHRpbWl6ZShleHByLmFyZyksCgkJfQoJZW5kCmVuZAoKZnVuY3Rpb24gb3B0aW1pemVycy5sZXQoZXhwcikKCXJldHVybiB7CgkJZXhwcl90eXBlID0gImxldCIsCgkJbmFtZSA9IGV4cHIubmFtZSwKCQl2YWx1ZSA9IG9wdGltaXplKGV4cHIudmFsdWUpLAoJCWJvZHkgPSBvcHRpbWl6ZShleHByLmJvZHkpLAoJfQplbmQKCmZ1bmN0aW9uIG9wdGltaXplcnMuc3RyKGV4cHIpCglyZXR1cm4gZXhwcgplbmQKCmxvY2FsIGV4cHIgPSB7CglleHByX3R5cGUgPSAiYWJzIiwKCXBhcmFtID0gIl8iLAoJYm9keSA9IHsKCQlleHByX3R5cGUgPSAiYXBwIiwKCQlmbiA9IHsKCQkJZXhwcl90eXBlID0gImFicyIsCgkJCXBhcmFtID0gIngiLAoJCQlib2R5ID0gewoJCQkJZXhwcl90eXBlID0gImFwcCIsCgkJCQlmbiA9IHsKCQkJCQlleHByX3R5cGUgPSAiYWJzIiwKCQkJCQlwYXJhbSA9ICJ5IiwKCQkJCQlib2R5ID0geyBleHByX3R5cGUgPSAidmFyIiwgbmFtZSA9ICJ5IiB9LAoJCQkJfSwKCQkJCWFyZyA9IHsgZXhwcl90eXBlID0gInZhciIsIG5hbWUgPSAieCIgfSwKCQkJfSwKCQl9LAoJCWFyZyA9IHsgZXhwcl90eXBlID0gInN0ciIsIHZhbHVlID0gIkhlbGxvLCB3b3JsZCEiIH0sCgl9LAp9CgpwcmludCgiLS0gdW5vcHRpbWl6ZWQiKQpwcmludCh0cmFuc2xhdGUoZXhwcikudGV4dCkKCnByaW50KCItLSBvcHRpbWl6ZWQiKQpwcmludCh0cmFuc2xhdGUob3B0aW1pemUoZXhwcikpLnRleHQpCg==