English {#english}
Dual-Mode Build: Interpret vs Native C
Challenges in post 039 culminated in a pragmatic build strategy: two execution backends, one frontend. The design chapter lives in arquitetura-design; Sprint 9 shipped the honesty baseline in release-v2-17-0.
Two doors, same Pascal source
┌── crab-pascal run ──→ CompletePascalRuntime (interpret)
.pas / .dpr ──┤
└── crab-pascal build-exe ──→ C codegen ──→ gcc/clang ──→ native .exe
Both paths share lexer, parser, preprocessor, and semantic analyzer. They diverge only at code generation vs direct execution.
| Mode | Speed to iterate | Output | Needs gcc |
|---|---|---|---|
run |
Fastest | stdout in terminal | No |
build-exe |
Slower |
.exe / binary |
Yes |
Daily development: run. Release artifact or benchmarking native code: build-exe.
Interpreter path in practice
crab-pascal run examples/crud/crud.dpr
The runtime walks the AST, maintains scopes, heap, and VMT — everything post 038 described. Horse servers stay up because the event loop lives in Pascal units loaded via ProjectConfig.
Pros: zero C toolchain, excellent error context, matches most sprint QA fixtures.
Cons: not a standalone binary you email to someone without CrabPascal installed.
Native path in practice
crab-pascal build-exe examples/hello.dpr
# Emits hello.c + invokes gcc/clang when available
./hello.exe
Codegen writes C calling stubs.c RTL helpers — strings, objects, SysUtils bridges. GCC produces the final executable.
Pros: real native speed, deploy without Rust runtime embedded.
Cons: parity gaps surface here first (exceptions, some generics edge cases) — tracked per sprint.
v2.17.0 honesty rules
Before v2.17.0, missing gcc could look like success. Now:
-
.cfiles still generate — inspect codegen diff in PRs - Link step errors if no compiler found
-
Undefined variablefails semantic pass consistently on both paths
Validate locally:
cargo test --test run_build_parity
cargo test --lib
These tests compare stdout and exit codes where parity is claimed.
When to choose which
Use run when:
- Writing Horse routes and Postman testing (post 036)
- TDD on parser/semantic fixtures
- Teaching — students see Pascal behavior immediately
Use build-exe when:
- Distributing a CLI tool to machines without CrabPascal
- Measuring performance vs FPC/Delphi baseline
- Verifying codegen for a sprint deliverable (strings Sprint 10, exceptions Sprint 13)
Use check when:
- IDE integration only — no execution (post 034)
Configuration touchpoints
crabpascal.toml can set default backend hints, search paths, and defines affecting both modes. Codegen respects the same conditional compilation as the interpreter after preprocessor expansion.
Windows: MSVC, MinGW, or clang — first found wins; document your CI image.
Known parity matrix (snapshot)
Green items run identically on most fixtures; yellow needs sprint attention:
- Hello world, arithmetic, records — green
- Generics collections — mostly green post Sprint 7
- Try/except in
build-exe— yellow until Sprint 13+ policies - Horse long-running — primarily
runtested; native path varies
Check project status before promising clients a native build.
CI pipeline example
A minimal Bitbucket pipeline exercising both modes:
pipelines:
default:
- step:
script:
- cargo test
- ./target/release/crab-pascal check examples/hello.dpr
- ./target/release/crab-pascal run examples/hello.dpr
- ./target/release/crab-pascal build-exe examples/hello.dpr # requires gcc image
Split jobs if gcc bloats your Rust image — but never skip check. release-v2-17-0 documents why faking native success hurt more than a red build badge.
Next in series
Post 041 — Sprint 1 Review: Real Diagnostic Spans closes the architecture arc by revisiting the first sprint deliverable — why accurate check output unlocked everything above (IDE, CI, honest errors).
Português {#portugus}
Dual-mode: interpretar vs C nativo
Os desafios do post 039 culminaram em estratégia pragmática de build: dois backends de execução, um frontend. O capítulo de design está em arquitetura-design; Sprint 9 entregou baseline honesto em release-v2-17-0.
Duas portas, mesma fonte Pascal
┌── crab-pascal run ──→ CompletePascalRuntime (interpreta)
.pas / .dpr ──┤
└── crab-pascal build-exe ──→ codegen C ──→ gcc/clang ──→ .exe nativo
Ambos os caminhos compartilham lexer, parser, preprocessador e analisador semântico. Divergem só em geração de código vs execução direta.
| Modo | Velocidade de iteração | Saída | Precisa gcc |
|---|---|---|---|
run |
Mais rápido | stdout no terminal | Não |
build-exe |
Mais lento |
.exe / binário |
Sim |
Desenvolvimento diário: run. Artefato de release ou benchmark nativo: build-exe.
Caminho interpretador na prática
crab-pascal run examples/crud/crud.dpr
O runtime percorre AST, mantém escopos, heap e VMT — tudo do post 038. Servidores Horse ficam de pé porque o loop de eventos vive em units Pascal via ProjectConfig.
Prós: zero toolchain C, excelente contexto de erro, alinha com fixtures QA dos sprints.
Contras: não é binário standalone para enviar sem CrabPascal instalado.
Caminho nativo na prática
crab-pascal build-exe examples/hello.dpr
# Emite hello.c + invoca gcc/clang quando disponível
./hello.exe
Codegen escreve C chamando helpers RTL em stubs.c — strings, objetos, pontes SysUtils. GCC produz o executável final.
Prós: velocidade nativa real, deploy sem runtime Rust embutido.
Contras: gaps de paridade aparecem aqui primeiro (exceções, alguns casos de generics) — rastreados por sprint.
Regras de honestidade v2.17.0
Antes da v2.17.0, gcc ausente podia parecer sucesso. Agora:
- Arquivos
.cainda geram — inspecione diff de codegen em PRs - Etapa de link errar se não achar compilador
-
Undefined variablefalha semântica consistente nos dois caminhos
Valide localmente:
cargo test --test run_build_parity
cargo test --lib
Estes testes comparam stdout e exit codes onde paridade é declarada.
Quando escolher qual
Use run quando:
- Escrever rotas Horse e testar com Postman (post 036)
- TDD em fixtures parser/semântica
- Ensinar — alunos veem comportamento Pascal na hora
Use build-exe quando:
- Distribuir CLI em máquinas sem CrabPascal
- Medir performance vs baseline FPC/Delphi
- Verificar codegen para entrega de sprint (strings Sprint 10, exceções Sprint 13)
Use check quando:
- Só integração IDE — sem execução (post 034)
Pontos de configuração
crabpascal.toml define hints de backend, search paths e defines que afetam ambos modos. Codegen respeita a mesma compilação condicional do interpretador após preprocessador.
Windows: MSVC, MinGW ou clang — primeiro encontrado vence; documente imagem CI.
Matriz de paridade conhecida (snapshot)
Verde na maioria dos fixtures; amarelo precisa atenção de sprint:
- Hello world, aritmética, records — verde
- Generics collections — mostly verde pós Sprint 7
- Try/except em
build-exe— amarelo até políticas Sprint 13+ - Horse long-running — testado principalmente em
run; nativo varia
Consulte status do projeto antes de prometer build nativo a clientes.
Exemplo de pipeline CI
Pipeline Bitbucket mínimo exercitando ambos modos:
pipelines:
default:
- step:
script:
- cargo test
- ./target/release/crab-pascal check examples/hello.dpr
- ./target/release/crab-pascal run examples/hello.dpr
- ./target/release/crab-pascal build-exe examples/hello.dpr # imagem com gcc
Separe jobs se gcc inchou imagem Rust — mas nunca pule check. release-v2-17-0 documenta por que fingir sucesso nativo doía mais que badge vermelho.
Próximo da série
Post 041 — Review Sprint 1: diagnósticos reais fecha o arco de arquitetura revisitando a primeira entrega de sprint — por que check preciso destravou tudo acima (IDE, CI, erros honestos).
Published on dev.to/@crabpascal · Código em CrabPascal