mirror of
https://github.com/leafo/moonscript.git
synced 2025-01-09 00:04:22 +00:00
continue support in foreach loop
This commit is contained in:
parent
9d6467977a
commit
0d5abf6cc4
@ -134,6 +134,17 @@ Block = (function()
|
||||
get = function(self, name)
|
||||
return self._state[name]
|
||||
end,
|
||||
listen = function(self, name, fn)
|
||||
self._listeners[name] = fn
|
||||
end,
|
||||
send = function(self, name, ...)
|
||||
do
|
||||
local fn = self._listeners[name]
|
||||
if fn then
|
||||
return fn(self, ...)
|
||||
end
|
||||
end
|
||||
end,
|
||||
declare = function(self, names)
|
||||
local undeclared = (function()
|
||||
local _accum_0 = { }
|
||||
@ -173,11 +184,15 @@ Block = (function()
|
||||
whitelist_names = function(self, names)
|
||||
self._name_whitelist = Set(names)
|
||||
end,
|
||||
put_name = function(self, name)
|
||||
put_name = function(self, name, ...)
|
||||
value = ...
|
||||
if select("#", ...) == 0 then
|
||||
value = true
|
||||
end
|
||||
if util.moon.type(name) == NameProxy then
|
||||
name = name:get_name(self)
|
||||
end
|
||||
self._names[name] = true
|
||||
self._names[name] = value
|
||||
end,
|
||||
has_name = function(self, name, skip_exports)
|
||||
if not skip_exports then
|
||||
@ -415,6 +430,14 @@ Block = (function()
|
||||
self:stm(stm)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
splice = function(self, fn)
|
||||
local lines = {
|
||||
"lines",
|
||||
self._lines
|
||||
}
|
||||
self._lines = { }
|
||||
return self:stms(fn(lines))
|
||||
end
|
||||
}
|
||||
_base_0.__index = _base_0
|
||||
@ -429,6 +452,7 @@ Block = (function()
|
||||
self._posmap = { }
|
||||
self._names = { }
|
||||
self._state = { }
|
||||
self._listeners = { }
|
||||
do
|
||||
local _with_0 = transform
|
||||
self.transform = {
|
||||
@ -439,9 +463,12 @@ Block = (function()
|
||||
if self.parent then
|
||||
self.root = self.parent.root
|
||||
self.indent = self.parent.indent + 1
|
||||
return setmetatable(self._state, {
|
||||
setmetatable(self._state, {
|
||||
__index = self.parent._state
|
||||
})
|
||||
return setmetatable(self._listeners, {
|
||||
__index = self.parent._listeners
|
||||
})
|
||||
else
|
||||
self.indent = 0
|
||||
end
|
||||
|
@ -70,6 +70,7 @@ class Block
|
||||
@_posmap = {}
|
||||
@_names = {}
|
||||
@_state = {}
|
||||
@_listeners = {}
|
||||
|
||||
with transform
|
||||
@transform = {
|
||||
@ -81,6 +82,7 @@ class Block
|
||||
@root = @parent.root
|
||||
@indent = @parent.indent + 1
|
||||
setmetatable @_state, { __index: @parent._state }
|
||||
setmetatable @_listeners, { __index: @parent._listeners }
|
||||
else
|
||||
@indent = 0
|
||||
|
||||
@ -98,6 +100,13 @@ class Block
|
||||
get: (name) =>
|
||||
@_state[name]
|
||||
|
||||
listen: (name, fn) =>
|
||||
@_listeners[name] = fn
|
||||
|
||||
send: (name, ...) =>
|
||||
if fn = @_listeners[name]
|
||||
fn self, ...
|
||||
|
||||
declare: (names) =>
|
||||
undeclared = for name in *names
|
||||
is_local = false
|
||||
@ -116,9 +125,12 @@ class Block
|
||||
whitelist_names: (names) =>
|
||||
@_name_whitelist = Set names
|
||||
|
||||
put_name: (name) =>
|
||||
put_name: (name, ...) =>
|
||||
value = ...
|
||||
value = true if select("#", ...) == 0
|
||||
|
||||
name = name\get_name self if util.moon.type(name) == NameProxy
|
||||
@_names[name] = true
|
||||
@_names[name] = value
|
||||
|
||||
has_name: (name, skip_exports) =>
|
||||
if not skip_exports
|
||||
@ -282,6 +294,11 @@ class Block
|
||||
@stm stm for stm in *stms
|
||||
nil
|
||||
|
||||
splice: (fn) =>
|
||||
lines = {"lines", @_lines}
|
||||
@_lines = {}
|
||||
@stms fn lines
|
||||
|
||||
class RootBlock extends Block
|
||||
new: (...) =>
|
||||
@root = self
|
||||
|
@ -2,6 +2,8 @@ module("moonscript.compile", package.seeall)
|
||||
local util = require("moonscript.util")
|
||||
require("moonscript.compile.format")
|
||||
local dump = require("moonscript.dump")
|
||||
local transform = require("moonscript.transform")
|
||||
local NameProxy = transform.NameProxy
|
||||
local reversed = util.reversed
|
||||
local ntype
|
||||
do
|
||||
@ -11,8 +13,14 @@ end
|
||||
local concat, insert = table.concat, table.insert
|
||||
line_compile = {
|
||||
raw = function(self, node)
|
||||
local _, text = unpack(node)
|
||||
return self:add(text)
|
||||
return self:add(node[2])
|
||||
end,
|
||||
lines = function(self, node)
|
||||
local _list_0 = node[2]
|
||||
for _index_0 = 1, #_list_0 do
|
||||
local line = _list_0[_index_0]
|
||||
self:add(line)
|
||||
end
|
||||
end,
|
||||
declare = function(self, node)
|
||||
local names = node[2]
|
||||
@ -142,6 +150,14 @@ line_compile = {
|
||||
end
|
||||
return root
|
||||
end,
|
||||
["repeat"] = function(self, node)
|
||||
local cond, block = unpack(node, 2)
|
||||
do
|
||||
local _with_0 = self:block("repeat", self:line("until ", self:value(cond)))
|
||||
_with_0:stms(block)
|
||||
return _with_0
|
||||
end
|
||||
end,
|
||||
["while"] = function(self, node)
|
||||
local _, cond, block = unpack(node)
|
||||
local out
|
||||
@ -215,12 +231,66 @@ line_compile = {
|
||||
_with_0:append(" do")
|
||||
loop = _with_0
|
||||
end
|
||||
local continue_name = nil
|
||||
local out
|
||||
do
|
||||
local _with_0 = self:block(loop)
|
||||
_with_0:listen("continue", function()
|
||||
if not (continue_name) then
|
||||
continue_name = NameProxy("continue")
|
||||
_with_0:put_name(continue_name)
|
||||
end
|
||||
return continue_name
|
||||
end)
|
||||
_with_0:declare(names)
|
||||
_with_0:stms(block)
|
||||
return _with_0
|
||||
out = _with_0
|
||||
end
|
||||
if continue_name then
|
||||
out:put_name(continue_name, nil)
|
||||
out:splice(function(lines)
|
||||
return {
|
||||
{
|
||||
"assign",
|
||||
{
|
||||
continue_name
|
||||
},
|
||||
{
|
||||
"false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"repeat",
|
||||
"true",
|
||||
{
|
||||
lines,
|
||||
{
|
||||
"assign",
|
||||
{
|
||||
continue_name
|
||||
},
|
||||
{
|
||||
"true"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if",
|
||||
{
|
||||
"not",
|
||||
continue_name
|
||||
},
|
||||
{
|
||||
{
|
||||
"break"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end)
|
||||
end
|
||||
return out
|
||||
end,
|
||||
export = function(self, node)
|
||||
local _, names = unpack(node)
|
||||
|
@ -4,7 +4,9 @@ util = require "moonscript.util"
|
||||
|
||||
require "moonscript.compile.format"
|
||||
dump = require "moonscript.dump"
|
||||
transform = require "moonscript.transform"
|
||||
|
||||
import NameProxy from transform
|
||||
import reversed from util
|
||||
import ntype from require "moonscript.types"
|
||||
import concat, insert from table
|
||||
@ -12,9 +14,11 @@ import concat, insert from table
|
||||
export line_compile
|
||||
|
||||
line_compile =
|
||||
raw: (node) =>
|
||||
_, text = unpack node
|
||||
@add text
|
||||
raw: (node) => @add node[2]
|
||||
|
||||
lines: (node) =>
|
||||
for line in *node[2]
|
||||
@add line
|
||||
|
||||
declare: (node) =>
|
||||
names = node[2]
|
||||
@ -82,6 +86,11 @@ line_compile =
|
||||
add_clause cond for cond in *node[4,]
|
||||
root
|
||||
|
||||
repeat: (node) =>
|
||||
cond, block = unpack node, 2
|
||||
with @block "repeat", @line "until ", @value cond
|
||||
\stms block
|
||||
|
||||
while: (node) =>
|
||||
_, cond, block = unpack node
|
||||
|
||||
@ -113,10 +122,33 @@ line_compile =
|
||||
\append_list [@value exp for exp in *exps], ","
|
||||
\append " do"
|
||||
|
||||
with @block loop
|
||||
continue_name = nil
|
||||
out = with @block loop
|
||||
\listen "continue", ->
|
||||
unless continue_name
|
||||
continue_name = NameProxy"continue"
|
||||
\put_name continue_name
|
||||
continue_name
|
||||
|
||||
\declare names
|
||||
\stms block
|
||||
|
||||
-- todo: figure out how to put this in the transformer
|
||||
if continue_name
|
||||
out\put_name continue_name, nil
|
||||
out\splice (lines) -> {
|
||||
{"assign", {continue_name}, {"false"}}
|
||||
{"repeat", "true", {
|
||||
lines
|
||||
{"assign", {continue_name}, {"true"}}
|
||||
}}
|
||||
{"if", {"not", continue_name}, {
|
||||
{"break"}
|
||||
}}
|
||||
}
|
||||
|
||||
out
|
||||
|
||||
export: (node) =>
|
||||
_, names = unpack node
|
||||
if type(names) == "string"
|
||||
|
@ -368,7 +368,7 @@ local build_grammar = wrap_env(function()
|
||||
|
||||
NameList = Name * (sym"," * Name)^0,
|
||||
|
||||
BreakLoop = Ct(key"break"/trim),
|
||||
BreakLoop = Ct(key"break"/trim) + Ct(key"continue"/trim),
|
||||
|
||||
Return = key"return" * (ExpListLow/mark"explist" + C"") / mark"return",
|
||||
|
||||
|
@ -414,6 +414,18 @@ Statement = Transformer({
|
||||
end
|
||||
return transformed or node
|
||||
end,
|
||||
continue = function(self, node)
|
||||
local continue_name = self:send("continue")
|
||||
if not (continue_name) then
|
||||
error("continue must be inside of a loop")
|
||||
end
|
||||
return build.group({
|
||||
build.assign_one(continue_name, "true"),
|
||||
{
|
||||
"break"
|
||||
}
|
||||
})
|
||||
end,
|
||||
export = function(self, node)
|
||||
if #node > 2 then
|
||||
if node[2] == "class" then
|
||||
|
@ -181,6 +181,13 @@ Statement = Transformer {
|
||||
|
||||
transformed or node
|
||||
|
||||
continue: (node) =>
|
||||
continue_name = @send"continue"
|
||||
error "continue must be inside of a loop" unless continue_name
|
||||
build.group {
|
||||
build.assign_one continue_name, "true"
|
||||
{"break"}
|
||||
}
|
||||
|
||||
export: (node) =>
|
||||
-- assign values if they are included
|
||||
|
Loading…
Reference in New Issue
Block a user