Page 3 of 8
Re: LuaPreprocess
Posted: Wed Jan 13, 2021 5:19 pm
by ReFreezed
This declares a local variable both in the metaprogram and the output. It's the same as doing this:
Code: Select all
!local TWO_PI = 2 * math.pi
local TWO_PI = !(TWO_PI)
Omitting 'local' would assign the value to a global instead.
I admit, assignments using !! is probably the least useful feature of the preprocessor and I only use it myself in very few places, usually in the following case...
In the metaprogram in my files I never create globals (with a couple of exceptions**). This way I only need to preprocess files that have changed since the last run before I run the game again (as the output will always be the same for unchanged files), and thus the preprocessing step is quicker.
Anyway, a file may do something like this:
Code: Select all
!local foo = someValue
-- Later in the file I use !(foo) in multiple places.
But at some point in the development I need to access 'foo' in other files, so I change the declaration to this:
Code: Select all
_G.!(local )!!foo = someValue
-- ...which essentially means:
_G.
!local foo = someValue -- It's ok to put metaprogram code "in the middle" of normal code.
foo = !(foo)
This will keep the variable local in the metaprogram in this file, but it will also create a global 'foo' in the output so I can use it anywhere. It's like a hacky temporary solution until I have a better system in place for accessing the value of 'foo' globally.
** I have a couple of files that do declare globals for the metaprogram, and if any of those change then I preprocess every single file again as any file may have gotten affected by the changes.
Re: LuaPreprocess
Posted: Wed Jan 13, 2021 5:25 pm
by pgimeno
I see, thanks for the clarification.
Re: LuaPreprocess
Posted: Thu Jan 14, 2021 2:02 am
by yetneverdone
I'm also confused by the `!` syntax in other cases, perhaps another symbol or token to denote it easily (and for reading ofc).
Re: LuaPreprocess
Posted: Thu Jan 14, 2021 11:29 am
by ReFreezed
What more exactly is confusing?
Re: LuaPreprocess
Posted: Sat Jan 16, 2021 3:52 am
by yetneverdone
Ahh let me try to explain what I've meant.
The lpp uses `!` as a token to denote that the line or block should be processed by lpp, right?
Combining that with another `!` like `!!` does other things as well as `!(...)`, which for me can be confusing like which of it
evaluates it and which of it evaluates it and outputs the string, etc.
What I am suggesting is, since the lpp is preprocessing, maybe use another token for such cases? Like `!` + `@` or `#` to mean something else. Like seeing `!` and `!#` or `!@` can easily be determined what they do.
I hope I got my point across haha.
Re: LuaPreprocess
Posted: Sat Jan 16, 2021 1:27 pm
by ReFreezed
Ah, I see. Yeah, the fact that `!(...)` does two different things (output a value or don't output a value, depending on whether the contents is an expression or not) is definitively a design flaw. I though about changing the variant that doesn't output anything to use `!{...}` but such a change would make existing code stop working. I'd have to change it for the next major version or maybe add a setting for it. If I made the change then any amount of `!` followed by a parenthesis would always output something, while no parenthesis would not output anything, thus there would be more consistency.
The idea to only use `!` for everything was really to keep things simple, as in, whenever you see it then you know that the following code is part of the metaprogram. Another reason is that the character is easy to type and doesn't look noisy among the rest of the code. Using more symbols, e.g. `!#(...)`, would make things a bit too noisy I think. Same with replacing `!!` with e.g. `!#`.
Re: LuaPreprocess
Posted: Mon Jan 25, 2021 4:00 pm
by ReFreezed
Update 1.12
Changes since 1.11.2:
Library:
- Added support for LuaJIT-specific syntax.
- Output validation can be disabled with `params.validate = false`.
- Added aliases for some number formats.
- Fixed parsing of `&`, `|` and `~` operators.
Command line program:
Re: LuaPreprocess - straightforward preprocessor with simple syntax
Posted: Mon May 10, 2021 2:06 am
by pgimeno
As a result of a recent question, I decided to try to write a proper assert using LuaPreprocess, but I'm having trouble.
A proper assert is one where:
- with assertions disabled, the result is no code at all (i.e. even if the conditions are complex, they won't be included in the program if assertions are disabled, and same for the message if present);
- with assertions enabled, the error message argument is only evaluated if the condition is true; for example, assert(x, f()) will not call f() unless x is true.
This is obviously impossible with plain Lua. In C, assert.h uses a preprocessor; in Python, assert is a language construct, allowing the above semantics. This is easy to implement with a C preprocessor:
Code: Select all
#if DEBUG
#define assert(cond, msg) do { if (cond) { error(msg); } } while (0)
#else
#define assert(cond, msg) do { } while (0)
#endif
but I'm having trouble figuring out how to do something similar with LuaPreprocess. Is it possible at all?
Re: LuaPreprocess - straightforward preprocessor with simple syntax
Posted: Mon May 10, 2021 10:59 am
by monolifed
Code: Select all
!if DEBUG then
myassert = assert
!else
myassert = function() end
!end
Then you use myassert, which ends up with a function call either case (in C, no op one would probably be optimized out).
But you probably meant a no call one: a short hand for typing something like the following for every assert call
I'd expect something like !assert(x,y,z) however I can't figure out how to do that in luapreprocess
Re: LuaPreprocess - straightforward preprocessor with simple syntax
Posted: Mon May 10, 2021 12:04 pm
by ReFreezed
In addition to monolifed's solutions, the most straight-forward one-liner way is probably something like this:
Code: Select all
local ok = false
!!(DEBUG and "assert(ok)" or "")
-- Result:
local ok = false
assert(ok)
!!(...) outputs a string as Lua code.
You could also do something like this:
Code: Select all
!(
function ASSERT(conditionCode) return function(message)
if not DEBUG then return end
outputLua("if not (", conditionCode, ") then error(")
outputValue(message)
outputLua(") end")
end end
)
local ok = false
!ASSERT "ok" "Assertion failed!"
-- Result:
local ok = false
if not (ok) then error("Assertion failed!") end
If you want a formatted message you could do this:
Code: Select all
!(
function ASSERTF(conditionCode) return function(messageAndValuesCode)
if not DEBUG then return end
outputLua("if not (", conditionCode, ") then error(string.format(", messageAndValuesCode, ")) end")
end end
)
local i = -8
!ASSERTF "i > 0" [["Invalid index. (It is %d)", i]]
-- Result:
local i = -8
if not (i > 0) then error(string.format("Invalid index. (It is %d)", i)) end