Overhaul with smaller, more concise codebase around defining
actions/macros, and deleting some dead code.
This commit is contained in:
parent
2abaf67b66
commit
bf60ac28c5
@ -5,7 +5,7 @@
|
|||||||
# Compile-time action to make compile-time actions:
|
# Compile-time action to make compile-time actions:
|
||||||
immediately
|
immediately
|
||||||
lua> ".."
|
lua> ".."
|
||||||
nomsu:define_compile_action("compile %actions to %lua", \(!! code location !!), function(tree, \%actions, \%lua)
|
nomsu:define_compile_action("compile %actions to %lua", function(tree, \%actions, \%lua)
|
||||||
local lua = Lua(tree.source, "nomsu:define_compile_action(");
|
local lua = Lua(tree.source, "nomsu:define_compile_action(");
|
||||||
local stubs = {};
|
local stubs = {};
|
||||||
for i, action in ipairs(\%actions.value) do
|
for i, action in ipairs(\%actions.value) do
|
||||||
@ -17,7 +17,7 @@ immediately
|
|||||||
else
|
else
|
||||||
lua:append(stubs,", ");
|
lua:append(stubs,", ");
|
||||||
end
|
end
|
||||||
lua:append(repr(tree.source:get_line()), ", function(tree");
|
lua:append("function(tree");
|
||||||
local args = {};
|
local args = {};
|
||||||
for i,tok in ipairs(\%actions.value[1].value) do
|
for i,tok in ipairs(\%actions.value[1].value) do
|
||||||
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
|
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
|
||||||
@ -49,7 +49,7 @@ immediately
|
|||||||
else
|
else
|
||||||
lua:append(stubs,", ");
|
lua:append(stubs,", ");
|
||||||
end
|
end
|
||||||
lua:append(repr(tree.source:get_line()), ", function(");
|
lua:append("function(");
|
||||||
local args = {};
|
local args = {};
|
||||||
for i,tok in ipairs(\%actions.value[1].value) do
|
for i,tok in ipairs(\%actions.value[1].value) do
|
||||||
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
|
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
|
||||||
@ -80,7 +80,7 @@ immediately
|
|||||||
else
|
else
|
||||||
lua:append(stubs,", ");
|
lua:append(stubs,", ");
|
||||||
end
|
end
|
||||||
lua:append(repr(tree.source:get_line()), ", function(tree");
|
lua:append("function(tree");
|
||||||
local args = {};
|
local args = {};
|
||||||
for i,tok in ipairs(\%shorthand.value[1].value) do
|
for i,tok in ipairs(\%shorthand.value[1].value) do
|
||||||
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
|
if tok.type == "Var" then args[#args+1] = nomsu:var_to_lua_identifier(tok.value); end
|
||||||
@ -103,12 +103,11 @@ immediately
|
|||||||
action [remove action %stub]
|
action [remove action %stub]
|
||||||
lua> ".."
|
lua> ".."
|
||||||
local fn = ACTIONS[\%stub];
|
local fn = ACTIONS[\%stub];
|
||||||
local metadata = nomsu.action_metadata[fn];
|
local stubs = ARG_ORDERS[fn];
|
||||||
for i=#metadata.aliases,1,-1 do
|
for stub in pairs(stubs) do
|
||||||
metadata.arg_orders[metadata.aliases[i]] = nil;
|
ACTIONS[stub] = nil;
|
||||||
table.remove(metadata.aliases, i);
|
|
||||||
end
|
end
|
||||||
ACTIONS[\%stub] = nil;
|
ARG_ORDERS[fn] = nil;
|
||||||
|
|
||||||
immediately
|
immediately
|
||||||
action [%tree as lua]
|
action [%tree as lua]
|
||||||
@ -142,7 +141,7 @@ immediately
|
|||||||
|
|
||||||
|
|
||||||
action [%tree's stub]
|
action [%tree's stub]
|
||||||
=lua "nomsu:tree_to_stub(\%tree)"
|
=lua "\%tree:get_stub()"
|
||||||
|
|
||||||
immediately
|
immediately
|
||||||
parse [%var <-write %code] as: lua> "\%var:append(\%code);"
|
parse [%var <-write %code] as: lua> "\%var:append(\%code);"
|
||||||
|
@ -18,11 +18,6 @@ compile [capitalized %text, %text capitalized] to
|
|||||||
compile [%text with %sub instead of %patt, %text s/%patt/%sub] to
|
compile [%text with %sub instead of %patt, %text s/%patt/%sub] to
|
||||||
Lua value "((\(%text as lua expr)):gsub(\(%patt as lua expr), \(%sub as lua expr)))"
|
Lua value "((\(%text as lua expr)):gsub(\(%patt as lua expr), \(%sub as lua expr)))"
|
||||||
|
|
||||||
# TODO: figure out whether indent/dedent should affect first line
|
|
||||||
compile [indented %text, %text indented] to: Lua value "((\%text):gsub('\\n','\\n'..(' ')))"
|
|
||||||
compile [dedented %obj, %obj dedented] to: Lua value "nomsu:dedent(\(%obj as lua expr))"
|
|
||||||
compile [%text indented %n times] to: Lua value "((\%text):gsub('\\n','\\n'..(' '):rep(\%n)))"
|
|
||||||
|
|
||||||
# Text literals
|
# Text literals
|
||||||
lua> ".."
|
lua> ".."
|
||||||
do
|
do
|
||||||
@ -32,7 +27,7 @@ lua> ".."
|
|||||||
};
|
};
|
||||||
for name, e in pairs(escapes) do
|
for name, e in pairs(escapes) do
|
||||||
local lua = "'"..e.."'";
|
local lua = "'"..e.."'";
|
||||||
nomsu:define_compile_action(name, \(!! code location !!), function(tree) return Lua.Value(tree.source, lua); end);
|
nomsu:define_compile_action(name, function(tree) return Lua.Value(tree.source, lua); end);
|
||||||
end
|
end
|
||||||
local colors = {
|
local colors = {
|
||||||
["reset color"]="\\\\27[0m", bright="\\\\27[1m", dim="\\\\27[2m", underscore="\\\\27[4m",
|
["reset color"]="\\\\27[0m", bright="\\\\27[1m", dim="\\\\27[2m", underscore="\\\\27[4m",
|
||||||
@ -47,8 +42,8 @@ lua> ".."
|
|||||||
for name, c in pairs(colors) do
|
for name, c in pairs(colors) do
|
||||||
local color = "'"..c.."'";
|
local color = "'"..c.."'";
|
||||||
local reset = "'"..colors["reset color"].."'";
|
local reset = "'"..colors["reset color"].."'";
|
||||||
nomsu:define_compile_action(name, \(!! code location !!), function(tree) return Lua.Value(tree.source, color); end);
|
nomsu:define_compile_action(name, function(tree) return Lua.Value(tree.source, color); end);
|
||||||
nomsu:define_compile_action(name.." %", \(!! code location !!), function(\%)
|
nomsu:define_compile_action(name.." %", function(\%)
|
||||||
return Lua.Value(tree.source, color, "..", \%:as_lua(nomsu), "..", reset);
|
return Lua.Value(tree.source, color, "..", \%:as_lua(nomsu), "..", reset);
|
||||||
end);
|
end);
|
||||||
end
|
end
|
||||||
|
233
nomsu.moon
233
nomsu.moon
@ -223,7 +223,6 @@ class NomsuCompiler
|
|||||||
})
|
})
|
||||||
@use_stack = {}
|
@use_stack = {}
|
||||||
@file_metadata = setmetatable({}, {__mode:"k"})
|
@file_metadata = setmetatable({}, {__mode:"k"})
|
||||||
@action_metadata = setmetatable({}, {__mode:"k"})
|
|
||||||
|
|
||||||
@environment = {
|
@environment = {
|
||||||
-- Discretionary/convenience stuff
|
-- Discretionary/convenience stuff
|
||||||
@ -241,69 +240,47 @@ class NomsuCompiler
|
|||||||
@environment.Nomsu = Nomsu
|
@environment.Nomsu = Nomsu
|
||||||
@environment.Source = Source
|
@environment.Source = Source
|
||||||
@environment.ACTIONS = setmetatable({}, {__index:(key)=>
|
@environment.ACTIONS = setmetatable({}, {__index:(key)=>
|
||||||
error("Attempt to run undefined action: #{key}", 0)
|
(...)->
|
||||||
|
error("Attempt to run undefined action: #{key}", 0)
|
||||||
})
|
})
|
||||||
|
@environment.MACROS = {}
|
||||||
|
@environment.ARG_ORDERS = setmetatable({}, {__mode:"k"})
|
||||||
@environment.LOADED = {}
|
@environment.LOADED = {}
|
||||||
@environment.Types = Types
|
@environment.Types = Types
|
||||||
@initialize_core!
|
@initialize_core!
|
||||||
|
|
||||||
define_action: (signature, source, fn)=>
|
stub_defs = {
|
||||||
if type(fn) != 'function'
|
space:(P(' ') + P('\n..'))^0
|
||||||
error 'function', "Bad fn: #{repr fn}"
|
word:(NOMSU_DEFS.ident_char^1 + NOMSU_DEFS.operator^1)
|
||||||
|
varname:(R('az','AZ','09') + P('_') + NOMSU_DEFS.utf8_char)^0
|
||||||
|
}
|
||||||
|
stub_pattern = re.compile [=[
|
||||||
|
{~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~}
|
||||||
|
]=], stub_defs
|
||||||
|
var_pattern = re.compile "{| %space ((('%' {%varname}) / %word) %space)+ |}", stub_defs
|
||||||
|
define_action: (signature, fn, is_macro=false)=>
|
||||||
|
assert(type(fn) == 'function', "Bad fn: #{repr fn}")
|
||||||
if type(signature) == 'string'
|
if type(signature) == 'string'
|
||||||
signature = {signature}
|
signature = {signature}
|
||||||
elseif type(signature) != 'table' or signature.type != nil
|
elseif type(signature) != 'table'
|
||||||
error("Invalid signature, expected list of strings, but got: #{repr signature}", 0)
|
error("Invalid signature, expected list of strings, but got: #{repr signature}", 0)
|
||||||
stubs = @get_stubs_from_signature signature
|
|
||||||
stub_args = @get_args_from_signature signature
|
stubs = [assert(stub_pattern\match(alias)) for alias in *signature]
|
||||||
|
stub_args = [assert(var_pattern\match(alias)) for alias in *signature]
|
||||||
|
|
||||||
fn_info = debug_getinfo(fn, "u")
|
fn_info = debug_getinfo(fn, "u")
|
||||||
local fn_arg_positions, arg_orders
|
assert(not fn_info.isvararg, "Vararg functions aren't supported. Sorry, use a list instead.")
|
||||||
unless fn_info.isvararg
|
fn_arg_positions = {debug.getlocal(fn, i), i for i=1,fn_info.nparams}
|
||||||
fn_arg_positions = {debug.getlocal(fn, i), i for i=1,fn_info.nparams}
|
arg_orders = {}
|
||||||
arg_orders = {} -- Map from stub -> index where each arg in the stub goes in the function call
|
for alias in *signature
|
||||||
for sig_i=1,#stubs
|
stub = assert(stub_pattern\match(alias))
|
||||||
stub, args = stubs[sig_i], stub_args[sig_i]
|
stub_args = assert(var_pattern\match(alias))
|
||||||
@environment.ACTIONS[stub] = fn
|
(is_macro and @environment.MACROS or @environment.ACTIONS)[stub] = fn
|
||||||
unless fn_info.isvararg
|
arg_orders[stub] = [fn_arg_positions[@var_to_lua_identifier(a)] for a in *stub_args]
|
||||||
arg_positions = [fn_arg_positions[a] for a in *args]
|
@environment.ARG_ORDERS[fn] = arg_orders
|
||||||
-- TODO: better error checking?
|
|
||||||
--if #arg_positions != #args
|
|
||||||
-- error("Mismatch in args between lua function's #{repr fn_arg_positions} and stub's #{repr args} for #{repr stub}", 0)
|
|
||||||
arg_orders[stub] = arg_positions
|
|
||||||
|
|
||||||
@action_metadata[fn] = {
|
define_compile_action: (signature, fn)=>
|
||||||
:fn, :source, aliases:stubs, :arg_orders,
|
return @define_action(signature, fn, true)
|
||||||
arg_positions:fn_arg_positions, def_number:@@def_number,
|
|
||||||
}
|
|
||||||
|
|
||||||
define_compile_action: (signature, source, fn, src)=>
|
|
||||||
@define_action(signature, source, fn)
|
|
||||||
@action_metadata[fn].compile_time = true
|
|
||||||
|
|
||||||
serialize_defs: (scope=nil, after=nil)=>
|
|
||||||
-- TODO: repair
|
|
||||||
error("Not currently functional.", 0)
|
|
||||||
|
|
||||||
dedent: (code)=>
|
|
||||||
unless code\find("\n")
|
|
||||||
return code
|
|
||||||
spaces, indent_spaces = math.huge, math.huge
|
|
||||||
for line in code\gmatch("\n([^\n]*)")
|
|
||||||
if line\match("^%s*#.*") or line\match("^%s*$")
|
|
||||||
continue -- skip comments and blank lines
|
|
||||||
elseif s = line\match("^(%s*)%.%..*")
|
|
||||||
spaces = math.min(spaces, #s)
|
|
||||||
elseif s = line\match("^(%s*)%S.*")
|
|
||||||
indent_spaces = math.min(indent_spaces, #s)
|
|
||||||
if spaces != math.huge and spaces < indent_spaces
|
|
||||||
return (code\gsub("\n"..(" ")\rep(spaces), "\n"))
|
|
||||||
elseif indent_spaces != math.huge
|
|
||||||
return (code\gsub("\n"..(" ")\rep(indent_spaces), "\n "))
|
|
||||||
else return code
|
|
||||||
|
|
||||||
indent: (code, levels=1)=>
|
|
||||||
return code\gsub("\n","\n"..(" ")\rep(levels))
|
|
||||||
|
|
||||||
parse: (nomsu_code)=>
|
parse: (nomsu_code)=>
|
||||||
if type(nomsu_code) == 'string'
|
if type(nomsu_code) == 'string'
|
||||||
@ -409,31 +386,6 @@ class NomsuCompiler
|
|||||||
lua = Lua(tree.source, "return ",tree\as_lua(@),";")
|
lua = Lua(tree.source, "return ",tree\as_lua(@),";")
|
||||||
return @run_lua(lua)
|
return @run_lua(lua)
|
||||||
|
|
||||||
value_to_nomsu: (value)=>
|
|
||||||
switch type(value)
|
|
||||||
when "nil"
|
|
||||||
return "(nil)"
|
|
||||||
when "bool"
|
|
||||||
return value and "(yes)" or "(no)"
|
|
||||||
when "number"
|
|
||||||
-- TODO: support NaN, inf, etc.?
|
|
||||||
return repr(value)
|
|
||||||
when "table"
|
|
||||||
if is_list(value)
|
|
||||||
return "[#{concat [@value_to_nomsu(v) for v in *value], ", "}]"
|
|
||||||
else
|
|
||||||
return "{#{concat ["#{@value_to_nomsu(k)}:#{@value_to_nomsu(v)}" for k,v in pairs(value)], ", "}}"
|
|
||||||
when "string"
|
|
||||||
if value == "\n"
|
|
||||||
return "'\\n'"
|
|
||||||
elseif not value\find[["]] and not value\find"\n" and not value\find"\\"
|
|
||||||
return "\""..value.."\""
|
|
||||||
else
|
|
||||||
-- TODO: This might fail if it's being put inside a list or something
|
|
||||||
return '".."\n '..(@indent value)
|
|
||||||
else
|
|
||||||
error("Unsupported value_to_nomsu type: #{type(value)}", 0)
|
|
||||||
|
|
||||||
walk_tree: (tree, depth=0)=>
|
walk_tree: (tree, depth=0)=>
|
||||||
coroutine.yield(tree, depth)
|
coroutine.yield(tree, depth)
|
||||||
return unless Types.is_node(tree)
|
return unless Types.is_node(tree)
|
||||||
@ -466,107 +418,19 @@ class NomsuCompiler
|
|||||||
insert bits, ((" ")\rep(depth)..repr(node))
|
insert bits, ((" ")\rep(depth)..repr(node))
|
||||||
return concat(bits, "\n")
|
return concat(bits, "\n")
|
||||||
|
|
||||||
@unescape_string: (str)=>
|
|
||||||
Cs(((P("\\\\")/"\\") + (P("\\\"")/'"') + NOMSU_DEFS.escaped_char + P(1))^0)\match(str)
|
|
||||||
|
|
||||||
@comma_separated_items: (open, items, close)=>
|
|
||||||
bits = {open}
|
|
||||||
so_far = 0
|
|
||||||
for i,item in ipairs(items)
|
|
||||||
if i < #items then item ..= ", "
|
|
||||||
insert bits, item
|
|
||||||
so_far += #item
|
|
||||||
if so_far >= 80
|
|
||||||
insert bits, "\n"
|
|
||||||
so_far = 0
|
|
||||||
insert bits, close
|
|
||||||
return concat(bits)
|
|
||||||
|
|
||||||
tree_map: (tree, fn)=>
|
tree_map: (tree, fn)=>
|
||||||
-- Return a new tree with fn mapped to each node. If fn provides a replacement,
|
-- Return a new tree with fn mapped to each node. If fn provides a replacement,
|
||||||
-- use that and stop recursing, otherwise recurse.
|
-- use that and stop recursing, otherwise recurse.
|
||||||
unless Types.is_node(tree) then return tree
|
unless Types.is_node(tree) then return tree
|
||||||
replacement = fn(tree)
|
return tree\map(fn)
|
||||||
if replacement != nil
|
|
||||||
return replacement
|
|
||||||
switch tree.type
|
|
||||||
when "File", "Nomsu", "Block", "List", "Action", "Text", "IndexChain"
|
|
||||||
new_values, is_changed = {}, false
|
|
||||||
for i,old_value in ipairs(tree.value)
|
|
||||||
new_value = type(old_value) != "string" and @tree_map(old_value, fn) or nil
|
|
||||||
if new_value != nil and new_value != old_value
|
|
||||||
is_changed = true
|
|
||||||
new_values[i] = new_value
|
|
||||||
else
|
|
||||||
new_values[i] = old_value
|
|
||||||
if is_changed
|
|
||||||
return tree\with_value Tuple(table.unpack(new_values))
|
|
||||||
|
|
||||||
when "Dict"
|
|
||||||
new_values, is_changed = {}, false
|
|
||||||
for i,e in ipairs tree.value
|
|
||||||
new_key = @tree_map(e.key, fn)
|
|
||||||
new_value = @tree_map(e.value, fn)
|
|
||||||
if (new_key != nil and new_key != e.key) or (new_value != nil and new_value != e.value)
|
|
||||||
is_changed = true
|
|
||||||
new_values[i] = DictEntry(new_key, new_value)
|
|
||||||
else
|
|
||||||
new_values[i] = e
|
|
||||||
if is_changed
|
|
||||||
return tree\with_value Tuple(table.unpack(new_values))
|
|
||||||
when nil -- Raw table, probably from one of the .value of a multi-value tree (e.g. List)
|
|
||||||
error("Invalid tree: #{repr tree}")
|
|
||||||
|
|
||||||
return tree
|
|
||||||
|
|
||||||
tree_with_replaced_vars: (tree, replacements)=>
|
tree_with_replaced_vars: (tree, replacements)=>
|
||||||
return @tree_map tree, (t)->
|
tree\map (t)->
|
||||||
if t.type == "Var"
|
if t.type == "Var"
|
||||||
id = tostring(t\as_lua(self))
|
id = tostring(t\as_lua(self))
|
||||||
if replacements[id] != nil
|
if replacements[id] != nil
|
||||||
return replacements[id]
|
return replacements[id]
|
||||||
|
|
||||||
tree_to_stub: (tree)=>
|
|
||||||
if tree.type != "Action" then error "Tried to get stub from non-functioncall tree: #{tree.type}", 0
|
|
||||||
return concat([(t.type == "Word" and t.value or "%") for t in *tree.value], " ")
|
|
||||||
|
|
||||||
tree_to_named_stub: (tree)=>
|
|
||||||
if tree.type != "Action" then error "Tried to get stub from non-functioncall tree: #{tree.type}", 0
|
|
||||||
return concat([(t.type == "Word" and t.value or "%#{t.value}") for t in *tree.value], " ")
|
|
||||||
|
|
||||||
stub_defs = {
|
|
||||||
space:(P(' ') + P('\n..'))^0
|
|
||||||
word:(NOMSU_DEFS.ident_char^1 + NOMSU_DEFS.operator^1)
|
|
||||||
varname:(R('az','AZ','09') + P('_') + NOMSU_DEFS.utf8_char)^0
|
|
||||||
}
|
|
||||||
stub_pattern = re.compile("{~ (%space->'') (('%' (%varname->'')) / %word)? ((%space->' ') (('%' (%varname->'')) / %word))* (%space->'') ~}", stub_defs)
|
|
||||||
get_stubs_from_signature: (signature)=>
|
|
||||||
if type(signature) != 'table' or signature.type
|
|
||||||
error("Invalid signature: #{repr signature}", 0)
|
|
||||||
stubs = {}
|
|
||||||
for i,alias in ipairs(signature)
|
|
||||||
if type(alias) != 'string'
|
|
||||||
error("Expected entries in signature to be strings, not #{type(alias)}s like: #{repr alias}\nsignature: #{repr signature}", 0)
|
|
||||||
stubs[i] = stub_pattern\match(alias)
|
|
||||||
unless stubs[i]
|
|
||||||
error("Failed to match stub pattern on alias: #{repr alias}")
|
|
||||||
return stubs
|
|
||||||
|
|
||||||
var_pattern = re.compile("{| %space ((('%' {%varname}) / %word) %space)+ |}", stub_defs)
|
|
||||||
get_args_from_signature: (signature)=>
|
|
||||||
if type(signature) != 'table' or signature.type
|
|
||||||
error("Invalid signature: #{repr signature}", 0)
|
|
||||||
stub_args = {}
|
|
||||||
for i,alias in ipairs(signature)
|
|
||||||
if type(alias) != 'string'
|
|
||||||
error("Invalid type for signature: #{type(alias)} for:\n#{repr alias}", 0)
|
|
||||||
args = var_pattern\match(alias)
|
|
||||||
unless args
|
|
||||||
error("Failed to match arg pattern on alias: #{repr alias}", 0)
|
|
||||||
for j=1,#args do args[j] = @var_to_lua_identifier(args[j])
|
|
||||||
stub_args[i] = args
|
|
||||||
return stub_args
|
|
||||||
|
|
||||||
var_to_lua_identifier: (var)=>
|
var_to_lua_identifier: (var)=>
|
||||||
-- Converts arbitrary nomsu vars to valid lua identifiers by replacing illegal
|
-- Converts arbitrary nomsu vars to valid lua identifiers by replacing illegal
|
||||||
-- characters with escape sequences
|
-- characters with escape sequences
|
||||||
@ -577,9 +441,8 @@ class NomsuCompiler
|
|||||||
|
|
||||||
initialize_core: =>
|
initialize_core: =>
|
||||||
-- Sets up some core functionality
|
-- Sets up some core functionality
|
||||||
get_line_no = -> "nomsu.moon:#{debug_getinfo(2).currentline}"
|
|
||||||
nomsu = self
|
nomsu = self
|
||||||
@define_compile_action "immediately %block", get_line_no!, (_block)=>
|
@define_compile_action "immediately %block", (_block)=>
|
||||||
lua = _block\as_lua(nomsu)
|
lua = _block\as_lua(nomsu)
|
||||||
lua\convert_to_statements!
|
lua\convert_to_statements!
|
||||||
lua\declare_locals!
|
lua\declare_locals!
|
||||||
@ -601,31 +464,31 @@ class NomsuCompiler
|
|||||||
error "#{line}: Cannot use #{colored.yellow src} as a string interpolation value, since it's not an expression."
|
error "#{line}: Cannot use #{colored.yellow src} as a string interpolation value, since it's not an expression."
|
||||||
lua\append bit_lua
|
lua\append bit_lua
|
||||||
|
|
||||||
@define_compile_action "Lua %code", get_line_no!, (_code)=>
|
@define_compile_action "Lua %code", (_code)=>
|
||||||
lua = Lua.Value(@source, "Lua(", tostring(_code.source))
|
lua = Lua.Value(@source, "Lua(", tostring(_code.source))
|
||||||
add_lua_bits(lua, _code)
|
add_lua_bits(lua, _code)
|
||||||
lua\append ")"
|
lua\append ")"
|
||||||
return lua
|
return lua
|
||||||
|
|
||||||
@define_compile_action "Lua %source %code", get_line_no!, (_source, _code)=>
|
@define_compile_action "Lua %source %code", (_source, _code)=>
|
||||||
lua = Lua.Value(@source, "Lua(", _source\as_lua(nomsu))
|
lua = Lua.Value(@source, "Lua(", _source\as_lua(nomsu))
|
||||||
add_lua_bits(lua, _code)
|
add_lua_bits(lua, _code)
|
||||||
lua\append ")"
|
lua\append ")"
|
||||||
return lua
|
return lua
|
||||||
|
|
||||||
@define_compile_action "Lua value %code", get_line_no!, (_code)=>
|
@define_compile_action "Lua value %code", (_code)=>
|
||||||
lua = Lua.Value(@source, "Lua.Value(", tostring(_code.source))
|
lua = Lua.Value(@source, "Lua.Value(", tostring(_code.source))
|
||||||
add_lua_bits(lua, _code)
|
add_lua_bits(lua, _code)
|
||||||
lua\append ")"
|
lua\append ")"
|
||||||
return lua
|
return lua
|
||||||
|
|
||||||
@define_compile_action "Lua value %source %code", get_line_no!, (_source, _code)=>
|
@define_compile_action "Lua value %source %code", (_source, _code)=>
|
||||||
lua = Lua.Value(@source, "Lua.Value(", _source\as_lua(nomsu))
|
lua = Lua.Value(@source, "Lua.Value(", _source\as_lua(nomsu))
|
||||||
add_lua_bits(lua, _code)
|
add_lua_bits(lua, _code)
|
||||||
lua\append ")"
|
lua\append ")"
|
||||||
return lua
|
return lua
|
||||||
|
|
||||||
@define_compile_action "lua> %code", get_line_no!, (_code)=>
|
@define_compile_action "lua> %code", (_code)=>
|
||||||
if _code.type != "Text"
|
if _code.type != "Text"
|
||||||
return Lua.Value @source, "nomsu:run_lua(Lua(",repr(_code.source),
|
return Lua.Value @source, "nomsu:run_lua(Lua(",repr(_code.source),
|
||||||
", ",repr(tostring(_code\as_lua(nomsu))),"))"
|
", ",repr(tostring(_code\as_lua(nomsu))),"))"
|
||||||
@ -642,7 +505,7 @@ class NomsuCompiler
|
|||||||
lua\append bit_lua
|
lua\append bit_lua
|
||||||
return lua
|
return lua
|
||||||
|
|
||||||
@define_compile_action "=lua %code", get_line_no!, (_code)=>
|
@define_compile_action "=lua %code", (_code)=>
|
||||||
if _code.type != "Text"
|
if _code.type != "Text"
|
||||||
return Lua.Value @source, "nomsu:run_lua(Lua(",repr(_code.source),
|
return Lua.Value @source, "nomsu:run_lua(Lua(",repr(_code.source),
|
||||||
", ",repr(tostring(_code\as_lua(nomsu))),"))"
|
", ",repr(tostring(_code\as_lua(nomsu))),"))"
|
||||||
@ -659,13 +522,13 @@ class NomsuCompiler
|
|||||||
lua\append bit_lua
|
lua\append bit_lua
|
||||||
return lua
|
return lua
|
||||||
|
|
||||||
@define_compile_action "!! code location !!", get_line_no!, =>
|
@define_compile_action "!! code location !!", =>
|
||||||
return Lua.Value(@source, repr(tostring(@source)))
|
return Lua.Value(@source, repr(tostring(@source)))
|
||||||
|
|
||||||
@define_action "run file %filename", get_line_no!, (_filename)->
|
@define_action "run file %filename", (_filename)->
|
||||||
return nomsu\run_file(_filename)
|
return nomsu\run_file(_filename)
|
||||||
|
|
||||||
@define_compile_action "use %path", get_line_no!, (_path)=>
|
@define_compile_action "use %path", (_path)=>
|
||||||
path = nomsu\tree_to_value(_path)
|
path = nomsu\tree_to_value(_path)
|
||||||
nomsu\use_file(path)
|
nomsu\use_file(path)
|
||||||
return Lua(@source, "nomsu:use_file(#{repr path});")
|
return Lua(@source, "nomsu:use_file(#{repr path});")
|
||||||
@ -730,9 +593,13 @@ OPTIONS
|
|||||||
else debug_getinfo(thread,f,what)
|
else debug_getinfo(thread,f,what)
|
||||||
if not info or not info.func then return info
|
if not info or not info.func then return info
|
||||||
if info.short_src or info.source or info.linedefine or info.currentline
|
if info.short_src or info.source or info.linedefine or info.currentline
|
||||||
|
for k,v in pairs(nomsu.environment.ACTIONS)
|
||||||
|
if v == info.func
|
||||||
|
info.name = k
|
||||||
|
break
|
||||||
|
[=[
|
||||||
if metadata = nomsu.action_metadata[info.func]
|
if metadata = nomsu.action_metadata[info.func]
|
||||||
info.name = metadata.aliases[1]
|
info.name = metadata.aliases[1]
|
||||||
[=[
|
|
||||||
filename = if type(metadata.source) == 'string'
|
filename = if type(metadata.source) == 'string'
|
||||||
metadata.source\match("^[^[:]*")
|
metadata.source\match("^[^[:]*")
|
||||||
else metadata.source.filename
|
else metadata.source.filename
|
||||||
@ -815,7 +682,6 @@ OPTIONS
|
|||||||
else io.stdout
|
else io.stdout
|
||||||
|
|
||||||
nomsu.skip_precompiled = not args.optimized
|
nomsu.skip_precompiled = not args.optimized
|
||||||
compile_fn = nil
|
|
||||||
if print_file == nil
|
if print_file == nil
|
||||||
nomsu.environment.print = ->
|
nomsu.environment.print = ->
|
||||||
elseif print_file != io.stdout
|
elseif print_file != io.stdout
|
||||||
@ -828,10 +694,11 @@ OPTIONS
|
|||||||
print_file\write('\n')
|
print_file\write('\n')
|
||||||
print_file\flush!
|
print_file\flush!
|
||||||
|
|
||||||
if output_file
|
compile_fn = if output_file
|
||||||
compile_fn = (code)->
|
(code)->
|
||||||
output_file\write("local IMMEDIATE = true;\n"..tostring(code))
|
output_file\write("local IMMEDIATE = true;\n"..tostring(code))
|
||||||
output_file\flush!
|
output_file\flush!
|
||||||
|
else nil
|
||||||
|
|
||||||
parse_errs = {}
|
parse_errs = {}
|
||||||
for input in *args.inputs
|
for input in *args.inputs
|
||||||
|
@ -63,6 +63,9 @@ Tree "File",
|
|||||||
nomsu\append "\n"
|
nomsu\append "\n"
|
||||||
return nomsu
|
return nomsu
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
|
||||||
|
|
||||||
Tree "Nomsu",
|
Tree "Nomsu",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
Lua.Value(@source, "nomsu:parse(Nomsu(",repr(@value.source),", ",repr(tostring(@value.source\get_text!)),")).value[1]")
|
Lua.Value(@source, "nomsu:parse(Nomsu(",repr(@value.source),", ",repr(tostring(@value.source\get_text!)),")).value[1]")
|
||||||
@ -74,6 +77,9 @@ Tree "Nomsu",
|
|||||||
return nomsu and Nomsu(@source, "\\:\n ", nomsu)
|
return nomsu and Nomsu(@source, "\\:\n ", nomsu)
|
||||||
return nomsu and Nomsu(@source, "\\(", nomsu, ")")
|
return nomsu and Nomsu(@source, "\\(", nomsu, ")")
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
fn(self) or @with_value(@value\map(fn))
|
||||||
|
|
||||||
Tree "Block",
|
Tree "Block",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
lua = Lua(@source)
|
lua = Lua(@source)
|
||||||
@ -103,24 +109,24 @@ Tree "Block",
|
|||||||
nomsu\append "\n"
|
nomsu\append "\n"
|
||||||
return nomsu
|
return nomsu
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
|
||||||
|
|
||||||
math_expression = re.compile [[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]]
|
math_expression = re.compile [[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]]
|
||||||
Tree "Action",
|
Tree "Action",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
stub = @get_stub!
|
stub = @get_stub!
|
||||||
action = rawget(nomsu.environment.ACTIONS, stub)
|
macro = nomsu.environment.MACROS[stub]
|
||||||
metadata = nomsu.action_metadata[action]
|
if macro
|
||||||
if metadata and metadata.compile_time
|
|
||||||
args = [arg for arg in *@value when arg.type != "Word"]
|
args = [arg for arg in *@value when arg.type != "Word"]
|
||||||
-- Force all compile-time actions to take a tree location
|
-- Force all compile-time actions to take a tree location
|
||||||
if metadata.arg_orders
|
args = [args[p-1] for p in *nomsu.environment.ARG_ORDERS[macro][stub]]
|
||||||
new_args = [args[p-1] for p in *metadata.arg_orders[stub]]
|
|
||||||
args = new_args
|
|
||||||
-- Force Lua to avoid tail call optimization for debugging purposes
|
-- Force Lua to avoid tail call optimization for debugging purposes
|
||||||
ret = action(self, unpack(args))
|
ret = macro(self, unpack(args))
|
||||||
return ret
|
return ret
|
||||||
|
action = rawget(nomsu.environment.ACTIONS, stub)
|
||||||
lua = Lua.Value(@source)
|
lua = Lua.Value(@source)
|
||||||
if not metadata and math_expression\match(stub)
|
if not action and math_expression\match(stub)
|
||||||
-- This is a bit of a hack, but this code handles arbitrarily complex
|
-- This is a bit of a hack, but this code handles arbitrarily complex
|
||||||
-- math expressions like 2*x + 3^2 without having to define a single
|
-- math expressions like 2*x + 3^2 without having to define a single
|
||||||
-- action for every possibility.
|
-- action for every possibility.
|
||||||
@ -148,8 +154,8 @@ Tree "Action",
|
|||||||
error "#{line}: Cannot use:\n#{colored.yellow src}\nas an argument to #{stub}, since it's not an expression, it produces: #{repr arg_lua}", 0
|
error "#{line}: Cannot use:\n#{colored.yellow src}\nas an argument to #{stub}, since it's not an expression, it produces: #{repr arg_lua}", 0
|
||||||
insert args, arg_lua
|
insert args, arg_lua
|
||||||
|
|
||||||
if metadata and metadata.arg_orders
|
if action
|
||||||
args = [args[p] for p in *metadata.arg_orders[stub]]
|
args = [args[p] for p in *nomsu.environment.ARG_ORDERS[action][stub]]
|
||||||
|
|
||||||
-- Not really worth bothering with ACTIONS.foo(...) style since almost every action
|
-- Not really worth bothering with ACTIONS.foo(...) style since almost every action
|
||||||
-- has arguments, so it won't work
|
-- has arguments, so it won't work
|
||||||
@ -228,6 +234,8 @@ Tree "Action",
|
|||||||
next_space = "\n.."
|
next_space = "\n.."
|
||||||
return nomsu
|
return nomsu
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
|
||||||
|
|
||||||
Tree "Text",
|
Tree "Text",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
@ -296,6 +304,9 @@ Tree "Text",
|
|||||||
nomsu\append "\n .."
|
nomsu\append "\n .."
|
||||||
return nomsu
|
return nomsu
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
fn(self) or @with_value(Tuple(unpack([type(v) == 'string' and v or v\map(fn) for v in *@value])))
|
||||||
|
|
||||||
Tree "List",
|
Tree "List",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
lua = Lua.Value @source, "{"
|
lua = Lua.Value @source, "{"
|
||||||
@ -357,6 +368,9 @@ Tree "List",
|
|||||||
nomsu\append line
|
nomsu\append line
|
||||||
return nomsu
|
return nomsu
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
|
||||||
|
|
||||||
Tree "Dict",
|
Tree "Dict",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
lua = Lua.Value @source, "{"
|
lua = Lua.Value @source, "{"
|
||||||
@ -441,6 +455,10 @@ Tree "Dict",
|
|||||||
nomsu\append line
|
nomsu\append line
|
||||||
return nomsu
|
return nomsu
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
DictEntry = Types.DictEntry
|
||||||
|
fn(self) or @with_value(Tuple(unpack([DictEntry(e.key\map(fn), e.value\map(fn)) for e in *@value])))
|
||||||
|
|
||||||
Tree "IndexChain",
|
Tree "IndexChain",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
lua = @value[1]\as_lua(nomsu)
|
lua = @value[1]\as_lua(nomsu)
|
||||||
@ -479,6 +497,9 @@ Tree "IndexChain",
|
|||||||
nomsu\append bit_nomsu
|
nomsu\append bit_nomsu
|
||||||
return nomsu
|
return nomsu
|
||||||
|
|
||||||
|
map: (fn)=>
|
||||||
|
fn(self) or @with_value(Tuple(unpack([v\map(fn) for v in *@value])))
|
||||||
|
|
||||||
Tree "Number",
|
Tree "Number",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
Lua.Value(@source, tostring(@value))
|
Lua.Value(@source, tostring(@value))
|
||||||
@ -486,6 +507,8 @@ Tree "Number",
|
|||||||
as_nomsu: (inline=false)=>
|
as_nomsu: (inline=false)=>
|
||||||
return Nomsu(@source, tostring(@value))
|
return Nomsu(@source, tostring(@value))
|
||||||
|
|
||||||
|
map: (fn)=> fn(self) or self
|
||||||
|
|
||||||
Tree "Var",
|
Tree "Var",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
lua_id = "_"..(@value\gsub "%W", (verboten)->
|
lua_id = "_"..(@value\gsub "%W", (verboten)->
|
||||||
@ -495,6 +518,8 @@ Tree "Var",
|
|||||||
as_nomsu: (inline=false)=>
|
as_nomsu: (inline=false)=>
|
||||||
return Nomsu(@source, "%", @value)
|
return Nomsu(@source, "%", @value)
|
||||||
|
|
||||||
|
map: (fn)=> fn(self) or self
|
||||||
|
|
||||||
Tree "Word",
|
Tree "Word",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
error("Attempt to convert Word to lua")
|
error("Attempt to convert Word to lua")
|
||||||
@ -502,6 +527,8 @@ Tree "Word",
|
|||||||
as_nomsu: (inline=false)=>
|
as_nomsu: (inline=false)=>
|
||||||
return Nomsu(@source, @value)
|
return Nomsu(@source, @value)
|
||||||
|
|
||||||
|
map: (fn)=> fn(self) or self
|
||||||
|
|
||||||
Tree "Comment",
|
Tree "Comment",
|
||||||
as_lua: (nomsu)=>
|
as_lua: (nomsu)=>
|
||||||
Lua(@source, "--"..@value\gsub("\n","\n--").."\n")
|
Lua(@source, "--"..@value\gsub("\n","\n--").."\n")
|
||||||
@ -513,4 +540,6 @@ Tree "Comment",
|
|||||||
else
|
else
|
||||||
return Nomsu(@source, "#", @value)
|
return Nomsu(@source, "#", @value)
|
||||||
|
|
||||||
|
map: (fn)=> fn(self) or self
|
||||||
|
|
||||||
return Types
|
return Types
|
||||||
|
@ -7,7 +7,6 @@ assume ((["x","y"] joined with ",") = "x,y") or barf "joined with failed"
|
|||||||
assume ((["x","y"] joined) = "xy") or barf "joined failed"
|
assume ((["x","y"] joined) = "xy") or barf "joined failed"
|
||||||
assume (("asdf" capitalized) = "Asdf") or barf "capitalized failed"
|
assume (("asdf" capitalized) = "Asdf") or barf "capitalized failed"
|
||||||
assume (("asdf" with "X" instead of "s") = "aXdf") or barf "substitution failed"
|
assume (("asdf" with "X" instead of "s") = "aXdf") or barf "substitution failed"
|
||||||
# TODO: add tests for indent/dedent
|
|
||||||
assume ("\n" = (newline)) or barf "Text literals failed."
|
assume ("\n" = (newline)) or barf "Text literals failed."
|
||||||
%x <- "\(green)hello\(reset color)"
|
%x <- "\(green)hello\(reset color)"
|
||||||
assume (("x" + "y") = "xy")
|
assume (("x" + "y") = "xy")
|
||||||
|
Loading…
Reference in New Issue
Block a user