From 2fbbef9c44716bbb60b3151bbc18c0c104b3c9df Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Wed, 10 Aug 2011 21:16:41 -0700 Subject: [PATCH] added using keyword in functions, type accessors in compiler --- moonscript-dev-1.rockspec | 1 + moonscript/compile.lua | 25 ++++++++++---------- moonscript/compile.moon | 17 +++++++------- moonscript/compile/line.lua | 13 +++++++---- moonscript/compile/line.moon | 14 ++++++----- moonscript/compile/types.lua | 44 +++++++++++++++++++++++++++++++++++ moonscript/compile/types.moon | 38 ++++++++++++++++++++++++++++++ moonscript/compile/value.lua | 5 +++- moonscript/compile/value.moon | 5 +++- moonscript/parse.lua | 7 ++++-- todo | 32 ++++++++++++------------- 11 files changed, 149 insertions(+), 52 deletions(-) create mode 100644 moonscript/compile/types.lua create mode 100644 moonscript/compile/types.moon diff --git a/moonscript-dev-1.rockspec b/moonscript-dev-1.rockspec index 8a7806b..381d8d1 100644 --- a/moonscript-dev-1.rockspec +++ b/moonscript-dev-1.rockspec @@ -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", diff --git a/moonscript/compile.lua b/moonscript/compile.lua index e798622..90e1b4b 100644 --- a/moonscript/compile.lua +++ b/moonscript/compile.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 diff --git a/moonscript/compile.moon b/moonscript/compile.moon index 29a96ce..b72772d 100644 --- a/moonscript/compile.moon +++ b/moonscript/compile.moon @@ -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] diff --git a/moonscript/compile/line.lua b/moonscript/compile/line.lua index 8389050..5262968 100644 --- a/moonscript/compile/line.lua +++ b/moonscript/compile/line.lua @@ -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", { { diff --git a/moonscript/compile/line.moon b/moonscript/compile/line.moon index f15ef13..d2238f0 100644 --- a/moonscript/compile/line.moon +++ b/moonscript/compile/line.moon @@ -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" diff --git a/moonscript/compile/types.lua b/moonscript/compile/types.lua new file mode 100644 index 0000000..b9fb9f1 --- /dev/null +++ b/moonscript/compile/types.lua @@ -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 diff --git a/moonscript/compile/types.moon b/moonscript/compile/types.moon new file mode 100644 index 0000000..3637244 --- /dev/null +++ b/moonscript/compile/types.moon @@ -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 + } + diff --git a/moonscript/compile/value.lua b/moonscript/compile/value.lua index 7176ec9..5a8f1f1 100644 --- a/moonscript/compile/value.lua +++ b/moonscript/compile/value.lua @@ -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 diff --git a/moonscript/compile/value.moon b/moonscript/compile/value.moon index 82e181c..245b423 100644 --- a/moonscript/compile/value.moon +++ b/moonscript/compile/value.moon @@ -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 diff --git a/moonscript/parse.lua b/moonscript/parse.lua index ac00549..7124612 100644 --- a/moonscript/parse.lua +++ b/moonscript/parse.lua @@ -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", diff --git a/todo b/todo index 532cd75..64e944c 100644 --- a/todo +++ b/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 { } +