Skip to content

Commit 71d9de0

Browse files
committed
Added callMacro().
1 parent 44cad22 commit 71d9de0

File tree

2 files changed

+63
-14
lines changed

2 files changed

+63
-14
lines changed

preprocess.lua

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
Only during processing:
2929
- getCurrentPathIn, getCurrentPathOut
3030
- getOutputSoFar, getOutputSoFarOnLine, getOutputSizeSoFar, getCurrentLineNumberInOutput, getCurrentIndentationInOutput
31-
- loadResource
31+
- loadResource, callMacro
3232
- outputValue, outputLua, outputLuaTemplate
3333
- startInterceptingOutput, stopInterceptingOutput
3434
Macros:
@@ -209,6 +209,8 @@ local current_parsing_insertCount = 0
209209
local current_parsingAndMeta_onInsert = nil
210210
local current_parsingAndMeta_fileBuffers = nil
211211
local current_parsingAndMeta_addLineNumbers = false
212+
local current_parsingAndMeta_macroPrefix = ""
213+
local current_parsingAndMeta_macroSuffix = ""
212214
local current_parsingAndMeta_strictMacroArguments = true
213215
local current_meta_pathForErrorMessages = ""
214216
local current_meta_outputStack = nil
@@ -1997,7 +1999,6 @@ function metaFuncs.getNextUsefulToken(tokens, i1, steps)
19971999
end
19982000

