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

317
nomsu.lua
View File

@ -21,141 +21,135 @@ 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
n = "\n",
t = "\t",
b = "\b",
a = "\a",
v = "\v",
f = "\f",
r = "\r"
}
local DIGIT, HEX = R('09'), R('09', 'af', 'AF')
local ESCAPE_CHAR = (P("\\") * S("xX") * C(HEX * HEX)) / function(self)
return string.char(tonumber(self, 16))
end
ESCAPE_CHAR = ESCAPE_CHAR + ((P("\\") * C(DIGIT * (DIGIT ^ -2))) / function(self)
return string.char(tonumber(self))
end)
ESCAPE_CHAR = ESCAPE_CHAR + ((P("\\") * C(S("ntbavfr"))) / STRING_ESCAPES)
local 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"))
local IDENT_CHAR = R("az", "AZ", "09") + P("_") + UTF8_CHAR
local parse
do do
local ctx = { } local _with_0 = { }
local indent_patt = P(function(self, start) _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",
t = "\t",
b = "\b",
a = "\a",
v = "\v",
f = "\f",
r = "\r"
}
local digit, hex = R('09'), R('09', 'af', 'AF')
_with_0.escaped_char = (P("\\") * S("xX") * C(hex * hex)) / function(self)
return string.char(tonumber(self, 16))
end
_with_0.escaped_char = _with_0.escaped_char + ((P("\\") * C(digit * (digit ^ -2))) / function(self)
return string.char(tonumber(self))
end)
_with_0.escaped_char = _with_0.escaped_char + ((P("\\") * C(S("ntbavfr"))) / string_escapes)
_with_0.operator_char = S("'~`!@$^&*-+=|<>?/")
_with_0.operator = _with_0.operator_char ^ 1
_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"))
_with_0.ident_char = R("az", "AZ", "09") + P("_") + _with_0.utf8_char
_with_0.indent = 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, end
operator = OPERATOR_CHAR, local line_no = 1
print = function(src, pos, msg) while (lpeg.userdata.line_starts[line_no + 1] or math.huge) < pos do
return print(msg, pos, repr(src:sub(math.max(0, pos - 16), math.max(0, pos - 1)) .. "|" .. src:sub(pos, pos + 16))) or true line_no = line_no + 1
end, 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")), local prev_line
indented = indent_patt, if line_no > 1 then
nodented = nodent_patt, prev_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no - 1])
dedented = dedent_patt, else
gt_nodented = gt_nodent_patt, prev_line = ""
escape_char = ESCAPE_CHAR, end
error = function(src, pos, err_msg) local err_line = lpeg.userdata.source_code:match("[^\n]*", lpeg.userdata.line_starts[line_no])
if ctx.source_code:sub(pos, pos) == "\n" then local next_line
pos = pos + #ctx.source_code:match("[ \t\n]*", pos) 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"
return error(err_msg)
end
_with_0.FunctionCall = function(start, value, stop)
local stub = concat((function()
local _accum_0 = { }
local _len_0 = 1
for _index_0 = 1, #value do
local t = value[_index_0]
_accum_0[_len_0] = (t.type == "Word" and t.value or "%")
_len_0 = _len_0 + 1
end end
local line_no = 1 return _accum_0
while (ctx.line_starts[line_no + 1] or math.huge) < pos do end)(), " ")
line_no = line_no + 1 local src = lpeg.userdata.source_code:sub(start, stop - 1)
end return {
local prev_line = line_no > 1 and ctx.source_code:match("[^\n]*", ctx.line_starts[line_no - 1]) or "" start = start,
local err_line = ctx.source_code:match("[^\n]*", ctx.line_starts[line_no]) stop = stop,
local next_line = line_no < #ctx.line_starts and ctx.source_code:match("[^\n]*", ctx.line_starts[line_no + 1]) or "" type = "FunctionCall",
local pointer = ("-"):rep(pos - ctx.line_starts[line_no]) .. "^" src = src,
err_msg = (err_msg or "Parse error") .. " in " .. tostring(ctx.filename) .. " on line " .. tostring(line_no) .. ":\n" get_line_no = lpeg.userdata.get_line_no,
err_msg = err_msg .. "\n" .. tostring(prev_line) .. "\n" .. tostring(err_line) .. "\n" .. tostring(pointer) .. "\n" .. tostring(next_line) .. "\n" value = value,
return error(err_msg) stub = stub
end, }
FunctionCall = function(start, value, stop) end
local stub = concat((function() NOMSU_DEFS = _with_0
local _accum_0 = { } end
local _len_0 = 1 setmetatable(NOMSU_DEFS, {
for _index_0 = 1, #value do __index = function(self, key)
local t = value[_index_0] local make_node
_accum_0[_len_0] = (t.type == "Word" and t.value or "%") make_node = function(start, value, stop)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), " ")
local src = ctx.source_code:sub(start, stop - 1)
return { return {
start = start, start = start,
stop = stop, stop = stop,
type = "FunctionCall",
src = src,
get_line_no = ctx.get_line_no,
value = value, value = value,
stub = stub src = lpeg.userdata.source_code:sub(start, stop - 1),
get_line_no = lpeg.userdata.get_line_no,
type = key
} }
end end
} self[key] = make_node
setmetatable(defs, { return make_node
__index = function(self, key) end
local make_node })
make_node = function(start, value, stop) local NOMSU
return { do
start = start,
stop = stop,
value = value,
src = ctx.source_code:sub(start, stop - 1),
get_line_no = ctx.get_line_no,
type = key
}
end
self[key] = make_node
return make_node
end
})
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)
end return error("Attempt to run undefined action: " .. tostring(key), 0)
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