LuaPreprocess - straightforward preprocessor with simple syntax

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: LuaPreprocess

Post by ReFreezed »

Code: Select all

!!local TWO_PI = 2 * math.pi
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.
Last edited by ReFreezed on Wed Jan 13, 2021 5:39 pm, edited 2 times in total.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: LuaPreprocess

Post by pgimeno »

I see, thanks for the clarification.
User avatar
yetneverdone
Party member
Posts: 446
Joined: Sat Sep 24, 2016 11:20 am
Contact:

Re: LuaPreprocess

Post 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).
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: LuaPreprocess

Post by ReFreezed »

What more exactly is confusing?
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
User avatar
yetneverdone
Party member
Posts: 446
Joined: Sat Sep 24, 2016 11:20 am
Contact:

Re: LuaPreprocess

Post 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.
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: LuaPreprocess

Post 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. `!#`.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: LuaPreprocess

Post 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:
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: LuaPreprocess - straightforward preprocessor with simple syntax

Post 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?
monolifed
Party member
Posts: 188
Joined: Sat Feb 06, 2016 9:42 pm

Re: LuaPreprocess - straightforward preprocessor with simple syntax

Post 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

Code: Select all

!if DEBUG then
  assert(x,y,z)
!end
I'd expect something like !assert(x,y,z) however I can't figure out how to do that in luapreprocess
Last edited by monolifed on Mon May 10, 2021 12:15 pm, edited 1 time in total.
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: LuaPreprocess - straightforward preprocessor with simple syntax

Post 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
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
Post Reply

Who is online

Users browsing this forum: No registered users and 16 guests