19992001
local numberFormatters = {
2000-
-- @Incomplete: Hexadecimal floats.
20012002
auto = function(n) return tostring(n) end,
20022003
integer = function(n) return F("%d", n) end,
20032004
int = function(n) return F("%d", n) end,
@@ -2247,6 +2248,32 @@ function metaFuncs.loadResource(resourceName)
22472248
return (_loadResource(resourceName, false, 2))
22482249
end
22492250

2251+
local function isCallable(v)
2252+
return type(v) == "function"
2253+
-- We use debug.getmetatable instead of _G.getmetatable because we don't want to
2254+
-- potentially invoke user code - we just want to know if the value is callable.
2255+
or (type(v) == "table" and debug.getmetatable(v) ~= nil and type(debug.getmetatable(v).__call) == "function")
2256+
end
2257+
2258+
-- callMacro()
2259+
-- luaString = callMacro( macroName, argument1, ... )
2260+
-- Call a macro function (which must be a global in metaEnvironment).
2261+
-- The arguments should be Lua code strings.
2262+
function metaFuncs.callMacro(name, ...)
2263+
errorIfNotRunningMeta(2)
2264+
2265+
local nameResult = current_parsingAndMeta_macroPrefix .. name .. current_parsingAndMeta_macroSuffix
2266+
local f = metaEnv[nameResult]
2267+
2268+
if not isCallable(f) then
2269+
if name == nameResult
2270+
then errorf(2, "'%s' is not a macro/global function. (Got %s)", name, type(f))
2271+
else errorf(2, "'%s' (resolving to '%s') is not a macro/global function. (Got %s)", name, nameResult, type(f)) end
2272+
end
2273+
2274+
return (metaEnv.__M()(f(...)))
2275+
end
2276+
22502277
-- :PredefinedMacros
22512278

22522279
-- ASSERT()
@@ -2379,13 +2406,7 @@ function metaEnv.__ARG(locTokNum, v)
23792406
end
23802407

23812408
function metaEnv.__EVAL(v) -- For symbols.
2382-
if
2383-
type(v) == "function"
2384-
-- We use debug.getmetatable instead of _G.getmetatable because we
2385-
-- don't want to potentially invoke user code right here - we just
2386-
-- want to know if the value is callable.
2387-
or (type(v) == "table" and debug.getmetatable(v) and debug.getmetatable(v).__call)
2388-
then
2409+
if isCallable(v) then
23892410
v = v()
23902411
end
23912412
return v
@@ -2609,12 +2630,8 @@ end
26092630

26102631
-- outTokens = doExpansions( params, tokensToExpand, stats )
26112632
local function doExpansions(params, tokens, stats)
2612-
local macroPrefix = params.macroPrefix or ""
2613-
local macroSuffix = params.macroSuffix or ""
2614-
26152633
tokens = doEarlyExpansions(tokens, stats)
26162634
tokens = doLateExpansions (tokens, stats, params.backtickStrings, params.jitSyntax) -- Resources.
2617-
26182635
return tokens
26192636
end
26202637

@@ -2908,7 +2925,7 @@ local function astParseMacro(params, tokens)
29082925
local initialCalleeIdentTok = tokNext
29092926

29102927
-- Add macro prefix and suffix. (Note: We only edit the initial identifier in the callee if there are more.)
2911-
initialCalleeIdentTok.value = (params.macroPrefix or "") .. initialCalleeIdentTok.value .. (params.macroSuffix or "")
2928+
initialCalleeIdentTok.value = current_parsingAndMeta_macroPrefix .. initialCalleeIdentTok.value .. current_parsingAndMeta_macroSuffix
29122929
initialCalleeIdentTok.representation = initialCalleeIdentTok.value
29132930

29142931
-- Maybe add '.field[expr]:method' for rest of callee.
@@ -3486,6 +3503,8 @@ local function _processFileOrString(params, isFile)
34863503
current_parsingAndMeta_fileBuffers = {[virtualPathIn]=luaUnprocessed} -- Doesn't have to be the contents of files if params.onInsert() is defined.
34873504
current_parsingAndMeta_onInsert = params.onInsert
34883505
current_parsingAndMeta_addLineNumbers = params.addLineNumbers
3506+
current_parsingAndMeta_macroPrefix = params.macroPrefix or ""
3507+
current_parsingAndMeta_macroSuffix = params.macroSuffix or ""
34893508
current_parsingAndMeta_strictMacroArguments = params.strictMacroArguments ~= false
34903509
current_meta_locationTokens = {}
34913510

@@ -3654,6 +3673,8 @@ local function _processFileOrString(params, isFile)
36543673
current_parsingAndMeta_fileBuffers = nil
36553674
current_parsingAndMeta_onInsert = nil
36563675
current_parsingAndMeta_addLineNumbers = false
3676+
current_parsingAndMeta_macroPrefix = ""
3677+
current_parsingAndMeta_macroSuffix = ""
36573678
current_parsingAndMeta_strictMacroArguments = true
36583679

36593680
if isFile then
@@ -3712,6 +3733,8 @@ local function processFileOrString(params, isFile)
37123733
current_parsingAndMeta_onInsert = nil
37133734
current_parsingAndMeta_fileBuffers = nil
37143735
current_parsingAndMeta_addLineNumbers = false
3736+
current_parsingAndMeta_macroPrefix = ""
3737+
current_parsingAndMeta_macroSuffix = ""
37153738
current_parsingAndMeta_strictMacroArguments = true
37163739
current_meta_pathForErrorMessages = ""
37173740
current_meta_outputStack = nil

tests/suite.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,8 @@ end)
729729
doTest("Misc.", function()
730730
local pp = ppChunk()
731731

732+
-- metaEnvironment is a shallow copy of _G.
733+
assert(pp.metaEnvironment ~= _G)
732734
assert(pp.metaEnvironment.table == table)
733735

734736
-- Natural comparisons.
@@ -763,6 +765,30 @@ doTest("Misc.", function()
763765
)
764766
y = 2
765767
]]})
768+
769+
-- Macros.
770+
local luaOut = assert(pp.processString{ code=[[
771+
!!(callMacro("ASSERT", "x", "foo()"))
772+
]]})
773+
assertCodeOutput(luaOut, "if not (x) then error((foo())) end")
774+
775+
local luaOut = assert(pp.processString{ macroPrefix="MACRO_", code=[[
776+
!function _G.MACRO_MOO() return "foo()" end -- Must be global!
777+
!!(callMacro("MOO"))
778+
]]})
779+
assertCodeOutput(luaOut, "foo()")
780+
pp.metaEnvironment.MACRO_MOO = nil
781+
782+
assert(not pp.processString{ macroPrefix="MACRO_", code=[[
783+
!local function MACRO_MOO() return "foo()" end -- Not a global!
784+
!!(callMacro("MOO"))
785+
]]})
786+
787+
assert(not pp.processString{ macroPrefix="MACRO_", code=[[
788+
!function _G.MACRO_MOO() return "foo()" end
789+
!!(callMacro("MACRO_MOO")) -- Calls MACRO_MACRO_MOO!
790+
]]})
791+
pp.metaEnvironment.MACRO_MOO = nil
766792
end)
767793

768794

0 commit comments

Comments
 (0)