-
Notifications
You must be signed in to change notification settings - Fork 3.4k
[WIP] more robust JS preprocessor #7105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
7c6348c
to
ae57def
Compare
cc @gyagp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I appreciate the effort that went into this, but we should perhaps talk about the overall plan here.
This does provide useful benefits, however, it's also a lot of code and complexity, which makes me worry about what will happen if we need to debug an issue there.
For things like #if FULL_ES2 || LEGACY_GL_EMULATION
I was actually hoping something much simpler could work, just do eval()
on the rest of the line, as those are all global variables. There may be issues I'm not thinking of, though.
emscripten.py
Outdated
@@ -522,7 +522,9 @@ def compile_settings(compiler_engine, libraries, temp_files): | |||
# Save settings to a file to work around v8 issue 1579 | |||
with temp_files.get_file('.txt') as settings_file: | |||
with open(settings_file, 'w') as s: | |||
json.dump(shared.Settings.to_dict(), s, sort_keys=True) | |||
settings = shared.Settings.to_dict() | |||
settings = { key: int(value) if isinstance(value, bool) else value for key, value in settings.items() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does json.dump
not work on bool
values?
if so maybe it would make sense to have a helper function as this appears in another place too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True
/False
in Python is dumped as true
/false
. Since I'm making very strict type checking here, only string and integers are accepted, and by intention true
/false
is not automatically converted to 1
/0
. The change is not necessary otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thanks.
I'm not fully convinced yet, but the idea of |
3846ae4
to
3fa4eb9
Compare
I'd say it's better to allow arbitrary JS there, if it greatly simplifies our implementation, by just using eval. (And we can be careful about not using really weird JS in practice in preprocessor operations.) |
src/settings.js uses 0/1 instead of false/true.
The patch is a complete rework of JS preprocessing with stricter syntax validation. It also adds support for more expressive preprocessor directives like the following: #include "foobar.js" #if !(VAR1 /* comment */ && VAR2 >= 2) #elif !VAR3 || VAR4 != "four" // comment #else #endif The directives are parsed according to an LL(1) grammar, using a stack for syntax-directed translation.
3fa4eb9
to
a977211
Compare
Picking up the PR again, and the Currently there's a problem that a few identifiers like Before
After
|
@juj added those |
The This is probably third or fourth time that better preprocessing support has been proposed (and shied away from). I implemented one in parseTools.js some years back (#1969), then added LLVM/Clang preprocessing with I still think what we should do is delete our own preprocessor and migrate to running LLVM/Clang
would make a lot of JS code look much cleaner, same for GL_DEBUG, GL_ASSERTIONS, FETCH_DEBUG, PTHREADS_DEBUG, etc, which have a lot of inconvenient one-liners. Also things like
would have potential to become much cleaner looking with C preprocessor macros. If we used LLVM/Clang, we would have 100% guarantee that it is bug-free, and would only need to do brief smoke testing without needing to build up extensive preprocessor test suites. There have been arguments before that C preprocessor or macros "would not belong to JS" or that Closure would be able to optimize the same things away (some thoughts in #5732), but both arguments fall short in real world when you do need to both optimize and maintain the code. In my experience, C preprocessor really efficiently complements the power that Closure has, and both are needed. In branch incoming...juj:november_2018 I am implementing a new runtime that optimizes the runtime from ~100KB to down to ~5.4KB for small applications ( https://github.com/juj/webgl_render_test, http://clbri.com/webgl_render_test_size_optimized/ ), and it has not been possible without both C preprocessing and Closure. One can kind of do without C macros, but it would be much cleaner with them. |
@juj I tend to agree that using clang's preprocessor may be a good solution. The main downside is we need clang, which we normally have for C/C++, but maybe some user just compiling Rust or something else might not. However, in any case I think we we may have a similarly easy possible solution with using |
Passes tests locally for me, so I think the approach can work, I opened #7651 |
I remembered that the preprocessor from Clang will warn about certain JS constructs like #7113 ( |
The other PR to implement the preprocessor using eval has landed (#7651), so i think we can close this. Thanks again though for the work here. It's taken us a while to figure out how to move forward with preprocessing, sorry this didn't happen faster. |
The patchset is a complete rework of JS preprocessing with stricter syntax validation. It also adds support for more expressive preprocessor directives like the following:
The directives are parsed according to an LL(1) grammar, using a stack for syntax-directed translation.