This fixes invalid IR on early returns. For example:
if (i == 2) {
return "two"
}
return work()
would not produce end label after `return "two"`, and QBE will fail
because it expects a label or } after ret instruction.
* Only build standard library for JS target
* Add initial data structures for QBE generator
* Allow generators to return an error
Required for QBE generator
* qbe: implement function generation
* qbe: generate integer literal expression
* qbe: generate return with expression
* qbe: generate boolean expression
* qbe: implement most of binary operations
* qbe: store a type in scope maps
* qbe: implement variable access expression
* qbe: implement function declarations
* qbe: implement if/else
* qbe: implement while loops
* qbe: implement break in loops
* qbe: implement continue
* qbe: implement expression statement
* qbe: implement function calls
* qbe: implement assignment for variables
* qbe: add QbeValue, use it instead of temporaries
With old approach, it was not possible for function call instruction to
accept a $-global value (for static strings), as well as having an
inconsistent API for QbeInstr::Copy because of Either<...>.
QbeValue can hold either a temporary, global or a constant literal. This
allows it to be used everywhere, without hacks like Either for copy.
* qbe: implement string literals
* qbe: move Assign into generate_assignment
* qbe: add typedefs
* qbe: generate offset table for structs
* qbe: implement struct initialization
* qbe: resolve struct variable types
* qbe: convert assignment QBE statements to base types
This prevents generating incorrect IR with structs
* qbe: implement field access
* qbe: do not cast to ABI types in scope
* qbe: implement assignments to field access
* qbe: store loop labels as a stack
Fixes issues when using continue/break in nested loops.
* docs: add QBE to supported backends
* Add QBE backend to changelog
* qbe: implement assignment BinOps (e.g. +=)
* qbe: resolve arrays in variable types
* qbe: implement array initialization
* qbe: add aggregate type fills (e.g. { w 12 })
* qbe: generate aggregate types for arrays
* Print error Strings from main verbatim
When returning Result<(), String> from main(), the error message is
escaped. This results in errors like this:
$ sb build ...
Error: "Re-declaration of variable \'v\'"
This probably happens because the error from main() is passed to the
debug formatter, but in this case it's better to use the default one.
The solution is to wrap the real main into a function like run(), and
then printing to stderr followed by exit(1) on an error from it.
* util: rewrite source file highlight
Old variant was a bit unintuitive on showing where the error occured.
The new implementation is inspired by what Rust and Zig are doing.
* parser: improve error messages
* Use standard format "<line>:<column>: <message>" everywhere. And if
possible, include source file snippet.
* Deduplicate some messages
* Add improved parser errors to changelog
* feat: add array capacity inference
* feat: add capacity to array type
* feat(js): initialize empty arrays
* chore: fix clippy warning
* lexer: refactor number parsing
Earlier lexer was just eating whatever is a valid hex number (implies
lower radixes) and then parser checks that nonsense later.
This patch restructures the lexing of numbers a bit, where numbers are
firstly checked for b|o|x prefix and then later action is determined:
b => eat_binary_digits(); // 0-1
o => eat_octal_digits(); // 0-7
x => eat_hex_digits(); // 0-F
else => eat_digits(); // Classic 0-9
This would prevent treating something like 0b1337 as a valid number
literal.
* lexer: add tests for number literals
* tests: add array capacity test
* docs: add array capacity to changelog
* docs: add array capacities
Co-authored-by: Alexey Yerin <yyp@disroot.org>