symbol.lua
Branches > main > 302c951 > files / org / faddle / lang / symbol.lua
-- Symbol type
-- Interned and immutable outside of rawset
local symbol_registry = setmetatable({}, {__mode = "v"})
-- TODO is this lua's whole identifier namespace?
-- Also needs to support `.f`, +, -, ?, ->, etc, probably, if that's how I want to do this (bi-directional munging to lua names)
local symbol_regex = "^[%a_][%w_]*$"
local SYMBOL_METATABLE = {}
local NAME = {}
local MODULE = {}
local NEWINDEX = function() error("Cannot mutate list!") end
local function is_valid_part(s)
return s:match(symbol_regex) ~= nil
end
local function is_valid_symbol(module, name)
if name == nil then
if module == "." then return true end
return is_valid_part(module)
else
return is_valid_part(module) and is_valid_part(name)
end
end
local function is_symbol(x)
return getmetatable(x) == SYMBOL_METATABLE
end
local function name(sym)
if is_symbol(sym) then
return sym[NAME]
else
error("Cannot get the symbol name of type " .. type(sym), 2)
end
end
local function module(sym)
if is_symbol(sym) then
return sym[MODULE]
else
error("Cannot get the symbol table of type " .. type(sym), 2)
end
end
-- Eventually munge these names.
-- I guess table is referring to any table but perhaps it should refer strictly to an aliased module...
-- Maybe should be 'module'
local function intern(m, n)
if not is_valid_symbol(m, n) then
error("Cannot intern invalid symbol!", 2)
end
if n == nil then
n = m
m = nil
end
local id = (m or "") .. ":" .. n
if not symbol_registry[id] then
symbol_registry[id] = setmetatable({}, {__newindex = NEWINDEX, __index = {[NAME] = n, [MODULE] = m}, __metatable = SYMBOL_METATABLE})
end
return symbol_registry[id]
end
-- local function munge(sym) end
-- local function demunge(sym) end ?
return {is_symbol = is_symbol, intern = intern, is_valid_symbol = is_valid_symbol, name = name, module = module}