Optimizations and cleanup. Build script now fails on first error and

uses the precompiled versions it has just compiled.
This commit is contained in:
Bruce Hill 2018-06-04 20:41:20 -07:00
parent 563e415e07
commit 83183122f1
8 changed files with 72 additions and 156 deletions

View File

@ -11,16 +11,6 @@ Source = immutable({
"stop"
}, {
name = "Source",
__new = function(self, filename, start, stop)
assert(type(filename) == 'string')
if not start then
start, stop = 1, #FILE_CACHE[filename]
end
if stop and start > stop + 1 then
error("Invalid range: " .. tostring(start) .. ", " .. tostring(stop))
end
return filename, start, stop
end,
from_string = function(self, str)
local filename, start, stop = str:match("^@(.-)%[(%d+):(%d+)%]$")
if not (filename) then
@ -60,44 +50,6 @@ Source = immutable({
end
end
return Source(self.filename, self.start + offset, self.stop)
end,
sub = function(self, start, stop)
start = start or 1
assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported")
if not self.stop then
assert(not stop, "cannot subscript non-range with range")
return Source(self.filename, self.start + start - 1)
else
stop = stop or self.stop
return Source(self.filename, self.start + start - 1, self.start + stop - 1)
end
end,
get_text = function(self)
return FILE_CACHE[self.filename]:sub(self.start, self.stop)
end,
get_line_number = function(self)
local src = FILE_CACHE[self.filename]
local line_starts = LINE_STARTS[src]
local start_line = 1
while (line_starts[start_line + 1] or math.huge) <= self.start do
start_line = start_line + 1
end
local stop_line = start_line
while (line_starts[stop_line + 1] or math.huge) <= self.stop do
stop_line = stop_line + 1
end
return start_line, stop_line
end,
get_line = function(self)
return tostring(self.filename) .. ":" .. tostring(self:get_line_number())
end,
get_line_range = function(self)
local start_line, stop_line = self:get_line_number()
if stop_line == start_line then
return tostring(self.filename) .. ":" .. tostring(start_line)
else
return tostring(self.filename) .. ":" .. tostring(start_line) .. "-" .. tostring(stop_line)
end
end
})
local Code

View File

@ -5,12 +5,6 @@ export LINE_STARTS
Source = immutable {"filename","start","stop"}, {
name:"Source"
__new: (filename, start, stop)=>
assert(type(filename) == 'string')
if not start
start, stop = 1, #FILE_CACHE[filename]
if stop and start > stop+1 then error("Invalid range: #{start}, #{stop}")
return filename, start, stop
from_string: (str)=>
filename,start,stop = str\match("^@(.-)%[(%d+):(%d+)%]$")
unless filename
@ -36,34 +30,6 @@ Source = immutable {"filename","start","stop"}, {
offset, self = self, offset
else if type(offset) != 'number' then error("Cannot add Source and #{type(offset)}")
return Source(@filename, @start+offset, @stop)
sub: (start, stop)=>
start or= 1
assert(start > 0 and (stop == nil or stop > 0), "Negative subscripts not supported")
if not @stop
assert(not stop, "cannot subscript non-range with range")
return Source(@filename, @start + start - 1)
else
stop or= @stop
return Source(@filename, @start + start - 1, @start + stop - 1)
get_text: =>
FILE_CACHE[@filename]\sub(@start,@stop)
get_line_number: =>
-- TODO: do a binary search if this is actually slow, which I doubt
src = FILE_CACHE[@filename]
line_starts = LINE_STARTS[src]
start_line = 1
while (line_starts[start_line+1] or math.huge) <= @start
start_line += 1
stop_line = start_line
while (line_starts[stop_line+1] or math.huge) <= @stop
stop_line += 1
return start_line, stop_line
get_line: => "#{@filename}:#{@get_line_number!}"
get_line_range: =>
start_line, stop_line = @get_line_number!
return if stop_line == start_line
"#{@filename}:#{start_line}"
else "#{@filename}:#{start_line}-#{stop_line}"
}
class Code

View File

@ -1,14 +1,16 @@
#!/bin/sh
# This file is a script that converts the .nom files in lib/ into slightly more optimized
# precompiled versions that are only lua> ".." and =lua ".." bits which are faster to load.
set -e
moonc *.moon
rm -f core/*.lua lib/*.lua
for file in core/*.nom; do
printf "Compiling $file ..."
./nomsu.moon -o "core/$(basename $file .nom).lua" $file
lua ./nomsu.lua -O -o "core/$(basename $file .nom).lua" $file
echo "done."
done
for file in lib/*.nom; do
printf "Compiling $file ..."
./nomsu.moon -o "lib/$(basename $file .nom).lua" $file
lua ./nomsu.lua -O -o "lib/$(basename $file .nom).lua" $file
echo "done."
done

View File

@ -172,5 +172,3 @@ immediately
(% in %seen) <- (yes)
return %unique
# TODO: maybe make a generator/coroutine?

View File

@ -211,7 +211,6 @@ immediately
error(\(repr %assumption), 0);
end
# TODO: factor this out and replace with "unless %condition: barf %message"
compile [assume %condition or barf %message] to
Lua ".."
if not \(%condition as lua expr) then

View File

@ -22,7 +22,6 @@ immediately
compile [%x > %y] to: Lua value "(\(%x as lua expr) > \(%y as lua expr))"
compile [%x <= %y] to: Lua value "(\(%x as lua expr) <= \(%y as lua expr))"
compile [%x >= %y] to: Lua value "(\(%x as lua expr) >= \(%y as lua expr))"
# TODO: optimize case of [%x,%y] = [1,2]
compile [%a is %b, %a = %b, %a == %b] to
lua> ".."
local safe = {Text=true, Number=true}

View File

@ -132,6 +132,20 @@ LINE_STARTS = setmetatable({ }, {
return line_starts
end
})
local pos_to_line
pos_to_line = function(str, pos)
local line_starts = LINE_STARTS[str]
local lo, hi = 1, #line_starts
while lo <= hi do
local mid = math.floor((lo + hi) / 2)
if line_starts[mid] > pos then
hi = mid - 1
else
lo = mid + 1
end
end
return hi
end
do
local STRING_METATABLE = getmetatable("")
STRING_METATABLE.__add = function(self, other)
@ -204,13 +218,13 @@ do
return #src + 1
end
local err_pos = start_pos
local text_loc = userdata.source:sub(err_pos, err_pos)
local line_no = text_loc:get_line_number()
src = FILE_CACHE[text_loc.filename]
local prev_line = line_no == 1 and "" or src:sub(LINE_STARTS[src][line_no - 1] or 1, LINE_STARTS[src][line_no] - 2)
local err_line = src:sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no + 1] or 0) - 2)
local next_line = src:sub(LINE_STARTS[src][line_no + 1] or -1, (LINE_STARTS[src][line_no + 2] or 0) - 2)
local i = err_pos - LINE_STARTS[src][line_no]
local line_no = pos_to_line(src, err_pos)
src = FILE_CACHE[userdata.source.filename]
local line_starts = LINE_STARTS[src]
local prev_line = line_no == 1 and "" or src:sub(line_starts[line_no - 1] or 1, line_starts[line_no] - 2)
local err_line = src:sub(line_starts[line_no], (line_starts[line_no + 1] or 0) - 2)
local next_line = src:sub(line_starts[line_no + 1] or -1, (line_starts[line_no + 2] or 0) - 2)
local i = err_pos - line_starts[line_no]
local pointer = ("-"):rep(i) .. "^"
err_msg = colored.bright(colored.yellow(colored.onred((err_msg or "Parse error") .. " at " .. tostring(userdata.source.filename) .. ":" .. tostring(line_no) .. ":")))
if #prev_line > 0 then
@ -230,7 +244,11 @@ setmetatable(NOMSU_DEFS, {
__index = function(self, key)
local make_node
make_node = function(start, value, stop, userdata)
local source = userdata.source:sub(start, stop - 1)
local source
do
local _with_0 = userdata.source
source = Source(_with_0.filename, _with_0.start + start - 1, _with_0.start + stop - 1)
end
local tree
if Types[key].is_multi then
tree = Types[key](source, unpack(value))
@ -391,13 +409,13 @@ do
insert(_running_files, filename)
if filename:match("%.lua$") then
local file = assert(FILE_CACHE[filename], "Could not find file: " .. tostring(filename))
ret = self:run_lua(Lua(Source(filename), file))
ret = self:run_lua(Lua(Source(filename, 1, #file), file))
elseif filename:match("%.nom$") or filename:match("^/dev/fd/[012]$") then
if not self.skip_precompiled then
local lua_filename = filename:gsub("%.nom$", ".lua")
local file = FILE_CACHE[lua_filename]
if file then
ret = self:run_lua(Lua(Source(filename), file))
ret = self:run_lua(Lua(Source(filename, 1, #file), file))
remove(_running_files)
_continue_0 = true
break
@ -441,24 +459,9 @@ do
local map = { }
local offset = 1
local source = lua.source
local nomsu_raw = FILE_CACHE[source.filename]:sub(source.start, source.stop)
local nomsu_line_to_pos = LINE_STARTS[nomsu_raw]
local lua_line_to_pos = LINE_STARTS[tostring(lua)]
local pos_to_line
pos_to_line = function(line_starts, pos)
local lo, hi = 1, #line_starts
while lo <= hi do
local mid = math.floor((lo + hi) / 2)
if line_starts[mid] > pos then
hi = mid - 1
else
lo = mid + 1
end
end
return hi
end
local nomsu_str = tostring(FILE_CACHE[source.filename]:sub(source.start, source.stop))
local lua_line = 1
local nomsu_line = pos_to_line(nomsu_line_to_pos, lua.source.start)
local nomsu_line = pos_to_line(nomsu_str, lua.source.start)
local fn
fn = function(s)
if type(s) == 'string' then
@ -469,7 +472,7 @@ do
else
local old_line = nomsu_line
if s.source then
nomsu_line = pos_to_line(nomsu_line_to_pos, s.source.start)
nomsu_line = pos_to_line(nomsu_str, s.source.start)
end
local _list_0 = s.bits
for _index_0 = 1, #_list_0 do
@ -1598,18 +1601,12 @@ OPTIONS
}
args.interactive = true
end
local output_file
if args.output_file == "-" then
output_file = io.stdout
elseif args.output_file then
output_file = io.open(args.output_file, 'w')
end
local print_file
if args.print_file == "-" then
print_file = io.stdout
elseif args.print_file then
print_file = io.open(args.print_file, 'w')
elseif output_file == io.stdout then
elseif args.output_file == '-' then
print_file = nil
else
print_file = io.stdout
@ -1631,8 +1628,14 @@ OPTIONS
end
end
local compile_fn
if output_file then
if args.output_file then
compile_fn = function(code)
local output_file
if args.output_file == "-" then
output_file = io.stdout
elseif args.output_file then
output_file = io.open(args.output_file, 'w')
end
output_file:write("local IMMEDIATE = true;\n" .. tostring(code))
return output_file:flush()
end

View File

@ -111,6 +111,16 @@ LINE_STARTS = setmetatable {}, {
self[k] = line_starts
return line_starts
}
pos_to_line = (str, pos)->
line_starts = LINE_STARTS[str]
-- Binary search for line number of position
lo, hi = 1, #line_starts
while lo <= hi
mid = math.floor((lo+hi)/2)
if line_starts[mid] > pos
hi = mid-1
else lo = mid+1
return hi
-- Use + operator for string coercive concatenation (note: "asdf" + 3 == "asdf3")
-- Use [] for accessing string characters, or s[{3,4}] for s:sub(3,4)
@ -173,13 +183,13 @@ NOMSU_DEFS = with {}
err_pos = start_pos
--if src\sub(err_pos,err_pos)\match("[\r\n]")
-- err_pos += #src\match("[ \t\n\r]*", err_pos)
text_loc = userdata.source\sub(err_pos,err_pos)
line_no = text_loc\get_line_number!
src = FILE_CACHE[text_loc.filename]
prev_line = line_no == 1 and "" or src\sub(LINE_STARTS[src][line_no-1] or 1, LINE_STARTS[src][line_no]-2)
err_line = src\sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no+1] or 0)-2)
next_line = src\sub(LINE_STARTS[src][line_no+1] or -1, (LINE_STARTS[src][line_no+2] or 0)-2)
i = err_pos-LINE_STARTS[src][line_no]
line_no = pos_to_line(src, err_pos)
src = FILE_CACHE[userdata.source.filename]
line_starts = LINE_STARTS[src]
prev_line = line_no == 1 and "" or src\sub(line_starts[line_no-1] or 1, line_starts[line_no]-2)
err_line = src\sub(line_starts[line_no], (line_starts[line_no+1] or 0)-2)
next_line = src\sub(line_starts[line_no+1] or -1, (line_starts[line_no+2] or 0)-2)
i = err_pos-line_starts[line_no]
pointer = ("-")\rep(i) .. "^"
err_msg = colored.bright colored.yellow colored.onred (err_msg or "Parse error").." at #{userdata.source.filename}:#{line_no}:"
if #prev_line > 0 then err_msg ..= "\n"..colored.dim(prev_line)
@ -192,7 +202,9 @@ NOMSU_DEFS = with {}
setmetatable(NOMSU_DEFS, {__index:(key)=>
make_node = (start, value, stop, userdata)->
source = userdata.source\sub(start, stop-1)
local source
with userdata.source
source = Source(.filename, .start + start-1, .start + stop-1)
tree = if Types[key].is_multi
Types[key](source, unpack(value))
else Types[key](source, value)
@ -366,13 +378,13 @@ class NomsuCompiler
insert _running_files, filename
if filename\match("%.lua$")
file = assert(FILE_CACHE[filename], "Could not find file: #{filename}")
ret = @run_lua(Lua(Source(filename), file))
ret = @run_lua(Lua(Source(filename, 1, #file), file))
elseif filename\match("%.nom$") or filename\match("^/dev/fd/[012]$")
if not @skip_precompiled -- Look for precompiled version
lua_filename = filename\gsub("%.nom$", ".lua")
file = FILE_CACHE[lua_filename]
if file
ret = @run_lua(Lua(Source(filename), file))
ret = @run_lua(Lua(Source(filename, 1, #file), file))
remove _running_files
continue
file = file or FILE_CACHE[filename]
@ -403,23 +415,9 @@ class NomsuCompiler
map = {}
offset = 1
source = lua.source
nomsu_raw = FILE_CACHE[source.filename]\sub(source.start, source.stop)
nomsu_line_to_pos = LINE_STARTS[nomsu_raw]
lua_line_to_pos = LINE_STARTS[tostring(lua)]
pos_to_line = (line_starts, pos)->
-- Binary search for line number of position
lo, hi = 1, #line_starts
while lo <= hi
mid = math.floor((lo+hi)/2)
if line_starts[mid] > pos
hi = mid-1
else lo = mid+1
return hi
nomsu_str = tostring(FILE_CACHE[source.filename]\sub(source.start, source.stop))
lua_line = 1
nomsu_line = pos_to_line(nomsu_line_to_pos, lua.source.start)
nomsu_line = pos_to_line(nomsu_str, lua.source.start)
fn = (s)->
if type(s) == 'string'
for nl in s\gmatch("\n")
@ -428,7 +426,7 @@ class NomsuCompiler
else
old_line = nomsu_line
if s.source
nomsu_line = pos_to_line(nomsu_line_to_pos, s.source.start)
nomsu_line = pos_to_line(nomsu_str, s.source.start)
for b in *s.bits do fn(b)
fn(lua)
map[lua_line] or= nomsu_line
@ -1113,12 +1111,9 @@ OPTIONS
args.inputs = {"core"}
args.interactive = true
output_file = if args.output_file == "-" then io.stdout
elseif args.output_file then io.open(args.output_file, 'w')
print_file = if args.print_file == "-" then io.stdout
elseif args.print_file then io.open(args.print_file, 'w')
elseif output_file == io.stdout then nil
elseif args.output_file == '-' then nil
else io.stdout
nomsu.skip_precompiled = not args.optimized
@ -1134,8 +1129,10 @@ OPTIONS
print_file\write('\n')
print_file\flush!
compile_fn = if output_file
compile_fn = if args.output_file
(code)->
output_file = if args.output_file == "-" then io.stdout
elseif args.output_file then io.open(args.output_file, 'w')
output_file\write("local IMMEDIATE = true;\n"..tostring(code))
output_file\flush!
else nil