aboutsummaryrefslogtreecommitdiff
path: root/nomsu.moon
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-06-12 18:04:18 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-06-12 18:04:41 -0700
commit3c510e4ee5027aa5191e994bdf0a080a32a4b082 (patch)
treeb8d740f6ce0e263faa92967a63d16af07f3d45e7 /nomsu.moon
parentb5fb8933af283d2b873a03ded085e8b69f374e81 (diff)
Lots of optimizations and simplifications, especially towards getting
better performance on luajit.
Diffstat (limited to 'nomsu.moon')
-rwxr-xr-xnomsu.moon119
1 files changed, 40 insertions, 79 deletions
diff --git a/nomsu.moon b/nomsu.moon
index bef479b..5aaf683 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -14,27 +14,12 @@ export lpeg, re
_pairs, _ipairs = pairs, ipairs
if jit
package.cpath = "./luajit_lpeg/?.so;"..package.cpath
- --package.path = "./LPegLJ/src/?.lua;"..package.path
- --lpeg = require "lpeglj"
- lpeg = require 'lpeg'
+ package.path = "./luajit_lpeg/?.lua;"..package.path
export bit32
bit32 = require('bit')
- export pairs, ipairs
- pairs = (x)->
- if mt = getmetatable(x)
- if mt.__pairs
- return mt.__pairs(x)
- return _pairs(x)
- ipairs = (x)->
- if mt = getmetatable(x)
- if mt.__ipairs
- return mt.__ipairs(x)
- return _ipairs(x)
-else
- lpeg = require 'lpeg'
-
+lpeg = require 'lpeg'
re = require 're'
lpeg.setmaxstack 10000
{:P,:R,:V,:S,:Cg,:C,:Cp,:B,:Cmt,:Carg} = lpeg
@@ -45,12 +30,13 @@ colors = setmetatable({}, {__index:->""})
export colored
colored = setmetatable({}, {__index:(_,color)-> ((msg)-> colors[color]..tostring(msg or '')..colors.reset)})
{:insert, :remove, :concat} = table
+{:match, :sub, :rep, :gsub, :format, :byte, :match} = string
debug_getinfo = debug.getinfo
{:Nomsu, :Lua, :Source} = require "code_obj"
STDIN, STDOUT, STDERR = "/dev/fd/0", "/dev/fd/1", "/dev/fd/2"
string.as_lua_id = (str)->
- "_"..(str\gsub("%W", (c)-> if c == "_" then "__" else ("_%x")\format(c\byte!)))
+ "_"..(gsub(str, "%W", (c)-> if c == "_" then "__" else format("_%x", byte(c))))
-- TODO:
-- consider non-linear codegen, rather than doing thunks for things like comprehensions
@@ -77,10 +63,13 @@ FILE_CACHE = setmetatable {}, {
iterate_single = (item, prev) -> if item == prev then nil else item
all_files = (path)->
-- Sanitize path
- if path\match("%.nom$") or path\match("%.lua$") or path\match("^/dev/fd/[012]$")
+ if match(path, "%.nom$") or match(path, "%.lua$") or match(path, "^/dev/fd/[012]$")
return iterate_single, path
-- TODO: improve sanitization
- path = path\gsub("\\","\\\\")\gsub("`","")\gsub('"','\\"')\gsub("$","")
+ path = gsub(path,"\\","\\\\")
+ path = gsub(path,"`","")
+ path = gsub(path,'"','\\"')
+ path = gsub(path,"$","")
return coroutine.wrap ->
f = io.popen('find -L "'..path..'" -not -path "*/\\.*" -type f -name "*.nom"')
for line in f\lines!
@@ -128,8 +117,8 @@ do
STRING_METATABLE.__index = (i)=>
ret = string[i]
if ret != nil then return ret
- if type(i) == 'number' then return string.sub(@, i, i)
- elseif type(i) == 'table' then return string.sub(@, i[1], i[2])
+ if type(i) == 'number' then return sub(@, i, i)
+ elseif type(i) == 'table' then return sub(@, i[1], i[2])
AST = require "nomsu_tree"
@@ -153,19 +142,19 @@ NOMSU_DEFS = with {}
-- If the line begins with #indent+4 spaces, the pattern matches *those* spaces
-- and adds them to the stack (not any more).
.indent = Cmt Carg(1), (start, userdata)=>
- if #@match("^[ ]*", start) >= userdata.indent + 4
+ if #match(@, "^[ ]*", start) >= userdata.indent + 4
userdata.indent += 4
return start + userdata.indent
-- If the number of leading space characters is <= the number of space on the top of the
-- stack minus 4, this pattern matches and pops off the top of the stack exactly once.
.dedent = Cmt Carg(1), (start, userdata)=>
- if #@match("^[ ]*", start) <= userdata.indent - 4
+ if #match(@, "^[ ]*", start) <= userdata.indent - 4
userdata.indent -= 4
return start
-- If the number of leading space characters is >= the number on the top of the
-- stack, this pattern matches and does not modify the stack.
.nodent = Cmt Carg(1), (start, userdata)=>
- if #@match("^[ ]*", start) >= userdata.indent
+ if #match(@, "^[ ]*", start) >= userdata.indent
return start + userdata.indent
.userdata = Carg(1)
@@ -178,8 +167,6 @@ NOMSU_DEFS = with {}
seen_errors[start_pos+1] = colored.bright colored.yellow colored.onred "Too many errors, canceling parsing..."
return #src+1
err_pos = start_pos
- --if src\sub(err_pos,err_pos)\match("[\r\n]")
- -- err_pos += #src\match("[ \t\n\r]*", err_pos)
line_no = pos_to_line(src, err_pos)
src = FILE_CACHE[userdata.source.filename]
line_starts = LINE_STARTS[src]
@@ -276,34 +263,10 @@ class NomsuCompiler
:error, :package, :os, :require, :tonumber, :tostring, :string, :xpcall, :module,
:print, :loadfile, :rawset, :_VERSION, :collectgarbage, :rawget, :bit32, :rawlen,
:table, :assert, :dofile, :loadstring, :type, :select, :debug, :math, :io, :load,
+ :pairs, :ipairs,
-- Nomsu types:
:list, :dict,
}
- @environment.len = if jit
- (x)->
- if mt = getmetatable(x)
- if mt.__len
- return mt.__len(x)
- return #x
- else ((x) -> #x)
- @environment.ipairs = (x)->
- if type(x) == 'function'
- return coroutine.wrap(x)
- elseif type(x) == 'thread'
- return coroutine.resume, x, nil
- elseif mt = getmetatable(x)
- if mt.__ipairs
- return mt.__ipairs(x)
- return _ipairs(x)
- @environment.pairs = (x)->
- if type(x) == 'function'
- return coroutine.wrap(x)
- elseif type(x) == 'thread'
- return coroutine.resume, x, nil
- elseif mt = getmetatable(x)
- if mt.__pairs
- return mt.__pairs(x)
- return _pairs(x)
for k,v in pairs(AST) do @environment[k] = v
@environment.Lua = Lua
@environment.Nomsu = Nomsu
@@ -400,12 +363,12 @@ class NomsuCompiler
error("Circular import, this loops forever: #{concat loop, " -> "}")
insert _running_files, filename
- if filename\match("%.lua$")
+ if match(filename, "%.lua$")
file = assert(FILE_CACHE[filename], "Could not find file: #{filename}")
ret = @run_lua(Lua(Source(filename, 1, #file), file))
- elseif filename\match("%.nom$") or filename\match("^/dev/fd/[012]$")
+ elseif match(filename, "%.nom$") or match(filename, "^/dev/fd/[012]$")
if not @skip_precompiled -- Look for precompiled version
- lua_filename = filename\gsub("%.nom$", ".lua")
+ lua_filename = gsub(filename, "%.nom$", ".lua")
file = FILE_CACHE[lua_filename]
if file
ret = @run_lua(Lua(Source(filename, 1, #file), file))
@@ -426,7 +389,7 @@ class NomsuCompiler
run_lua: (lua)=>
assert(type(lua) != 'string', "Attempt to run lua string instead of Lua (object)")
lua_string = tostring(lua)
- run_lua_fn, err = load(lua_string, nil and tostring(lua.source), "t", @environment)
+ run_lua_fn, err = load(lua_string, tostring(lua.source), "t", @environment)
if not run_lua_fn
n = 1
fn = ->
@@ -526,11 +489,8 @@ class NomsuCompiler
make_tree = (t)->
unless AST.is_syntax_tree(t)
return repr(t)
- if t.value
- return t.type.."("..repr(tostring t.source)..", "..repr(t.value)..")"
- else
- bits = [make_tree(bit) for bit in *t]
- return t.type.."("..repr(tostring t.source)..", "..table.concat(bits, ", ")..")"
+ bits = [make_tree(bit) for bit in *t]
+ return t.type.."("..repr(tostring t.source)..", "..table.concat(bits, ", ")..")"
Lua.Value tree.source, make_tree(tree[1])
when "Block"
@@ -555,7 +515,7 @@ class NomsuCompiler
string_buffer = ""
bit_lua = @tree_to_lua(bit)
unless bit_lua.is_value
- src = ' '..tostring(@tree_to_nomsu(bit))\gsub('\n','\n ')
+ src = ' '..gsub(tostring(@tree_to_nomsu(bit)), '\n','\n ')
line = "#{bit.source.filename}:#{pos_to_line(FILE_CACHE[bit.source.filename], bit.source.start)}"
compile_error bit,
"Cannot use:\n%s\nas a string interpolation value, since it's not an expression."
@@ -582,8 +542,8 @@ class NomsuCompiler
"Cannot use:\n%s\nas a list item, since it's not an expression."
lua\append item_lua
item_string = tostring(item_lua)
- last_line = item_string\match("[^\n]*$")
- if item_string\match("\n")
+ last_line = match(item_string, "[^\n]*$")
+ if match(item_string, "\n")
line_length = #last_line
else
line_length += #last_line
@@ -605,7 +565,7 @@ class NomsuCompiler
lua\append entry_lua
entry_lua_str = tostring(entry_lua)
-- TODO: maybe make this more accurate? It's only a heuristic, so eh...
- last_line = entry_lua_str\match("\n([^\n]*)$")
+ last_line = match(entry_lua_str, "\n([^\n]*)$")
if last_line
line_length = #last_line
else
@@ -630,10 +590,10 @@ class NomsuCompiler
unless value_lua.is_value
compile_error tree[2],
"Cannot use:\n%s\nas a dict value, since it's not an expression."
- key_str = tostring(key_lua)\match([=[["']([a-zA-Z_][a-zA-Z0-9_]*)['"]]=])
+ key_str = match(tostring(key_lua), [=[["']([a-zA-Z_][a-zA-Z0-9_]*)['"]]=])
return if key_str
Lua tree.source, key_str,"=",value_lua
- elseif tostring(key_lua)\sub(1,1) == "["
+ elseif sub(tostring(key_lua),1,1) == "["
-- NOTE: this *must* use a space after the [ to avoid freaking out
-- Lua's parser if the inner expression is a long string. Lua
-- parses x[[[y]]] as x("[y]"), not as x["y"]
@@ -646,7 +606,7 @@ class NomsuCompiler
unless lua.is_value
compile_error tree[1],
"Cannot index:\n%s\nsince it's not an expression."
- first_char = tostring(lua)\sub(1,1)
+ first_char = sub(tostring(lua),1,1)
if first_char == "{" or first_char == '"' or first_char == "["
lua\parenthesize!
@@ -657,9 +617,9 @@ class NomsuCompiler
compile_error key,
"Cannot use:\n%s\nas an index, since it's not an expression."
key_lua_str = tostring(key_lua)
- if lua_id = key_lua_str\match("^['\"]([a-zA-Z_][a-zA-Z0-9_]*)['\"]$")
+ if lua_id = match(key_lua_str, "^['\"]([a-zA-Z_][a-zA-Z0-9_]*)['\"]$")
lua\append ".#{lua_id}"
- elseif key_lua_str\sub(1,1) == '['
+ elseif sub(key_lua_str,1,1) == '['
-- NOTE: this *must* use a space after the [ to avoid freaking out
-- Lua's parser if the inner expression is a long string. Lua
-- parses x[[[y]]] as x("[y]"), not as x["y"]
@@ -669,10 +629,10 @@ class NomsuCompiler
return lua
when "Number"
- Lua.Value(tree.source, tostring(tree.value))
+ Lua.Value(tree.source, tostring(tree[1]))
when "Var"
- Lua.Value(tree.source, string.as_lua_id(tree.value))
+ Lua.Value(tree.source, string.as_lua_id(tree[1]))
else
error("Unknown type: #{tree.type}")
@@ -713,7 +673,7 @@ class NomsuCompiler
if arg_nomsu and #arg_nomsu < MAX_LINE
if bit.type == "Action"
if can_use_colon and i > 1
- nomsu\append next_space\match("[^ ]*"), ": ", arg_nomsu
+ nomsu\append match(next_space,"[^ ]*"), ": ", arg_nomsu
next_space = "\n.."
last_colon = i
else
@@ -737,7 +697,7 @@ class NomsuCompiler
nomsu\append next_space, arg_nomsu
next_space = "\n.."
- if next_space == " " and #(tostring(nomsu)\match("[^\n]*$")) > MAX_LINE
+ if next_space == " " and #(match(tostring(nomsu),"[^\n]*$")) > MAX_LINE
next_space = "\n.."
return nomsu
@@ -764,7 +724,7 @@ class NomsuCompiler
nomsu\append line
if i < #tree
nomsu\append "\n"
- if tostring(line)\match("\n")
+ if match(tostring(line), "\n")
nomsu\append "\n"
return nomsu
@@ -774,7 +734,7 @@ class NomsuCompiler
for bit in *tree
if type(bit) == 'string'
-- TODO: unescape better?
- nomsu\append (bit\gsub("\\","\\\\")\gsub("\n","\\n"))
+ nomsu\append (gsub(gsub(bit,"\\","\\\\"),"\n","\\n"))
else
interp_nomsu = @tree_to_nomsu(bit, true)
if interp_nomsu
@@ -791,7 +751,8 @@ class NomsuCompiler
nomsu = Nomsu(tree.source, '".."\n ')
for i, bit in ipairs @
if type(bit) == 'string'
- nomsu\append (bit\gsub("\\","\\\\")\gsub("\n","\n "))
+ -- TODO: unescape better?
+ nomsu\append (gsub(gsub(bit,"\\","\\\\"),"\n","\\n"))
else
interp_nomsu = @tree_to_nomsu(bit, true)
if interp_nomsu
@@ -902,10 +863,10 @@ class NomsuCompiler
return nomsu
when "Number"
- return Nomsu(tree.source, tostring(tree.value))
+ return Nomsu(tree.source, tostring(tree[1]))
when "Var"
- return Nomsu(tree.source, "%", tree.value)
+ return Nomsu(tree.source, "%", tree[1])
else
error("Unknown type: #{tree.type}")