Skip to content

Commit 4670621

Browse files
committed
Macro callees can now have simple lookups.
Link to new website.
1 parent 1d5d2fe commit 4670621

File tree

5 files changed

+86
-33
lines changed

5 files changed

+86
-33
lines changed

LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright © 2018 Marcus 'ReFreezed' Thunström
1+
Copyright © 2018-2021 Marcus 'ReFreezed' Thunström
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy
44
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ A separate [command line program](preprocess-cl.lua) is available too.
2121
- [Usage](#usage)
2222
- [Library](#preprocess-files-using-the-library)
2323
- [Command Line](#preprocess-files-from-the-command-line)
24-
- [Documentation](https://github.com/ReFreezed/LuaPreprocess/wiki)
24+
- [Documentation](http://luapreprocess.refreezed.com/docs/)
2525
- [Help](#help)
2626

2727

2828

2929
## Example Program
30-
The exclamation mark (!) is used to indicate what code is part of the metaprogram.
30+
31+
The exclamation mark (`!`) is used to indicate what code is part of the metaprogram.
3132
([See screenshot of processing steps with highlighting](https://raw.githubusercontent.com/ReFreezed/LuaPreprocess/master/misc/processingSteps.png))
3233

3334
```lua
@@ -75,6 +76,7 @@ local text = !("Precalculated hash: "..getHash())
7576
```
7677

7778
#### Output
79+
7880
```lua
7981
-- Normal Lua.
8082
local n = 0
@@ -111,13 +113,15 @@ See the [examples folder](examples) for more.
111113

112114

113115
## Usage
114-
First you need [Lua](https://www.lua.org/versions.html) installed on your system. (Binaries can be
116+
117+
First you need [Lua](https://www.lua.org/) installed on your system. (Binaries can be
115118
downloaded from [LuaBinaries via SourceForge](https://sourceforge.net/projects/luabinaries/files/5.1.5/Tools%20Executables/)
116119
if you don't want to, or can't, compile Lua from source. For Windows I can recommend installing
117120
[LuaForWindows](https://github.com/rjpcomputing/luaforwindows) which is a "batteries included" Lua package.)
118121

119122

120123
### Preprocess Files Using the Library
124+
121125
```lua
122126
local pp = require("preprocess")
123127

@@ -134,20 +138,22 @@ end
134138
print("Lines of code processed: "..info.lineCount)
135139
```
136140

137-
See the [wiki](https://github.com/ReFreezed/LuaPreprocess/wiki)
141+
See the [website](http://luapreprocess.refreezed.com/docs/)
138142
or the top of [preprocess.lua](preprocess.lua) for documentation.
139143

140144

141145
### Preprocess Files from the Command Line
142146

143147
#### Windows
148+
144149
```batch
145150
Preprocess.cmd [options] filepath1 [filepath2 ...]
146151
OR
147152
Preprocess.cmd --outputpaths [options] inputpath1 outputpath1 [inputpath2 outputpath2 ...]
148153
```
149154

150155
#### Any System
156+
151157
```batch
152158
lua preprocess-cl.lua [options] filepath1 [filepath2 ...]
153159
OR
@@ -156,20 +162,22 @@ lua preprocess-cl.lua --outputpaths [options] inputpath1 outputpath1 [inputpath2
156162

157163
If a filepath is, for example, `C:/MyApp/app.lua2p` then LuaPreprocess will write the processed file to `C:/MyApp/app.lua`.
158164

159-
See the [wiki](https://github.com/ReFreezed/LuaPreprocess/wiki/Command-Line),
165+
See the [website](http://luapreprocess.refreezed.com/docs/command-line/),
160166
or the top of [preprocess-cl.lua](preprocess-cl.lua)
161167
and [preprocess.lua](preprocess.lua), for the options and more documentation.
162168

163169

164170

165171
## Documentation
166-
- [Wiki](https://github.com/ReFreezed/LuaPreprocess/wiki)
172+
173+
- [Website](http://luapreprocess.refreezed.com/docs/)
167174
- Library: See the top of [preprocess.lua](preprocess.lua)
168175
- Command line: See the top of [preprocess-cl.lua](preprocess-cl.lua)
169176

170177

171178

172179
## Help
180+
173181
Got a question?
174182
Look if someone has asked the question in the [issue tracker](https://github.com/ReFreezed/LuaPreprocess/issues?q=is%3Aissue),
175183
or [create a new issue](https://github.com/ReFreezed/LuaPreprocess/issues/new).

preprocess-cl.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ exec lua "$0" "$@"
1010
--= Requires preprocess.lua to be in the same folder!
1111
--=
1212
--= License: MIT (see the bottom of this file)
13-
--= Website: https://github.com/ReFreezed/LuaPreprocess
13+
--= Website: http://luapreprocess.refreezed.com/
1414
--=
1515
--= Tested with Lua 5.1, 5.2, 5.3 and 5.4.
1616
--=

preprocess.lua

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
--= by Marcus 'ReFreezed' Thunström
55
--=
66
--= License: MIT (see the bottom of this file)
7-
--= Website: https://github.com/ReFreezed/LuaPreprocess
8-
--= Documentation: https://github.com/ReFreezed/LuaPreprocess/wiki
7+
--= Website: http://luapreprocess.refreezed.com/
8+
--= Documentation: http://luapreprocess.refreezed.com/docs/
99
--=
1010
--= Tested with Lua 5.1, 5.2, 5.3 and 5.4.
1111
--=
@@ -112,7 +112,7 @@
112112
-- Though in this specific case a preprocessor line (without the parenthesis) would be nicer:
113113
!func()
114114
115-
-- For the full documentation, see: https://github.com/ReFreezed/LuaPreprocess/wiki
115+
-- For the full documentation, see: http://luapreprocess.refreezed.com/docs/
116116
117117
--============================================================]]
118118

@@ -1942,7 +1942,11 @@ local function doLateExpansionsResources(tokensToExpand, fileBuffers, params, st
19421942
if isTokenAndNotNil(tokenStack[iNext+1], "whitespace") and tokenStack[iNext+1].value:find"\n" then
19431943
errorAtToken(fileBuffers, tokNext, nil, "Macro", "Ambiguous syntax near '(' - part of macro, or new statement?")
19441944
end
1945-
elseif not (isTokenAndNotNil(tokNext, "string") or isTokenAndNotNil(tokNext, "punctuation", "{")) then
1945+
1946+
elseif not (tokNext and (
1947+
tokNext.type == "string"
1948+
or (tokNext.type == "punctuation" and isAny(tokNext.value, "{",".",":"))
1949+
)) then
19461950
errorAtToken(fileBuffers, identTok, identTok.position+#identTok.representation, "Macro", "Syntax error: Expected '(' after macro name '%s'.", identTok.value)
19471951
end
19481952

@@ -2032,16 +2036,6 @@ end
20322036

20332037
local function expandMacro(tokens, fileBuffers, tokenStack, macroStartTok, isNested)
20342038
-- @Robustness: Make sure key tokens came from the same source file.
2035-
local tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack-1, nil, -1)
2036-
2037-
if not isTokenAndNotNil(tokNext, "identifier") then
2038-
printErrorTraceback("Internal error.")
2039-
errorAtToken(fileBuffers, tokNext, nil, "Macro", "Internal error. (%s)", (tokNext and tokNext.type or "?"))
2040-
end
2041-
2042-
local identTok = tokNext
2043-
popTokens(tokenStack, iNext) -- the identifier
2044-
20452039
-- Add '!!(' for start of preprocessor block.
20462040
if isNested then
20472041
tableInsert(tokens, newTokenAt({type="identifier", value="__ASSERTLUA", representation="__ASSERTLUA"}, macroStartTok))
@@ -2050,16 +2044,45 @@ local function expandMacro(tokens, fileBuffers, tokenStack, macroStartTok, isNes
20502044
end
20512045
tableInsert(tokens, newTokenAt({type="punctuation", value="(", representation="("}, macroStartTok))
20522046

2047+
-- Add 'ident' for start of (or whole) callee.
2048+
local tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack-1, nil, -1)
2049+
if not isTokenAndNotNil(tokNext, "identifier") then
2050+
printErrorTraceback("Internal error.")
2051+
errorAtToken(fileBuffers, tokNext, nil, "Macro", "Internal error. (%s)", (tokNext and tokNext.type or "?"))
2052+
end
2053+
popTokens(tokenStack, iNext) -- the identifier
2054+
tableInsert(tokens, tokNext)
2055+
local lastCalleeTok = tokNext
2056+
2057+
-- Maybe add '.field:method' for end of callee.
2058+
-- @Incomplete: @@name[expr]()
20532059
tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack, nil, -1)
20542060

2061+
while isTokenAndNotNil(tokNext, "punctuation") and (tokNext.value == "." or tokNext.value == ":") do
2062+
local punctTok = tokNext
2063+
local isMethodCall = (punctTok.value == ":")
2064+
2065+
popTokens(tokenStack, iNext) -- '.' or ':'
2066+
tableInsert(tokens, tokNext)
2067+
2068+
tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack, nil, -1)
2069+
if not tokNext then
2070+
errorAfterToken(fileBuffers, punctTok, "Macro", "Syntax error: Expected an identifier after '%s'.", punctTok.value)
2071+
end
2072+
popTokens(tokenStack, iNext) -- the identifier
2073+
tableInsert(tokens, tokNext)
2074+
lastCalleeTok = tokNext
2075+
2076+
tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack, nil, -1)
2077+
if isMethodCall then break end
2078+
end
2079+
20552080
-- @insert identifier " ... "
20562081
if isTokenAndNotNil(tokNext, "string") then
20572082
local stringTok = tokNext
20582083
popTokens(tokenStack, iNext) -- the string
20592084

2060-
-- Add 'ident' for start of call. We don't need parenthesis for this macro variant.
2061-
tableInsert(tokens, identTok)
2062-
2085+
-- Note: We don't need parenthesis for this macro variant.
20632086
stringTok.value = stringTok.representation
20642087
stringTok.representation = F("%q", stringTok.value):gsub("\n", "n")
20652088
tableInsert(tokens, stringTok)
@@ -2072,9 +2095,8 @@ local function expandMacro(tokens, fileBuffers, tokenStack, macroStartTok, isNes
20722095
-- (Similar code as `@insert identifier()` below.)
20732096
--
20742097

2075-
-- Add 'ident(' for start of call.
2076-
tableInsert(tokens, identTok)
2077-
tableInsert(tokens, newTokenAt({type="punctuation", value="(", representation="("}, identTok))
2098+
-- Add '(' for start of call.
2099+
tableInsert(tokens, newTokenAt({type="punctuation", value="(", representation="("}, tokNext))
20782100

20792101
-- Collect tokens for the table arg.
20802102
-- We're looking for the closing '}'.
@@ -2153,14 +2175,15 @@ local function expandMacro(tokens, fileBuffers, tokenStack, macroStartTok, isNes
21532175
else
21542176
if not isTokenAndNotNil(tokNext, "punctuation", "(") then
21552177
printErrorTraceback("Internal error.")
2156-
errorAtToken(fileBuffers, tokNext, nil, "Macro", "Internal error. (%s)", (tokNext and tokNext.type or "?"))
2178+
errorAfterToken(fileBuffers, lastCalleeTok, "Macro", "Syntax error: Expected '(' after macro name.")
2179+
elseif isTokenAndNotNil(tokenStack[iNext+1], "whitespace") and tokenStack[iNext+1].value:find"\n" then
2180+
errorAtToken(fileBuffers, tokNext, nil, "Macro", "Ambiguous syntax near '(' - part of macro, or new statement?")
21572181
end
21582182

21592183
local parensStartTok = tokNext
21602184
popTokens(tokenStack, iNext) -- '('
21612185

2162-
-- Add 'ident(' for start of call.
2163-
tableInsert(tokens, identTok)
2186+
-- Add '(' for start of call.
21642187
tableInsert(tokens, parensStartTok)
21652188

21662189
tokNext, iNext = getNextUsableToken(tokenStack, #tokenStack, nil, -1)
@@ -2943,7 +2966,7 @@ local pp = {
29432966
-- fastStrings = boolean -- [Optional] Force fast serialization of string values. (Non-ASCII characters will look ugly.) (Default: false)
29442967
-- validate = boolean -- [Optional] Validate output. (Default: true)
29452968
--
2946-
-- onInsert = function( name ) -- [Optional] Called for each @insert"name" statement. It's expected to return a Lua code string. By default 'name' is a path to a file to be inserted.
2969+
-- onInsert = function( name ) -- [Optional] Called for each @insert"name" instruction. It's expected to return a Lua code string. By default 'name' is a path to a file to be inserted.
29472970
-- onBeforeMeta = function( ) -- [Optional] Called before the metaprogram runs.
29482971
-- onAfterMeta = function( luaString ) -- [Optional] Here you can modify and return the Lua code before it's written to 'pathOut'.
29492972
-- onError = function( error ) -- [Optional] You can use this to get traceback information. 'error' is the same value as what is returned from processFile().
@@ -2969,7 +2992,7 @@ local pp = {
29692992
-- fastStrings = boolean -- [Optional] Force fast serialization of string values. (Non-ASCII characters will look ugly.) (Default: false)
29702993
-- validate = boolean -- [Optional] Validate output. (Default: true)
29712994
--
2972-
-- onInsert = function( name ) -- [Optional] Called for each @insert"name" statement. It's expected to return a Lua code string. By default 'name' is a path to a file to be inserted.
2995+
-- onInsert = function( name ) -- [Optional] Called for each @insert"name" instruction. It's expected to return a Lua code string. By default 'name' is a path to a file to be inserted.
29732996
-- onBeforeMeta = function( ) -- [Optional] Called before the metaprogram runs.
29742997
-- onError = function( error ) -- [Optional] You can use this to get traceback information. 'error' is the same value as the second returned value from processString().
29752998
--

tests/suite.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,22 @@ doTest("Macros", function()
263263
]]})
264264
assertCodeOutput(luaOut, [[t = {}]])
265265

266+
-- Macro with lookups.
267+
local luaOut = assert(pp.processString{ code=[[
268+
!t = {o={m=function(o,v) return v end}}
269+
v = @@t.o:m(foo)
270+
]]})
271+
assertCodeOutput(luaOut, [[v = foo]])
272+
273+
assert(not pp.processString{ code=[[
274+
!t = {o={m=function(o,v) return v end}}
275+
v = @@t.(foo)
276+
]]})
277+
assert(not pp.processString{ code=[[
278+
!t = {o={m=function(o,v) return v end}}
279+
v = @@t.o:(foo)
280+
]]})
281+
266282
-- Function as an argument.
267283
local luaOut = assert(pp.processString{ code=[[
268284
!function ECHO(v) return v end
@@ -310,6 +326,12 @@ doTest("Macros", function()
310326
() 1
311327
]]})
312328

329+
assert(not pp.processString{ code=[[
330+
!t = {o={m=function(o,v) return v end}}
331+
v = @@t.o:m
332+
(foo)
333+
]]})
334+
313335
-- Invalid: Bad macro arguments format.
314336
assert(not pp.processString{ code=[[ @insert type[] ]]})
315337
assert(not pp.processString{ code=[[ @insert type + 1 ]]})

0 commit comments

Comments
 (0)