aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-06-04 20:41:20 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-06-04 20:44:58 -0700
commit83183122f180ce0fdbf3b5c1c8ff828d762348a8 (patch)
tree0f536166e9e2169b8aa33a8a8a20ba7e29109950
parent563e415e07ea45df8c80fc9a2afc652e3e6d8c83 (diff)
Optimizations and cleanup. Build script now fails on first error and
uses the precompiled versions it has just compiled.
-rw-r--r--code_obj.lua48
-rw-r--r--code_obj.moon34
-rwxr-xr-xcompile_lib.sh6
-rw-r--r--core/collections.nom2
-rw-r--r--core/metaprogramming.nom1
-rw-r--r--core/operators.nom1
-rw-r--r--nomsu.lua75
-rwxr-xr-xnomsu.moon61
8 files changed, 72 insertions, 156 deletions
diff --git a/code_obj.lua b/code_obj.lua
index dcdd95a..fa36234 100644
--- a/code_obj.lua
+++ b/code_obj.lua
@@ -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
diff --git a/code_obj.moon b/code_obj.moon
index 8dfc0a1..5fe6c98 100644
--- a/code_obj.moon
+++ b/code_obj.moon
@@ -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
diff --git a/compile_lib.sh b/compile_lib.sh
index 9bf0487..fa932b3 100755
--- a/compile_lib.sh
+++ b/compile_lib.sh
@@ -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
diff --git a/core/collections.nom b/core/collections.nom
index 8e7576d..0bf5cef 100644
--- a/core/collections.nom
+++ b/core/collections.nom
@@ -172,5 +172,3 @@ immediately
(% in %seen) <- (yes)
return %unique
-
-# TODO: maybe make a generator/coroutine?
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 66af1e6..c54a72f 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -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
diff --git a/core/operators.nom b/core/operators.nom
index 5222a69..dd57cea 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -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}
diff --git a/nomsu.lua b/nomsu.lua
index 8121a18..54a6cd8 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -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
diff --git a/nomsu.moon b/nomsu.moon
index c2e2ca9..15028cc 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -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