added using keyword in functions, type accessors in compiler

This commit is contained in:
leaf corcoran 2011-08-10 21:16:41 -07:00
parent 13747aa955
commit 2fbbef9c44
11 changed files with 149 additions and 52 deletions

View File

@ -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",

View File

@ -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

View File

@ -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]

View File

@ -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",
{
{

View File

@ -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"

View 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

View 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
}

View File

@ -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

View File

@ -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

View File

@ -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",

30
todo
View File

@ -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 = (...) ->
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 { }