aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-08-31 15:21:47 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-08-31 15:22:32 -0700
commite1bc075bb5319b3903f66e141810dcb9ef53042e (patch)
tree734035fe118971150c7e9a4aaaa32511926d0caf
parentee10b788e30a06d6da2676e1af49da9c094f07ee (diff)
Removing the "A_" prefix on action names, and improving the quality of
as_lua_id() (guaranteed injectivity).
-rw-r--r--core/metaprogramming.nom12
-rw-r--r--lib/object.nom6
-rw-r--r--nomsu_compiler.lua33
-rw-r--r--nomsu_compiler.moon29
4 files changed, 43 insertions, 37 deletions
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 0f894b8..0f64bac 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -94,13 +94,13 @@ test:
assume ((foo 1) == "outer")
compile [local action %actions %body] to:
lua> ".."
- local fn_name = "A_"..string.as_lua_id(\%actions[1].stub)
+ local fn_name = string.as_lua_id(\%actions[1].stub)
local \%args = table.map(\%actions[1]:get_args(), function(a) return tostring(nomsu:compile(a)) end)
local lua = LuaCode(tree.source, fn_name, " = ", \(compile as (%args -> %body)))
lua:add_free_vars({fn_name})
for i=2,#\%actions do
local alias = \%actions[i]
- local alias_name = "A_"..string.as_lua_id(alias.stub)
+ local alias_name = string.as_lua_id(alias.stub)
lua:add_free_vars({alias_name})
local \%alias_args = table.map(alias:get_args(), function(a) return tostring(nomsu:compile(a)) end)
lua:append("\\n", alias_name, " = ")
@@ -125,11 +125,11 @@ test:
compile [action %actions %body] to (..)
lua> ".."
local lua = \(compile as (local action %actions %body))
- lua:remove_free_vars(table.map(\%actions, function(a) return "A_"..string.as_lua_id(a.stub) end))
+ lua:remove_free_vars(table.map(\%actions, function(a) return string.as_lua_id(a.stub) end))
return lua
test:
- assume ((action (say %)) == (=lua "A_say_1"))
+ assume ((action (say %)) == (=lua "say_1"))
compile [action %action] to (Lua value (%action as lua id))
test:
@@ -209,7 +209,7 @@ compile [%tree as lua return] to (..)
Lua value "nomsu:compile(\(%tree as lua expr)):as_statements('return ')"
compile [remove action %action] to (..)
- Lua "A_\(=lua "string.as_lua_id(\(%action.stub))") = nil"
+ Lua "\(=lua "string.as_lua_id(\(%action.stub))") = nil"
test:
assume ("\(\(foo \%x) as nomsu)" == "foo %x") or barf ".."
@@ -224,7 +224,7 @@ action [%var as lua identifier, %var as lua id] (..)
lua> ".."
if type(\%var) == 'string' then return string.as_lua_id(\%var)
elseif \%var.type == 'Var' then return "_"..string.as_lua_id(\%var[1])
- elseif \%var.type == 'Action' then return "A_"..string.as_lua_id(\%var.stub)
+ elseif \%var.type == 'Action' then return string.as_lua_id(\%var.stub)
end
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/lib/object.nom b/lib/object.nom
index 6aa0630..8d59190 100644
--- a/lib/object.nom
+++ b/lib/object.nom
@@ -84,9 +84,9 @@ compile [object %classname extends %parent %class_body] to:
return inst
end,
})
- nomsu["A_"..string.as_lua_id("new "..class.name)] = class
- nomsu["A_"..string.as_lua_id("new "..class.name.." 1")] = class
- nomsu["A_"..string.as_lua_id(class.name)] = function() return class end
+ nomsu[string.as_lua_id("new "..class.name)] = class
+ nomsu[string.as_lua_id("new "..class.name.." 1")] = class
+ nomsu[string.as_lua_id(class.name)] = function() return class end
class.__index = class
class.class = class
class.__tostring = function(inst)
diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua
index 11bdc9d..f37960f 100644
--- a/nomsu_compiler.lua
+++ b/nomsu_compiler.lua
@@ -37,7 +37,8 @@ local AST = require("syntax_tree")
local Parser = require("parser")
SOURCE_MAP = { }
string.as_lua_id = function(str)
- str = gsub(str, "x([0-9A-F][0-9A-F])", "x\0%1")
+ str = gsub(str, "^\0*$", "%1\0")
+ str = gsub(str, "x([0-9A-F][0-9A-F])", "x78%1")
str = gsub(str, "%W", function(c)
if c == ' ' then
return '_'
@@ -45,16 +46,19 @@ string.as_lua_id = function(str)
return format("x%02X", byte(c))
end
end)
+ str = str:gsub("^_*%d", "_%1")
return str
end
-table.map = function(self, fn)
- local _accum_0 = { }
- local _len_0 = 1
- for _, v in ipairs(self) do
- _accum_0[_len_0] = fn(v)
- _len_0 = _len_0 + 1
- end
- return _accum_0
+table.map = function(t, fn)
+ return setmetatable((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _, v in ipairs(t) do
+ _accum_0[_len_0] = fn(v)
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), getmetatable(t))
end
table.fork = function(t, values)
return setmetatable(values or { }, {
@@ -106,7 +110,7 @@ local NomsuCompiler = setmetatable({
end
})
do
- NomsuCompiler.NOMSU_COMPILER_VERSION = 5
+ NomsuCompiler.NOMSU_COMPILER_VERSION = 6
NomsuCompiler.NOMSU_SYNTAX_VERSION = Parser.version
NomsuCompiler.nomsu = NomsuCompiler
NomsuCompiler.parse = function(self, ...)
@@ -489,10 +493,10 @@ do
NomsuCompiler.compile = function(self, tree)
if tree.version then
do
- local get_version = self['A_' .. string.as_lua_id("Nomsu version")]
+ local get_version = self[string.as_lua_id("Nomsu version")]
if get_version then
do
- local upgrade = self['A_' .. string.as_lua_id("1 upgraded from 2 to 3")]
+ local upgrade = self[string.as_lua_id("1 upgraded from 2 to 3")]
if upgrade then
tree = upgrade(tree, tree.version, get_version())
end
@@ -529,11 +533,6 @@ do
local lua = LuaCode.Value(tree.source)
if tree.target then
lua:append(self:compile(tree.target), ":")
- if string.as_lua_id(stub):match("^[0-9]") then
- lua:append("_")
- end
- else
- lua:append("A_")
end
lua:append(string.as_lua_id(stub), "(")
local args = { }
diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon
index 70e3f40..439285e 100644
--- a/nomsu_compiler.moon
+++ b/nomsu_compiler.moon
@@ -29,16 +29,27 @@ Parser = require("parser")
export SOURCE_MAP
SOURCE_MAP = {}
+-- Convert an arbitrary string into a valid Lua identifier. This function is injective,
+-- but not idempotent, i.e. if (x != y) then (as_lua_id(x) != as_lua_id(y)),
+-- but as_lua_id(x) is not necessarily equal to as_lua_id(as_lua_id(x))
string.as_lua_id = (str)->
- -- Cut up escape-sequence-like chunks
- str = gsub str, "x([0-9A-F][0-9A-F])", "x\0%1"
- -- Alphanumeric unchanged, spaces to underscores, and everything else to hex escape sequences
+ -- Empty strings are not valid lua identifiers, so treat them like "\0",
+ -- and treat "\0" as "\0\0", etc. to preserve injectivity.
+ str = gsub str, "^\0*$", "%1\0"
+ -- Escape 'x' when it precedes something that looks like an uppercase hex sequence.
+ -- This way, all Lua IDs can be unambiguously reverse-engineered, but normal usage
+ -- of 'x' won't produce ugly Lua IDs.
+ -- i.e. "x" -> "x", "oxen" -> "oxen", but "Hex2Dec" -> "Hex782Dec" and "He-ec" -> "Hex2Dec"
+ str = gsub str, "x([0-9A-F][0-9A-F])", "x78%1"
+ -- Map spaces to underscores, and everything else non-alphanumeric to hex escape sequences
str = gsub str, "%W", (c)->
if c == ' ' then '_'
else format("x%02X", byte(c))
+ -- Lua IDs can't start with numbers, so map "1" -> "_1", "_1" -> "__1", etc.
+ str = str\gsub "^_*%d", "_%1"
return str
-table.map = (fn)=> [fn(v) for _,v in ipairs(@)]
+table.map = (t, fn)-> setmetatable([fn(v) for _,v in ipairs(t)], getmetatable(t))
table.fork = (t, values)-> setmetatable(values or {}, {__index:t})
table.copy = (t)-> setmetatable({k,v for k,v in pairs(t)}, getmetatable(t))
@@ -63,7 +74,7 @@ NomsuCompiler = setmetatable {name:"Nomsu"},
__index: (k)=> if _self = rawget(@, "self") then _self[k] else nil
__tostring: => @name
with NomsuCompiler
- .NOMSU_COMPILER_VERSION = 5
+ .NOMSU_COMPILER_VERSION = 6
.NOMSU_SYNTAX_VERSION = Parser.version
.nomsu = NomsuCompiler
.parse = (...)=> Parser.parse(...)
@@ -312,8 +323,8 @@ with NomsuCompiler
.compile = (tree)=>
if tree.version
- if get_version = @['A_'..string.as_lua_id("Nomsu version")]
- if upgrade = @['A_'..string.as_lua_id("1 upgraded from 2 to 3")]
+ if get_version = @[string.as_lua_id("Nomsu version")]
+ if upgrade = @[string.as_lua_id("1 upgraded from 2 to 3")]
tree = upgrade(tree, tree.version, get_version!)
switch tree.type
when "Action"
@@ -331,10 +342,6 @@ with NomsuCompiler
lua = LuaCode.Value(tree.source)
if tree.target
lua\append @compile(tree.target), ":"
- if string.as_lua_id(stub)\match("^[0-9]")
- lua\append "_"
- else
- lua\append "A_"
lua\append(string.as_lua_id(stub),"(")
args = {}
for i, tok in ipairs tree