DEV Community

CrabPascal
CrabPascal

Posted on

Dual-Mode Build: Interpret vs Native C | Dual-mode: interpretar vs C nativo

Bilingual post · Post bilíngue

Jump to: English · Português


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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  • .c files still generate — inspect codegen diff in PRs
  • Link step errors if no compiler found
  • Undefined variable fails semantic pass consistently on both paths

Validate locally:

cargo test --test run_build_parity
cargo test --lib
Enter fullscreen mode Exit fullscreen mode

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 run tested; 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 .c ainda geram — inspecione diff de codegen em PRs
  • Etapa de link errar se não achar compilador
  • Undefined variable falha semântica consistente nos dois caminhos

Valide localmente:

cargo test --test run_build_parity
cargo test --lib
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)