mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
move class transformer to own module
This commit is contained in:
parent
5a0c5d1e55
commit
ca21c216ea
436
moonscript/transform/class.lua
Normal file
436
moonscript/transform/class.lua
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
local NameProxy, LocalName
|
||||||
|
do
|
||||||
|
local _obj_0 = require("moonscript.transform.names")
|
||||||
|
NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName
|
||||||
|
end
|
||||||
|
local Run
|
||||||
|
Run = require("moonscript.transform.statements").Run
|
||||||
|
local CONSTRUCTOR_NAME = "new"
|
||||||
|
local insert
|
||||||
|
insert = table.insert
|
||||||
|
local build, ntype, NOOP
|
||||||
|
do
|
||||||
|
local _obj_0 = require("moonscript.types")
|
||||||
|
build, ntype, NOOP = _obj_0.build, _obj_0.ntype, _obj_0.NOOP
|
||||||
|
end
|
||||||
|
return function(self, node, ret, parent_assign)
|
||||||
|
local _, name, parent_val, body = unpack(node)
|
||||||
|
if parent_val == "" then
|
||||||
|
parent_val = nil
|
||||||
|
end
|
||||||
|
local statements = { }
|
||||||
|
local properties = { }
|
||||||
|
for _index_0 = 1, #body do
|
||||||
|
local item = body[_index_0]
|
||||||
|
local _exp_0 = item[1]
|
||||||
|
if "stm" == _exp_0 then
|
||||||
|
insert(statements, item[2])
|
||||||
|
elseif "props" == _exp_0 then
|
||||||
|
for _index_1 = 2, #item do
|
||||||
|
local tuple = item[_index_1]
|
||||||
|
if ntype(tuple[1]) == "self" then
|
||||||
|
insert(statements, build.assign_one(unpack(tuple)))
|
||||||
|
else
|
||||||
|
insert(properties, tuple)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local constructor
|
||||||
|
do
|
||||||
|
local _accum_0 = { }
|
||||||
|
local _len_0 = 1
|
||||||
|
for _index_0 = 1, #properties do
|
||||||
|
local _continue_0 = false
|
||||||
|
repeat
|
||||||
|
local tuple = properties[_index_0]
|
||||||
|
local key = tuple[1]
|
||||||
|
local _value_0
|
||||||
|
if key[1] == "key_literal" and key[2] == CONSTRUCTOR_NAME then
|
||||||
|
constructor = tuple[2]
|
||||||
|
_continue_0 = true
|
||||||
|
break
|
||||||
|
else
|
||||||
|
_value_0 = tuple
|
||||||
|
end
|
||||||
|
_accum_0[_len_0] = _value_0
|
||||||
|
_len_0 = _len_0 + 1
|
||||||
|
_continue_0 = true
|
||||||
|
until true
|
||||||
|
if not _continue_0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
properties = _accum_0
|
||||||
|
end
|
||||||
|
local parent_cls_name = NameProxy("parent")
|
||||||
|
local base_name = NameProxy("base")
|
||||||
|
local self_name = NameProxy("self")
|
||||||
|
local cls_name = NameProxy("class")
|
||||||
|
if not (constructor) then
|
||||||
|
if parent_val then
|
||||||
|
constructor = build.fndef({
|
||||||
|
args = {
|
||||||
|
{
|
||||||
|
"..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
arrow = "fat",
|
||||||
|
body = {
|
||||||
|
build.chain({
|
||||||
|
base = "super",
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
"..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else
|
||||||
|
constructor = build.fndef()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local real_name = name or parent_assign and parent_assign[2][1]
|
||||||
|
local _exp_0 = ntype(real_name)
|
||||||
|
if "chain" == _exp_0 then
|
||||||
|
local last = real_name[#real_name]
|
||||||
|
local _exp_1 = ntype(last)
|
||||||
|
if "dot" == _exp_1 then
|
||||||
|
real_name = {
|
||||||
|
"string",
|
||||||
|
'"',
|
||||||
|
last[2]
|
||||||
|
}
|
||||||
|
elseif "index" == _exp_1 then
|
||||||
|
real_name = last[2]
|
||||||
|
else
|
||||||
|
real_name = "nil"
|
||||||
|
end
|
||||||
|
elseif "nil" == _exp_0 then
|
||||||
|
real_name = "nil"
|
||||||
|
else
|
||||||
|
local name_t = type(real_name)
|
||||||
|
local flattened_name
|
||||||
|
if name_t == "string" then
|
||||||
|
flattened_name = real_name
|
||||||
|
elseif name_t == "table" and real_name[1] == "ref" then
|
||||||
|
flattened_name = real_name[2]
|
||||||
|
else
|
||||||
|
flattened_name = error("don't know how to extract name from " .. tostring(name_t))
|
||||||
|
end
|
||||||
|
real_name = {
|
||||||
|
"string",
|
||||||
|
'"',
|
||||||
|
flattened_name
|
||||||
|
}
|
||||||
|
end
|
||||||
|
local cls = build.table({
|
||||||
|
{
|
||||||
|
"__init",
|
||||||
|
constructor
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__base",
|
||||||
|
base_name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__name",
|
||||||
|
real_name
|
||||||
|
},
|
||||||
|
parent_val and {
|
||||||
|
"__parent",
|
||||||
|
parent_cls_name
|
||||||
|
} or nil
|
||||||
|
})
|
||||||
|
local class_index
|
||||||
|
if parent_val then
|
||||||
|
local class_lookup = build["if"]({
|
||||||
|
cond = {
|
||||||
|
"exp",
|
||||||
|
{
|
||||||
|
"ref",
|
||||||
|
"val"
|
||||||
|
},
|
||||||
|
"==",
|
||||||
|
"nil"
|
||||||
|
},
|
||||||
|
["then"] = {
|
||||||
|
build.assign_one(LocalName("parent"), build.chain({
|
||||||
|
base = "rawget",
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"ref",
|
||||||
|
"cls"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"string",
|
||||||
|
'"',
|
||||||
|
"__parent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
build["if"]({
|
||||||
|
cond = LocalName("parent"),
|
||||||
|
["then"] = {
|
||||||
|
build.chain({
|
||||||
|
base = LocalName("parent"),
|
||||||
|
{
|
||||||
|
"index",
|
||||||
|
"name"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
insert(class_lookup, {
|
||||||
|
"else",
|
||||||
|
{
|
||||||
|
"val"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class_index = build.fndef({
|
||||||
|
args = {
|
||||||
|
{
|
||||||
|
"cls"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
body = {
|
||||||
|
build.assign_one(LocalName("val"), build.chain({
|
||||||
|
base = "rawget",
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
base_name,
|
||||||
|
{
|
||||||
|
"ref",
|
||||||
|
"name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
class_lookup
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else
|
||||||
|
class_index = base_name
|
||||||
|
end
|
||||||
|
local cls_mt = build.table({
|
||||||
|
{
|
||||||
|
"__index",
|
||||||
|
class_index
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__call",
|
||||||
|
build.fndef({
|
||||||
|
args = {
|
||||||
|
{
|
||||||
|
"cls"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
body = {
|
||||||
|
build.assign_one(self_name, build.chain({
|
||||||
|
base = "setmetatable",
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
"{}",
|
||||||
|
base_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
build.chain({
|
||||||
|
base = "cls.__init",
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
self_name,
|
||||||
|
"..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
self_name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
cls = build.chain({
|
||||||
|
base = "setmetatable",
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
cls,
|
||||||
|
cls_mt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
local value = nil
|
||||||
|
do
|
||||||
|
local out_body = {
|
||||||
|
Run(function(self)
|
||||||
|
if name then
|
||||||
|
self:put_name(name)
|
||||||
|
end
|
||||||
|
return self:set("super", function(block, chain)
|
||||||
|
local relative_parent = {
|
||||||
|
"chain",
|
||||||
|
cls_name,
|
||||||
|
{
|
||||||
|
"dot",
|
||||||
|
"__parent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if not (chain) then
|
||||||
|
return relative_parent
|
||||||
|
end
|
||||||
|
local chain_tail = {
|
||||||
|
unpack(chain, 3)
|
||||||
|
}
|
||||||
|
local head = chain_tail[1]
|
||||||
|
if head == nil then
|
||||||
|
return relative_parent
|
||||||
|
end
|
||||||
|
local new_chain = relative_parent
|
||||||
|
local _exp_1 = head[1]
|
||||||
|
if "call" == _exp_1 then
|
||||||
|
local calling_name = block:get("current_block")
|
||||||
|
assert(calling_name, "missing calling name")
|
||||||
|
chain_tail[1] = {
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
"self",
|
||||||
|
unpack(head[2])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ntype(calling_name) == "key_literal" then
|
||||||
|
insert(new_chain, {
|
||||||
|
"dot",
|
||||||
|
calling_name[2]
|
||||||
|
})
|
||||||
|
else
|
||||||
|
insert(new_chain, {
|
||||||
|
"index",
|
||||||
|
calling_name
|
||||||
|
})
|
||||||
|
end
|
||||||
|
elseif "colon" == _exp_1 then
|
||||||
|
local call = chain_tail[2]
|
||||||
|
if call and call[1] == "call" then
|
||||||
|
chain_tail[1] = {
|
||||||
|
"dot",
|
||||||
|
head[2]
|
||||||
|
}
|
||||||
|
chain_tail[2] = {
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
"self",
|
||||||
|
unpack(call[2])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _index_0 = 1, #chain_tail do
|
||||||
|
local item = chain_tail[_index_0]
|
||||||
|
insert(new_chain, item)
|
||||||
|
end
|
||||||
|
return new_chain
|
||||||
|
end)
|
||||||
|
end),
|
||||||
|
{
|
||||||
|
"declare",
|
||||||
|
{
|
||||||
|
cls_name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"declare_glob",
|
||||||
|
"*"
|
||||||
|
},
|
||||||
|
parent_val and build.assign_one(parent_cls_name, parent_val) or NOOP,
|
||||||
|
build.assign_one(base_name, {
|
||||||
|
"table",
|
||||||
|
properties
|
||||||
|
}),
|
||||||
|
build.assign_one(base_name:chain("__index"), base_name),
|
||||||
|
parent_val and build.chain({
|
||||||
|
base = "setmetatable",
|
||||||
|
{
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
base_name,
|
||||||
|
build.chain({
|
||||||
|
base = parent_cls_name,
|
||||||
|
{
|
||||||
|
"dot",
|
||||||
|
"__base"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) or NOOP,
|
||||||
|
build.assign_one(cls_name, cls),
|
||||||
|
build.assign_one(base_name:chain("__class"), cls_name),
|
||||||
|
build.group((function()
|
||||||
|
if #statements > 0 then
|
||||||
|
return {
|
||||||
|
build.assign_one(LocalName("self"), cls_name),
|
||||||
|
build.group(statements)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end)()),
|
||||||
|
parent_val and build["if"]({
|
||||||
|
cond = {
|
||||||
|
"exp",
|
||||||
|
parent_cls_name:chain("__inherited")
|
||||||
|
},
|
||||||
|
["then"] = {
|
||||||
|
parent_cls_name:chain("__inherited", {
|
||||||
|
"call",
|
||||||
|
{
|
||||||
|
parent_cls_name,
|
||||||
|
cls_name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}) or NOOP,
|
||||||
|
build.group((function()
|
||||||
|
if name then
|
||||||
|
return {
|
||||||
|
build.assign_one(name, cls_name)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end)()),
|
||||||
|
(function()
|
||||||
|
if ret then
|
||||||
|
return ret(cls_name)
|
||||||
|
end
|
||||||
|
end)()
|
||||||
|
}
|
||||||
|
value = build.group({
|
||||||
|
build.group((function()
|
||||||
|
if ntype(name) == "value" then
|
||||||
|
return {
|
||||||
|
build.declare({
|
||||||
|
names = {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end)()),
|
||||||
|
build["do"](out_body)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end
|
256
moonscript/transform/class.moon
Normal file
256
moonscript/transform/class.moon
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
import NameProxy, LocalName from require "moonscript.transform.names"
|
||||||
|
import Run from require "moonscript.transform.statements"
|
||||||
|
|
||||||
|
CONSTRUCTOR_NAME = "new"
|
||||||
|
|
||||||
|
import insert from table
|
||||||
|
import build, ntype, NOOP from require "moonscript.types"
|
||||||
|
|
||||||
|
(node, ret, parent_assign) =>
|
||||||
|
_, name, parent_val, body = unpack node
|
||||||
|
parent_val = nil if parent_val == ""
|
||||||
|
|
||||||
|
-- split apart properties and statements
|
||||||
|
statements = {}
|
||||||
|
properties = {}
|
||||||
|
for item in *body
|
||||||
|
switch item[1]
|
||||||
|
when "stm"
|
||||||
|
insert statements, item[2]
|
||||||
|
when "props"
|
||||||
|
for tuple in *item[2,]
|
||||||
|
if ntype(tuple[1]) == "self"
|
||||||
|
insert statements, build.assign_one unpack tuple
|
||||||
|
else
|
||||||
|
insert properties, tuple
|
||||||
|
|
||||||
|
-- find constructor
|
||||||
|
local constructor
|
||||||
|
properties = for tuple in *properties
|
||||||
|
key = tuple[1]
|
||||||
|
if key[1] == "key_literal" and key[2] == CONSTRUCTOR_NAME
|
||||||
|
constructor = tuple[2]
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
tuple
|
||||||
|
|
||||||
|
parent_cls_name = NameProxy "parent"
|
||||||
|
base_name = NameProxy "base"
|
||||||
|
self_name = NameProxy "self"
|
||||||
|
cls_name = NameProxy "class"
|
||||||
|
|
||||||
|
unless constructor
|
||||||
|
constructor = if parent_val
|
||||||
|
build.fndef {
|
||||||
|
args: {{"..."}}
|
||||||
|
arrow: "fat"
|
||||||
|
body: {
|
||||||
|
build.chain { base: "super", {"call", {"..."}} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
build.fndef!
|
||||||
|
|
||||||
|
real_name = name or parent_assign and parent_assign[2][1]
|
||||||
|
real_name = switch ntype real_name
|
||||||
|
when "chain"
|
||||||
|
last = real_name[#real_name]
|
||||||
|
switch ntype last
|
||||||
|
when "dot"
|
||||||
|
{"string", '"', last[2]}
|
||||||
|
when "index"
|
||||||
|
last[2]
|
||||||
|
else
|
||||||
|
"nil"
|
||||||
|
when "nil"
|
||||||
|
"nil"
|
||||||
|
else
|
||||||
|
name_t = type real_name
|
||||||
|
-- TODO: don't use string literal as ref
|
||||||
|
flattened_name = if name_t == "string"
|
||||||
|
real_name
|
||||||
|
elseif name_t == "table" and real_name[1] == "ref"
|
||||||
|
real_name[2]
|
||||||
|
else
|
||||||
|
error "don't know how to extract name from #{name_t}"
|
||||||
|
|
||||||
|
{"string", '"', flattened_name}
|
||||||
|
|
||||||
|
cls = build.table {
|
||||||
|
{"__init", constructor}
|
||||||
|
{"__base", base_name}
|
||||||
|
{"__name", real_name} -- "quote the string"
|
||||||
|
parent_val and {"__parent", parent_cls_name} or nil
|
||||||
|
}
|
||||||
|
|
||||||
|
-- looking up a name in the class object
|
||||||
|
class_index = if parent_val
|
||||||
|
class_lookup = build["if"] {
|
||||||
|
cond: { "exp", {"ref", "val"}, "==", "nil" }
|
||||||
|
then: {
|
||||||
|
build.assign_one LocalName"parent", build.chain {
|
||||||
|
base: "rawget"
|
||||||
|
{
|
||||||
|
"call", {
|
||||||
|
{"ref", "cls"}
|
||||||
|
{"string", '"', "__parent"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.if {
|
||||||
|
cond: LocalName "parent"
|
||||||
|
then: {
|
||||||
|
build.chain {
|
||||||
|
base: LocalName "parent"
|
||||||
|
{"index", "name"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insert class_lookup, {"else", {"val"}}
|
||||||
|
|
||||||
|
build.fndef {
|
||||||
|
args: {{"cls"}, {"name"}}
|
||||||
|
body: {
|
||||||
|
build.assign_one LocalName"val", build.chain {
|
||||||
|
base: "rawget", {"call", {base_name, {"ref", "name"}}}
|
||||||
|
}
|
||||||
|
class_lookup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
base_name
|
||||||
|
|
||||||
|
cls_mt = build.table {
|
||||||
|
{"__index", class_index}
|
||||||
|
{"__call", build.fndef {
|
||||||
|
args: {{"cls"}, {"..."}}
|
||||||
|
body: {
|
||||||
|
build.assign_one self_name, build.chain {
|
||||||
|
base: "setmetatable"
|
||||||
|
{"call", {"{}", base_name}}
|
||||||
|
}
|
||||||
|
build.chain {
|
||||||
|
base: "cls.__init"
|
||||||
|
{"call", {self_name, "..."}}
|
||||||
|
}
|
||||||
|
self_name
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
cls = build.chain {
|
||||||
|
base: "setmetatable"
|
||||||
|
{"call", {cls, cls_mt}}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = nil
|
||||||
|
with build
|
||||||
|
out_body = {
|
||||||
|
Run =>
|
||||||
|
-- make sure we don't assign the class to a local inside the do
|
||||||
|
@put_name name if name
|
||||||
|
|
||||||
|
@set "super", (block, chain) ->
|
||||||
|
relative_parent = {
|
||||||
|
"chain",
|
||||||
|
cls_name
|
||||||
|
{"dot", "__parent"}
|
||||||
|
}
|
||||||
|
|
||||||
|
return relative_parent unless chain
|
||||||
|
|
||||||
|
chain_tail = { unpack chain, 3 }
|
||||||
|
head = chain_tail[1]
|
||||||
|
|
||||||
|
if head == nil
|
||||||
|
return relative_parent
|
||||||
|
|
||||||
|
new_chain = relative_parent
|
||||||
|
|
||||||
|
switch head[1]
|
||||||
|
-- calling super, inject calling name and self into chain
|
||||||
|
when "call"
|
||||||
|
calling_name = block\get"current_block"
|
||||||
|
assert calling_name, "missing calling name"
|
||||||
|
chain_tail[1] = {"call", {"self", unpack head[2]}}
|
||||||
|
|
||||||
|
if ntype(calling_name) == "key_literal"
|
||||||
|
insert new_chain, {"dot", calling_name[2]}
|
||||||
|
else
|
||||||
|
insert new_chain, {"index", calling_name}
|
||||||
|
|
||||||
|
-- colon call on super, replace class with self as first arg
|
||||||
|
when "colon"
|
||||||
|
call = chain_tail[2]
|
||||||
|
-- calling chain tail
|
||||||
|
if call and call[1] == "call"
|
||||||
|
chain_tail[1] = {
|
||||||
|
"dot"
|
||||||
|
head[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
chain_tail[2] = {
|
||||||
|
"call"
|
||||||
|
{
|
||||||
|
"self"
|
||||||
|
unpack call[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insert new_chain, item for item in *chain_tail
|
||||||
|
new_chain
|
||||||
|
|
||||||
|
{"declare", { cls_name }}
|
||||||
|
{"declare_glob", "*"}
|
||||||
|
|
||||||
|
parent_val and .assign_one(parent_cls_name, parent_val) or NOOP
|
||||||
|
|
||||||
|
.assign_one base_name, {"table", properties}
|
||||||
|
.assign_one base_name\chain"__index", base_name
|
||||||
|
|
||||||
|
parent_val and .chain({
|
||||||
|
base: "setmetatable"
|
||||||
|
{"call", {
|
||||||
|
base_name,
|
||||||
|
.chain { base: parent_cls_name, {"dot", "__base"}}
|
||||||
|
}}
|
||||||
|
}) or NOOP
|
||||||
|
|
||||||
|
.assign_one cls_name, cls
|
||||||
|
.assign_one base_name\chain"__class", cls_name
|
||||||
|
|
||||||
|
.group if #statements > 0 then {
|
||||||
|
.assign_one LocalName"self", cls_name
|
||||||
|
.group statements
|
||||||
|
}
|
||||||
|
|
||||||
|
-- run the inherited callback
|
||||||
|
parent_val and .if({
|
||||||
|
cond: {"exp", parent_cls_name\chain "__inherited" }
|
||||||
|
then: {
|
||||||
|
parent_cls_name\chain "__inherited", {"call", {
|
||||||
|
parent_cls_name, cls_name
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
}) or NOOP
|
||||||
|
|
||||||
|
.group if name then {
|
||||||
|
.assign_one name, cls_name
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret
|
||||||
|
ret cls_name
|
||||||
|
}
|
||||||
|
|
||||||
|
value = .group {
|
||||||
|
.group if ntype(name) == "value" then {
|
||||||
|
.declare names: {name}
|
||||||
|
}
|
||||||
|
|
||||||
|
.do out_body
|
||||||
|
}
|
||||||
|
|
||||||
|
value
|
@ -1,10 +1,7 @@
|
|||||||
local Transformer
|
local Transformer
|
||||||
Transformer = require("moonscript.transform.transformer").Transformer
|
Transformer = require("moonscript.transform.transformer").Transformer
|
||||||
local NameProxy, LocalName
|
local NameProxy
|
||||||
do
|
NameProxy = require("moonscript.transform.names").NameProxy
|
||||||
local _obj_0 = require("moonscript.transform.names")
|
|
||||||
NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName
|
|
||||||
end
|
|
||||||
local Run, transform_last_stm, implicitly_return, last_stm
|
local Run, transform_last_stm, implicitly_return, last_stm
|
||||||
do
|
do
|
||||||
local _obj_0 = require("moonscript.transform.statements")
|
local _obj_0 = require("moonscript.transform.statements")
|
||||||
@ -18,7 +15,6 @@ insert = table.insert
|
|||||||
local destructure = require("moonscript.transform.destructure")
|
local destructure = require("moonscript.transform.destructure")
|
||||||
local construct_comprehension
|
local construct_comprehension
|
||||||
construct_comprehension = require("moonscript.transform.comprehension").construct_comprehension
|
construct_comprehension = require("moonscript.transform.comprehension").construct_comprehension
|
||||||
local CONSTRUCTOR_NAME = "new"
|
|
||||||
local with_continue_listener
|
local with_continue_listener
|
||||||
with_continue_listener = function(body)
|
with_continue_listener = function(body)
|
||||||
local continue_name = nil
|
local continue_name = nil
|
||||||
@ -739,425 +735,5 @@ return Transformer({
|
|||||||
if_stm
|
if_stm
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
class = function(self, node, ret, parent_assign)
|
class = require("moonscript.transform.class")
|
||||||
local _, name, parent_val, body = unpack(node)
|
|
||||||
if parent_val == "" then
|
|
||||||
parent_val = nil
|
|
||||||
end
|
|
||||||
local statements = { }
|
|
||||||
local properties = { }
|
|
||||||
for _index_0 = 1, #body do
|
|
||||||
local item = body[_index_0]
|
|
||||||
local _exp_0 = item[1]
|
|
||||||
if "stm" == _exp_0 then
|
|
||||||
insert(statements, item[2])
|
|
||||||
elseif "props" == _exp_0 then
|
|
||||||
for _index_1 = 2, #item do
|
|
||||||
local tuple = item[_index_1]
|
|
||||||
if ntype(tuple[1]) == "self" then
|
|
||||||
insert(statements, build.assign_one(unpack(tuple)))
|
|
||||||
else
|
|
||||||
insert(properties, tuple)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local constructor
|
|
||||||
do
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
for _index_0 = 1, #properties do
|
|
||||||
local _continue_0 = false
|
|
||||||
repeat
|
|
||||||
local tuple = properties[_index_0]
|
|
||||||
local key = tuple[1]
|
|
||||||
local _value_0
|
|
||||||
if key[1] == "key_literal" and key[2] == CONSTRUCTOR_NAME then
|
|
||||||
constructor = tuple[2]
|
|
||||||
_continue_0 = true
|
|
||||||
break
|
|
||||||
else
|
|
||||||
_value_0 = tuple
|
|
||||||
end
|
|
||||||
_accum_0[_len_0] = _value_0
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
_continue_0 = true
|
|
||||||
until true
|
|
||||||
if not _continue_0 then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
properties = _accum_0
|
|
||||||
end
|
|
||||||
local parent_cls_name = NameProxy("parent")
|
|
||||||
local base_name = NameProxy("base")
|
|
||||||
local self_name = NameProxy("self")
|
|
||||||
local cls_name = NameProxy("class")
|
|
||||||
if not (constructor) then
|
|
||||||
if parent_val then
|
|
||||||
constructor = build.fndef({
|
|
||||||
args = {
|
|
||||||
{
|
|
||||||
"..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
arrow = "fat",
|
|
||||||
body = {
|
|
||||||
build.chain({
|
|
||||||
base = "super",
|
|
||||||
{
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
"..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
else
|
|
||||||
constructor = build.fndef()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local real_name = name or parent_assign and parent_assign[2][1]
|
|
||||||
local _exp_0 = ntype(real_name)
|
|
||||||
if "chain" == _exp_0 then
|
|
||||||
local last = real_name[#real_name]
|
|
||||||
local _exp_1 = ntype(last)
|
|
||||||
if "dot" == _exp_1 then
|
|
||||||
real_name = {
|
|
||||||
"string",
|
|
||||||
'"',
|
|
||||||
last[2]
|
|
||||||
}
|
|
||||||
elseif "index" == _exp_1 then
|
|
||||||
real_name = last[2]
|
|
||||||
else
|
|
||||||
real_name = "nil"
|
|
||||||
end
|
|
||||||
elseif "nil" == _exp_0 then
|
|
||||||
real_name = "nil"
|
|
||||||
else
|
|
||||||
local name_t = type(real_name)
|
|
||||||
local flattened_name
|
|
||||||
if name_t == "string" then
|
|
||||||
flattened_name = real_name
|
|
||||||
elseif name_t == "table" and real_name[1] == "ref" then
|
|
||||||
flattened_name = real_name[2]
|
|
||||||
else
|
|
||||||
flattened_name = error("don't know how to extract name from " .. tostring(name_t))
|
|
||||||
end
|
|
||||||
real_name = {
|
|
||||||
"string",
|
|
||||||
'"',
|
|
||||||
flattened_name
|
|
||||||
}
|
|
||||||
end
|
|
||||||
local cls = build.table({
|
|
||||||
{
|
|
||||||
"__init",
|
|
||||||
constructor
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__base",
|
|
||||||
base_name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__name",
|
|
||||||
real_name
|
|
||||||
},
|
|
||||||
parent_val and {
|
|
||||||
"__parent",
|
|
||||||
parent_cls_name
|
|
||||||
} or nil
|
|
||||||
})
|
|
||||||
local class_index
|
|
||||||
if parent_val then
|
|
||||||
local class_lookup = build["if"]({
|
|
||||||
cond = {
|
|
||||||
"exp",
|
|
||||||
{
|
|
||||||
"ref",
|
|
||||||
"val"
|
|
||||||
},
|
|
||||||
"==",
|
|
||||||
"nil"
|
|
||||||
},
|
|
||||||
["then"] = {
|
|
||||||
build.assign_one(LocalName("parent"), build.chain({
|
|
||||||
base = "rawget",
|
|
||||||
{
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"ref",
|
|
||||||
"cls"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"string",
|
|
||||||
'"',
|
|
||||||
"__parent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
build["if"]({
|
|
||||||
cond = LocalName("parent"),
|
|
||||||
["then"] = {
|
|
||||||
build.chain({
|
|
||||||
base = LocalName("parent"),
|
|
||||||
{
|
|
||||||
"index",
|
|
||||||
"name"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
insert(class_lookup, {
|
|
||||||
"else",
|
|
||||||
{
|
|
||||||
"val"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
class_index = build.fndef({
|
|
||||||
args = {
|
|
||||||
{
|
|
||||||
"cls"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
body = {
|
|
||||||
build.assign_one(LocalName("val"), build.chain({
|
|
||||||
base = "rawget",
|
|
||||||
{
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
base_name,
|
|
||||||
{
|
|
||||||
"ref",
|
|
||||||
"name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
class_lookup
|
|
||||||
}
|
|
||||||
})
|
|
||||||
else
|
|
||||||
class_index = base_name
|
|
||||||
end
|
|
||||||
local cls_mt = build.table({
|
|
||||||
{
|
|
||||||
"__index",
|
|
||||||
class_index
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__call",
|
|
||||||
build.fndef({
|
|
||||||
args = {
|
|
||||||
{
|
|
||||||
"cls"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"..."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
body = {
|
|
||||||
build.assign_one(self_name, build.chain({
|
|
||||||
base = "setmetatable",
|
|
||||||
{
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
"{}",
|
|
||||||
base_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
build.chain({
|
|
||||||
base = "cls.__init",
|
|
||||||
{
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
self_name,
|
|
||||||
"..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
self_name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
cls = build.chain({
|
|
||||||
base = "setmetatable",
|
|
||||||
{
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
cls,
|
|
||||||
cls_mt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
local value = nil
|
|
||||||
do
|
|
||||||
local out_body = {
|
|
||||||
Run(function(self)
|
|
||||||
if name then
|
|
||||||
self:put_name(name)
|
|
||||||
end
|
|
||||||
return self:set("super", function(block, chain)
|
|
||||||
local relative_parent = {
|
|
||||||
"chain",
|
|
||||||
cls_name,
|
|
||||||
{
|
|
||||||
"dot",
|
|
||||||
"__parent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if not (chain) then
|
|
||||||
return relative_parent
|
|
||||||
end
|
|
||||||
local chain_tail = {
|
|
||||||
unpack(chain, 3)
|
|
||||||
}
|
|
||||||
local head = chain_tail[1]
|
|
||||||
if head == nil then
|
|
||||||
return relative_parent
|
|
||||||
end
|
|
||||||
local new_chain = relative_parent
|
|
||||||
local _exp_1 = head[1]
|
|
||||||
if "call" == _exp_1 then
|
|
||||||
local calling_name = block:get("current_block")
|
|
||||||
assert(calling_name, "missing calling name")
|
|
||||||
chain_tail[1] = {
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
"self",
|
|
||||||
unpack(head[2])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ntype(calling_name) == "key_literal" then
|
|
||||||
insert(new_chain, {
|
|
||||||
"dot",
|
|
||||||
calling_name[2]
|
|
||||||
})
|
|
||||||
else
|
|
||||||
insert(new_chain, {
|
|
||||||
"index",
|
|
||||||
calling_name
|
|
||||||
})
|
|
||||||
end
|
|
||||||
elseif "colon" == _exp_1 then
|
|
||||||
local call = chain_tail[2]
|
|
||||||
if call and call[1] == "call" then
|
|
||||||
chain_tail[1] = {
|
|
||||||
"dot",
|
|
||||||
head[2]
|
|
||||||
}
|
|
||||||
chain_tail[2] = {
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
"self",
|
|
||||||
unpack(call[2])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _index_0 = 1, #chain_tail do
|
|
||||||
local item = chain_tail[_index_0]
|
|
||||||
insert(new_chain, item)
|
|
||||||
end
|
|
||||||
return new_chain
|
|
||||||
end)
|
|
||||||
end),
|
|
||||||
{
|
|
||||||
"declare",
|
|
||||||
{
|
|
||||||
cls_name
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"declare_glob",
|
|
||||||
"*"
|
|
||||||
},
|
|
||||||
parent_val and build.assign_one(parent_cls_name, parent_val) or NOOP,
|
|
||||||
build.assign_one(base_name, {
|
|
||||||
"table",
|
|
||||||
properties
|
|
||||||
}),
|
|
||||||
build.assign_one(base_name:chain("__index"), base_name),
|
|
||||||
parent_val and build.chain({
|
|
||||||
base = "setmetatable",
|
|
||||||
{
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
base_name,
|
|
||||||
build.chain({
|
|
||||||
base = parent_cls_name,
|
|
||||||
{
|
|
||||||
"dot",
|
|
||||||
"__base"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}) or NOOP,
|
|
||||||
build.assign_one(cls_name, cls),
|
|
||||||
build.assign_one(base_name:chain("__class"), cls_name),
|
|
||||||
build.group((function()
|
|
||||||
if #statements > 0 then
|
|
||||||
return {
|
|
||||||
build.assign_one(LocalName("self"), cls_name),
|
|
||||||
build.group(statements)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end)()),
|
|
||||||
parent_val and build["if"]({
|
|
||||||
cond = {
|
|
||||||
"exp",
|
|
||||||
parent_cls_name:chain("__inherited")
|
|
||||||
},
|
|
||||||
["then"] = {
|
|
||||||
parent_cls_name:chain("__inherited", {
|
|
||||||
"call",
|
|
||||||
{
|
|
||||||
parent_cls_name,
|
|
||||||
cls_name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}) or NOOP,
|
|
||||||
build.group((function()
|
|
||||||
if name then
|
|
||||||
return {
|
|
||||||
build.assign_one(name, cls_name)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end)()),
|
|
||||||
(function()
|
|
||||||
if ret then
|
|
||||||
return ret(cls_name)
|
|
||||||
end
|
|
||||||
end)()
|
|
||||||
}
|
|
||||||
value = build.group({
|
|
||||||
build.group((function()
|
|
||||||
if ntype(name) == "value" then
|
|
||||||
return {
|
|
||||||
build.declare({
|
|
||||||
names = {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end)()),
|
|
||||||
build["do"](out_body)
|
|
||||||
})
|
|
||||||
end
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Transformer from require "moonscript.transform.transformer"
|
import Transformer from require "moonscript.transform.transformer"
|
||||||
|
|
||||||
import NameProxy, LocalName from require "moonscript.transform.names"
|
import NameProxy from require "moonscript.transform.names"
|
||||||
|
|
||||||
import Run, transform_last_stm, implicitly_return, last_stm
|
import Run, transform_last_stm, implicitly_return, last_stm
|
||||||
from require "moonscript.transform.statements"
|
from require "moonscript.transform.statements"
|
||||||
@ -15,8 +15,6 @@ import insert from table
|
|||||||
destructure = require "moonscript.transform.destructure"
|
destructure = require "moonscript.transform.destructure"
|
||||||
import construct_comprehension from require "moonscript.transform.comprehension"
|
import construct_comprehension from require "moonscript.transform.comprehension"
|
||||||
|
|
||||||
CONSTRUCTOR_NAME = "new"
|
|
||||||
|
|
||||||
with_continue_listener = (body) ->
|
with_continue_listener = (body) ->
|
||||||
continue_name = nil
|
continue_name = nil
|
||||||
|
|
||||||
@ -470,252 +468,6 @@ Transformer {
|
|||||||
if_stm
|
if_stm
|
||||||
}
|
}
|
||||||
|
|
||||||
class: (node, ret, parent_assign) =>
|
class: require "moonscript.transform.class"
|
||||||
_, name, parent_val, body = unpack node
|
|
||||||
parent_val = nil if parent_val == ""
|
|
||||||
|
|
||||||
-- split apart properties and statements
|
|
||||||
statements = {}
|
|
||||||
properties = {}
|
|
||||||
for item in *body
|
|
||||||
switch item[1]
|
|
||||||
when "stm"
|
|
||||||
insert statements, item[2]
|
|
||||||
when "props"
|
|
||||||
for tuple in *item[2,]
|
|
||||||
if ntype(tuple[1]) == "self"
|
|
||||||
insert statements, build.assign_one unpack tuple
|
|
||||||
else
|
|
||||||
insert properties, tuple
|
|
||||||
|
|
||||||
-- find constructor
|
|
||||||
local constructor
|
|
||||||
properties = for tuple in *properties
|
|
||||||
key = tuple[1]
|
|
||||||
if key[1] == "key_literal" and key[2] == CONSTRUCTOR_NAME
|
|
||||||
constructor = tuple[2]
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
tuple
|
|
||||||
|
|
||||||
parent_cls_name = NameProxy "parent"
|
|
||||||
base_name = NameProxy "base"
|
|
||||||
self_name = NameProxy "self"
|
|
||||||
cls_name = NameProxy "class"
|
|
||||||
|
|
||||||
unless constructor
|
|
||||||
constructor = if parent_val
|
|
||||||
build.fndef {
|
|
||||||
args: {{"..."}}
|
|
||||||
arrow: "fat"
|
|
||||||
body: {
|
|
||||||
build.chain { base: "super", {"call", {"..."}} }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
build.fndef!
|
|
||||||
|
|
||||||
real_name = name or parent_assign and parent_assign[2][1]
|
|
||||||
real_name = switch ntype real_name
|
|
||||||
when "chain"
|
|
||||||
last = real_name[#real_name]
|
|
||||||
switch ntype last
|
|
||||||
when "dot"
|
|
||||||
{"string", '"', last[2]}
|
|
||||||
when "index"
|
|
||||||
last[2]
|
|
||||||
else
|
|
||||||
"nil"
|
|
||||||
when "nil"
|
|
||||||
"nil"
|
|
||||||
else
|
|
||||||
name_t = type real_name
|
|
||||||
-- TODO: don't use string literal as ref
|
|
||||||
flattened_name = if name_t == "string"
|
|
||||||
real_name
|
|
||||||
elseif name_t == "table" and real_name[1] == "ref"
|
|
||||||
real_name[2]
|
|
||||||
else
|
|
||||||
error "don't know how to extract name from #{name_t}"
|
|
||||||
|
|
||||||
{"string", '"', flattened_name}
|
|
||||||
|
|
||||||
cls = build.table {
|
|
||||||
{"__init", constructor}
|
|
||||||
{"__base", base_name}
|
|
||||||
{"__name", real_name} -- "quote the string"
|
|
||||||
parent_val and {"__parent", parent_cls_name} or nil
|
|
||||||
}
|
|
||||||
|
|
||||||
-- looking up a name in the class object
|
|
||||||
class_index = if parent_val
|
|
||||||
class_lookup = build["if"] {
|
|
||||||
cond: { "exp", {"ref", "val"}, "==", "nil" }
|
|
||||||
then: {
|
|
||||||
build.assign_one LocalName"parent", build.chain {
|
|
||||||
base: "rawget"
|
|
||||||
{
|
|
||||||
"call", {
|
|
||||||
{"ref", "cls"}
|
|
||||||
{"string", '"', "__parent"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
build.if {
|
|
||||||
cond: LocalName "parent"
|
|
||||||
then: {
|
|
||||||
build.chain {
|
|
||||||
base: LocalName "parent"
|
|
||||||
{"index", "name"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insert class_lookup, {"else", {"val"}}
|
|
||||||
|
|
||||||
build.fndef {
|
|
||||||
args: {{"cls"}, {"name"}}
|
|
||||||
body: {
|
|
||||||
build.assign_one LocalName"val", build.chain {
|
|
||||||
base: "rawget", {"call", {base_name, {"ref", "name"}}}
|
|
||||||
}
|
|
||||||
class_lookup
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
base_name
|
|
||||||
|
|
||||||
cls_mt = build.table {
|
|
||||||
{"__index", class_index}
|
|
||||||
{"__call", build.fndef {
|
|
||||||
args: {{"cls"}, {"..."}}
|
|
||||||
body: {
|
|
||||||
build.assign_one self_name, build.chain {
|
|
||||||
base: "setmetatable"
|
|
||||||
{"call", {"{}", base_name}}
|
|
||||||
}
|
|
||||||
build.chain {
|
|
||||||
base: "cls.__init"
|
|
||||||
{"call", {self_name, "..."}}
|
|
||||||
}
|
|
||||||
self_name
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
cls = build.chain {
|
|
||||||
base: "setmetatable"
|
|
||||||
{"call", {cls, cls_mt}}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = nil
|
|
||||||
with build
|
|
||||||
out_body = {
|
|
||||||
Run =>
|
|
||||||
-- make sure we don't assign the class to a local inside the do
|
|
||||||
@put_name name if name
|
|
||||||
|
|
||||||
@set "super", (block, chain) ->
|
|
||||||
relative_parent = {
|
|
||||||
"chain",
|
|
||||||
cls_name
|
|
||||||
{"dot", "__parent"}
|
|
||||||
}
|
|
||||||
|
|
||||||
return relative_parent unless chain
|
|
||||||
|
|
||||||
chain_tail = { unpack chain, 3 }
|
|
||||||
head = chain_tail[1]
|
|
||||||
|
|
||||||
if head == nil
|
|
||||||
return relative_parent
|
|
||||||
|
|
||||||
new_chain = relative_parent
|
|
||||||
|
|
||||||
switch head[1]
|
|
||||||
-- calling super, inject calling name and self into chain
|
|
||||||
when "call"
|
|
||||||
calling_name = block\get"current_block"
|
|
||||||
assert calling_name, "missing calling name"
|
|
||||||
chain_tail[1] = {"call", {"self", unpack head[2]}}
|
|
||||||
|
|
||||||
if ntype(calling_name) == "key_literal"
|
|
||||||
insert new_chain, {"dot", calling_name[2]}
|
|
||||||
else
|
|
||||||
insert new_chain, {"index", calling_name}
|
|
||||||
|
|
||||||
-- colon call on super, replace class with self as first arg
|
|
||||||
when "colon"
|
|
||||||
call = chain_tail[2]
|
|
||||||
-- calling chain tail
|
|
||||||
if call and call[1] == "call"
|
|
||||||
chain_tail[1] = {
|
|
||||||
"dot"
|
|
||||||
head[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
chain_tail[2] = {
|
|
||||||
"call"
|
|
||||||
{
|
|
||||||
"self"
|
|
||||||
unpack call[2]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
insert new_chain, item for item in *chain_tail
|
|
||||||
new_chain
|
|
||||||
|
|
||||||
{"declare", { cls_name }}
|
|
||||||
{"declare_glob", "*"}
|
|
||||||
|
|
||||||
parent_val and .assign_one(parent_cls_name, parent_val) or NOOP
|
|
||||||
|
|
||||||
.assign_one base_name, {"table", properties}
|
|
||||||
.assign_one base_name\chain"__index", base_name
|
|
||||||
|
|
||||||
parent_val and .chain({
|
|
||||||
base: "setmetatable"
|
|
||||||
{"call", {
|
|
||||||
base_name,
|
|
||||||
.chain { base: parent_cls_name, {"dot", "__base"}}
|
|
||||||
}}
|
|
||||||
}) or NOOP
|
|
||||||
|
|
||||||
.assign_one cls_name, cls
|
|
||||||
.assign_one base_name\chain"__class", cls_name
|
|
||||||
|
|
||||||
.group if #statements > 0 then {
|
|
||||||
.assign_one LocalName"self", cls_name
|
|
||||||
.group statements
|
|
||||||
}
|
|
||||||
|
|
||||||
-- run the inherited callback
|
|
||||||
parent_val and .if({
|
|
||||||
cond: {"exp", parent_cls_name\chain "__inherited" }
|
|
||||||
then: {
|
|
||||||
parent_cls_name\chain "__inherited", {"call", {
|
|
||||||
parent_cls_name, cls_name
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
}) or NOOP
|
|
||||||
|
|
||||||
.group if name then {
|
|
||||||
.assign_one name, cls_name
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret
|
|
||||||
ret cls_name
|
|
||||||
}
|
|
||||||
|
|
||||||
value = .group {
|
|
||||||
.group if ntype(name) == "value" then {
|
|
||||||
.declare names: {name}
|
|
||||||
}
|
|
||||||
|
|
||||||
.do out_body
|
|
||||||
}
|
|
||||||
|
|
||||||
value
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user