Lua is good at domain-specific languages. There's no reason we should preprocess source code.
Instead of:
e2function number operator==(complex lhs, complex rhs)
if abs(lhs[1] - rhs[1]) > delta then return 0 end
if abs(lhs[2] - rhs[2]) > delta then return 0 end
return 1
end
We could get away with:
e2function [[number operator==(complex, complex)]] ..
function(lhs, rhs)
if abs(lhs[1] - rhs[1]) > delta then return 0 end
if abs(lhs[2] - rhs[2]) > delta then return 0 end
return 1
end
And that's valid pure Lua.
It's not _quite_ as nice a syntax, I grant you that, but it would actually work correctly with code editors, and it would get rid of a significant amount of code. We could also use the same syntax for registerType / registerOperator, which currently use pure Lua to define their E2 names and types.
The two editors i have used with lua in the past always highlighted e2function syntax correctly.
In addition to that, extpp is standard lua so you can run extpp in whatever external environment you want to test your code in.
EDIT: btw, is there any particular reason why the bodies of the two functions aren't identical?
EDIT2: btw that's not valid Lua, at least not in 5.1.
And how were you going to get the function out of there anyway? :)
@TomyLobo, it is valid Lua, and this is how it would work:
function e2function(signature)
return setmetatable({}, {
__concat = function(_, func) return registerE2Function(signature, func) end
})
end
Yes, that's a bit weird, but defining DSLs often is - and it's something that we can explain in one small part of the code.
The bodies aren't identical because the body of the first one wasn't valid pure Lua, and I thought while fixing it up I may as well fix up the awful formatting caused by using an if statement.
Editors which only do basic syntax highlighting via tokenization can handle e2function functions mostly just fine, but others which actually parse the code get very tripped up by it. (The editor I use - the Lua plugin for IntelliJ - does things like highlighting locals, globals and upvalues separately, which has helped me spot a whole class of bugs.)
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> function e2function(signature) return setmetatable({}, { __concat = function(_, func) return registerE2Function(signature, func) }) end
stdin:1: 'end' expected near '}'
> function e2function(signature) return setmetatable({}, { __concat = function(_, func) return registerE2Function(signature, func) end }) end
> e2function [[number operator==(complex, complex)]] .. function(lhs, rhs) local equal = abs(lhs[1]-rhs[1])<=delta and abs(lhs[2]-rhs[2])<=delta return equal and 1 or 0 end
stdin:1: unexpected symbol near '..'
try again?
Btw the body of both of your example function is valid standard Lua.
If you're gonna fix one, fix both. The difference between your examples should be what you want to show, not some random thing you noticed while editing code.
Btw the body of both of your example function is valid standard Lua.
No, it uses &&, which is Garrys Mod specific.
Urgh, Lua doesn't allow arbitrary expressions as statements. So you have to bind it to a local.
function registerE2Function(signature, func)
return print("Registering E2 function " .. signature .. " = " .. tostring(func))
end
function e2function(signature)
print(signature)
return setmetatable({}, {
__concat = function(_, func) return registerE2Function(signature, func) end
})
end
local __eq = e2function([[number operator==(complex, complex)]]) ..
function(lhs, rhs)
end
In that case, can I propose:
e2function([[number operator==(complex, complex)]],
function(lhs, rhs)
end)
Even simpler, with no special DSL magic. Would still remove a lot of preprocessing code.
at least half of extpp.lua has to do with:
You would need all of that in your implementation as well.
I updated your original post with a body that's better than both your example bodies :)
For member functions 'this' will need to be added as a parameter.
Also, your examples don't show the function name anywhere. Would it be like this?
E2Functions["myfunctionname"] = e2function([[number operator==(complex, complex)]],
function(lhs, rhs)
end)
That's because it's not a function, it's an operator. And it is defined here
[[number operator==(complex, complex)]]
@bigdogmat if you are talking about "Foo:pos()", that's not an operator.
Oh sorry, duh. I'm sleepy. I guess the function name would go where the operator is.
e2function([[vector entity:pos()]],
function(this)
end)
Would probably be abbreviated types instead of this, but yea
yeah, @AbigailBuccaneer picked kinda the most extreme example
@thegrb93 well the point of e2function, or at least one of them, is to make E2 function signatures readable and less boilerplate-y.
So you're supposed to use typenames there, not typeids.
Just make it a straightforward function call - why use weird tricks to get weird syntax that's not even an improvement?
e2function("number operator==(complex, complex)",
function(lhs, rhs)
if abs(lhs[1] - rhs[1]) > delta then return 0 end
if abs(lhs[2] - rhs[2]) > delta then return 0 end
return 1
end
)
or (different whitespace):
e2function("number operator==(complex, complex)",
function(lhs, rhs)
if abs(lhs[1] - rhs[1]) > delta then return 0 end
if abs(lhs[2] - rhs[2]) > delta then return 0 end
return 1
end)
why use weird tricks to get weird syntax that's not even an improvement?
I guess because it was a way to make E2 functions into a "valid" format that could be loaded from file instead of having to do it in a function(which it ultimately does when parsed).
@immibis that's functionally identical to what @thegrb93 suggested, except not with the multi-line string syntax.
I removed the extraneous "]]" from your 2nd example, btw.
So what @bigdogmat said is true for both @thegrb93's and your suggestion as well.
I don't agree that it's necessary, however.
The part that implements the e2function syntax (extpp) is 100% standard Lua and can thus be invoked externally if one so desires.
The syntaxes proposed here would reintroduce some of the boilerplate I sought to remove with the e2function syntax, while offering no benefit.
The current e2syntax functionality works perfectly fine, and it's only preprocessed once when the server launches, so speed is not an issue here. I see no reason to replace it.
@TomyLobo The difference between my way and @thegrb93's is that mine does what it says on the tin, whereas thegrb93 wants to do a weird hack, and all the hack achieves is saving one character and making future programmers think "WTF?".
@immibis Which one of @thegrb93 examples are you talking about?
I think we should rather move on to the part where everyone says how silly this issue is :)
i.e. let's vote on this.
I vote against this new preprocessor-less proposal as it clutters the code with boilerplate once again.
The only thing it clutters the code with is the naming convention of functions, I don't see how removing the preprocessing makes that much more clutter. If anything the part that does the preprocessing creates more clutter than it saves.
We have a thousand functions and only one preprocessor. Guess where we want to reduce the amount of code.
@bigdogmat The one where you do this:
e2function "number operator==(complex, complex)" ..
function(lhs, rhs)
-- code
end
instead of this:
e2function("number operator==(complex, complex)",
function(lhs, rhs)
-- code
end)
The plan is to make e2function take one parameter (the signature) and return an object with an overridden .. operator whose second parameter will be used as the function to register... instead of just making e2function take two parameters.
@thegrb93 didn't come up with that idea, @AbigailBuccaneer did. And it wasn't a hack, it was just giving the function a meta table to change the functionality of how concatenation worked. It also didn't work unless bound to something, so that's not an option anyway.
Ignore what I said about operator overloading with metatables, I no longer agree with my past self. If this were to go through I'd prefer e2function(signature :: string, body :: function).
Too lazy to re-read this thread but I believe I previously said "too much
work for too little gain". If not, I'm saying it now.
On Mon, Apr 4, 2016 at 11:16 AM, Abigail [email protected] wrote:
Ignore what I said about operator overloading with metatables, I no longer
agree with my past self.—
You are receiving this because you commented.
Reply to this email directly or view it on GitHub
https://github.com/wiremod/wire/issues/1087#issuecomment-205206896
Plus it would break 3rd party e2 extensions
@thegrb93
Only if we also remove the preprocessor.
Most helpful comment
Ignore what I said about operator overloading with metatables, I no longer agree with my past self. If this were to go through I'd prefer
e2function(signature :: string, body :: function).