1
0
Fork 0
mirror of https://github.com/Reuh/anselme.git synced 2025-10-27 16:49:31 +00:00
anselme/state/translation_manager.lua

78 lines
2.6 KiB
Lua

local class = require("class")
local ast = require("ast")
local Table, Identifier
local translations_identifier, translations_symbol
local translation_manager = class {
init = false,
setup = function(self, state)
state.scope:define(translations_symbol, Table:new(state))
end,
-- context is the context Struct - when translating, the translation will only be used for nodes that at least match this context
-- original is the original node (non-evaluated)
-- translated is the translated node (non-evaluated)
set = function(self, state, context, original, translated)
local translations = state.scope:get(translations_identifier)
if not translations:has(state, original) then
translations:set(state, original, Table:new(state))
end
local tr = translations:get(state, original)
return tr:set(state, context, translated)
end,
-- context is the context Struct of the calling translation
-- original is the original node to translate (non-evaluated)
-- returns the (evaluated) translated node, or the original node if no translation defined
eval = function(self, state, context, original)
local translations = state.scope:get(translations_identifier)
if translations:has(state, original) then
local tr = translations:get(state, original)
-- find most specific translation
local translated, specificity = nil, -1
for match_context, match_translated in tr:iter(state) do
local matched, match_specificity = true, 0
for key, val in match_context:iter() do
if context:has(key) and val:hash() == context:get(key):hash() then
match_specificity = match_specificity + 1
else
matched = false
break
end
end
if matched then
if match_specificity > specificity then
translated, specificity = match_translated, match_specificity
elseif match_specificity == specificity then
print("a a dà é payé")
end
end
end
-- found, evaluate translated
if translated then
-- eval in a scope where all active translations, as translating the translation would be stupid
state.scope:push_partial(translations_identifier)
state.scope:define(translations_symbol, Table:new(state))
local r = translated:eval(state)
state.scope:pop()
return r
end
end
-- no matching translation
return original.expression:eval(state)
end,
}
package.loaded[...] = translation_manager
Table, Identifier = ast.Table, ast.Identifier
translations_identifier = Identifier:new("_translations") -- Table of { Translatable = Table{ Struct context = translated node, ... }, ... }
translations_symbol = translations_identifier:to_symbol()
return translation_manager