SaladDais / tailslide

Embeddable parser, AST, tree walker and compiler for the Linden Scripting Language based on LSLint
MIT License
5 stars 1 forks source link

Support for Firestorm Preprocessor #26

Open FixedBit opened 7 months ago

FixedBit commented 7 months ago

I would love to update my extension for VSCode to support your plugin! LSLint For VSCode

I did some testing last night and it seems to output the same as lslint command line, which is awesome! I would just need to add an option to use tailslide vs lslint.

All of that is just a side note of why I am posting this... I use a lot of the features from Firestorm's Preprocessor, such as define and include [EXAMPLES], but it is not currently supported by your linting and spits out an error:

❯ tailslide --lint example.lsl
ERROR:: (  1,  9): [E10020] syntax error, unexpected IDENTIFIER, expecting '('
TOTAL:: Errors: 1  Warnings: 0

which is just from trying to use a #define SOMETHING 123 in the script.

It is "tolerated" so to speak by lslint since it has a -i option to ignore/skip those directives, which would be helpful! [PR from lslint where it was implemented]

It would be even better if you were able to handle it, or at the least in this category handle #include so it could trace through the other included files for that script.

I know it is a big ask, but your project is close enough to lslint in its output (which means I can use it for the VSCode GUI) and the only one that seems to be in active development. If this is something you would consider supporting, it would help a LOT of people since handling includes is the biggest downfall from lslint that people ask me about for the extension.

Thanks!

Also feel free to reach out to me in SL or email (info on my account page).

SaladDais commented 7 months ago

Hi there, thanks for your interest!

I currently don't use Firestorm's LSL extensions because I use GNU cpp as my C preprocessor externally, but I could look into how much effort an embedded C preprocessor would take, if that's something people are interested in.

Note that this would be strictly for the C-compatible preprocessor stuff, and not Firestorm's lazy list accessors or switch(){...} extensions, since I'm not looking to extend the grammar of LSL itself beyond what SL would actually support, but support for #defines and #includes would be a reasonable ask.

FixedBit commented 7 months ago

Thank you for your reply! I understand about the switch handling and wonder if there was a way to just ignore "valid" preprocessor stuff you do not support this way it did not actually flag as an error?

The #define and #include being usable would be beyond a blessing! I have had quite a few people ask me about it and while lslint lets you ignore it, it does not actually parse it which makes something declared in an include, for lack of a better word, useless, lol!

SaladDais commented 7 months ago

Unfortunately, the way the grammar is constructed, I believe I'd have to maintain a separate grammar file to keep the switch keyword unreserved in regular contexts (I believe it is currently an error to have a variable named switch case or break in variable names under lslint versions that support switch.) If someone was to contribute a Firestorm-specific grammar and a way to swap between the two grammars via a command-line flag, I'd be willing to accept that PR and write proper support for other preprocessor includes derived from C. I believe some of the code from the other lslint forks for this should be more-or-less portable to Tailslide.

If I'd changed Tailslide to use a hand-written parser & lexer like lsl-pyoptimizer uses, this would be easier, but alas, I'm too lazy to do that or write a separate grammar. I try to stay quite close to what LL actually does in their compiler, and that includes the weirdness of their compiler construction (except where I can decompose things to make more sense without changing the behavior.)

On that note, have you looked at lsl-pyoptimizer? Even though it isn't billed as a linter, its linting capabilities are pretty good, and it has built-in support for an embedded preprocessor, along with support for switch and lazy lists. I use it myself for a number of things, and it has the additional benefit that it can optimize code as well.

SaladDais commented 7 months ago

Hmmm, actually, it looks like the firestorm preprocessor just uses regex search and replace to handle lazy list and switch in scripts, so that could be reasonably done without a separate grammar: https://github.com/FirestormViewer/phoenix-firestorm/blob/1f75fbd3b56d69fb4883b99fc8e9f1162a04043a/indra/newview/fslslpreproc.cpp#L855-L1116

I can't use that code because it's licensed under the LGPL and I want to keep Tailslide MIT licensed, but if someone could do something similar using std::regex (i.e. not Boost,) I could handle the rest of the preprocessor directives easily.

FixedBit commented 7 months ago

That is an interesting idea, I never actually looked at how they did it... Good catch!

I am looking into lsl-pyoptomizer now and while it is very nice and a great tool, the output does not match a drop in solution like yours actually is. I ran it against some of my scripts and it seems to be complaining about #define and even switch even though it looks like it should not on the project documents.

I am quite happy that you are even willing to help do this, and I feel that it would be a much better choice than lslint for my extension and I would rather switch over to it by default.

I also feel not enough people really even know about this as an option, even my extension... It has a following and I have heard from a few people that use it, but its not something I would consider widespread sadly... I really need to work on that once I update it since it is one heck of a great option when combined with a command line tool like yours!