aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/metaprogramming.nom27
-rw-r--r--lua_obj.moon24
-rw-r--r--nomsu.lua82
-rwxr-xr-xnomsu.moon62
4 files changed, 76 insertions, 119 deletions
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index f01e59a..5d6b59c 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -26,7 +26,7 @@ immediately:
end
local body_lua = nomsu:tree_to_lua(\%lua):as_statements();
body_lua:declare_locals(args);
- lua:append("\n ", body_lua, "\nend);")
+ lua:append("\\n ", body_lua, "\\nend);")
return lua;
end);
@@ -51,7 +51,7 @@ immediately:
end
local body_lua = nomsu:tree_to_lua(\%lua):as_statements();
body_lua:declare_locals(args);
- lua:append("\n ", body_lua, "\nend);")
+ lua:append("\\n ", body_lua, "\\nend);")
return lua;
# Macro to make nomsu macros:
@@ -76,10 +76,10 @@ immediately:
local template;
if \%longhand.type == "Block" then
local lines = {};
- for i, line in ipairs(\%longhand.value) do lines[i] = nomsu:get_source_code(line); end
+ for i, line in ipairs(\%longhand.value) do lines[i] = line.source:get_text(); end
template = repr(table.concat(lines, "\\n"));
else
- template = repr(nomsu:get_source_code(\%longhand));
+ template = repr(\%longhand.source:get_text());
end
local replacements = {};
for i, a in ipairs(args) do replacements[i] = a.."="..a; end
@@ -109,19 +109,16 @@ immediately:
action [%tree as lua expr]:
lua> ".."
local lua = nomsu:tree_to_lua(\%tree);
- if lua.locals or not lua.expr then
- error("Invalid thing to convert to lua expr: "..nomsu:get_source_code(\%tree));
+ if not lua.is_value then
+ error("Invalid thing to convert to lua expr: "..\%tree.source:get_text());
end
- return lua.expr;
+ return lua;
action [%tree as lua statements]:
lua> ".."
- local lua = nomsu:tree_to_lua(\%tree);
- local code = lua.statements or (lua.expr..";");
- if lua.locals then
- code = "local "..table.concat(lua.locals, ", ")..";\\n"..code;
- end
- return code;
+ local lua = nomsu:tree_to_lua(\%tree):as_statements();
+ lua:declare_locals();
+ return lua;
action [%tree as value]:
=lua "nomsu:tree_to_value(\%tree)"
@@ -130,7 +127,7 @@ immediately:
=lua "nomsu:tree_to_stub(\%tree)"
immediately:
- compile [%tree's source code, %tree' source code] to {expr:"nomsu:get_source_code(\(%tree as lua expr))"}
+ compile [%tree's source code, %tree' source code] to {expr:"\(%tree as lua expr).source:get_text()"}
compile [repr %obj] to {expr:"repr(\(%obj as lua expr))"}
compile [type of %obj] to {expr:"type(\(%obj as lua expr))"}
@@ -190,7 +187,7 @@ immediately:
compile [barf] to {statements:"error(nil, 0);"}
compile [barf %msg] to {statements:"error(\(%msg as lua expr), 0);"}
compile [assume %condition] to:
- lua> "local \%assumption = 'Assumption failed: '..nomsu:get_source_code(\%condition);"
+ lua> "local \%assumption = 'Assumption failed: '..\%condition.source:get_text();"
return {..}
statements:".."
if not \(%condition as lua expr) then
diff --git a/lua_obj.moon b/lua_obj.moon
index ba2d0bb..1565fcb 100644
--- a/lua_obj.moon
+++ b/lua_obj.moon
@@ -1,10 +1,12 @@
{:insert, :remove, :concat} = table
immutable = require 'immutable'
local Lua, LuaValue, Location
+export LINE_STARTS
Location = immutable {"text_name","text","start","stop"}, {
- __new: (text_name, text, start, stop)-> text_name, text, start, stop or start
- __tostring: "#{text_name}[#{start}:#{stop}]"
+ name:"Location"
+ __new: (text_name, text, start, stop)=> text_name, text, start, stop or start
+ __tostring: => "#{@text_name}[#{@start}:#{@stop}]"
__lt: (other)=>
assert(@text == other.text, "Cannot compare sources from different texts")
return if @start == other.start
@@ -20,10 +22,10 @@ Location = immutable {"text_name","text","start","stop"}, {
-- TODO: do a binary search if this is actually slow, which I doubt
line_starts = LINE_STARTS[@text]
start_line = 1
- while start_line < #line_starts and line_starts[start_line+1] <= @start
+ while (line_starts[start_line+1] or (#src+1)) <= @start
start_line += 1
stop_line = start_line
- while stop_line < #line_starts and line_starts[stop_line+1] <= @stop
+ while (line_starts[stop_line+1] or (#src+1)) <= @stop
stop_line += 1
return start_line, stop_line
get_line: => "#{@text_name}:#{@get_line_number}"
@@ -38,7 +40,7 @@ class Lua
is_statement: true
is_value: false
- __new: (@source, ...)=>
+ new: (@source, ...)=>
@bits = {...}
@free_vars = {}
@@ -63,11 +65,7 @@ class Lua
__tostring: =>
buff = {}
for b in *@bits
- if type(b) == 'string'
- buff[#buff+1] = b
- else
- for sub in *b\render!
- buff[#buff+1] = sub
+ buff[#buff+1] = tostring(b)
return concat(buff, "")
__len: =>
@@ -105,7 +103,7 @@ class Lua
lua_offset += #lua
else
lua_start = lua_offset
- for b in lua.bits
+ for b in *lua.bits
walk b
lua_stop = lua_offset
nomsu_src, lua_src = lua.souce, Location(lua_chunkname, lua_str, lua_start, lua_stop)
@@ -118,7 +116,7 @@ class LuaValue extends Lua
is_statement: false
is_value: true
- __new: (@source, ...)=>
+ new: (@source, ...)=>
@bits = {...}
as_statements: =>
@@ -130,4 +128,4 @@ class LuaValue extends Lua
@prepend "("
@append ")"
-return {:Lua, :LuaValue}
+return {:Lua, :LuaValue, :Location}
diff --git a/nomsu.lua b/nomsu.lua
index 30bad0f..2bd41b8 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -27,6 +27,11 @@ do
insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
end
local debug_getinfo = debug.getinfo
+local Lua, LuaValue, Location
+do
+ local _obj_0 = require("lua_obj")
+ Lua, LuaValue, Location = _obj_0.Lua, _obj_0.LuaValue, _obj_0.Location
+end
local FILE_CACHE = setmetatable({ }, {
__index = function(self, filename)
local file = io.open(filename)
@@ -44,7 +49,7 @@ local line_counter = re.compile([[ lines <- {| line (%nl line)* |}
]], {
nl = P("\r") ^ -1 * P("\n")
})
-local LINE_STARTS = setmetatable({ }, {
+LINE_STARTS = setmetatable({ }, {
__mode = "k",
__index = function(self, k)
local line_starts = line_counter:match(k)
@@ -83,16 +88,7 @@ end
local Types = { }
local type_tostring
type_tostring = function(self)
- return tostring(self.name) .. "(" .. tostring(concat((function()
- local _accum_0 = { }
- local _len_0 = 1
- for _index_0 = 1, #self do
- local x = self[_index_0]
- _accum_0[_len_0] = repr(x)
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)(), ", ")) .. ")"
+ return tostring(self.name) .. "(" .. tostring(repr(self.value)) .. ")"
end
local type_with_value
type_with_value = function(self, value)
@@ -200,12 +196,12 @@ do
pos = pos + #lpeg.userdata.source_code:match("[ \t\n\r]*", pos)
end
local line_no = 1
- local text_loc = Source(lpeg.userdata.filename, src, pos)
+ local text_loc = Location(lpeg.userdata.filename, src, pos)
line_no = text_loc:get_line_number()
local prev_line = src:sub(LINE_STARTS[src][line_no - 1] or 1, LINE_STARTS[src][line_no] - 1)
local err_line = src:sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no + 1] or 0) - 1)
local next_line = src:sub(LINE_STARTS[src][line_no + 1] or -1, (LINE_STARTS[src][line_no + 2] or 0) - 1)
- local pointer = ("-"):rep(pos - LINE_STARTS[line_no]) .. "^"
+ local pointer = ("-"):rep(pos - LINE_STARTS[src][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)
@@ -219,7 +215,7 @@ setmetatable(NOMSU_DEFS, {
if type(value) == 'table' then
error("Not a tuple: " .. tostring(repr(value)))
end
- local loc = Source(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
+ local loc = Location(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
local node = Types[key](value, loc)
return node
end
@@ -360,13 +356,6 @@ do
end
return code:gsub("\n", "\n" .. (" "):rep(levels))
end,
- get_source_code = function(self, tree)
- local metadata = self.tree_metadata[tree]
- if not (metadata) then
- return self:tree_to_nomsu(tree)
- end
- return self:dedent(metadata.source_code:sub(metadata.start, metadata.stop - 1))
- end,
parse = function(self, nomsu_code, filename)
assert(type(filename) == "string", "Bad filename type: " .. tostring(type(filename)))
local userdata = {
@@ -374,8 +363,7 @@ do
filename = filename,
indent_stack = {
""
- },
- tree_metadata = self.tree_metadata
+ }
}
local old_userdata
old_userdata, lpeg.userdata = lpeg.userdata, userdata
@@ -461,12 +449,12 @@ do
_chunk_counter = _chunk_counter + 1
filename = "<lua chunk #" .. tostring(_chunk_counter) .. ">"
else
- filename = lua.source.filename .. ".lua"
+ filename = lua.source.text_name .. ".lua"
end
end
if type(lua) ~= 'string' then
local metadata
- lua, metadata = make_offset_table(filename)
+ lua, metadata = lua:make_offset_table(filename)
LUA_METADATA[lua] = metadata
end
local run_lua_fn, err = load(lua, filename, "t", self.environment)
@@ -487,7 +475,7 @@ do
return tree.value[1]
end
local lua = Lua(tree.source, "return ", self:tree_to_lua(tree), ";")
- return self:run_lua(lua, tree.source.filename)
+ return self:run_lua(lua, tree.source.text_name)
end,
tree_to_nomsu = function(self, tree, indentation, max_line, expr_type)
if indentation == nil then
@@ -885,7 +873,7 @@ do
tree_to_lua = function(self, tree)
assert(tree, "No tree provided.")
if not Types.is_node(tree) then
- error("Invalid tree: " .. tostring(repr(tree)), 0)
+ error("Invalid tree")
end
local _exp_0 = tree.type
if "File" == _exp_0 then
@@ -894,25 +882,23 @@ do
end
local file_lua = Lua(tree.source)
local declared_locals = { }
- local _list_1 = tree.value
- for _index_0 = 1, #_list_1 do
- local line = _list_1[_index_0]
+ for i, line in ipairs(tree.value) do
local line_lua = self:tree_to_lua(line)
if not line_lua then
error("No lua produced by " .. tostring(repr(line)), 0)
end
- local lua = lua:as_statements()
+ line_lua = line_lua:as_statements()
if i < #tree.value then
file_lua:append("\n")
end
- file_lua:append(lua)
+ file_lua:append(line_lua)
end
file_lua:declare_locals()
return file_lua
elseif "Comment" == _exp_0 then
return Lua(tree.source, "--" .. tree.value:gsub("\n", "\n--"))
elseif "Nomsu" == _exp_0 then
- return Lua(tree.source, "nomsu:parse(", tree.source:get_text(), ", ", repr(tree.source.filename), ")")
+ return Lua(tree.source, "nomsu:parse(", tree.source:get_text(), ", ", repr(tree.source.text_name), ")")
elseif "Block" == _exp_0 then
local block_lua = Lua(tree.source)
for i, arg in ipairs(tree.value) do
@@ -947,7 +933,6 @@ do
end
args = _accum_0
end
- table.insert(args, 1, tree.source)
if metadata and metadata.arg_orders then
local new_args
do
@@ -1002,7 +987,7 @@ do
local line, src = tok.source:get_line(), tok.source:get_text()
error(tostring(line) .. ": Cannot use:\n" .. tostring(colored.yellow(src)) .. "\nas an argument to " .. tostring(stub) .. ", since it's not an expression, it produces: " .. tostring(repr(arg_lua)), 0)
end
- insert(args, lua)
+ insert(args, arg_lua)
_continue_0 = true
until true
if not _continue_0 then
@@ -1402,7 +1387,7 @@ do
lua:append(bit)
else
local bit_lua = nomsu:tree_to_lua(bit)
- if not (lua.is_value) then
+ if not (bit_lua.is_value) then
local line, src = bit.source:get_line(), bit.source:get_text()
error(tostring(line) .. ": Cannot use " .. tostring(colored.yellow(src)) .. " as a string interpolation value, since it's not an expression.", 0)
end
@@ -1434,16 +1419,9 @@ do
end)
self:define_compile_action("!! code location !!", get_line_no(), function()
local tree = nomsu.compilestack[#nomsu.compilestack - 1]
- local metadata = self.tree_metadata[tree]
- if metadata then
- return LuaValue(tree.source, {
- repr(tostring(metadata.filename) .. ":" .. tostring(metadata.start) .. "," .. tostring(metadata.stop))
- })
- else
- return LuaValue(tree.source, {
- repr("<dynamically generated>")
- })
- end
+ return LuaValue(tree.source, {
+ repr(tostring(tree.source))
+ })
end)
self:define_action("run file %filename", get_line_no(), function(_filename)
return nomsu:run_file(_filename)
@@ -1624,20 +1602,16 @@ if arg and debug_getinfo(2).func ~= require then
if not info or not info.func then
return info
end
- if info.source and NOMSU_LINE_TABLES[info.source] then
+ if info.source and info.source:sub(1, 1) ~= "@" and LINE_STARTS[info.source] then
do
local metadata = nomsu.action_metadata[info.func]
if metadata then
info.name = metadata.aliases[1]
end
end
- info.short_src = NOMSU_SOURCE_FILE[info.source]
- lua_line_to_nomsu_line(info.source, info)
- info.short_src = metadata.source.text_name
- info.source = metadata.source.text
- info.linedefined = metadata.source:get_line_number()
- info.currentline = LUA_LINE_TO_NOMSU_LINE[metadata.source.filename][info.currentline]
- local name = colored.bright(colored.yellow(metadata.aliases[1]))
+ if info.source:sub(1, 1) == "@" then
+ error("Not-yet-loaded source: " .. tostring(info.source))
+ end
else
if info.short_src and info.short_src:match("^.*%.moon$") then
local line_table = moonscript_line_tables[info.short_src]
diff --git a/nomsu.moon b/nomsu.moon
index a74191c..e736128 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -23,6 +23,7 @@ colors = setmetatable({}, {__index:->""})
colored = setmetatable({}, {__index:(_,color)-> ((msg)-> colors[color]..tostring(msg or '')..colors.reset)})
{:insert, :remove, :concat} = table
debug_getinfo = debug.getinfo
+{:Lua, :LuaValue, :Location} = require "lua_obj"
-- TODO:
-- consider non-linear codegen, rather than doing thunks for things like comprehensions
@@ -49,6 +50,7 @@ line_counter = re.compile([[
line <- {} (!%nl .)*
]], nl:P("\r")^-1 * P("\n"))
-- Mapping from line number -> character offset
+export LINE_STARTS
LINE_STARTS = setmetatable {}, {
__mode:"k"
__index: (k)=>
@@ -86,7 +88,7 @@ do
Types = {}
type_tostring = =>
- "#{@name}(#{concat [repr(x) for x in *@], ", "})"
+ "#{@name}(#{repr(@value)})"
type_with_value = (value)=> getmetatable(self)(@source, value)
Tuple = immutable(nil, {name:"Tuple"})
for t in *{"File", "Nomsu", "Block", "List", "FunctionCall", "Text", "Dict", "Number", "Word", "Var", "Comment", "IndexChain"}
@@ -146,12 +148,12 @@ NOMSU_DEFS = with {}
if lpeg.userdata.source_code\sub(pos,pos)\match("[\r\n]")
pos += #lpeg.userdata.source_code\match("[ \t\n\r]*", pos)
line_no = 1
- text_loc = Source(lpeg.userdata.filename, src, pos)
+ text_loc = Location(lpeg.userdata.filename, src, pos)
line_no = text_loc\get_line_number!
prev_line = src\sub(LINE_STARTS[src][line_no-1] or 1, LINE_STARTS[src][line_no]-1)
err_line = src\sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no+1] or 0)-1)
next_line = src\sub(LINE_STARTS[src][line_no+1] or -1, (LINE_STARTS[src][line_no+2] or 0)-1)
- pointer = ("-")\rep(pos-LINE_STARTS[line_no]) .. "^"
+ pointer = ("-")\rep(pos-LINE_STARTS[src][line_no]) .. "^"
err_msg = (err_msg or "Parse error").." in #{lpeg.userdata.filename} on line #{line_no}:\n"
err_msg ..="\n#{prev_line}\n#{err_line}\n#{pointer}\n#{next_line}\n"
error(err_msg)
@@ -159,7 +161,7 @@ NOMSU_DEFS = with {}
setmetatable(NOMSU_DEFS, {__index:(key)=>
make_node = (start, value, stop)->
if type(value) == 'table' then error("Not a tuple: #{repr value}")-- = Tuple(value)
- loc = Source(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
+ loc = Location(lpeg.userdata.filename, lpeg.userdata.source_code, start, stop)
node = Types[key](value, loc)
return node
self[key] = make_node
@@ -279,19 +281,11 @@ class NomsuCompiler
indent: (code, levels=1)=>
return code\gsub("\n","\n"..(" ")\rep(levels))
- get_source_code: (tree)=>
- -- Return the (dedented) source code of a tree, or construct some if the tree was
- -- dynamically generated.
- metadata = @tree_metadata[tree]
- unless metadata
- return @tree_to_nomsu(tree)
- return @dedent metadata.source_code\sub(metadata.start, metadata.stop-1)
-
parse: (nomsu_code, filename)=>
assert type(filename) == "string", "Bad filename type: #{type filename}"
userdata = {
- source_code:nomsu_code, :filename, indent_stack: {""}, tree_metadata:@tree_metadata,
+ source_code:nomsu_code, :filename, indent_stack: {""}
}
old_userdata, lpeg.userdata = lpeg.userdata, userdata
@@ -355,9 +349,9 @@ class NomsuCompiler
_chunk_counter += 1
"<lua chunk ##{_chunk_counter}>"
else
- lua.source.filename..".lua"
+ lua.source.text_name..".lua"
if type(lua) != 'string'
- lua, metadata = make_offset_table(filename)
+ lua, metadata = lua\make_offset_table(filename)
LUA_METADATA[lua] = metadata
run_lua_fn, err = load(lua, filename, "t", @environment)
@@ -375,7 +369,7 @@ class NomsuCompiler
if tree.type == 'Text' and #tree.value == 1 and type(tree.value[1]) == 'string'
return tree.value[1]
lua = Lua(tree.source, "return ",@tree_to_lua(tree),";")
- return @run_lua(lua, tree.source.filename)
+ return @run_lua(lua, tree.source.text_name)
tree_to_nomsu: (tree, indentation="", max_line=80, expr_type=nil)=>
-- Convert a tree into nomsu code that satisfies the max line requirement or nil
@@ -640,22 +634,23 @@ class NomsuCompiler
-- Return <lua code for value>, <additional lua code>
assert tree, "No tree provided."
if not Types.is_node(tree)
- error("Invalid tree: #{repr(tree)}", 0)
+ --error("Invalid tree: #{repr(tree)}", 0)
+ error("Invalid tree")
switch tree.type
when "File"
if #tree.value == 1
return @tree_to_lua(tree.value[1])
file_lua = Lua(tree.source)
declared_locals = {}
- for line in *tree.value
+ for i, line in ipairs tree.value
line_lua = @tree_to_lua line
if not line_lua
error("No lua produced by #{repr line}", 0)
- lua = lua\as_statements!
+ line_lua = line_lua\as_statements!
if i < #tree.value
file_lua\append "\n"
- file_lua\append lua
+ file_lua\append line_lua
file_lua\declare_locals!
return file_lua
@@ -664,7 +659,7 @@ class NomsuCompiler
when "Nomsu"
--return Lua(tree.source, repr(tree.value))
- return Lua(tree.source, "nomsu:parse(",tree.source\get_text!,", ",repr(tree.source.filename),")")
+ return Lua(tree.source, "nomsu:parse(",tree.source\get_text!,", ",repr(tree.source.text_name),")")
when "Block"
block_lua = Lua(tree.source)
@@ -688,7 +683,6 @@ class NomsuCompiler
if metadata and metadata.compile_time
args = [arg for arg in *tree.value when arg.type != "Word"]
-- Force all compile-time actions to take a tree location
- table.insert args, 1, tree.source
if metadata and metadata.arg_orders
new_args = [args[p] for p in *metadata.arg_orders[stub]]
args = new_args
@@ -722,7 +716,7 @@ class NomsuCompiler
unless arg_lua.is_value
line, src = tok.source\get_line!, tok.source\get_text!
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, lua
+ insert args, arg_lua
if metadata and metadata.arg_orders
args = [args[p] for p in *metadata.arg_orders[stub]]
@@ -1023,7 +1017,7 @@ class NomsuCompiler
lua\append bit
else
bit_lua = nomsu\tree_to_lua bit
- unless lua.is_value
+ unless bit_lua.is_value
line, src = bit.source\get_line!, bit.source\get_text!
error "#{line}: Cannot use #{colored.yellow src} as a string interpolation value, since it's not an expression.", 0
lua\append bit_lua
@@ -1047,11 +1041,7 @@ class NomsuCompiler
@define_compile_action "!! code location !!", get_line_no!, ->
tree = nomsu.compilestack[#nomsu.compilestack-1]
- metadata = @tree_metadata[tree]
- if metadata
- return LuaValue(tree.source, {repr("#{metadata.filename}:#{metadata.start},#{metadata.stop}")})
- else
- return LuaValue(tree.source, {repr("<dynamically generated>")})
+ return LuaValue(tree.source, {repr(tostring(tree.source))})
@define_action "run file %filename", get_line_no!, (_filename)->
return nomsu\run_file(_filename)
@@ -1094,16 +1084,14 @@ if arg and debug_getinfo(2).func != require
debug.getinfo = (...)->
info = debug_getinfo(...)
if not info or not info.func then return info
- if info.source and NOMSU_LINE_TABLES[info.source]
+ if info.source and info.source\sub(1,1) != "@" and LINE_STARTS[info.source]
if metadata = nomsu.action_metadata[info.func]
info.name = metadata.aliases[1]
- info.short_src = NOMSU_SOURCE_FILE[info.source]
- lua_line_to_nomsu_line(info.source, info)
- info.short_src = metadata.source.text_name
- info.source = metadata.source.text
- info.linedefined = metadata.source\get_line_number!
- info.currentline = LUA_LINE_TO_NOMSU_LINE[metadata.source.filename][info.currentline]
- name = colored.bright(colored.yellow(metadata.aliases[1]))
+ if info.source\sub(1,1) == "@" then error("Not-yet-loaded source: #{info.source}")
+ --info.linedefined = lua_line_to_nomsu_line(info.short_src, info.linedefined)
+ --info.currentline = lua_line_to_nomsu_line(info.short_src, info.currentline)
+ --info.short_src = metadata.source.text_name
+ --info.source = metadata.source.text
else
if info.short_src and info.short_src\match("^.*%.moon$")
line_table = moonscript_line_tables[info.short_src]