mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
import statement, and some docs
This commit is contained in:
parent
c70b298b68
commit
06693fbd66
92
docs/index.md
Normal file
92
docs/index.md
Normal file
@ -0,0 +1,92 @@
|
||||
# MoonScript
|
||||
|
||||
MoonScript compiles to Lua
|
||||
|
||||
## Function Literals
|
||||
|
||||
## Table Literals
|
||||
|
||||
## Table Comprehensions
|
||||
|
||||
## Conditionals
|
||||
|
||||
## Import Statement
|
||||
|
||||
Often you want to bring some values from a table into the current scope as
|
||||
local variables by their name. The import statement lets us accomplish this:
|
||||
|
||||
import insert from table
|
||||
|
||||
The multiple names can be given, each separated by a comma:
|
||||
|
||||
import C, Ct, Cmt from lpeg
|
||||
|
||||
Sometimes a function requires that the table be sent in as the first argument
|
||||
(when using the `:` syntax). As a shortcut, we can prefix the name with a `:`
|
||||
to bind it to that table:
|
||||
|
||||
-- some object
|
||||
my_module =
|
||||
state: 100
|
||||
add: (value) =>
|
||||
self.state + value
|
||||
|
||||
import :add from my_module
|
||||
|
||||
print add(22) -- equivalent to calling my_module:get(22)
|
||||
|
||||
## The Using Clause; Controlling Destructive Assignment
|
||||
|
||||
While lexical scoping can be a great help in reducing the complexity of the
|
||||
code we write, things can get unwieldy as the code size increases. Consider
|
||||
the following snippet:
|
||||
|
||||
i = 100
|
||||
|
||||
-- many lines of code...
|
||||
|
||||
my_func = ->
|
||||
i = 10
|
||||
while i > 0
|
||||
print i
|
||||
i -= 1
|
||||
|
||||
my_func()
|
||||
|
||||
print i -- will print 0
|
||||
|
||||
|
||||
In `my_func`, we've overwritten the value of `i` mistakenly. In this example it
|
||||
is quite obvious, but consider a large, or foreign code base where it isn't
|
||||
clear what names have already been declared.
|
||||
|
||||
It would be helpful to say which variables from the enclosing scope we intend
|
||||
on change, in order to prevent us from changing others by accident.
|
||||
|
||||
The `using` keyword lets us do that. `using nil` makes sure that no closed
|
||||
variables are overwritten in assignment. The `using` clause is placed after the
|
||||
argument list in a function, or in place of it if there are no arguments.
|
||||
|
||||
i = 100
|
||||
|
||||
my_func = (using nil) ->
|
||||
i = "hello" -- a new local variable is created here
|
||||
|
||||
my_func()
|
||||
print i -- prints 100, i is unaffected
|
||||
|
||||
|
||||
Multiple names can be separated by commas. Closure values can still be
|
||||
accessed, they just cant be modified:
|
||||
|
||||
tmp = 1213
|
||||
i, k = 100, 50
|
||||
|
||||
my_func = (add using k,i) ->
|
||||
tmp = tmp + add -- a new local tmp is created
|
||||
i += tmp
|
||||
k += tmp
|
||||
|
||||
my_func(22)
|
||||
print i,k -- these have been updated
|
||||
|
@ -21,6 +21,14 @@ function ntype(node)
|
||||
return node[1]
|
||||
end
|
||||
|
||||
-- functions that can be inlined, or called from build in library
|
||||
local moonlib = {
|
||||
bind = function(tbl, name)
|
||||
return table.concat{"moon.bind(", tbl, ".",
|
||||
name, ", ", tbl, ")"}
|
||||
end
|
||||
}
|
||||
|
||||
local compiler_index = {
|
||||
push = function(self) self._scope:push{} end,
|
||||
pop = function(self) self._scope:pop() end,
|
||||
@ -40,8 +48,29 @@ local compiler_index = {
|
||||
self._scope:top()[name] = true
|
||||
end,
|
||||
|
||||
ichar = function(self)
|
||||
return indent_char:rep(self._indent)
|
||||
get_free_name = function(self, basename)
|
||||
basename = basename or "moon"
|
||||
local i = 0
|
||||
local name
|
||||
repeat
|
||||
name = table.concat({"", basename, i}, "_")
|
||||
i = i + 1
|
||||
until not self:has_name(name)
|
||||
|
||||
return name
|
||||
end,
|
||||
|
||||
ichar = function(self, ...)
|
||||
local depths = {...}
|
||||
if #depths == 0 then
|
||||
return indent_char:rep(self._indent)
|
||||
else
|
||||
local indents = {}
|
||||
for _, v in ipairs(depths) do
|
||||
table.insert(indents, indent_char:rep(self._indent+v))
|
||||
end
|
||||
return unpack(indents)
|
||||
end
|
||||
end,
|
||||
|
||||
chain = function(self, node)
|
||||
@ -66,6 +95,52 @@ local compiler_index = {
|
||||
return callee_value..table.concat(actions)
|
||||
end,
|
||||
|
||||
import = function(self, node)
|
||||
local _, names, source = unpack(node)
|
||||
|
||||
local to_bind = {}
|
||||
local final_names = {}
|
||||
for _, name in ipairs(names) do
|
||||
if type(name) == "table" then
|
||||
name = name[2]
|
||||
to_bind[name] = true
|
||||
end
|
||||
table.insert(final_names, name)
|
||||
self:put_name(name)
|
||||
end
|
||||
|
||||
local function get_values(from)
|
||||
local values = {}
|
||||
for _, name in ipairs(final_names) do
|
||||
local v = to_bind[name] and
|
||||
moonlib.bind(from, name) or from.."."..name
|
||||
table.insert(values, v)
|
||||
end
|
||||
return values
|
||||
end
|
||||
|
||||
if type(source) == "string" then
|
||||
local values = get_values(source)
|
||||
return table.concat({"local", table.concat(final_names, ", "),
|
||||
"=", table.concat(values, ", ")}, " ")
|
||||
end
|
||||
|
||||
local outer, inner = self:ichar(0, 1)
|
||||
local tmp_name = self:get_free_name("table")
|
||||
out = {
|
||||
"local "..table.concat(final_names, ", "),
|
||||
outer.."do",
|
||||
inner.."local "..tmp_name.." = "..self:value(source)
|
||||
}
|
||||
|
||||
for i, value in ipairs(get_values(tmp_name)) do
|
||||
table.insert(out, inner..final_names[i].." = "..value)
|
||||
end
|
||||
|
||||
table.insert(out, outer.."end")
|
||||
return table.concat(out, "\n")
|
||||
end,
|
||||
|
||||
fndef = function(self, node)
|
||||
local _, args, block = unpack(node)
|
||||
self:push()
|
||||
|
@ -177,13 +177,19 @@ local build_grammar = wrap(function()
|
||||
File = Block + Ct"",
|
||||
Block = Ct(Line * (Break^1 * Line)^0),
|
||||
Line = Cmt(Indent, check_indent) * Statement + _Space * Comment,
|
||||
Statement = If + While + Exp * Space,
|
||||
Statement = Import + If + While + Exp * Space,
|
||||
|
||||
Body = Break * InBlock + Ct(Statement),
|
||||
|
||||
InBlock = #Cmt(Indent, advance_indent) * Block * OutBlock,
|
||||
OutBlock = Cmt("", pop_indent),
|
||||
|
||||
Import = key"import"* Ct(ImportNameList) * key"from" * Exp / mark"import",
|
||||
ImportName = (Ct(C(sym":") * Name) + Name),
|
||||
ImportNameList = ImportName * (sym"," * ImportName)^0,
|
||||
|
||||
NameList = Name * (sym"," * Name)^0,
|
||||
|
||||
If = key"if" * Exp * key"then"^-1 * Body *
|
||||
((Break * Cmt(Indent, check_indent))^-1 * key"elseif" * Exp * key"then"^-1 * Body / mark"elseif")^0 *
|
||||
((Break * Cmt(Indent, check_indent))^-1 * key"else" * Body / mark"else")^-1 / mark"if",
|
||||
|
22
tests/inputs/import.moon
Normal file
22
tests/inputs/import.moon
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
import hello from yeah
|
||||
import hello, world from table["cool"]
|
||||
|
||||
import a, :b, c from items
|
||||
|
||||
|
||||
import master, :ghost from find "mytable"
|
||||
|
||||
|
||||
a, yumm = 3434, "hello"
|
||||
|
||||
|
||||
_table_0 = 232
|
||||
|
||||
import something from a table
|
||||
|
||||
|
||||
if indent
|
||||
import okay, :well from tables[100]
|
||||
|
30
tests/outputs/import.lua
Normal file
30
tests/outputs/import.lua
Normal file
@ -0,0 +1,30 @@
|
||||
local hello = yeah.hello
|
||||
local hello, world
|
||||
do
|
||||
local _table_0 = table["cool"]
|
||||
hello = _table_0.hello
|
||||
world = _table_0.world
|
||||
end
|
||||
local a, b, c = items.a, moon.bind(items.b, items), items.c
|
||||
local master, ghost
|
||||
do
|
||||
local _table_0 = find("mytable")
|
||||
master = _table_0.master
|
||||
ghost = moon.bind(_table_0.ghost, _table_0)
|
||||
end
|
||||
a = 3434
|
||||
local yumm = "hello"
|
||||
local _table_0 = 232
|
||||
local something
|
||||
do
|
||||
local _table_1 = a(table)
|
||||
something = _table_1.something
|
||||
end
|
||||
if indent then
|
||||
local okay, well
|
||||
do
|
||||
local _table_1 = tables[100]
|
||||
okay = _table_1.okay
|
||||
well = moon.bind(_table_1.well, _table_1)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user