English {#english}
Run vs build-exe: Honest Parity in CrabPascal (v2.17.0)
CrabPascal offers two execution paths: run (internal Rust runtime) and build-exe (generate C, compile with gcc/clang). Sprint 9 (v2.17.0) made the relationship between them honest — no fake success, no silent semantic gaps.
The dual-mode mental model
| Mode | Best for | Requires |
|---|---|---|
run |
Fast iteration, examples, teaching | Rust binary only |
build-exe |
Native speed, shipping small tools | gcc, clang, or MSVC |
They should produce the same stdout for supported programs. Sprint 9 introduced tests/run_build_parity.rs to enforce that contract.
Semantic hardening
Assigning to an undeclared variable now fails clearly:
program BadAssign;
begin
UnknownVar := 1; // error: Undefined variable
end.
Before v2.17.0, some assignments slipped through and failed later with confusing runtime errors. check and semantic analysis now agree: if it is not declared, it is not assignable.
Build without a C toolchain
A common footgun: build-exe generated .c files but reported success even when no compiler was installed. v2.17.0 fails with a clear message after codegen if gcc/clang/msvc is missing — it does not fall back to pretending the native binary exists.
crab-pascal build-exe Hello.dpr
# fails loudly if no C compiler — by design
String builtins in codegen
Sprint 9 mapped SysUtils string calls to pascal_Length, pascal_Copy, pascal_Pos, pascal_UpperCase, and pascal_LowerCase in generated C, sharing logic with stubs.c. That closed part of the drift between interpreter and native output.
Example program to compare:
program Parity;
uses System.SysUtils;
begin
WriteLn(UpperCase(Trim(' crab ')));
end.
crab-pascal run Parity.dpr > run.txt
crab-pascal build-exe Parity.dpr && ./Parity > build.txt
diff run.txt build.txt
On v2.17.0, some cases still differ — notably Trim parsing in codegen — which Sprint 10 addressed.
Generics runtime fixes
TDictionary<string, Integer>.Create allocates a real instance; TryGetValue with var write-back works in both modes where codegen supports the call path. Parity tests catch regressions when someone optimizes only the interpreter.
Living technical debt doc
Sprint 9 formalized backlog in docs/DEBITO_TECNICO_FUTURO.md: OO codegen, exceptions in C, marketplace extension versioning. Parity is a process, not a single commit.
Run the gate locally
cargo test --test run_build_parity
cargo test --test generics_collections
Philosophy
Dual-mode compilers tempt teams to optimize the happy path in one mode and ship the other as "experimental forever." v2.17.0 draws a line: if we claim build-exe, tests must prove it. That baseline unlocked Sprint 10's native string conformance gate and later OO codegen work.
Choose run for speed while learning Pascal on CrabPascal. Choose build-exe when you need a real executable — and trust that CI will tell you when the two modes diverge.
Português {#portugus}
Run vs build-exe: paridade honesta no CrabPascal (v2.17.0)
O CrabPascal oferece dois caminhos de execução: run (runtime Rust interno) e build-exe (gera C, compila com gcc/clang). A Sprint 9 (v2.17.0) tornou a relação entre eles honesta — sem sucesso falso, sem gaps semânticos silenciosos.
Modelo mental dual-mode
| Modo | Melhor para | Requer |
|---|---|---|
run |
Iteração rápida, exemplos, ensino | Só binário Rust |
build-exe |
Velocidade nativa, entregar ferramentas | gcc, clang ou MSVC |
Devem produzir o mesmo stdout para programas suportados. A Sprint 9 introduziu tests/run_build_parity.rs para impor esse contrato.
Endurecimento semântico
Atribuir a variável não declarada agora falha claramente:
program BadAssign;
begin
UnknownVar := 1; // error: Undefined variable
end.
Antes da v2.17.0, algumas atribuições passavam e falhavam depois com erros confusos em runtime. check e análise semântica agora concordam: se não está declarado, não é atribuível.
Build sem toolchain C
Armadilha comum: build-exe gerava .c mas reportava sucesso mesmo sem compilador instalado. A v2.17.0 falha com mensagem clara após codegen se gcc/clang/msvc falta — não finge que o binário nativo existe.
crab-pascal build-exe Hello.dpr
# falha alto se não houver compilador C — de propósito
Builtins de string no codegen
A Sprint 9 mapeou chamadas SysUtils de string para pascal_Length, pascal_Copy, pascal_Pos, pascal_UpperCase e pascal_LowerCase no C gerado, compartilhando lógica com stubs.c. Isso fechou parte do drift entre interpretador e saída nativa.
Programa exemplo para comparar:
program Parity;
uses System.SysUtils;
begin
WriteLn(UpperCase(Trim(' crab ')));
end.
crab-pascal run Parity.dpr > run.txt
crab-pascal build-exe Parity.dpr && ./Parity > build.txt
diff run.txt build.txt
Na v2.17.0, alguns casos ainda diferiam — notably parse de Trim no codegen — o que a Sprint 10 endereçou.
Fixes de runtime em generics
TDictionary<string, Integer>.Create aloca instância real; TryGetValue com var write-back funciona nos dois modos onde codegen suporta o caminho de chamada. Testes de paridade pegam regressões quando alguém otimiza só o interpretador.
Doc vivo de débito técnico
A Sprint 9 formalizou backlog em docs/DEBITO_TECNICO_FUTURO.md: codegen OO, exceções em C, versionamento da extensão marketplace. Paridade é processo, não commit único.
Rodar o gate localmente
cargo test --test run_build_parity
cargo test --test generics_collections
Filosofia
Compiladores dual-mode tentam otimizar o caminho feliz em um modo e shippar o outro como "experimental para sempre". A v2.17.0 traça linha: se declaramos build-exe, testes devem provar. Essa baseline destravou o gate de conformidade nativa de strings da Sprint 10 e trabalho posterior de codegen OO.
Escolha run por velocidade ao aprender Pascal no CrabPascal. Escolha build-exe quando precisar de executável real — e confie que o CI avisa quando os modos divergem.
Published on dev.to/@crabpascal · Código em CrabPascal
Top comments (0)