Added scratch folder to .gitignore

This commit is contained in:
Bruce Hill 2018-01-19 17:28:40 -08:00
parent d888b1134a
commit ca07d84b4c
2 changed files with 156 additions and 162 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
lib/*.lua lib/*.lua
scratch/*
.pending-post-commit .pending-post-commit

237
nomsu.lua
View File

@ -21,23 +21,20 @@ do
local _obj_0 = table local _obj_0 = table
insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
end end
if _VERSION == "Lua 5.1" then
local xp = xpcall
local xpcall
xpcall = function(f, errhandler, ...)
local args = {
n = select("#", ...),
...
}
return xp(function(...)
return f(unpack(args, 1, args.n))
end), errhandler
end
end
lpeg.setmaxstack(10000) lpeg.setmaxstack(10000)
local P, R, V, S, Cg, C, Cp, B, Cmt local P, R, V, S, Cg, C, Cp, B, Cmt
P, R, V, S, Cg, C, Cp, B, Cmt = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C, lpeg.Cp, lpeg.B, lpeg.Cmt P, R, V, S, Cg, C, Cp, B, Cmt = lpeg.P, lpeg.R, lpeg.V, lpeg.S, lpeg.Cg, lpeg.C, lpeg.Cp, lpeg.B, lpeg.Cmt
local STRING_ESCAPES = { local NOMSU_DEFS
do
local _with_0 = { }
_with_0.nl = P("\n")
_with_0.ws = S(" \t")
_with_0.tonumber = tonumber
_with_0.print = function(src, pos, msg)
print(msg, pos, repr(src:sub(math.max(0, pos - 16), math.max(0, pos - 1)) .. "|" .. src:sub(pos, pos + 16)))
return true
end
local string_escapes = {
n = "\n", n = "\n",
t = "\t", t = "\t",
b = "\b", b = "\b",
@ -45,78 +42,72 @@ local STRING_ESCAPES = {
v = "\v", v = "\v",
f = "\f", f = "\f",
r = "\r" r = "\r"
} }
local DIGIT, HEX = R('09'), R('09', 'af', 'AF') local digit, hex = R('09'), R('09', 'af', 'AF')
local ESCAPE_CHAR = (P("\\") * S("xX") * C(HEX * HEX)) / function(self) _with_0.escaped_char = (P("\\") * S("xX") * C(hex * hex)) / function(self)
return string.char(tonumber(self, 16)) return string.char(tonumber(self, 16))
end end
ESCAPE_CHAR = ESCAPE_CHAR + ((P("\\") * C(DIGIT * (DIGIT ^ -2))) / function(self) _with_0.escaped_char = _with_0.escaped_char + ((P("\\") * C(digit * (digit ^ -2))) / function(self)
return string.char(tonumber(self)) return string.char(tonumber(self))
end) end)
ESCAPE_CHAR = ESCAPE_CHAR + ((P("\\") * C(S("ntbavfr"))) / STRING_ESCAPES) _with_0.escaped_char = _with_0.escaped_char + ((P("\\") * C(S("ntbavfr"))) / string_escapes)
local OPERATOR_CHAR = S("'~`!@$^&*-+=|<>?/") _with_0.operator_char = S("'~`!@$^&*-+=|<>?/")
local UTF8_CHAR = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191")) _with_0.operator = _with_0.operator_char ^ 1
local IDENT_CHAR = R("az", "AZ", "09") + P("_") + UTF8_CHAR _with_0.utf8_char = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191"))
local parse _with_0.ident_char = R("az", "AZ", "09") + P("_") + _with_0.utf8_char
do _with_0.indent = P(function(self, start)
local ctx = { }
local indent_patt = P(function(self, start)
local spaces = self:match("[ \t]*", start) local spaces = self:match("[ \t]*", start)
if #spaces > ctx.indent_stack[#ctx.indent_stack] then if #spaces > lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] then
insert(ctx.indent_stack, #spaces) insert(lpeg.userdata.indent_stack, #spaces)
return start + #spaces return start + #spaces
end end
end) end)
local dedent_patt = P(function(self, start) _with_0.dedent = P(function(self, start)
local spaces = self:match("[ \t]*", start) local spaces = self:match("[ \t]*", start)
if #spaces < ctx.indent_stack[#ctx.indent_stack] then if #spaces < lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] then
remove(ctx.indent_stack) remove(lpeg.userdata.indent_stack)
return start return start
end end
end) end)
local nodent_patt = P(function(self, start) _with_0.nodent = P(function(self, start)
local spaces = self:match("[ \t]*", start) local spaces = self:match("[ \t]*", start)
if #spaces == ctx.indent_stack[#ctx.indent_stack] then if #spaces == lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] then
return start + #spaces return start + #spaces
end end
end) end)
local gt_nodent_patt = P(function(self, start) _with_0.gt_nodent = P(function(self, start)
local spaces = self:match("[ \t]*", start) local spaces = self:match("[ \t]*", start)
if #spaces >= ctx.indent_stack[#ctx.indent_stack] + 4 then if #spaces >= lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] + 4 then
return start + ctx.indent_stack[#ctx.indent_stack] + 4 return start + lpeg.userdata.indent_stack[#lpeg.userdata.indent_stack] + 4
end end
end) end)
local defs = { _with_0.error = function(src, pos, err_msg)
nl = P("\n"), if lpeg.userdata.source_code:sub(pos, pos) == "\n" then
ws = S(" \t"), pos = pos + #lpeg.userdata.source_code:match("[ \t\n]*", pos)
tonumber = tonumber,
operator = OPERATOR_CHAR,
print = function(src, pos, msg)
return print(msg, pos, repr(src:sub(math.max(0, pos - 16), math.max(0, pos - 1)) .. "|" .. src:sub(pos, pos + 16))) or true
end,
utf8_char = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191")),
indented = indent_patt,
nodented = nodent_patt,
dedented = dedent_patt,
gt_nodented = gt_nodent_patt,
escape_char = ESCAPE_CHAR,
error = function(src, pos, err_msg)
if ctx.source_code:sub(pos, pos) == "\n" then
pos = pos + #ctx.source_code:match("[ \t\n]*", pos)
end end
local line_no = 1 local line_no = 1
while (ctx.line_starts[line_no + 1] or math.huge) < pos do while (lpeg.userdata.line_starts[line_no + 1] or math.huge) < pos do
line_no = line_no + 1 line_no = line_no + 1
end end
local prev_line = line_no > 1 and ctx.source_code:match("[^\n]*", ctx.line_starts[line_no - 1]) or "" local prev_line
local err_line = ctx.source_code:match("[^\n]*", ctx.line_starts[line_no]) if line_no > 1 then
local next_line = line_no < #ctx.line_starts and ctx.source_code:match("[^\n]*", ctx.line_starts[line_no + 1]) or "" prev_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no - 1])
local pointer = ("-"):rep(pos - ctx.line_starts[line_no]) .. "^" else
err_msg = (err_msg or "Parse error") .. " in " .. tostring(ctx.filename) .. " on line " .. tostring(line_no) .. ":\n" prev_line = ""
end
local err_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no])
local next_line
if line_no < #lpeg.userdata.line_starts then
next_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no + 1])
else
next_line = ""
end
local pointer = ("-"):rep(pos - lpeg.userdata.line_starts[line_no]) .. "^"
err_msg = (err_msg or "Parse error") .. " in " .. tostring(lpeg.userdata.filename) .. " on line " .. tostring(line_no) .. ":\n"
err_msg = err_msg .. "\n" .. tostring(prev_line) .. "\n" .. tostring(err_line) .. "\n" .. tostring(pointer) .. "\n" .. tostring(next_line) .. "\n" err_msg = err_msg .. "\n" .. tostring(prev_line) .. "\n" .. tostring(err_line) .. "\n" .. tostring(pointer) .. "\n" .. tostring(next_line) .. "\n"
return error(err_msg) return error(err_msg)
end, end
FunctionCall = function(start, value, stop) _with_0.FunctionCall = function(start, value, stop)
local stub = concat((function() local stub = concat((function()
local _accum_0 = { } local _accum_0 = { }
local _len_0 = 1 local _len_0 = 1
@ -127,19 +118,20 @@ do
end end
return _accum_0 return _accum_0
end)(), " ") end)(), " ")
local src = ctx.source_code:sub(start, stop - 1) local src = lpeg.userdata.source_code:sub(start, stop - 1)
return { return {
start = start, start = start,
stop = stop, stop = stop,
type = "FunctionCall", type = "FunctionCall",
src = src, src = src,
get_line_no = ctx.get_line_no, get_line_no = lpeg.userdata.get_line_no,
value = value, value = value,
stub = stub stub = stub
} }
end end
} NOMSU_DEFS = _with_0
setmetatable(defs, { end
setmetatable(NOMSU_DEFS, {
__index = function(self, key) __index = function(self, key)
local make_node local make_node
make_node = function(start, value, stop) make_node = function(start, value, stop)
@ -147,15 +139,17 @@ do
start = start, start = start,
stop = stop, stop = stop,
value = value, value = value,
src = ctx.source_code:sub(start, stop - 1), src = lpeg.userdata.source_code:sub(start, stop - 1),
get_line_no = ctx.get_line_no, get_line_no = lpeg.userdata.get_line_no,
type = key type = key
} }
end end
self[key] = make_node self[key] = make_node
return make_node return make_node
end end
}) })
local NOMSU
do
local peg_tidier = re.compile([[ file <- {~ %nl* (def/comment) (%nl+ (def/comment))* %nl* ~} local peg_tidier = re.compile([[ file <- {~ %nl* (def/comment) (%nl+ (def/comment))* %nl* ~}
def <- anon_def / captured_def def <- anon_def / captured_def
anon_def <- ({ident} (" "*) ":" anon_def <- ({ident} (" "*) ":"
@ -165,33 +159,8 @@ do
ident <- [a-zA-Z_][a-zA-Z0-9_]* ident <- [a-zA-Z_][a-zA-Z0-9_]*
comment <- "--" [^%nl]* comment <- "--" [^%nl]*
]]) ]])
local nomsu = peg_tidier:match(io.open("nomsu.peg"):read("*a")) local nomsu_peg = peg_tidier:match(io.open("nomsu.peg"):read("*a"))
nomsu = re.compile(nomsu, defs) NOMSU = re.compile(nomsu_peg, NOMSU_DEFS)
parse = function(source_code, filename)
local _ctx = {
source_code = source_code,
filename = filename,
indent_stack = {
0
}
}
_ctx.line_starts = re.compile("lines <- {| line ('\n' line)* |} line <- {} [^\n]*"):match(source_code)
_ctx.get_line_no = function(self)
if not (self._line_no) then
local line_no = 1
while (_ctx.line_starts[line_no + 1] or math.huge) < self.start do
line_no = line_no + 1
end
self._line_no = tostring(_ctx.filename) .. ":" .. tostring(line_no)
end
return self._line_no
end
local old_ctx = ctx
ctx = _ctx
local tree = nomsu:match(source_code)
ctx = old_ctx
return tree
end
end end
local NomsuCompiler local NomsuCompiler
do do
@ -385,14 +354,39 @@ do
end end
return code:gsub("\n", "\n" .. (" "):rep(levels)) return code:gsub("\n", "\n" .. (" "):rep(levels))
end, end,
parse = function(self, str, filename) parse = function(self, nomsu_code, filename)
assert(type(filename) == "string", "Bad filename type: " .. tostring(type(filename))) assert(type(filename) == "string", "Bad filename type: " .. tostring(type(filename)))
if self.debug then if self.debug then
self:writeln(tostring(colored.bright("PARSING:")) .. "\n" .. tostring(colored.yellow(str))) self:writeln(tostring(colored.bright("PARSING:")) .. "\n" .. tostring(colored.yellow(nomsu_code)))
end end
str = str:gsub("\r", "") nomsu_code = nomsu_code:gsub("\r", "")
local tree = parse(str, filename) local userdata
assert(tree, "In file " .. tostring(colored.blue(filename)) .. " failed to parse:\n" .. tostring(colored.onyellow(colored.black(str)))) do
local _with_0 = {
source_code = nomsu_code,
filename = filename,
indent_stack = {
0
}
}
_with_0.line_starts = re.compile("lines <- {| line ('\n' line)* |} line <- {} [^\n]*"):match(nomsu_code)
_with_0.get_line_no = function(self)
if not (self._line_no) then
local line_no = 1
while (_with_0.line_starts[line_no + 1] or math.huge) < self.start do
line_no = line_no + 1
end
self._line_no = tostring(_with_0.filename) .. ":" .. tostring(line_no)
end
return self._line_no
end
userdata = _with_0
end
local old_userdata
old_userdata, lpeg.userdata = lpeg.userdata, userdata
local tree = NOMSU:match(nomsu_code)
lpeg.userdata = old_userdata
assert(tree, "In file " .. tostring(colored.blue(filename)) .. " failed to parse:\n" .. tostring(colored.onyellow(colored.black(nomsu_code))))
if self.debug then if self.debug then
self:writeln("PARSE TREE:") self:writeln("PARSE TREE:")
self:print_tree(tree, " ") self:print_tree(tree, " ")
@ -518,7 +512,7 @@ do
end end
local is_operator local is_operator
is_operator = function(tok) is_operator = function(tok)
return tok and tok.type == "Word" and OPERATOR_CHAR:match(tok.value) return tok and tok.type == "Word" and NOMSU_DEFS.operator:match(tok.value)
end end
local inline_expression, noeol_expression, expression local inline_expression, noeol_expression, expression
inline_expression = function(tok) inline_expression = function(tok)
@ -930,7 +924,7 @@ do
} }
elseif "FunctionCall" == _exp_0 then elseif "FunctionCall" == _exp_0 then
insert(self.compilestack, tree) insert(self.compilestack, tree)
local fn = self.environment.ACTIONS[tree.stub] local fn = rawget(self.environment.ACTIONS, tree.stub)
local metadata = self.environment.ACTION_METADATA[fn] local metadata = self.environment.ACTION_METADATA[fn]
if metadata and metadata.compile_time then if metadata and metadata.compile_time then
local args local args
@ -1397,7 +1391,7 @@ do
} }
_base_0.__index = _base_0 _base_0.__index = _base_0
_class_0 = setmetatable({ _class_0 = setmetatable({
__init = function(self, parent) __init = function(self)
self.write = function(self, ...) self.write = function(self, ...)
return io.write(...) return io.write(...)
end end
@ -1412,14 +1406,8 @@ do
return id return id
end end
}) })
if parent then
error("Not implemented")
end
self.compilestack = { } self.compilestack = { }
self.debug = false self.debug = false
self.action_metadata = setmetatable({ }, {
__mode = "k"
})
self.environment = { self.environment = {
nomsu = self, nomsu = self,
repr = repr, repr = repr,
@ -1427,9 +1415,6 @@ do
utils = utils, utils = utils,
lpeg = lpeg, lpeg = lpeg,
re = re, re = re,
ACTIONS = { },
ACTION_METADATA = self.action_metadata,
LOADED = { },
next = next, next = next,
unpack = unpack, unpack = unpack,
setmetatable = setmetatable, setmetatable = setmetatable,
@ -1467,9 +1452,17 @@ do
load = load, load = load,
ipairs = ipairs ipairs = ipairs
} }
if not parent then self.environment.ACTIONS = setmetatable({ }, {
return self:initialize_core() __index = function(self, key)
return error("Attempt to run undefined action: " .. tostring(key), 0)
end end
})
self.action_metadata = setmetatable({ }, {
__mode = "k"
})
self.environment.ACTION_METADATA = self.action_metadata
self.environment.LOADED = { }
return self:initialize_core()
end, end,
__base = _base_0, __base = _base_0,
__name = "NomsuCompiler" __name = "NomsuCompiler"
@ -1486,7 +1479,7 @@ do
self.def_number = 0 self.def_number = 0
self.math_patt = re.compile([[ "%" (" " [*/^+-] " %")+ ]]) self.math_patt = re.compile([[ "%" (" " [*/^+-] " %")+ ]])
self.unescape_string = function(self, str) self.unescape_string = function(self, str)
return Cs(((P("\\\\") / "\\") + (P("\\\"") / '"') + ESCAPE_CHAR + P(1)) ^ 0):match(str) return Cs(((P("\\\\") / "\\") + (P("\\\"") / '"') + NOMSU_DEFS.escaped_char + P(1)) ^ 0):match(str)
end end
self.comma_separated_items = function(self, open, items, close) self.comma_separated_items = function(self, open, items, close)
local bits = { local bits = {
@ -1508,8 +1501,8 @@ do
return concat(bits) return concat(bits)
end end
self.stub_patt = re.compile("{|(' '+ / '\n..' / {'%' %id*} / {%id+} / {%op})*|}", { self.stub_patt = re.compile("{|(' '+ / '\n..' / {'%' %id*} / {%id+} / {%op})*|}", {
id = IDENT_CHAR, id = NOMSU_DEFS.ident_char,
op = OPERATOR_CHAR op = NOMSU_DEFS.operator
}) })
NomsuCompiler = _class_0 NomsuCompiler = _class_0
end end
@ -1628,15 +1621,15 @@ if arg then
name = "<tail call>" name = "<tail call>"
end end
if calling_fn.short_src == "./nomsu.moon" then if calling_fn.short_src == "./nomsu.moon" then
local char = line_table[calling_fn.linedefined - 2] local char = line_table[calling_fn.currentline]
local line_num = 3 local line_num = 1
for _ in nomsu_source:sub(1, char):gmatch("\n") do for _ in nomsu_source:sub(1, char):gmatch("\n") do
line_num = line_num + 1 line_num = line_num + 1
end end
line = colored.cyan(tostring(calling_fn.short_src) .. ":" .. tostring(line_num)) line = colored.cyan(tostring(calling_fn.short_src) .. ":" .. tostring(line_num))
name = colored.bright(colored.cyan(name or "???")) name = colored.bright(colored.cyan(name or "???"))
else else
line = colored.blue(tostring(calling_fn.short_src) .. ":" .. tostring(calling_fn.linedefined)) line = colored.blue(tostring(calling_fn.short_src) .. ":" .. tostring(calling_fn.currentline))
name = colored.bright(colored.blue(name or "???")) name = colored.bright(colored.blue(name or "???"))
end end
end end