mirror of
https://github.com/leafo/moonscript.git
synced 2025-01-09 00:04:22 +00:00
added using keyword in functions, type accessors in compiler
This commit is contained in:
parent
13747aa955
commit
2fbbef9c44
@ -27,6 +27,7 @@ build = {
|
||||
["moonscript.compile.line"] = "moonscript/compile/line.lua",
|
||||
["moonscript.compile.value"] = "moonscript/compile/value.lua",
|
||||
["moonscript.compile.format"] = "moonscript/compile/format.lua",
|
||||
["moonscript.compile.types"] = "moonscript/compile/types.lua",
|
||||
["moonscript.parse"] = "moonscript/parse.lua",
|
||||
["moonscript.dump"] = "moonscript/dump.lua",
|
||||
["moonscript.data"] = "moonscript/data.lua",
|
||||
|
@ -121,11 +121,21 @@ Block_ = (function(_parent_0)
|
||||
end
|
||||
return undeclared
|
||||
end,
|
||||
whitelist_names = function(self, names)
|
||||
self._name_whitelist = Set(names)
|
||||
end,
|
||||
put_name = function(self, name)
|
||||
self._names[name] = true
|
||||
end,
|
||||
has_name = function(self, name)
|
||||
return self._names[name]
|
||||
local yes = self._names[name]
|
||||
if yes == nil and self.parent then
|
||||
if not self._name_whitelist or self._name_whitelist[name] then
|
||||
return self.parent:has_name(name)
|
||||
end
|
||||
else
|
||||
return yes
|
||||
end
|
||||
end,
|
||||
shadow_name = function(self, name)
|
||||
self._names[name] = false
|
||||
@ -224,14 +234,6 @@ Block_ = (function(_parent_0)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
push = function(self)
|
||||
self._names = setmetatable({ }, {
|
||||
__index = self._names
|
||||
})
|
||||
end,
|
||||
pop = function(self)
|
||||
self._names = getmetatable(self._names).__index
|
||||
end,
|
||||
_insert_breaks = function(self)
|
||||
for i = 1, #self._lines - 1 do
|
||||
local left, right = self._lines[i], self._lines[i + 1]
|
||||
@ -405,12 +407,9 @@ Block_ = (function(_parent_0)
|
||||
self._state = { }
|
||||
if self.parent then
|
||||
self.indent = self.parent.indent + 1
|
||||
setmetatable(self._state, {
|
||||
return setmetatable(self._state, {
|
||||
__index = self.parent._state
|
||||
})
|
||||
return setmetatable(self._names, {
|
||||
__index = self.parent._names
|
||||
})
|
||||
else
|
||||
self.indent = 0
|
||||
end
|
||||
|
@ -60,7 +60,6 @@ class Block_
|
||||
if @parent
|
||||
@indent = @parent.indent + 1
|
||||
setmetatable @_state, { __index: @parent._state }
|
||||
setmetatable @_names, { __index: @parent._names }
|
||||
else
|
||||
@indent = 0
|
||||
|
||||
@ -78,11 +77,19 @@ class Block_
|
||||
@put_name name for name in *undeclared
|
||||
undeclared
|
||||
|
||||
whitelist_names: (names) =>
|
||||
@_name_whitelist = Set names
|
||||
|
||||
put_name: (name) =>
|
||||
@_names[name] = true
|
||||
|
||||
has_name: (name) =>
|
||||
@_names[name]
|
||||
yes = @_names[name]
|
||||
if yes == nil and @parent
|
||||
if not @_name_whitelist or @_name_whitelist[name]
|
||||
@parent\has_name name
|
||||
else
|
||||
yes
|
||||
|
||||
shadow_name: (name) =>
|
||||
@_names[name] = false
|
||||
@ -153,12 +160,6 @@ class Block_
|
||||
error "Adding unknown item"
|
||||
nil
|
||||
|
||||
push: =>
|
||||
@_names = setmetatable {}, { __index: @_names }
|
||||
|
||||
pop: =>
|
||||
@_names = getmetatable(@_names).__index
|
||||
|
||||
_insert_breaks: =>
|
||||
for i = 1, #@_lines - 1
|
||||
left, right = @_lines[i], @_lines[i+1]
|
||||
|
@ -3,6 +3,7 @@ local util = require("moonscript.util")
|
||||
local data = require("moonscript.data")
|
||||
local dump = require("moonscript.dump")
|
||||
require("moonscript.compile.format")
|
||||
require("moonscript.compile.types")
|
||||
local reversed = util.reversed
|
||||
local ntype = data.ntype
|
||||
local concat, insert = table.concat, table.insert
|
||||
@ -425,6 +426,7 @@ line_compile = {
|
||||
{
|
||||
"..."
|
||||
},
|
||||
{ },
|
||||
"fat",
|
||||
{
|
||||
{
|
||||
@ -446,6 +448,7 @@ line_compile = {
|
||||
}
|
||||
}
|
||||
end
|
||||
smart_node(constructor)
|
||||
local self_args = { }
|
||||
local get_initializers
|
||||
get_initializers = function(arg)
|
||||
@ -455,10 +458,10 @@ line_compile = {
|
||||
end
|
||||
return arg
|
||||
end
|
||||
constructor[2] = (function()
|
||||
constructor.args = (function()
|
||||
local _accum_0 = { }
|
||||
do
|
||||
local _item_0 = constructor[2]
|
||||
local _item_0 = constructor.args
|
||||
for _index_0 = 1, #_item_0 do
|
||||
local arg = _item_0[_index_0]
|
||||
table.insert(_accum_0, get_initializers(arg))
|
||||
@ -466,8 +469,7 @@ line_compile = {
|
||||
end
|
||||
return _accum_0
|
||||
end)()
|
||||
constructor[3] = "fat"
|
||||
local body = constructor[4]
|
||||
constructor.arrow = "fat"
|
||||
local dests = (function()
|
||||
local _accum_0 = { }
|
||||
do
|
||||
@ -483,7 +485,7 @@ line_compile = {
|
||||
return _accum_0
|
||||
end)()
|
||||
if #self_args > 0 then
|
||||
insert(body, 1, {
|
||||
insert(constructor.body, 1, {
|
||||
"assign",
|
||||
dests,
|
||||
self_args
|
||||
@ -605,6 +607,7 @@ line_compile = {
|
||||
"mt",
|
||||
"..."
|
||||
},
|
||||
{ },
|
||||
"slim",
|
||||
{
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ data = require "moonscript.data"
|
||||
dump = require "moonscript.dump"
|
||||
|
||||
require "moonscript.compile.format"
|
||||
require "moonscript.compile.types"
|
||||
|
||||
import reversed from util
|
||||
import ntype from data
|
||||
@ -223,12 +224,14 @@ line_compile =
|
||||
|
||||
-- synthesize constructor if needed
|
||||
if not constructor
|
||||
constructor = {"fndef", {"..."}, "fat", {
|
||||
constructor = {"fndef", {"..."}, {}, "fat", {
|
||||
{"if", parent_loc, {
|
||||
{"chain", "super", {"call", {"..."}}}
|
||||
}}
|
||||
}}
|
||||
|
||||
smart_node constructor
|
||||
|
||||
-- organize constructor arguments
|
||||
-- extract self arguments
|
||||
self_args = {}
|
||||
@ -238,13 +241,12 @@ line_compile =
|
||||
insert self_args, arg
|
||||
arg
|
||||
|
||||
constructor[2] = [get_initializers arg for arg in *constructor[2]]
|
||||
constructor[3] = "fat"
|
||||
body = constructor[4]
|
||||
constructor.args = [get_initializers arg for arg in *constructor.args]
|
||||
constructor.arrow = "fat"
|
||||
|
||||
-- insert self assigning arguments
|
||||
dests = [{"self", name} for name in *self_args]
|
||||
insert body, 1, {"assign", dests, self_args} if #self_args > 0
|
||||
insert constructor.body, 1, {"assign", dests, self_args} if #self_args > 0
|
||||
|
||||
def_scope = with @block!
|
||||
parent_val = @value parent_val if parent_val != ""
|
||||
@ -280,7 +282,7 @@ line_compile =
|
||||
-- the class's meta table, gives us call and access to base methods
|
||||
cls_mt = {"table", {
|
||||
{"__index", base_name}
|
||||
{"__call", {"fndef", {"mt", "..."}, "slim", {
|
||||
{"__call", {"fndef", {"mt", "..."}, {}, "slim", {
|
||||
{"raw", ("local self = setmetatable({}, %s)")\format(base_name)}
|
||||
{"chain", "mt.__init", {"call", {"self", "..."}}}
|
||||
"self"
|
||||
|
44
moonscript/compile/types.lua
Normal file
44
moonscript/compile/types.lua
Normal file
@ -0,0 +1,44 @@
|
||||
module("moonscript.compile", package.seeall)
|
||||
local util = require("moonscript.util")
|
||||
local data = require("moonscript.data")
|
||||
local ntype = data.ntype
|
||||
local key_table = {
|
||||
fndef = {
|
||||
"args",
|
||||
"whitelist",
|
||||
"arrow",
|
||||
"body"
|
||||
}
|
||||
}
|
||||
local build_table
|
||||
build_table = function()
|
||||
for key, value in pairs(key_table) do
|
||||
local index = { }
|
||||
for i, name in ipairs(value) do
|
||||
index[name] = i + 1
|
||||
end
|
||||
key_table[key] = index
|
||||
end
|
||||
end
|
||||
build_table()
|
||||
smart_node = function(node)
|
||||
local index = key_table[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
|
38
moonscript/compile/types.moon
Normal file
38
moonscript/compile/types.moon
Normal file
@ -0,0 +1,38 @@
|
||||
module "moonscript.compile", package.seeall
|
||||
|
||||
util = require "moonscript.util"
|
||||
data = require "moonscript.data"
|
||||
|
||||
import ntype from data
|
||||
export smart_node
|
||||
|
||||
-- todo: this should be merged into data
|
||||
-- lets us index a node by item name based on it's type
|
||||
|
||||
key_table = {
|
||||
fndef: {"args", "whitelist", "arrow", "body"}
|
||||
}
|
||||
|
||||
build_table = ->
|
||||
for key, value in pairs key_table
|
||||
index = {}
|
||||
index[name] = i + 1 for i, name in ipairs value
|
||||
key_table[key] = index
|
||||
|
||||
build_table!
|
||||
|
||||
smart_node = (node) ->
|
||||
index = key_table[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
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ value_compile = {
|
||||
return self:line(callee_value, actions)
|
||||
end,
|
||||
fndef = function(self, node)
|
||||
local _, args, arrow, block = unpack(node)
|
||||
local _, args, whitelist, arrow, block = unpack(node)
|
||||
local default_args = { }
|
||||
local format_names
|
||||
format_names = function(arg)
|
||||
@ -236,6 +236,9 @@ value_compile = {
|
||||
end
|
||||
do
|
||||
local _with_0 = self:block("function(" .. concat(args, ", ") .. ")")
|
||||
if #whitelist > 0 then
|
||||
_with_0:whitelist_names(whitelist)
|
||||
end
|
||||
do
|
||||
local _item_0 = args
|
||||
for _index_0 = 1, #_item_0 do
|
||||
|
@ -122,7 +122,7 @@ value_compile =
|
||||
@line callee_value, actions
|
||||
|
||||
fndef: (node) =>
|
||||
_, args, arrow, block = unpack node
|
||||
_, args, whitelist, arrow, block = unpack node
|
||||
|
||||
default_args = {}
|
||||
format_names = (arg) ->
|
||||
@ -138,6 +138,9 @@ value_compile =
|
||||
insert args, 1, "self"
|
||||
|
||||
with @block "function("..concat(args, ", ")..")"
|
||||
if #whitelist > 0
|
||||
\whitelist_names whitelist
|
||||
|
||||
\put_name name for name in *args
|
||||
|
||||
for default in *default_args
|
||||
|
@ -389,11 +389,14 @@ local build_grammar = wrap(function()
|
||||
KeyValueList = KeyValue * (sym"," * KeyValue)^0,
|
||||
KeyValueLine = Cmt(Indent, check_indent) * KeyValueList * sym","^-1,
|
||||
|
||||
FnArgsDef = sym"(" * Ct(FnArgDefList^-1) * sym")",
|
||||
FnArgsDef = sym"(" * Ct(FnArgDefList^-1) *
|
||||
(key"using" * Ct(NameList + Space * "nil") + Ct"") *
|
||||
sym")" + Ct"" * Ct"",
|
||||
|
||||
FnArgDefList = FnArgDef * (sym"," * FnArgDef)^0,
|
||||
FnArgDef = Name * (sym"=" * Exp)^-1 / wrap_default_arg,
|
||||
|
||||
FunLit = (FnArgsDef + Ct("")) *
|
||||
FunLit = FnArgsDef *
|
||||
(sym"->" * Cc"slim" + sym"=>" * Cc"fat") *
|
||||
(Body + Ct"") / mark"fndef",
|
||||
|
||||
|
32
todo
32
todo
@ -2,7 +2,14 @@
|
||||
|
||||
- varargs that get put in a nested generated function aren't valid anymore:
|
||||
|
||||
- cascading expressions in function
|
||||
- cascading expressions in function call? this looks too much like line decorator
|
||||
* maybe with assigns only
|
||||
|
||||
my_func if something
|
||||
"one arg"
|
||||
else
|
||||
"other arg"
|
||||
|
||||
|
||||
- class expressions, x = class extends Hello do new: => print "hello"
|
||||
|
||||
@ -16,10 +23,7 @@
|
||||
* elseif with value that inserts lines
|
||||
- need to decompose elif into if inside else
|
||||
|
||||
* export keyword, makes it so local is left off when variable is declared
|
||||
- or copies to global var when local already exists
|
||||
- or used for assignment to assign global var
|
||||
|
||||
* export could also be used like so:
|
||||
|
||||
export a = -> "hello"
|
||||
|
||||
@ -28,25 +32,21 @@ or
|
||||
x = 232
|
||||
export x
|
||||
|
||||
or
|
||||
|
||||
export x
|
||||
x = 3434
|
||||
|
||||
|
||||
* allow return anywhere in block
|
||||
* upercase constants and capital letter variables should automatically be exported (in the global scope?)
|
||||
|
||||
* any/every keywords for comprehensions?
|
||||
* any/every keywords for comprehensions? (what about iterators)
|
||||
|
||||
not working right:
|
||||
|
||||
... not working right
|
||||
|
||||
|
||||
double_args = (...) ->
|
||||
[x * 2 for x in *{...}]
|
||||
double_args = (...) ->
|
||||
[x * 2 for x in *{...}]
|
||||
|
||||
|
||||
still some issues with whitespace at end of line
|
||||
|
||||
* let array items in table be defined without {} when indented
|
||||
* key,value table comprehensions with { }
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user