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.line"] = "moonscript/compile/line.lua",
|
||||||
["moonscript.compile.value"] = "moonscript/compile/value.lua",
|
["moonscript.compile.value"] = "moonscript/compile/value.lua",
|
||||||
["moonscript.compile.format"] = "moonscript/compile/format.lua",
|
["moonscript.compile.format"] = "moonscript/compile/format.lua",
|
||||||
|
["moonscript.compile.types"] = "moonscript/compile/types.lua",
|
||||||
["moonscript.parse"] = "moonscript/parse.lua",
|
["moonscript.parse"] = "moonscript/parse.lua",
|
||||||
["moonscript.dump"] = "moonscript/dump.lua",
|
["moonscript.dump"] = "moonscript/dump.lua",
|
||||||
["moonscript.data"] = "moonscript/data.lua",
|
["moonscript.data"] = "moonscript/data.lua",
|
||||||
|
@ -121,11 +121,21 @@ Block_ = (function(_parent_0)
|
|||||||
end
|
end
|
||||||
return undeclared
|
return undeclared
|
||||||
end,
|
end,
|
||||||
|
whitelist_names = function(self, names)
|
||||||
|
self._name_whitelist = Set(names)
|
||||||
|
end,
|
||||||
put_name = function(self, name)
|
put_name = function(self, name)
|
||||||
self._names[name] = true
|
self._names[name] = true
|
||||||
end,
|
end,
|
||||||
has_name = function(self, name)
|
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,
|
end,
|
||||||
shadow_name = function(self, name)
|
shadow_name = function(self, name)
|
||||||
self._names[name] = false
|
self._names[name] = false
|
||||||
@ -224,14 +234,6 @@ Block_ = (function(_parent_0)
|
|||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end,
|
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)
|
_insert_breaks = function(self)
|
||||||
for i = 1, #self._lines - 1 do
|
for i = 1, #self._lines - 1 do
|
||||||
local left, right = self._lines[i], self._lines[i + 1]
|
local left, right = self._lines[i], self._lines[i + 1]
|
||||||
@ -405,12 +407,9 @@ Block_ = (function(_parent_0)
|
|||||||
self._state = { }
|
self._state = { }
|
||||||
if self.parent then
|
if self.parent then
|
||||||
self.indent = self.parent.indent + 1
|
self.indent = self.parent.indent + 1
|
||||||
setmetatable(self._state, {
|
return setmetatable(self._state, {
|
||||||
__index = self.parent._state
|
__index = self.parent._state
|
||||||
})
|
})
|
||||||
return setmetatable(self._names, {
|
|
||||||
__index = self.parent._names
|
|
||||||
})
|
|
||||||
else
|
else
|
||||||
self.indent = 0
|
self.indent = 0
|
||||||
end
|
end
|
||||||
|
@ -60,7 +60,6 @@ class Block_
|
|||||||
if @parent
|
if @parent
|
||||||
@indent = @parent.indent + 1
|
@indent = @parent.indent + 1
|
||||||
setmetatable @_state, { __index: @parent._state }
|
setmetatable @_state, { __index: @parent._state }
|
||||||
setmetatable @_names, { __index: @parent._names }
|
|
||||||
else
|
else
|
||||||
@indent = 0
|
@indent = 0
|
||||||
|
|
||||||
@ -78,11 +77,19 @@ class Block_
|
|||||||
@put_name name for name in *undeclared
|
@put_name name for name in *undeclared
|
||||||
undeclared
|
undeclared
|
||||||
|
|
||||||
|
whitelist_names: (names) =>
|
||||||
|
@_name_whitelist = Set names
|
||||||
|
|
||||||
put_name: (name) =>
|
put_name: (name) =>
|
||||||
@_names[name] = true
|
@_names[name] = true
|
||||||
|
|
||||||
has_name: (name) =>
|
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) =>
|
shadow_name: (name) =>
|
||||||
@_names[name] = false
|
@_names[name] = false
|
||||||
@ -153,12 +160,6 @@ class Block_
|
|||||||
error "Adding unknown item"
|
error "Adding unknown item"
|
||||||
nil
|
nil
|
||||||
|
|
||||||
push: =>
|
|
||||||
@_names = setmetatable {}, { __index: @_names }
|
|
||||||
|
|
||||||
pop: =>
|
|
||||||
@_names = getmetatable(@_names).__index
|
|
||||||
|
|
||||||
_insert_breaks: =>
|
_insert_breaks: =>
|
||||||
for i = 1, #@_lines - 1
|
for i = 1, #@_lines - 1
|
||||||
left, right = @_lines[i], @_lines[i+1]
|
left, right = @_lines[i], @_lines[i+1]
|
||||||
|
@ -3,6 +3,7 @@ local util = require("moonscript.util")
|
|||||||
local data = require("moonscript.data")
|
local data = require("moonscript.data")
|
||||||
local dump = require("moonscript.dump")
|
local dump = require("moonscript.dump")
|
||||||
require("moonscript.compile.format")
|
require("moonscript.compile.format")
|
||||||
|
require("moonscript.compile.types")
|
||||||
local reversed = util.reversed
|
local reversed = util.reversed
|
||||||
local ntype = data.ntype
|
local ntype = data.ntype
|
||||||
local concat, insert = table.concat, table.insert
|
local concat, insert = table.concat, table.insert
|
||||||
@ -425,6 +426,7 @@ line_compile = {
|
|||||||
{
|
{
|
||||||
"..."
|
"..."
|
||||||
},
|
},
|
||||||
|
{ },
|
||||||
"fat",
|
"fat",
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -446,6 +448,7 @@ line_compile = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
smart_node(constructor)
|
||||||
local self_args = { }
|
local self_args = { }
|
||||||
local get_initializers
|
local get_initializers
|
||||||
get_initializers = function(arg)
|
get_initializers = function(arg)
|
||||||
@ -455,10 +458,10 @@ line_compile = {
|
|||||||
end
|
end
|
||||||
return arg
|
return arg
|
||||||
end
|
end
|
||||||
constructor[2] = (function()
|
constructor.args = (function()
|
||||||
local _accum_0 = { }
|
local _accum_0 = { }
|
||||||
do
|
do
|
||||||
local _item_0 = constructor[2]
|
local _item_0 = constructor.args
|
||||||
for _index_0 = 1, #_item_0 do
|
for _index_0 = 1, #_item_0 do
|
||||||
local arg = _item_0[_index_0]
|
local arg = _item_0[_index_0]
|
||||||
table.insert(_accum_0, get_initializers(arg))
|
table.insert(_accum_0, get_initializers(arg))
|
||||||
@ -466,8 +469,7 @@ line_compile = {
|
|||||||
end
|
end
|
||||||
return _accum_0
|
return _accum_0
|
||||||
end)()
|
end)()
|
||||||
constructor[3] = "fat"
|
constructor.arrow = "fat"
|
||||||
local body = constructor[4]
|
|
||||||
local dests = (function()
|
local dests = (function()
|
||||||
local _accum_0 = { }
|
local _accum_0 = { }
|
||||||
do
|
do
|
||||||
@ -483,7 +485,7 @@ line_compile = {
|
|||||||
return _accum_0
|
return _accum_0
|
||||||
end)()
|
end)()
|
||||||
if #self_args > 0 then
|
if #self_args > 0 then
|
||||||
insert(body, 1, {
|
insert(constructor.body, 1, {
|
||||||
"assign",
|
"assign",
|
||||||
dests,
|
dests,
|
||||||
self_args
|
self_args
|
||||||
@ -605,6 +607,7 @@ line_compile = {
|
|||||||
"mt",
|
"mt",
|
||||||
"..."
|
"..."
|
||||||
},
|
},
|
||||||
|
{ },
|
||||||
"slim",
|
"slim",
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@ data = require "moonscript.data"
|
|||||||
dump = require "moonscript.dump"
|
dump = require "moonscript.dump"
|
||||||
|
|
||||||
require "moonscript.compile.format"
|
require "moonscript.compile.format"
|
||||||
|
require "moonscript.compile.types"
|
||||||
|
|
||||||
import reversed from util
|
import reversed from util
|
||||||
import ntype from data
|
import ntype from data
|
||||||
@ -223,12 +224,14 @@ line_compile =
|
|||||||
|
|
||||||
-- synthesize constructor if needed
|
-- synthesize constructor if needed
|
||||||
if not constructor
|
if not constructor
|
||||||
constructor = {"fndef", {"..."}, "fat", {
|
constructor = {"fndef", {"..."}, {}, "fat", {
|
||||||
{"if", parent_loc, {
|
{"if", parent_loc, {
|
||||||
{"chain", "super", {"call", {"..."}}}
|
{"chain", "super", {"call", {"..."}}}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
smart_node constructor
|
||||||
|
|
||||||
-- organize constructor arguments
|
-- organize constructor arguments
|
||||||
-- extract self arguments
|
-- extract self arguments
|
||||||
self_args = {}
|
self_args = {}
|
||||||
@ -238,13 +241,12 @@ line_compile =
|
|||||||
insert self_args, arg
|
insert self_args, arg
|
||||||
arg
|
arg
|
||||||
|
|
||||||
constructor[2] = [get_initializers arg for arg in *constructor[2]]
|
constructor.args = [get_initializers arg for arg in *constructor.args]
|
||||||
constructor[3] = "fat"
|
constructor.arrow = "fat"
|
||||||
body = constructor[4]
|
|
||||||
|
|
||||||
-- insert self assigning arguments
|
-- insert self assigning arguments
|
||||||
dests = [{"self", name} for name in *self_args]
|
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!
|
def_scope = with @block!
|
||||||
parent_val = @value parent_val if parent_val != ""
|
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
|
-- the class's meta table, gives us call and access to base methods
|
||||||
cls_mt = {"table", {
|
cls_mt = {"table", {
|
||||||
{"__index", base_name}
|
{"__index", base_name}
|
||||||
{"__call", {"fndef", {"mt", "..."}, "slim", {
|
{"__call", {"fndef", {"mt", "..."}, {}, "slim", {
|
||||||
{"raw", ("local self = setmetatable({}, %s)")\format(base_name)}
|
{"raw", ("local self = setmetatable({}, %s)")\format(base_name)}
|
||||||
{"chain", "mt.__init", {"call", {"self", "..."}}}
|
{"chain", "mt.__init", {"call", {"self", "..."}}}
|
||||||
"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)
|
return self:line(callee_value, actions)
|
||||||
end,
|
end,
|
||||||
fndef = function(self, node)
|
fndef = function(self, node)
|
||||||
local _, args, arrow, block = unpack(node)
|
local _, args, whitelist, arrow, block = unpack(node)
|
||||||
local default_args = { }
|
local default_args = { }
|
||||||
local format_names
|
local format_names
|
||||||
format_names = function(arg)
|
format_names = function(arg)
|
||||||
@ -236,6 +236,9 @@ value_compile = {
|
|||||||
end
|
end
|
||||||
do
|
do
|
||||||
local _with_0 = self:block("function(" .. concat(args, ", ") .. ")")
|
local _with_0 = self:block("function(" .. concat(args, ", ") .. ")")
|
||||||
|
if #whitelist > 0 then
|
||||||
|
_with_0:whitelist_names(whitelist)
|
||||||
|
end
|
||||||
do
|
do
|
||||||
local _item_0 = args
|
local _item_0 = args
|
||||||
for _index_0 = 1, #_item_0 do
|
for _index_0 = 1, #_item_0 do
|
||||||
|
@ -122,7 +122,7 @@ value_compile =
|
|||||||
@line callee_value, actions
|
@line callee_value, actions
|
||||||
|
|
||||||
fndef: (node) =>
|
fndef: (node) =>
|
||||||
_, args, arrow, block = unpack node
|
_, args, whitelist, arrow, block = unpack node
|
||||||
|
|
||||||
default_args = {}
|
default_args = {}
|
||||||
format_names = (arg) ->
|
format_names = (arg) ->
|
||||||
@ -138,6 +138,9 @@ value_compile =
|
|||||||
insert args, 1, "self"
|
insert args, 1, "self"
|
||||||
|
|
||||||
with @block "function("..concat(args, ", ")..")"
|
with @block "function("..concat(args, ", ")..")"
|
||||||
|
if #whitelist > 0
|
||||||
|
\whitelist_names whitelist
|
||||||
|
|
||||||
\put_name name for name in *args
|
\put_name name for name in *args
|
||||||
|
|
||||||
for default in *default_args
|
for default in *default_args
|
||||||
|
@ -389,11 +389,14 @@ local build_grammar = wrap(function()
|
|||||||
KeyValueList = KeyValue * (sym"," * KeyValue)^0,
|
KeyValueList = KeyValue * (sym"," * KeyValue)^0,
|
||||||
KeyValueLine = Cmt(Indent, check_indent) * KeyValueList * sym","^-1,
|
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,
|
FnArgDefList = FnArgDef * (sym"," * FnArgDef)^0,
|
||||||
FnArgDef = Name * (sym"=" * Exp)^-1 / wrap_default_arg,
|
FnArgDef = Name * (sym"=" * Exp)^-1 / wrap_default_arg,
|
||||||
|
|
||||||
FunLit = (FnArgsDef + Ct("")) *
|
FunLit = FnArgsDef *
|
||||||
(sym"->" * Cc"slim" + sym"=>" * Cc"fat") *
|
(sym"->" * Cc"slim" + sym"=>" * Cc"fat") *
|
||||||
(Body + Ct"") / mark"fndef",
|
(Body + Ct"") / mark"fndef",
|
||||||
|
|
||||||
|
28
todo
28
todo
@ -2,7 +2,14 @@
|
|||||||
|
|
||||||
- varargs that get put in a nested generated function aren't valid anymore:
|
- 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"
|
- class expressions, x = class extends Hello do new: => print "hello"
|
||||||
|
|
||||||
@ -16,10 +23,7 @@
|
|||||||
* elseif with value that inserts lines
|
* elseif with value that inserts lines
|
||||||
- need to decompose elif into if inside else
|
- need to decompose elif into if inside else
|
||||||
|
|
||||||
* export keyword, makes it so local is left off when variable is declared
|
* export could also be used like so:
|
||||||
- or copies to global var when local already exists
|
|
||||||
- or used for assignment to assign global var
|
|
||||||
|
|
||||||
|
|
||||||
export a = -> "hello"
|
export a = -> "hello"
|
||||||
|
|
||||||
@ -28,20 +32,13 @@ or
|
|||||||
x = 232
|
x = 232
|
||||||
export x
|
export x
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
export x
|
|
||||||
x = 3434
|
|
||||||
|
|
||||||
|
|
||||||
* allow return anywhere in block
|
* allow return anywhere in block
|
||||||
* upercase constants and capital letter variables should automatically be exported (in the global scope?)
|
* 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 = (...) ->
|
double_args = (...) ->
|
||||||
[x * 2 for x in *{...}]
|
[x * 2 for x in *{...}]
|
||||||
@ -49,4 +46,7 @@ double_args = (...) ->
|
|||||||
|
|
||||||
still some issues with whitespace at end of line
|
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