mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
transformers are instanced for for root blocks
This commit is contained in:
parent
44167c327a
commit
5f08b2f532
@ -317,7 +317,7 @@ Block = (function()
|
||||
return self:value(node)
|
||||
end,
|
||||
value = function(self, node, ...)
|
||||
node = transform.Value(node)
|
||||
node = self.root.transform.value(node)
|
||||
local action
|
||||
if type(node) ~= "table" then
|
||||
action = "raw_value"
|
||||
@ -353,7 +353,7 @@ Block = (function()
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
node = transform.Statement(node)
|
||||
node = self.root.transform.statement(node)
|
||||
local fn = line_compile[ntype(node)]
|
||||
if not fn then
|
||||
if has_value(node) then
|
||||
@ -403,6 +403,7 @@ Block = (function()
|
||||
self._names = { }
|
||||
self._state = { }
|
||||
if self.parent then
|
||||
self.root = self.parent.root
|
||||
self.indent = self.parent.indent + 1
|
||||
return setmetatable(self._state, {
|
||||
__index = self.parent._state
|
||||
@ -426,6 +427,9 @@ local RootBlock
|
||||
RootBlock = (function()
|
||||
local _parent_0 = Block
|
||||
local _base_0 = {
|
||||
__tostring = function(self)
|
||||
return "RootBlock<>"
|
||||
end,
|
||||
render = function(self)
|
||||
self:_insert_breaks()
|
||||
return concat(self._lines, "\n")
|
||||
@ -437,9 +441,12 @@ RootBlock = (function()
|
||||
end
|
||||
local _class_0 = setmetatable({
|
||||
__init = function(self, ...)
|
||||
if _parent_0 then
|
||||
return _parent_0.__init(self, ...)
|
||||
end
|
||||
self.root = self
|
||||
self.transform = {
|
||||
value = transform.Value:instance(self),
|
||||
statement = transform.Statement:instance(self)
|
||||
}
|
||||
return _parent_0.__init(self, ...)
|
||||
end
|
||||
}, {
|
||||
__index = _base_0,
|
||||
|
@ -64,6 +64,7 @@ class Block
|
||||
@_state = {}
|
||||
|
||||
if @parent
|
||||
@root = @parent.root
|
||||
@indent = @parent.indent + 1
|
||||
setmetatable @_state, { __index: @parent._state }
|
||||
else
|
||||
@ -226,7 +227,7 @@ class Block
|
||||
-- line wise compile functions
|
||||
name: (node) => @value node
|
||||
value: (node, ...) =>
|
||||
node = transform.Value node
|
||||
node = @root.transform.value node
|
||||
action = if type(node) != "table"
|
||||
"raw_value"
|
||||
else
|
||||
@ -244,7 +245,7 @@ class Block
|
||||
|
||||
stm: (node, ...) =>
|
||||
return if not node -- slip blank statements
|
||||
node = transform.Statement node
|
||||
node = @root.transform.statement node
|
||||
fn = line_compile[ntype(node)]
|
||||
if not fn
|
||||
-- coerce value into statement
|
||||
@ -264,6 +265,16 @@ class Block
|
||||
nil
|
||||
|
||||
class RootBlock extends Block
|
||||
new: (...) =>
|
||||
@root = self
|
||||
@transform = {
|
||||
value: transform.Value\instance self
|
||||
statement: transform.Statement\instance self
|
||||
}
|
||||
super ...
|
||||
|
||||
__tostring: => "RootBlock<>"
|
||||
|
||||
render: =>
|
||||
@_insert_breaks!
|
||||
concat @_lines, "\n"
|
||||
|
@ -7,7 +7,7 @@ local ntype, build, smart_node, is_slice = types.ntype, types.build, types.smart
|
||||
local insert = table.insert
|
||||
local is_value
|
||||
is_value = function(stm)
|
||||
return moonscript.compile.Block:is_value(stm) or Value.can_transform(stm)
|
||||
return moonscript.compile.Block:is_value(stm) or Value:can_transform(stm)
|
||||
end
|
||||
NameProxy = (function()
|
||||
local _parent_0 = nil
|
||||
@ -154,43 +154,63 @@ is_singular = function(body)
|
||||
end
|
||||
local constructor_name = "new"
|
||||
local Transformer
|
||||
Transformer = function(transformers)
|
||||
local seen_nodes = { }
|
||||
local tf = {
|
||||
transform = function(n, ...)
|
||||
if seen_nodes[n] then
|
||||
return n
|
||||
Transformer = (function()
|
||||
local _parent_0 = nil
|
||||
local _base_0 = {
|
||||
transform = function(self, scope, node, ...)
|
||||
if self.seen_nodes[node] then
|
||||
return node
|
||||
end
|
||||
seen_nodes[n] = true
|
||||
self.seen_nodes[node] = true
|
||||
while true do
|
||||
local transformer = transformers[ntype(n)]
|
||||
local transformer = self.transformers[ntype(node)]
|
||||
local res
|
||||
if transformer then
|
||||
res = transformer(n, ...) or n
|
||||
res = transformer(scope, node, ...) or node
|
||||
else
|
||||
res = n
|
||||
res = node
|
||||
end
|
||||
if res == n then
|
||||
return n
|
||||
if res == node then
|
||||
return node
|
||||
end
|
||||
n = res
|
||||
node = res
|
||||
end
|
||||
end,
|
||||
can_transform = function(node)
|
||||
return transformers[ntype(node)] ~= nil
|
||||
__call = function(self, node, ...)
|
||||
return self:transform(self.scope, node, ...)
|
||||
end,
|
||||
instance = function(self, scope)
|
||||
return Transformer(self.transformers, scope)
|
||||
end,
|
||||
can_transform = function(self, node)
|
||||
return self.transformers[ntype(node)] ~= nil
|
||||
end
|
||||
}
|
||||
return setmetatable(tf, {
|
||||
__call = function(self, ...)
|
||||
return self.transform(...)
|
||||
_base_0.__index = _base_0
|
||||
if _parent_0 then
|
||||
setmetatable(_base_0, getmetatable(_parent_0).__index)
|
||||
end
|
||||
local _class_0 = setmetatable({
|
||||
__init = function(self, transformers, scope)
|
||||
self.transformers, self.scope = transformers, scope
|
||||
self.seen_nodes = { }
|
||||
end
|
||||
}, {
|
||||
__index = _base_0,
|
||||
__call = function(cls, ...)
|
||||
local _self_0 = setmetatable({}, _base_0)
|
||||
cls.__init(_self_0, ...)
|
||||
return _self_0
|
||||
end
|
||||
})
|
||||
end
|
||||
_base_0.__class = _class_0
|
||||
return _class_0
|
||||
end)()
|
||||
Statement = Transformer({
|
||||
assign = function(node)
|
||||
assign = function(self, node)
|
||||
local _, names, values = unpack(node)
|
||||
if #values == 1 and types.cascading[ntype(values[1])] then
|
||||
values[1] = Statement(values[1], function(stm)
|
||||
values[1] = self.transform.statement(values[1], function(stm)
|
||||
local t = ntype(stm)
|
||||
if is_value(stm) then
|
||||
return {
|
||||
@ -215,7 +235,7 @@ Statement = Transformer({
|
||||
return node
|
||||
end
|
||||
end,
|
||||
export = function(node)
|
||||
export = function(self, node)
|
||||
if #node > 2 then
|
||||
if node[2] == "class" then
|
||||
local cls = smart_node(node[3])
|
||||
@ -241,7 +261,7 @@ Statement = Transformer({
|
||||
return nil
|
||||
end
|
||||
end,
|
||||
update = function(node)
|
||||
update = function(self, node)
|
||||
local _, name, op, exp = unpack(node)
|
||||
local op_final = op:match("^(.+)=$")
|
||||
if not op_final then
|
||||
@ -254,7 +274,7 @@ Statement = Transformer({
|
||||
exp
|
||||
})
|
||||
end,
|
||||
import = function(node)
|
||||
import = function(self, node)
|
||||
local _, names, source = unpack(node)
|
||||
local stubs = (function()
|
||||
local _accum_0 = { }
|
||||
@ -340,7 +360,7 @@ Statement = Transformer({
|
||||
})
|
||||
end
|
||||
end,
|
||||
comprehension = function(node, action)
|
||||
comprehension = function(self, node, action)
|
||||
local _, exp, clauses = unpack(node)
|
||||
action = action or function(exp)
|
||||
return {
|
||||
@ -376,7 +396,7 @@ Statement = Transformer({
|
||||
end
|
||||
return current_stms[1]
|
||||
end,
|
||||
["if"] = function(node, ret)
|
||||
["if"] = function(self, node, ret)
|
||||
if ret then
|
||||
smart_node(node)
|
||||
node['then'] = apply_to_last(node['then'], ret)
|
||||
@ -388,7 +408,7 @@ Statement = Transformer({
|
||||
end
|
||||
return node
|
||||
end,
|
||||
with = function(node, ret)
|
||||
with = function(self, node, ret)
|
||||
local _, exp, block = unpack(node)
|
||||
local scope_name = NameProxy("with")
|
||||
return build["do"]({
|
||||
@ -404,7 +424,7 @@ Statement = Transformer({
|
||||
end)()
|
||||
})
|
||||
end,
|
||||
foreach = function(node)
|
||||
foreach = function(self, node)
|
||||
smart_node(node)
|
||||
if ntype(node.iter) == "unpack" then
|
||||
local list = node.iter[2]
|
||||
@ -470,7 +490,7 @@ Statement = Transformer({
|
||||
})
|
||||
end
|
||||
end,
|
||||
class = function(node)
|
||||
class = function(self, node)
|
||||
local _, name, parent_val, tbl = unpack(node)
|
||||
local constructor = nil
|
||||
local properties = (function()
|
||||
@ -766,58 +786,62 @@ Accumulator = (function()
|
||||
return _class_0
|
||||
end)()
|
||||
local default_accumulator
|
||||
default_accumulator = function(node)
|
||||
default_accumulator = function(self, node)
|
||||
return Accumulator():convert(node)
|
||||
end
|
||||
local implicitly_return
|
||||
implicitly_return = function(stm)
|
||||
local t = ntype(stm)
|
||||
if types.manual_return[t] or not is_value(stm) then
|
||||
return stm
|
||||
elseif types.cascading[t] then
|
||||
return Statement(stm, implicitly_return)
|
||||
else
|
||||
return {
|
||||
"return",
|
||||
stm
|
||||
}
|
||||
implicitly_return = function(scope)
|
||||
local fn
|
||||
fn = function(stm)
|
||||
local t = ntype(stm)
|
||||
if types.manual_return[t] or not is_value(stm) then
|
||||
return stm
|
||||
elseif types.cascading[t] then
|
||||
return scope.transform.statement(stm, fn)
|
||||
else
|
||||
return {
|
||||
"return",
|
||||
stm
|
||||
}
|
||||
end
|
||||
end
|
||||
return fn
|
||||
end
|
||||
Value = Transformer({
|
||||
["for"] = default_accumulator,
|
||||
["while"] = default_accumulator,
|
||||
foreach = default_accumulator,
|
||||
comprehension = function(node)
|
||||
comprehension = function(self, node)
|
||||
local a = Accumulator()
|
||||
node = Statement(node, function(exp)
|
||||
node = self.transform.statement(node, function(exp)
|
||||
return a:mutate_body({
|
||||
exp
|
||||
}, false)
|
||||
end)
|
||||
return a:wrap(node)
|
||||
end,
|
||||
fndef = function(node)
|
||||
fndef = function(self, node)
|
||||
smart_node(node)
|
||||
node.body = apply_to_last(node.body, implicitly_return)
|
||||
node.body = apply_to_last(node.body, implicitly_return(self))
|
||||
return node
|
||||
end,
|
||||
["if"] = function(node)
|
||||
["if"] = function(self, node)
|
||||
return build.block_exp({
|
||||
node
|
||||
})
|
||||
end,
|
||||
with = function(node)
|
||||
with = function(self, node)
|
||||
return build.block_exp({
|
||||
node
|
||||
})
|
||||
end,
|
||||
chain = function(node)
|
||||
chain = function(self, node)
|
||||
local stub = node[#node]
|
||||
if type(stub) == "table" and stub[1] == "colon_stub" then
|
||||
table.remove(node, #node)
|
||||
local base_name = NameProxy("base")
|
||||
local fn_name = NameProxy("fn")
|
||||
return Value(build.block_exp({
|
||||
return self.transform.value(build.block_exp({
|
||||
build.assign({
|
||||
names = {
|
||||
base_name
|
||||
@ -862,7 +886,7 @@ Value = Transformer({
|
||||
}))
|
||||
end
|
||||
end,
|
||||
block_exp = function(node)
|
||||
block_exp = function(self, node)
|
||||
local _, body = unpack(node)
|
||||
local fn = nil
|
||||
local arg_list = { }
|
||||
|
@ -13,7 +13,7 @@ export Statement, Value, NameProxy, Run
|
||||
|
||||
-- TODO refactor
|
||||
is_value = (stm) ->
|
||||
moonscript.compile.Block\is_value(stm) or Value.can_transform stm
|
||||
moonscript.compile.Block\is_value(stm) or Value\can_transform stm
|
||||
|
||||
class NameProxy
|
||||
new: (@prefix) =>
|
||||
@ -82,35 +82,38 @@ is_singular = (body) ->
|
||||
|
||||
constructor_name = "new"
|
||||
|
||||
Transformer = (transformers) ->
|
||||
-- this is bad, instance it for compiler
|
||||
seen_nodes = {}
|
||||
tf = {
|
||||
transform: (n, ...) ->
|
||||
return n if seen_nodes[n]
|
||||
seen_nodes[n] = true
|
||||
while true
|
||||
transformer = transformers[ntype n]
|
||||
res = if transformer
|
||||
transformer(n, ...) or n
|
||||
else
|
||||
n
|
||||
return n if res == n
|
||||
n = res
|
||||
can_transform: (node) ->
|
||||
transformers[ntype node] != nil
|
||||
}
|
||||
class Transformer
|
||||
new: (@transformers, @scope) =>
|
||||
@seen_nodes = {}
|
||||
|
||||
setmetatable tf, {
|
||||
__call: (...) => self.transform ...
|
||||
}
|
||||
transform: (scope, node, ...) =>
|
||||
-- print scope, node, ...
|
||||
return node if @seen_nodes[node]
|
||||
@seen_nodes[node] = true
|
||||
while true
|
||||
transformer = @transformers[ntype node]
|
||||
res = if transformer
|
||||
transformer(scope, node, ...) or node
|
||||
else
|
||||
node
|
||||
return node if res == node
|
||||
node = res
|
||||
|
||||
__call: (node, ...) =>
|
||||
@transform @scope, node, ...
|
||||
|
||||
instance: (scope) =>
|
||||
Transformer @transformers, scope
|
||||
|
||||
can_transform: (node) =>
|
||||
@transformers[ntype node] != nil
|
||||
|
||||
Statement = Transformer {
|
||||
assign: (node) ->
|
||||
assign: (node) =>
|
||||
_, names, values = unpack node
|
||||
-- bubble cascading assigns
|
||||
if #values == 1 and types.cascading[ntype values[1]]
|
||||
values[1] = Statement values[1], (stm) ->
|
||||
values[1] = @transform.statement values[1], (stm) ->
|
||||
t = ntype stm
|
||||
if is_value stm
|
||||
{"assign", names, {stm}}
|
||||
@ -124,7 +127,7 @@ Statement = Transformer {
|
||||
else
|
||||
node
|
||||
|
||||
export: (node) ->
|
||||
export: (node) =>
|
||||
-- assign values if they are included
|
||||
if #node > 2
|
||||
if node[2] == "class"
|
||||
@ -144,13 +147,13 @@ Statement = Transformer {
|
||||
else
|
||||
nil
|
||||
|
||||
update: (node) ->
|
||||
update: (node) =>
|
||||
_, name, op, exp = unpack node
|
||||
op_final = op\match "^(.+)=$"
|
||||
error "Unknown op: "..op if not op_final
|
||||
build.assign_one name, {"exp", name, op_final, exp}
|
||||
|
||||
import: (node) ->
|
||||
import: (node) =>
|
||||
_, names, source = unpack node
|
||||
|
||||
stubs = for name in *names
|
||||
@ -180,7 +183,7 @@ Statement = Transformer {
|
||||
}
|
||||
}
|
||||
|
||||
comprehension: (node, action) ->
|
||||
comprehension: (node, action) =>
|
||||
_, exp, clauses = unpack node
|
||||
|
||||
action = action or (exp) -> {exp}
|
||||
@ -201,7 +204,7 @@ Statement = Transformer {
|
||||
current_stms[1]
|
||||
|
||||
-- handle cascading return decorator
|
||||
if: (node, ret) ->
|
||||
if: (node, ret) =>
|
||||
if ret
|
||||
smart_node node
|
||||
-- mutate all the bodies
|
||||
@ -212,7 +215,7 @@ Statement = Transformer {
|
||||
case[body_idx] = apply_to_last case[body_idx], ret
|
||||
node
|
||||
|
||||
with: (node, ret) ->
|
||||
with: (node, ret) =>
|
||||
_, exp, block = unpack node
|
||||
scope_name = NameProxy "with"
|
||||
build["do"] {
|
||||
@ -223,7 +226,7 @@ Statement = Transformer {
|
||||
ret scope_name
|
||||
}
|
||||
|
||||
foreach: (node) ->
|
||||
foreach: (node) =>
|
||||
smart_node node
|
||||
if ntype(node.iter) == "unpack"
|
||||
list = node.iter[2]
|
||||
@ -263,7 +266,7 @@ Statement = Transformer {
|
||||
}
|
||||
}
|
||||
|
||||
class: (node) ->
|
||||
class: (node) =>
|
||||
_, name, parent_val, tbl = unpack node
|
||||
|
||||
constructor = nil
|
||||
@ -422,39 +425,42 @@ class Accumulator
|
||||
|
||||
body
|
||||
|
||||
default_accumulator = (node) ->
|
||||
default_accumulator = (node) =>
|
||||
Accumulator!\convert node
|
||||
|
||||
implicitly_return = (stm) ->
|
||||
t = ntype stm
|
||||
if types.manual_return[t] or not is_value stm
|
||||
stm
|
||||
elseif types.cascading[t]
|
||||
Statement stm, implicitly_return
|
||||
else
|
||||
{"return", stm}
|
||||
implicitly_return = (scope) ->
|
||||
fn = (stm) ->
|
||||
t = ntype stm
|
||||
if types.manual_return[t] or not is_value stm
|
||||
stm
|
||||
elseif types.cascading[t]
|
||||
scope.transform.statement stm, fn
|
||||
else
|
||||
{"return", stm}
|
||||
|
||||
fn
|
||||
|
||||
Value = Transformer {
|
||||
for: default_accumulator
|
||||
while: default_accumulator
|
||||
foreach: default_accumulator
|
||||
|
||||
comprehension: (node) ->
|
||||
comprehension: (node) =>
|
||||
a = Accumulator!
|
||||
node = Statement node, (exp) ->
|
||||
node = @transform.statement node, (exp) ->
|
||||
a\mutate_body {exp}, false
|
||||
a\wrap node
|
||||
|
||||
fndef: (node) ->
|
||||
fndef: (node) =>
|
||||
smart_node node
|
||||
node.body = apply_to_last node.body, implicitly_return
|
||||
node.body = apply_to_last node.body, implicitly_return self
|
||||
node
|
||||
|
||||
if: (node) -> build.block_exp { node }
|
||||
with: (node) -> build.block_exp { node }
|
||||
if: (node) => build.block_exp { node }
|
||||
with: (node) => build.block_exp { node }
|
||||
|
||||
-- pull out colon chain
|
||||
chain: (node) ->
|
||||
chain: (node) =>
|
||||
stub = node[#node]
|
||||
if type(stub) == "table" and stub[1] == "colon_stub"
|
||||
table.remove node, #node
|
||||
@ -462,7 +468,7 @@ Value = Transformer {
|
||||
base_name = NameProxy "base"
|
||||
fn_name = NameProxy "fn"
|
||||
|
||||
Value build.block_exp {
|
||||
@transform.value build.block_exp {
|
||||
build.assign {
|
||||
names: {base_name}
|
||||
values: {node}
|
||||
@ -485,7 +491,7 @@ Value = Transformer {
|
||||
}
|
||||
}
|
||||
|
||||
block_exp: (node) ->
|
||||
block_exp: (node) =>
|
||||
_, body = unpack node
|
||||
|
||||
fn = nil
|
||||
|
Loading…
Reference in New Issue
Block a user