allow destructure in for in names

This commit is contained in:
leaf corcoran 2012-11-29 00:37:49 -08:00
parent 7498a52aee
commit 25b997e71f
9 changed files with 179 additions and 78 deletions

View File

@ -435,7 +435,7 @@ local build_grammar = wrap_env(function()
For = key"for" * DisableDo * ensure(Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1), PopDo) * For = key"for" * DisableDo * ensure(Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1), PopDo) *
key"do"^-1 * Body / mark"for", key"do"^-1 * Body / mark"for",
ForEach = key"for" * Ct(NameList) * key"in" * DisableDo * ensure(Ct(sym"*" * Exp / mark"unpack" + ExpList), PopDo) * key"do"^-1 * Body / mark"foreach", ForEach = key"for" * Ct(AssignableNameList) * key"in" * DisableDo * ensure(Ct(sym"*" * Exp / mark"unpack" + ExpList), PopDo) * key"do"^-1 * Body / mark"foreach",
Do = key"do" * Body / mark"do", Do = key"do" * Body / mark"do",
@ -575,7 +575,7 @@ local build_grammar = wrap_env(function()
(key"using" * Ct(NameList + Space * "nil") + Ct"") * (key"using" * Ct(NameList + Space * "nil") + Ct"") *
sym")" + Ct"" * Ct"", sym")" + Ct"" * Ct"",
FnArgDefList = FnArgDef * (sym"," * FnArgDef)^0, FnArgDefList = FnArgDef * (sym"," * FnArgDef)^0,
FnArgDef = Ct(Name * (sym"=" * Exp)^-1), FnArgDef = Ct(Name * (sym"=" * Exp)^-1),
FunLit = FnArgsDef * FunLit = FnArgsDef *
@ -583,6 +583,9 @@ local build_grammar = wrap_env(function()
(Body + Ct"") / mark"fndef", (Body + Ct"") / mark"fndef",
NameList = Name * (sym"," * Name)^0, NameList = Name * (sym"," * Name)^0,
NameOrDestructure = Name + TableLit,
AssignableNameList = NameOrDestructure * (sym"," * NameOrDestructure)^0,
ExpList = Exp * (sym"," * Exp)^0, ExpList = Exp * (sym"," * Exp)^0,
ExpListLow = Exp * ((sym"," + sym";") * Exp)^0, ExpListLow = Exp * ((sym"," + sym";") * Exp)^0,

View File

@ -2,7 +2,7 @@ local types = require("moonscript.types")
local util = require("moonscript.util") local util = require("moonscript.util")
local data = require("moonscript.data") local data = require("moonscript.data")
local reversed = util.reversed local reversed = util.reversed
local ntype, build, smart_node, is_slice, value_is_singular = types.ntype, types.build, types.smart_node, types.is_slice, types.value_is_singular local ntype, mtype, build, smart_node, is_slice, value_is_singular = types.ntype, types.mtype, types.build, types.smart_node, types.is_slice, types.value_is_singular
local insert = table.insert local insert = table.insert
local NameProxy, LocalName local NameProxy, LocalName
do do
@ -10,18 +10,6 @@ do
NameProxy, LocalName = _table_0.NameProxy, _table_0.LocalName NameProxy, LocalName = _table_0.NameProxy, _table_0.LocalName
end end
local destructure = require("moonscript.transform.destructure") local destructure = require("moonscript.transform.destructure")
local mtype
do
local moon_type = util.moon.type
mtype = function(val)
local t = type(val)
if "table" == t and rawget(val, "__class") then
return moon_type(val)
else
return t
end
end
end
local implicitly_return local implicitly_return
local Run local Run
do do
@ -670,6 +658,34 @@ local Statement = Transformer({
foreach = function(self, node) foreach = function(self, node)
smart_node(node) smart_node(node)
local source = unpack(node.iter) local source = unpack(node.iter)
local destructures = { }
node.names = (function()
local _accum_0 = { }
local _len_0 = 0
for i, name in ipairs(node.names) do
local _value_0
if ntype(name) == "table" then
do
local _with_0 = NameProxy("des")
local proxy = _with_0
local extracted = destructure.extract_assign_names(name)
insert(destructures, destructure.build_assign(extracted, proxy))
_value_0 = _with_0
end
else
_value_0 = name
end
if _value_0 ~= nil then
_len_0 = _len_0 + 1
_accum_0[_len_0] = _value_0
end
end
return _accum_0
end)()
if next(destructures) then
insert(destructures, build.group(node.body))
node.body = destructures
end
if ntype(source) == "unpack" then if ntype(source) == "unpack" then
local list = source[2] local list = source[2]
local index_name = NameProxy("index") local index_name = NameProxy("index")

View File

@ -4,22 +4,12 @@ util = require "moonscript.util"
data = require "moonscript.data" data = require "moonscript.data"
import reversed from util import reversed from util
import ntype, build, smart_node, is_slice, value_is_singular from types import ntype, mtype, build, smart_node, is_slice, value_is_singular from types
import insert from table import insert from table
import NameProxy, LocalName from require "moonscript.transform.names" import NameProxy, LocalName from require "moonscript.transform.names"
destructure = require "moonscript.transform.destructure" destructure = require "moonscript.transform.destructure"
mtype = do
moon_type = util.moon.type
-- lets us check a smart node without throwing an error
(val) ->
t = type(val)
if "table" == t and rawget(val, "__class")
moon_type val
else
t
local implicitly_return local implicitly_return
class Run class Run
@ -347,6 +337,19 @@ Statement = Transformer {
smart_node node smart_node node
source = unpack node.iter source = unpack node.iter
destructures = {}
node.names = for i, name in ipairs node.names
if ntype(name) == "table"
with proxy = NameProxy "des"
extracted = destructure.extract_assign_names name
insert destructures, destructure.build_assign extracted, proxy
else
name
if next destructures
insert destructures, build.group node.body
node.body = destructures
if ntype(source) == "unpack" if ntype(source) == "unpack"
list = source[2] list = source[2]

View File

@ -1,7 +1,7 @@
local ntype, build local ntype, mtype, build
do do
local _table_0 = require("moonscript.types") local _table_0 = require("moonscript.types")
ntype, build = _table_0.ntype, _table_0.build ntype, mtype, build = _table_0.ntype, _table_0.mtype, _table_0.build
end end
local NameProxy local NameProxy
do do
@ -48,9 +48,31 @@ has_destructure = function(names)
end end
local build_assign local build_assign
build_assign = function(extracted_names, receiver) build_assign = function(extracted_names, receiver)
local obj = NameProxy("obj")
local names = { } local names = { }
local values = { } local values = { }
local inner = {
"assign",
names,
values
}
local obj
if mtype(receiver) == NameProxy then
obj = receiver
else
do
local _with_0 = NameProxy("obj")
obj = _with_0
inner = build["do"]({
build.assign_one(obj, receiver),
{
"assign",
names,
values
}
})
obj = _with_0
end
end
local _list_0 = extracted_names local _list_0 = extracted_names
for _index_0 = 1, #_list_0 do for _index_0 = 1, #_list_0 do
local tuple = _list_0[_index_0] local tuple = _list_0[_index_0]
@ -62,14 +84,7 @@ build_assign = function(extracted_names, receiver)
"declare", "declare",
names names
}, },
build["do"]({ inner
build.assign_one(obj, receiver),
{
"assign",
names,
values
}
})
}) })
end end
local extract_assign_names local extract_assign_names

