We already notified the user on warning/error that the mistake
happened in a different script than the one we were currently
compiing. It's not too difficult to figure out whether that other
script was added due to an #include or an #appendto directive, so we
can just show the user which one it is.
We also don't show warnings in #include'd scripts anymore, since
they get compiled individually anyway and all warnings will show up
there. This way we don't duplicate warnings several times.
When we introduce block scoping, using variables declared in a more
narrow scope from a block with wider scope will fail. Warn about
these so people can avoid it and fix their code.
While I do not agree with the idea of using straight assignments in
the condition of a for loop, people are divided on the argument and
lots of old code uses it.
This introduces a new diagnostic (suspicious_assignment) which
issues when an the compiler finds an assignment either where a
condition is expected or as the parameter to return.
Consolidate the include statements scattered across the code in accordance
with the comment in C4Include.h. The advantages are listed in the same
comment.
Furthermore, it follows llvm-include-order which is the logical
extrapolation of the project's style guideline wherever possible
(C4Include.h being the most-frequent exception).
Compilation without an associated ScriptHost happens in a call to eval,
in which case we'll fall back to the default warning settings (because
we don't have a location which we could get settings from).
Fixes#1891.
Yeah. Aul looks up function parameters before local variables when
trying to resolve an identifier. Usually this doesn't matter, but you'll
notice it if you have a local variable and a parameter with the same
name, because the variable should be initialized to nil yet you get the
value of the parameter.
This commit introduces a new Aul directive "#warning", which can be used
to enable or disable warnings for a particular piece of code.
"#warning enable" enables all warnings.
"#warning disable" disables all warnings.
"#warning enable empty_parameter_in_call" selectively enables one
specific warning while not affecting any other.
All warnings that used to be controlled by Developer.ExtraWarnings
remain disabled by default.
Aul will now emit a warning if you type something like
if (...); return true;
(note the semicolon right after the condition). It will also warn on an
empty 'else' branch. If you actually intended to have a no-op there, use
an empty block '{}'.
Instead of jumping forward and back repeatedly per iteration, we're
moving the incrementor past the body, which is when it's supposed to be
executed anyway.
Letting the constant resolver throw exceptions prevented us from doing
checking on later initializers anyway, so instead we'll send them to the
error handler. As a special bonus this makes it so we don't crash when
a global variable initializer has errors. Fixes#1850, #1855.
By continuing to generate bytecode even after an error is found, we're
able to find more syntax errors and will also be able to keep the value
stack at the expected height.
When an error occurred during codegen of a function, the current
function pointer would not be reset to 0, leading to spurious warnings
about redeclaration of functions.
If a parse error occurs inside a declaration, the codegen should just go
on and deal with the next declaration instead of completely giving up on
the entire script.
The old parser threw a standard compile error in this case; the
AST-based parser threw an ICE, which is ultimately the same thing but
made it sound like the parser was at fault. And maybe it is, and we
should allow code like "local a; func a() {}" but that seems like it
should be a conscious design decision.
C4Value already handles refcounting properly for us, so we don't need to
do it manually. It might still be worth manually refcounting them
to avoid the boxing/unboxing overhead, but it's only needed at load and
unload so it's not a priority at the moment.
By using an extern error handler in the script engine, we can mock that
handler and make sure something that should fail actually does, instead
of having to parse log messages.
This commit contains a fairly substantial rewrite of the C4Script code
generator. Instead of generating bytecode while parsing the script,
we're now parsing the script into a syntax tree, and have any further
processing happen on that instead of the raw source.
At this time, the code generator emits the same bytecode as the old
parser; there are several optimization opportunities that arise from the
new possibility to emit code out of order from its specification by the
author.
Compared to the old compiler, this one is still rather deficient when
dealing with incorrect code; it's also not emitting several warnings
that used to be diagnosed.