import statement, and some docs

This commit is contained in:
leaf corcoran 2011-05-23 22:43:40 -07:00
parent c70b298b68
commit 06693fbd66
5 changed files with 228 additions and 3 deletions

92
docs/index.md Normal file
View 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

View File

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

View File

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