Backend Standards

HGPPascal keeps the language model backend-independent, but each backend has a different standard shape. Debugging, profiling, and SECD support must respect that shape.

C Backend

The C backend should stay portable. Debug and profiling features are emitted as plain C structures, comments, or optional generated hooks rather than requiring a non-standard runtime library.

Native Executable Backends

The native backends intentionally do not duplicate the C generator. They make the executable build step explicit and preserve the generated C source so users can inspect, debug, profile, or recompile it with their preferred GCC-compatible toolchain.

JVM Backend

The JVM backend should follow JVM expectations: strongly typed generated Java, clear runtime metadata, and a path toward standard class-file debug tables.

P-Code Backend

The P-Code backend is the research backend. It can expose compiler-internal concepts directly as uppercase tags, as long as extensions remain explicit and stable.

Runtime And SECD/SSTD Contract

The shared runtime contract has three linked engines:

Procedure and lambda calls enter a fresh callee frame. The callee stack is empty except for the actual call parameters. When the callable returns, the caller frame is restored from the dump and the return value is pushed onto the caller stack. One-argument application is represented separately so higher-order values can be curried until their arity is satisfied.

C and JVM artifacts link this runtime directly into the generated program. Native executable targets compile that generated C runtime into the executable. P-Code artifacts attach the runtime contract through RUNTIME_BLOCK hgppascal_runtime so an executable host can discover and call the runtime block.

Heap references are represented as runtime handles. A heap object stores its kind, type, value or fields, metadata, and live/free state. Record and object allocations therefore remain visible to profiling, debugging, and future garbage-collection experiments instead of being anonymous host allocations.

Optional Backend Optimization Triple

Backend optimization is opt-in. Existing compile output remains unchanged until :backend-optimizations or --backend-optimizations is supplied.

The pass order is fixed:

  1. register-allocation
  2. instruction-scheduling
  3. peephole

The order is intentionally strict. Register allocation establishes virtual register, local slot, or stack slot pressure before scheduling. Instruction scheduling can then respect calls, I/O, environment switching, and SECD/SSTD barriers. Peephole optimization runs last so it can simplify target artifacts created by both earlier passes.

Callers may enable the whole triple or a subset:

(hgppascal.compiler/compile-source source :pcode {:backend-optimizations true})
(hgppascal.compiler/compile-source source :c {:backend-optimizations {:passes [:register-allocation :peephole]}})

Even when a subset is requested, selected passes are reordered into the canonical sequence. The public API exposes this through hgppascal.interface/backend-optimization-order and backend-optimization-plan.

Shared Contract

All backends consume the same resolved AST and descriptor model:

The public API exposes this through hgppascal.interface/backend-capabilities, backend-standards, backend-optimization-plan, language-profile, and analyze-source.