Skip to content

Commit 6dd62c7

Browse files
committed
Fixed function arguments for macros: @insert func(function() return a,b end)
1 parent 1bc940c commit 6dd62c7

File tree

3 files changed

+94
-64
lines changed

3 files changed

+94
-64
lines changed

preprocess.lua

Lines changed: 80 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ local F, tryToFormatError
213213
local getFileContents, fileExists
214214
local getLineNumber
215215
local getNextUsableToken
216+
local getRelativeLocationText
216217
local insertTokenRepresentations
217218
local isAny
218219
local isToken, isTokenAndNotNil
@@ -535,9 +536,9 @@ function _tokenize(s, path, allowMetaTokens, allowBacktickStrings, allowJitSynta
535536

536537
if tok.long then
537538
-- Check for nesting of [[...]], which is depricated in Lua.
538-
local mainChunk, err = loadLuaString("--"..tok.representation, "")
539+
local mainChunk, err = loadLuaString("--"..tok.representation, "@")
539540
if not mainChunk then
540-
local lnInString, _err = err:match'^%[string ""%]:(%d+): (.*)'
541+
local lnInString, _err = err:match'^:(%d+): (.*)'
541542
if not _err then
542543
return nil, errorInFile(s, path, reprStart, "Tokenizer", "Malformed long comment.")
543544
end
@@ -619,9 +620,9 @@ function _tokenize(s, path, allowMetaTokens, allowBacktickStrings, allowJitSynta
619620
end
620621

621622
-- Check for nesting of [[...]], which is depricated in Lua.
622-
local valueChunk, err = loadLuaString("return"..tok.representation, "")
623+
local valueChunk, err = loadLuaString("return"..tok.representation, "@")
623624
if not valueChunk then
624-
local lnInString, _err = err:match'^%[string ""%]:(%d+): (.*)'
625+
local lnInString, _err = err:match'^:(%d+): (.*)'
625626
if not _err then
626627
return nil, errorInFile(s, path, reprStart, "Tokenizer", "Malformed long string.")
627628
end
@@ -1092,6 +1093,20 @@ end
10921093

10931094

10941095

1096+
-- getRelativeLocationText( tokenOfInterest, otherToken )
1097+
-- getRelativeLocationText( tokenOfInterest, otherFilename, otherLineNumber )
1098+
function getRelativeLocationText(tokOfInterest, otherFilename, otherLn)
1099+
if type(otherFilename) == "table" then
1100+
return getRelativeLocationText(tokOfInterest, otherFilename.file, otherFilename.line)
1101+
end
1102+
1103+
if tokOfInterest.file ~= otherFilename then return F("at %s:%d", tokOfInterest.file, tokOfInterest.line) end
1104+
if tokOfInterest.line ~= otherLn then return F("on line %d", tokOfInterest.line) end
1105+
return "on the same line"
1106+
end
1107+
1108+
1109+
10951110
--==============================================================
10961111
--= Preprocessor Functions =====================================
10971112
--==============================================================
@@ -1712,28 +1727,30 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
17121727
local bracketDepth = 1
17131728

17141729
while true do
1715-
if not tokenStack[1] then
1730+
tok = tokenStack[#tokenStack]
1731+
1732+
if not tok then
17161733
errorAtToken(fileBuffers, tableStartTok, nil, "Macro", "Syntax error: Could not find end of table constructor before EOF.")
17171734

17181735
-- @Copypaste from above. @Cleanup
1719-
elseif isLastToken(tokenStack, "pp_keyword", "file") then
1736+
elseif isToken(tok, "pp_keyword", "file") then
17201737
local ppKwTokInner = table.remove(tokenStack) -- "@file"
17211738
table.insert(argTokens, newTokenAt({type="string", value=ppKwTokInner.file, representation=F("%q",ppKwTokInner.file)}, ppKwTokInner))
1722-
elseif isLastToken(tokenStack, "pp_keyword", "line") then
1739+
elseif isToken(tok, "pp_keyword", "line") then
17231740
local ppKwTokInner = table.remove(tokenStack) -- "@line"
17241741
table.insert(argTokens, newTokenAt({type="number", value=ppKwTokInner.line, representation=F("%d",ppKwTokInner.line)}, ppKwTokInner))
17251742

1726-
elseif tokenStack[#tokenStack].type:find"^pp_" then
1727-
errorAtToken(fileBuffers, tokenStack[#tokenStack], nil, "Macro", "Preprocessor code not supported in macros.")
1743+
elseif tok.type:find"^pp_" then
1744+
errorAtToken(fileBuffers, tok, nil, "Macro", "Preprocessor code not supported in macros. (Macro starting %s)", getRelativeLocationText(ppKeywordTok, tok))
17281745

1729-
elseif bracketDepth == 1 and isLastToken(tokenStack, "punctuation", "}") then
1746+
elseif bracketDepth == 1 and isToken(tok, "punctuation", "}") then
17301747
table.insert(argTokens, table.remove(tokenStack))
17311748
break
17321749

17331750
else
1734-
if isLastToken(tokenStack, "punctuation", "{") then
1751+
if isToken(tok, "punctuation", "{") then
17351752
bracketDepth = bracketDepth + 1
1736-
elseif isLastToken(tokenStack, "punctuation", "}") then
1753+
elseif isToken(tok, "punctuation", "}") then
17371754
bracketDepth = bracketDepth - 1
17381755
end
17391756
table.insert(argTokens, table.remove(tokenStack))
@@ -1791,37 +1808,62 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
17911808
for argNum = 1, 1/0 do
17921809
local argStartTok = tokenStack[#tokenStack]
17931810
local argTokens = {}
1794-
local parensDepth = 0
1811+
local depthStack = {}
17951812
popUseless(tokenStack)
17961813

17971814
-- Collect tokens for this arg.
17981815
while true do
1799-
if not tokenStack[1] then
1816+
tok = tokenStack[#tokenStack]
1817+
1818+
if not tok then
18001819
errorAtToken(fileBuffers, parensStartTok, nil, "Macro", "Syntax error: Could not find end of argument list before EOF.")
18011820

18021821
-- @Copypaste from above. @Cleanup
1803-
elseif isLastToken(tokenStack, "pp_keyword", "file") then
1822+
elseif isToken(tok, "pp_keyword", "file") then
18041823
local ppKwTokInner = table.remove(tokenStack) -- "@file"
18051824
table.insert(argTokens, newTokenAt({type="string", value=ppKwTokInner.file, representation=F("%q",ppKwTokInner.file)}, ppKwTokInner))
1806-
elseif isLastToken(tokenStack, "pp_keyword", "line") then
1825+
elseif isToken(tok, "pp_keyword", "line") then
18071826
local ppKwTokInner = table.remove(tokenStack) -- "@line"
18081827
table.insert(argTokens, newTokenAt({type="number", value=ppKwTokInner.line, representation=F("%d",ppKwTokInner.line)}, ppKwTokInner))
18091828

1810-
elseif tokenStack[#tokenStack].type:find"^pp_" then
1811-
errorAtToken(fileBuffers, tokenStack[#tokenStack], nil, "Macro", "Preprocessor code not supported in macros.")
1829+
elseif tok.type:find"^pp_" then
1830+
errorAtToken(fileBuffers, tok, nil, "Macro", "Preprocessor code not supported in macros. (Macro starting %s)", getRelativeLocationText(ppKeywordTok, tok))
18121831

1813-
elseif parensDepth == 0 and isLastToken(tokenStack, "punctuation", ",") then
1814-
break
1815-
1816-
elseif parensDepth == 0 and isLastToken(tokenStack, "punctuation", ")") then
1832+
elseif not depthStack[1] and (isToken(tok, "punctuation", ",") or isToken(tok, "punctuation", ")")) then
18171833
break
18181834

18191835
else
1820-
if isLastToken(tokenStack, "punctuation", "(") then
1821-
parensDepth = parensDepth + 1
1822-
elseif isLastToken(tokenStack, "punctuation", ")") then
1823-
parensDepth = parensDepth - 1
1836+
if isToken(tok, "punctuation", "(") then
1837+
table.insert(depthStack, {startToken=tok, [1]="punctuation", [2]=")"})
1838+
elseif isToken(tok, "punctuation", "[") then
1839+
table.insert(depthStack, {startToken=tok, [1]="punctuation", [2]="]"})
1840+
elseif isToken(tok, "punctuation", "{") then
1841+
table.insert(depthStack, {startToken=tok, [1]="punctuation", [2]="}"})
1842+
elseif isToken(tok, "keyword", "function") or isToken(tok, "keyword", "if") or isToken(tok, "keyword", "do") then
1843+
table.insert(depthStack, {startToken=tok, [1]="keyword", [2]="end"})
1844+
elseif isToken(tok, "keyword", "repeat") then
1845+
table.insert(depthStack, {startToken=tok, [1]="keyword", [2]="until"})
1846+
1847+
elseif
1848+
isToken(tok, "punctuation", ")") or
1849+
isToken(tok, "punctuation", "]") or
1850+
isToken(tok, "punctuation", "}") or
1851+
isToken(tok, "keyword", "end") or
1852+
isToken(tok, "keyword", "until")
1853+
then
1854+
if not depthStack[1] then
1855+
errorAtToken(fileBuffers, tok, nil, "Macro", "Unexpected '%s'.", tok.value)
1856+
elseif not isToken(tok, unpack(depthStack[#depthStack])) then
1857+
local startTok = depthStack[#depthStack].startToken
1858+
errorAtToken(
1859+
fileBuffers, tok, nil, "Macro",
1860+
"Expected '%s' (to end '%s' %s) but got '%s'.",
1861+
depthStack[#depthStack][2], startTok.value, getRelativeLocationText(startTok, tok), tok.value
1862+
)
1863+
end
1864+
table.remove(depthStack)
18241865
end
1866+
18251867
table.insert(argTokens, table.remove(tokenStack))
18261868
end
18271869
end
@@ -1837,7 +1879,7 @@ local function processKeywords(tokensRaw, fileBuffers, params, stats)
18371879
end
18381880
local argStr = table.concat(parts)
18391881

1840-
local chunk, err = loadLuaString("return "..argStr, "@")
1882+
local chunk, err = loadLuaString("return ("..argStr..")", "@")
18411883
if not chunk then
18421884
errorAtToken(fileBuffers, argTokens[1], nil, "Macro", "Syntax error: Invalid expression for argument #%d.", argNum)
18431885
-- err = err:gsub("^:%d+: ", "")
@@ -2106,7 +2148,7 @@ local function _processFileOrString(params, isFile)
21062148
end--outputFinalDualValueStatement()
21072149

21082150
-- Note: Can be multiple lines if extended.
2109-
local function processMetaLine(isDual, metaStartFile, metaStartLine)
2151+
local function processMetaLine(isDual, metaStartTok)
21102152
local metaLineIndexStart = tokenIndex
21112153
local bracketBalance = 0
21122154

@@ -2115,20 +2157,11 @@ local function _processFileOrString(params, isFile)
21152157

21162158
if not tok then
21172159
if bracketBalance ~= 0 then
2118-
errorAtToken(
2119-
fileBuffers, tokens[tokenIndex-1], #fileBuffers[tokens[tokenIndex-1].file], "Parser",
2120-
"Unexpected end-of-data. Preprocessor line"..(
2121-
tokens[tokenIndex-1].file == metaStartFile and tokens[tokenIndex-1].line == metaStartLine
2122-
and ""
2123-
or " (starting at %s:%d)"
2124-
).." has unbalanced brackets.",
2125-
metaStartFile, metaStartLine
2126-
)
2127-
2128-
elseif isDual then
2160+
errorAtToken(fileBuffers, metaStartTok, nil, "Parser", "Preprocessor line has unbalanced brackets. (Reached EOF.)")
2161+
end
2162+
if isDual then
21292163
outputFinalDualValueStatement(metaLineIndexStart, tokenIndex-1)
21302164
end
2131-
21322165
return
21332166
end
21342167

@@ -2169,28 +2202,20 @@ local function _processFileOrString(params, isFile)
21692202
return
21702203

21712204
elseif tokType == "pp_entry" then
2172-
errorAtToken(
2173-
fileBuffers, tok, nil, "Parser",
2174-
"Preprocessor token inside metaprogram"
2175-
..(tok.file == metaStartFile and tok.line == metaStartLine and "." or " (starting at %s:%d)."),
2176-
metaStartFile, metaStartLine
2177-
)
2205+
errorAtToken(fileBuffers, tok, nil, "Parser", "Preprocessor token inside metaprogram (starting %s).", getRelativeLocationText(metaStartTok, tok))
21782206

21792207
else
21802208
table.insert(metaParts, tok.representation)
21812209

21822210
if tokType == "punctuation" and isAny(tok.value, "(","{","[") then
2183-
bracketBalance = bracketBalance+1
2211+
bracketBalance = bracketBalance + 1
21842212
elseif tokType == "punctuation" and isAny(tok.value, ")","}","]") then
2185-
bracketBalance = bracketBalance-1
2186-
2213+
bracketBalance = bracketBalance - 1
21872214
if bracketBalance < 0 then
21882215
errorAtToken(
21892216
fileBuffers, tok, nil, "Parser",
2190-
"Unexpected '%s'. Preprocessor line"
2191-
..(tok.file == metaStartFile and tok.line == metaStartLine and "" or " (starting at %s:%d)")
2192-
.." has unbalanced brackets.",
2193-
tok.value, metaStartFile, metaStartLine
2217+
"Unexpected '%s'. Preprocessor line (starting %s) has unbalanced brackets.",
2218+
tok.value, getRelativeLocationText(metaStartTok, tok)
21942219
)
21952220
end
21962221
end
@@ -2239,16 +2264,7 @@ local function _processFileOrString(params, isFile)
22392264
if depth == 0 then break end
22402265

22412266
elseif tokType == "pp_entry" then
2242-
errorAtToken(
2243-
fileBuffers, tok, nil, "Parser",
2244-
"Preprocessor token inside metaprogram"..(
2245-
tok.file == startToken.file and tok.line == startToken.line
2246-
and "."
2247-
or " (starting at %s:%d)."
2248-
),
2249-
startToken.file,
2250-
startToken.line
2251-
)
2267+
errorAtToken(fileBuffers, tok, nil, "Parser", "Preprocessor token inside metaprogram (starting %s).", getRelativeLocationText(startToken, tok))
22522268
end
22532269

22542270
table.insert(tokensInBlock, tok)
@@ -2293,7 +2309,7 @@ local function _processFileOrString(params, isFile)
22932309
flushTokensToProcess()
22942310

22952311
tokenIndex = tokenIndex+1
2296-
processMetaLine(tok.double, tok.file, tok.line)
2312+
processMetaLine(tok.double, tok)
22972313

22982314
-- Non-meta.
22992315
--------------------------------

tests/quickTest.lua2p

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ local ok = 1==1
110110
local s = @insert PASS_THROUGH "foo"
111111
local t = @insert PASS_THROUGH { 496, b=true }
112112

113+
local f = @insert PASS_THROUGH(function(a, b)
114+
while true do
115+
repeat until arePlanetsAligned("mars", "jupiter")
116+
break
117+
end
118+
return "", nil
119+
end)
120+
113121

114122

115123
-- Misc.

tests/runTests.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,12 @@ doTest("Preprocessor keywords", function()
232232
]]})
233233
assertCodeOutput(luaOut, [[t = {}]])
234234

235+
local luaOut = assert(pp.processString{ code=[[
236+
!function echo(v) return v end
237+
f = @insert echo(function() return a,b end)
238+
]]})
239+
assertCodeOutput(luaOut, [[f = function() return a,b end]])
240+
235241
-- Invalid: Ambiguous syntax.
236242
local luaOut = pp.processString{ code=[[
237243
!function void() return "" end

0 commit comments

Comments
 (0)