Files
RustAst/docs/record_optimizations_plan.md
T
Michael Schimmel bf74795e01 Refactor: Implement Record Layouts and Optimized Field Access
Introduces a new `RecordLayout` system for efficient and type-safe
record handling.

Key changes:
- `RecordLayout` struct with `O(1)` field lookup using FMap
  optimization.
- Field accessors (`.name`) are now first-class callable values.
- Parser recognizes dot-prefixed identifiers as field accessors.
- Binder and TypeChecker handle field accessors.
- Optimizer transforms field accessor calls into specialized `GetField`
  nodes.
- VM executes `GetField` efficiently by directly accessing record
  values.
- Adds a new `records.myc` example showcasing record features.
- Improves comparison logic for records to use pointer equality for
  layout.
2026-02-26 21:38:20 +01:00

2.7 KiB

Plan: Record Layout & Optimized Field Access

This document outlines the implementation plan for porting Delphi's TKeywordMappingRegistry optimizations to the Rust-based Myc AST compiler and integrating first-class field accessors.

1. Core Data Structures (src/ast/types.rs)

RecordLayout (The Schema)

  • Concept: Replaces IKeywordMapping<IStaticType>.
  • Interning: Managed via a global OnceLock<Mutex<HashMap<..., Arc<RecordLayout>>>>.
  • FMap Optimization:
    • Stores fields: Vec<(Keyword, StaticType)>.
    • Maintains a lookup array Vec<i32> mapping Keyword.idx - first_key to the index in the fields array.
    • Provides index_of(Keyword) -> Option<usize> with O(1) complexity.
  • Thread Safety: Uses Arc for global sharing across script threads.

Value & StaticType Updates

  • Value::Record points to an Arc<RecordLayout> and a flat Rc<Vec<Value>>.
  • Value::FieldAccessor(Keyword) added as a first-class callable value (e.g., .name).
  • StaticType::Record now holds Arc<RecordLayout>.

2. Compiler Pipeline

Parser (src/ast/parser.rs)

  • Identifiers starting with . (e.g., .age) are parsed as UntypedKind::FieldAccessor(Keyword).
  • This ensures interning happens immediately; strings are never used for field access in subsequent phases.

Binder (src/ast/compiler/binder.rs)

  • Maps UntypedKind::FieldAccessor to BoundKind::FieldAccessor.

TypeChecker (src/ast/compiler/type_checker.rs)

  • Analysis Only: When encountering Call { callee: FieldAccessor, args: [rec] }:
    • Validates that rec is a Record.
    • Uses RecordLayout::index_of to find the field's type.
    • Sets the call's return type accordingly.
    • Crucial: Does NOT modify the AST structure. It remains a Call.

Optimizer (src/ast/compiler/optimizer/engine.rs)

  • Transformation: Recognizes the Call { callee: FieldAccessor, ... } pattern.
  • Transforms it into a specialized BoundKind::GetField { rec, field: Keyword } node.

3. Execution (src/ast/vm.rs)

Optimized Path (GetField)

  • The VM executes GetField by:
    1. Evaluating the record.
    2. Calling layout.index_of(field) (O(1)).
    3. Fetching the value from the flat array.

Functional Path (FieldAccessor)

  • If .field is passed as a value (e.g., (map .name users)), the VM treats the FieldAccessor value as a standard function that takes one argument and performs the lookup.

4. Benefits

  • Type Identity: Arc::ptr_eq allows instant type comparison.
  • Performance: Field access in loops is O(1) without hash lookups.
  • Safety: The TypeChecker remains a pure analysis phase as per design requirements.