CrabPascal has always provided two execution paths: the run command, which uses an internal runtime interpreter, and build-exe, which compiles to native C code. Until recently, the native path pretended to support exceptions by generating placeholder blocks that compiled successfully but failed to behave like Delphi’s structured error handling. Version 2.21.0 (Sprint 13) puts an end to this inconsistency.
Why simulated exception handling was problematic
Delphi’s exception mechanism relies on stack unwinding and type matching within try/except blocks. For example:
try
ProcessOrder(OrderId);
except
on E: Exception do LogError(E.Message);
end;In the runtime interpreter, this works as expected. However, the old C backend emitted stub code that passed compilation but offered no real error handling. Worse, it masked critical gaps in parity—developers assumed their native builds would work in production only to face unexpected crashes that differed from the interpreter’s behavior.
This approach contradicted CrabPascal’s core principle of honest tooling. If a feature couldn’t be implemented correctly, the team believed it was better to state that limitation clearly than to deliver a false sense of functionality.
Key changes in v2.21.0
Starting with v2.21.0, the code generation module now refuses to produce C code for:
try/exceptblockstry/finallyblocksraisestatements
Instead, attempting to compile such code with build-exe results in a clear error message:
crab-pascal build-exe MyApp.dpr
# error: exception handling not supported in native codegen yet; use `crab-pascal run`This immediate feedback ensures that developers recognize the limitation before their code reaches production, preventing silent failures in pipelines or runtime environments.
Choosing the right execution path
CrabPascal’s commands serve distinct purposes based on project needs:
- `run` – Best for active development, Horse APIs, object-oriented code with exceptions, and rapid iteration.
- `check` – Ideal for IDE feedback and static analysis in CI pipelines.
- `build-exe` – Designed for performance-critical code that does not use exception constructs.
For instance, the CRUD example—which uses JSON and HTTP—compiles cleanly with build-exe where exceptions are absent. Developers can run:
crab-pascal check examples/crud/crud.dpr
crab-pascal run examples/crud/crud.dprRegression testing and future plans
Sprint 13 introduced a regression test, codegen::tests::test_codegen_errors_on_try_raise, to enforce the new behavior:
// Pseudocode intent: codegen must fail on try/raise, not emit fake C
assert!(codegen_result.is_err());
assert!(message.contains("use `run`"));The team’s next step is implementing real native exception support, likely using mechanisms like setjmp/longjmp, table-based handlers, or LLVM integration. This work will be coordinated with updates to the runtime library (RTL) types in System.SysUtils and adjustments to object layout in memory. Until then, documentation—including this article and release notes—will emphasize the split between supported and unsupported features.
What developers should do now
Projects that rely on Delphi-style structured exception handling should default to the run command. Native builds (build-exe) remain suitable only for language subsets where parity has been verified. By prioritizing transparency over convenience in v2.21.0, the CrabPascal team has made the tool safer for incremental adoption. Future releases will expand native support, but this version ensures developers work with clear expectations today.
For questions or feedback, reach out to the team via issues on Bitbucket.
AI summary
CrabPascal 2.21.0, exception işlemlerinde dürüstlük prensibini benimseyerek geliştiricilere açık hata mesajları sunuyor. Doğal derleme için desteklenmeyen özellikler hakkında neler değişti?