View File

@ -1,5 +1,5 @@
import ntype, build from require "moonscript.types" import ntype, mtype, build from require "moonscript.types"
import NameProxy from require "moonscript.transform.names" import NameProxy from require "moonscript.transform.names"
import insert from table import insert from table
@ -19,20 +19,27 @@ has_destructure = (names) ->
false false
build_assign = (extracted_names, receiver) -> build_assign = (extracted_names, receiver) ->
obj = NameProxy "obj"
names = {} names = {}
values = {} values = {}
inner = {"assign", names, values}
obj = if mtype(receiver) == NameProxy
receiver
else
with obj = NameProxy "obj"
inner = build.do {
build.assign_one obj, receiver
{"assign", names, values}
}
for tuple in *extracted_names for tuple in *extracted_names
insert names, tuple[1] insert names, tuple[1]
insert values, obj\chain unpack tuple[2] insert values, obj\chain unpack tuple[2]
build.group { build.group {
{"declare", names} {"declare", names}
build.do { inner
build.assign_one obj, receiver
{"assign", names, values}
}
} }
extract_assign_names = (name, accum={}, prefix={}) -> extract_assign_names = (name, accum={}, prefix={}) ->

View File

@ -26,6 +26,17 @@ ntype = function(node)
return "value" return "value"
end end
end end
local mtype
do
local moon_type = util.moon.type
mtype = function(val)
local mt = getmetatable(val)
if mt and mt.smart_node then
return "table"
end
return moon_type(val)
end
end
local has_value local has_value
has_value = function(node) has_value = function(node)
if ntype(node) == "chain" then if ntype(node) == "chain" then
@ -260,27 +271,32 @@ build = setmetatable({
return rawget(self, name) return rawget(self, name)
end end
}) })
local smart_node_mt = setmetatable({ }, {
__index = function(self, node_type)
local index = key_table[node_type]
local mt = {
smart_node = true,
__index = function(node, key)
if index[key] then
return rawget(node, index[key])
elseif type(key) == "string" then
return error("unknown key: `" .. key .. "` on node type: `" .. ntype(node) .. "`")
end
end,
__newindex = function(node, key, value)
if index[key] then
key = index[key]
end
return rawset(node, key, value)
end
}
self[node_type] = mt
return mt
end
})
local smart_node local smart_node
smart_node = function(node) smart_node = function(node)
local index = key_table[ntype(node)] return setmetatable(node, smart_node_mt[ntype(node)])
if not index then
return node
end
return setmetatable(node, {
__index = function(node, key)
if index[key] then
return rawget(node, index[key])
elseif type(key) == "string" then
return error("unknown key: `" .. key .. "` on node type: `" .. ntype(node) .. "`")
end
end,
__newindex = function(node, key, value)
if index[key] then
key = index[key]
end
return rawset(node, key, value)
end
})
end end
return { return {
ntype = ntype, ntype = ntype,
@ -292,5 +308,6 @@ return {
cascading = cascading, cascading = cascading,
value_is_singular = value_is_singular, value_is_singular = value_is_singular,
comprehension_has_value = comprehension_has_value, comprehension_has_value = comprehension_has_value,
has_value = has_value has_value = has_value,
mtype = mtype
} }

View File

@ -22,6 +22,14 @@ ntype = (node) ->
else else
"value" "value"
mtype = do
moon_type = util.moon.type
-- lets us check a smart node without throwing an error
(val) ->
mt = getmetatable val
return "table" if mt and mt.smart_node
moon_type val
-- does this always return a value -- does this always return a value
has_value = (node) -> has_value = (node) ->
if ntype(node) == "chain" if ntype(node) == "chain"
@ -142,25 +150,33 @@ build = setmetatable {
rawget self, name rawget self, name
} }
smart_node_mt = setmetatable {}, {
__index: (node_type) =>
index = key_table[node_type]
mt = {
smart_node: true
__index: (node, key) ->
if index[key]
rawget node, index[key]
elseif type(key) == "string"
error "unknown key: `"..key.."` on node type: `"..ntype(node).. "`"
__newindex: (node, key, value) ->
key = index[key] if index[key]
rawset node, key, value
}
self[node_type] = mt
mt
}
-- makes it so node properties can be accessed by name instead of index -- makes it so node properties can be accessed by name instead of index
smart_node = (node) -> smart_node = (node) ->
index = key_table[ntype node] setmetatable node, smart_node_mt[ntype node]
if not index then return node
setmetatable node, {
__index: (node, key) ->
if index[key]
rawget node, index[key]
elseif type(key) == "string"
error "unknown key: `"..key.."` on node type: `"..ntype(node).. "`"
__newindex: (node, key, value) ->
key = index[key] if index[key]
rawset node, key, value
}
{ {
:ntype, :smart_node, :build, :is_value, :is_slice, :manual_return, :ntype, :smart_node, :build, :is_value, :is_slice, :manual_return,
:cascading, :value_is_singular, :comprehension_has_value, :has_value :cascading, :value_is_singular, :comprehension_has_value, :has_value,
:mtype
} }

View File

@ -43,3 +43,11 @@ print name, street, city
{ world: @world } = x { world: @world } = x
--
thing = {{1,2}, {3,4}}
for {x,y} in *thing
print x,y

View File

@ -85,4 +85,20 @@ end
do do
local _obj_0 = x local _obj_0 = x
self.world = _obj_0.world self.world = _obj_0.world
end
thing = {
{
1,
2
},
{
3,
4
}
}
local _list_0 = thing
for _index_0 = 1, #_list_0 do
local _des_0 = _list_0[_index_0]
x, y = _des_0[1], _des_0[2]
print(x, y)
end end