The parser was only checking that the passed setting matched the
beginning of the expected keyword, instead of checking for the full
length. This way, users could write "#warning e" instead of the
expected "#warning enable" and still have it work.
When no parameter followed the "#warning" pragma, because the end
iterator would be located before the begin iterator, basic_string's
constructor would throw std::length_error. Check for this case
beforehand so we can throw the expected C4ParseError instead.
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.
All of our headers are designed to be included *after* C4Include.h,
which UnicodeHandlingTest.cpp didn't do, resulting in an ill-formed
program on some implementations.
TestHost can't check that SourceScripts is unmodified anymore because
C4ScriptHost contains a std::unique_ptr these days, so we can't copy
derived classes. Next best thing is just creating two instances of
TestHost and comparing those.
MSVC 2015 doesn't support raw strings that contain the sequence \"
(U+005C REVERSE SOLIDUS, U+0022 QUOTATION MARK) and fails to compile
with error C2017.
GTest usually only increments its part count per EXPECT_* call, which we
don't use in diagnostics tests, so all compilation failures would show
as part number 0.
Instead of declaring an error handler every time we run a subtest, we'll
just use a class member that we clear when we leave the scope of the
subtest.
The macro is a bit ugly but solves the issue with redeclaring the scope
guard.
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 '{}'.
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.
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.
RunExpr will evaluate and return the value of a single expression.
RunCode will evaluate a full function body.
RunScript will compile a complete standalone script and return the
return value of its Main() function.
So it turns out that the fix stops the engine from crashing, but it
still doesn't seem to generate valid code - Aul emits an internal error
at runtime.
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.