Skip to content

Latest commit

 

History

History
96 lines (72 loc) · 3.54 KB

File metadata and controls

96 lines (72 loc) · 3.54 KB

Architecture

elderheim is designed as a multi-frontend compiler with one shared backend.

Compiler Flow

  1. The CLI reads a source file and an explicit dialect flag.
  2. The selected parser frontend lexes and parses that dialect.
  3. The parser lowers dialect-specific syntax into elderheim-ast.
  4. Semantic analysis validates labels, control-flow targets, variables, types, scopes, arrays, and runtime calls.
  5. The Cranelift backend emits native object code.
  6. In 0.30.0, the experimental text-output linker stage resolves an absolute host C compiler path on Linux/macOS and links the generated object with a bundled elderheim text runtime source written to a temporary file.
  7. Before the supported stable release path, executable generation should move toward elderheim-owned linking/runtime packaging so users do not need Rust, rustc, Cargo, a C compiler, or an external linker where platform constraints allow it.

Standalone Goal

The long-term user contract is one elderheim binary per supported OS and architecture. Users should be able to run elderheim program.bas and compile old source code through elderheim itself.

The supported release path should not require users to install Rust, rustc, Cargo, a C compiler, or an external linker where platform constraints allow it. The 0.30.0 host C compiler linker is a temporary implementation bridge for testing the runtime ABI and executable flow, not the final architecture.

Workspace Crates

  • elderheim-ast: shared syntax tree and language-neutral node vocabulary.
  • elderheim-parsers: isolated dialect frontends.
  • elderheim-parsers::semantic: first semantic checks over parsed programs.
  • elderheim-codegen: Cranelift object backend and temporary Linux/macOS text executable linker.
  • elderheim: command-line compiler application.

These are local workspace crates. They are not intended for crates.io publishing while the compiler architecture is still changing; the workspace manifests keep publish = false.

Module Layout Policy

Keep files small enough to review. lib.rs files should declare modules and expose stable crate APIs; they should not accumulate compiler implementation logic.

Language frontends live under:

crates/elderheim-parsers/src/languages/

For example:

crates/elderheim-parsers/src/languages/basic.rs
crates/elderheim-parsers/src/languages/quickbasic.rs
crates/elderheim-parsers/src/languages/pascal.rs

When a frontend grows too large, split it by compiler phase before it becomes a single hard-to-review file:

languages/basic/
├── ast_lowering.rs
├── lexer.rs
├── mod.rs
└── parser.rs

As a rule of thumb, new feature work should split a module before it crosses a few thousand lines or mixes unrelated responsibilities such as lexing, parsing, semantic lowering, diagnostics, runtime modeling, and compatibility fixtures.

Dialect Policy

No dialect parser may rely on another dialect's syntax rules. A Commodore BASIC parser, for example, should not inherit QuickBASIC behavior accidentally.

The shared AST is the compatibility layer. Dialect-specific syntax such as PSET, PLOT, or HPLOT should lower into generic semantic operations once the feature is supported.

Security Model

Input source files are untrusted. Parser, codegen, and linker paths must avoid panics, unchecked indexing, shell interpolation, path traversal, and implicit execution of generated artifacts.

The compiler must reject unsupported constructs with explicit diagnostics rather than producing silently wrong binaries.