compiler: improve Value handling and expression evaluator
AST values:
- add
getValue()type methods for literal expr nodes, returning aValue - add
Value.castAs()type method - add
ValueKind.Errorfor invalid result and evaluation errors - add
Valuefactories for unsigned, signed, float, boolean and error
Simplify ctv_analyser:
- remove hard coded strings in
Limitsarray - dispatch to more
getValue()handlers
Expression evaluator:
- move generator/c/c_generator_pure_call.c2 to ast/ast_evaluator.c2
- support indirect pure functions calls including recursive
Improve C generator:
- add
Generator.need_const_expr, used for static intializers - add
Generator.emitConstExpr()to force pure function calls evaluation - simplify initializer generation
- pass Diags object for code generation errors
A big change.. took me a while to parse it.. Overall I like it. Many small TODO's cleaned etc.
2 issues i see:
- generator should not have a Diags. All diagnostics are done during the analyser phase.
- This patch changes behaviour of: u8 b= 1; u8 a = b + 200; // should not give an error..
A big change.. took me a while to parse it.. Overall I like it. Many small TODO's cleaned etc.
Yes, and an initial step for a full blown emulator. I shall first support pure functions using only arithmetic operators but allowing for local variables and calls to other pure functions.
2 issues i see:
- generator should not have a
Diags. All diagnostics are done during the analyser phase.
All diagnostics are done during the analyser phase, but some errors can still occur during the generation phase, such as file system errors, and in the case of pure functions, I implemented a limitation on the complexity and recursion depth to handle pathological cases gracefully. Reporting these errors directly via a console object seems less correct than using a Diags object which allows for location reporting.
- This patch changes behaviour of:
u8 b= 1; u8 a = b + 200; // should not give an error.
Yes I am aware of this. Truncation does occur if b is larger than 55. Can you summarize which implicit conversion losses are considered acceptable and which aren't?
The current system is approximate because it mixes tests about the type size and signedness and knowledge of the constant values and their sign.
I am working on a more precise analyser that would be more accurate and conformant: 2 << 31 should be reported as an arithmetic overflow, worse even, u32 TWO = 2; static_assert(TWO << 31, 0) fails, not because of overflow but because TWO << 31 has the value 4294967296, which is inconsistent with what the generated C code will compute: assert(TWO << 31, 0) will succeed.
I usually keep the same as in C, an u8 = u8 + (literal); is allowed as long as the literal fits an u8. Idem for other types
2 open issues:
- c_generator still relies on Diags
- ast_evaluator should not be part of AST, but of analyser_utils (like ctv_analyser)