Commit Graph

182 Commits

Author SHA1 Message Date
Brummel 8ef93e2af5 Refactor TypeChecker into modules
The TypeChecker implementation was becoming quite large, so it has been
refactored into several modules:
- `context`: Handles type checking contexts and inference access.
- `inference`: Contains the core Hindley-Milner inference logic
  (unification, generalization, etc.).
- `finalize`: Manages the finalization step, applying substitutions and
  dispatching hooks.
- `check`: Implements the main type checking logic for AST nodes.

This modularization improves code organization and maintainability.
2026-03-30 14:47:38 +02:00
Brummel 2a5b87f45f Add handling for new node kinds in visitors
The `analyzer.rs` and `lambda_collector.rs` files have been updated to
correctly traverse and process new node kinds in the Abstract Syntax
Tree (AST). This ensures that these new node types are properly included
in the analysis and lambda collection phases of the compiler.
2026-03-30 14:30:07 +02:00
Brummel 24d36a08a6 Refactor 'again' type check to use unify
This change replaces a manual type check for the `again` function with a
call to the generic `unify` function. This improves consistency and
leverages existing type-checking logic.

A new test case `test_again_type_mismatch` has been added to
specifically verify that type mismatches in `again` calls are caught at
compile time, preventing potential infinite loops.
2026-03-30 11:50:08 +02:00
Brummel c403c80f5b Refine type error reporting for readability
The `display_compact` method on `StaticType` has been enhanced to
provide more concise representations of types within error messages.
This change aims to improve the clarity of type-related diagnostics
generated by the compiler.
2026-03-30 11:45:31 +02:00
Brummel 8aa2a67b5b Introduce StaticType::Variadic for variadic parameters
This commit introduces `StaticType::Variadic` to represent variadic
parameter types in function signatures. This allows for more precise
type checking of functions that accept a variable number of arguments,
such as arithmetic operators.

Previously, variadic functions were handled using `StaticType::Any`,
which was too permissive and could lead to runtime errors. The new
`Variadic` type enforces that all arguments must conform to a specified
inner type.

Changes include:

- Adding `StaticType::Variadic` to `src/ast/types.rs`.
- Updating the type checker to handle `Variadic` types correctly when
  unifying with tuples or single arguments.
- Modifying built-in functions like arithmetic operators to use
  `Variadic` for their parameter types.
- Improving error messages for function call mismatches to be more
  specific.
- Adding a new test case to ensure arithmetic type mismatches are caught
  at compile time.
- A new example `data_stream_pipe_buffered.myc` is added.
- The `HMA.myc` example now has a `Skip: output` directive.
2026-03-30 11:36:26 +02:00
Brummel 1f3fb40bcc Update record type computation
This commit refactors the way record types are computed within the
optimizer. Previously, the optimizer would often reuse the existing
`NodeMetrics` for records, which could lead to stale or polymorphic
types.

The changes introduce a new function, `compute_record_type`, which
explicitly recalculates the `StaticType` for a `Record` node based on
the concrete types of its child fields. This ensures that after
optimizations like inlining and folding, record types are as concrete as
possible, eliminating unresolved `TypeVars`.

Additionally, the `folder.rs` module is updated to recompute the
`RecordLayout` when creating constant record values, further improving
type accuracy. Two new tests are added to verify that inlined records,
including those with multiple fields, correctly result in concrete
types.
2026-03-29 18:59:38 +02:00
Brummel 6c8e2df45c Refactor: Improve type propagation in optimizer
Refactor the `updated_metrics` function to `refreshed_metrics`. This
function now clones the `NodeMetrics` if the new type is identical to
the original, avoiding unnecessary allocations.

Also, adjust the `Block` and `Lambda` node kinds to correctly propagate
concrete types after inlining, especially when dealing with polymorphic
functions. This ensures that the return types of blocks and lambdas
reflect the actual computed types rather than stale type variables.

This change improves type inference accuracy and prepares for more
advanced optimizations by ensuring type information is correctly
propagated through the AST.
2026-03-29 18:50:05 +02:00
Brummel 03862d50c6 Add tuple type recomputation after inlining
Introduce helper functions to recompute the `StaticType` of a tuple node
based on its children's types. This ensures that after inlining, tuples
within the AST have concrete types, rather than unresolved type
variables, even when derived from polymorphic functions.

Also adds tests to verify this behavior for both homogeneous and
heterogeneous tuples.
2026-03-29 18:44:48 +02:00
Brummel 0e806b9e5d feat: Add compact AST dump
Introduce a new `dump_ast_compact` function for the environment and
Dumper. This function provides a simplified, human-readable
representation of the AST, focusing on inferred types and purity markers
instead of detailed debug information.

This change adds:
- A `compact` flag to the `Dumper` struct.
- The `dump_compact` method to the `Dumper`.
- The `dump_ast_compact` method to the `Environment`.
- A new `dump_ast_compact` command-line argument for the `ast` binary.
- A new MCP server endpoint `dump_ast_compact`.
- A `CompactMetadata` trait to abstract over different metadata types
  for compact display.
- Updates to documentation and CLI help messages.
2026-03-29 18:28:10 +02:00
Brummel 10a7fcb576 Refactor: Replace Object with StreamStorage for streams
The `Object` trait is too generic and has been causing confusion. This
commit introduces `StreamStorage` as a dedicated trait for reactive
stream types.

This change involves:

- Renaming `Object` to `StreamStorage` in relevant places.
- Updating the `Value::Object` enum variant to `Value::Stream`.
- Modifying how streams are handled in the compiler, VM, and tests to
  use the new `StreamStorage` trait.
- Adjusting example scripts and tests to reflect the change in type
  representation.
- The `StreamNode` struct now explicitly holds its `element_type`.
2026-03-29 18:01:46 +02:00
Brummel a665e2c1a5 Refactor call hooks to use trait objects
This commit refactors the call hook mechanism in the compiler. Instead
of using function pointer types (`PostCallHook`, `FinalizeHook`) and a
struct to hold them (`CallHooks`), it introduces a trait
`RtlCompilerHook` with default implementations for `post_call` and
`finalize`.

This change aligns with Rust's idiomatic way of handling extension
points and allows for more flexible and extensible compiler behavior.
The `TypeChecker` now holds a map of `Rc<dyn RtlCompilerHook>`, enabling
different RTL functions to register their specific compiler hooks. The
`SeriesHook` and `PushHook` structs are introduced to demonstrate this
new pattern.
2026-03-29 14:52:58 +02:00
Brummel 916460ab03 Remove IndexElementFn and series_element_type
The `IndexElementFn` trait and its associated `series_element_type`
function have been removed. The `TypeChecker` now directly inspects the
`StaticType::Series` variant to extract the element type when
propagating index constraints. This simplifies the type-checking logic
by removing an unnecessary layer of indirection and adhering to the
project rule of keeping the AST simple and pushing complexity into the
system.
2026-03-29 14:00:48 +02:00
Brummel 0292ead7a5 Refactor InferenceAccess for call hooks
The `TypeInferenceAccess` and `TypeSlotAccess` traits have been
consolidated into a single `InferenceAccess` trait. This simplifies the
call hook interface by providing a unified way to access type inference
operations and scope slot types.

A new struct, `CheckerInferenceAccess`, is introduced to provide a
concrete implementation of `InferenceAccess` for the `TypeChecker`. This
struct wraps both the `TypeChecker` and the `TypeContext`, allowing call
hooks to interact with both without needing to know their specific
types. This avoids potential circular dependencies between modules.

The `get_slot_type` method has been moved to the new `InferenceAccess`
trait. This method is crucial for call hooks that need to recover the
original `TypeVar` ID after substitutions have occurred, particularly in
the `push_post_call` function for series.
2026-03-29 13:55:32 +02:00
Brummel 93a85cd15c Add IndexElementFn for series type probing
Introduce `IndexElementFn` as a type alias for a function that maps a
`StaticType` to an optional `StaticType` representing its element type.
This allows the `TypeChecker` to determine the element type of indexable
types like `Series` without needing to be aware of their specific
implementations.

The `series_element_type` function is created and registered with the
`TypeChecker` to handle `Series` types. This design centralizes
type-specific logic for indexable types, making the `TypeChecker` more
generic and extensible for future indexable types such as `Stream`.
2026-03-29 13:20:49 +02:00
Brummel 9c434fb49d Fix: Unify TypeVars when indexing generic parameters twice
When a generic function indexes the same TypeVar parameter multiple
times,
all resulting TypeVars must share a single element type. This change
ensures
that subsequent indexing operations unify their fresh TypeVar with an
existing
one if the parameter has already been indexed, preventing incorrect type
inference and false negatives.

A new test, `test_let_poly_multi_index_all_results_typed`, is added to
verify this behavior.
2026-03-28 23:03:38 +01:00
Brummel 84abbd9721 Add Forall type for polymorphism
Introduce `StaticType::Forall` to represent universally quantified
types. This enables Hindley-Milner's let-polymorphism, allowing
functions to be generalized and reused with different concrete types.

- **Generalization at `def`:** Function values are now generalized using
  `self.generalize` when they are defined, wrapping their type in
  `Forall`. This occurs at `def` boundaries.
- **Instantiation at use:** Function types are instantiated with fresh
  type variables at each call site using `self.instantiate`. This
  ensures that different uses of the same polymorphic function do not
  interfere with each other's type inference.
- **Value restriction:** Only function-typed definitions are
  generalized. Mutable state like series and scalars remain monomorphic
  to prevent unexpected behavior.
- **Type context awareness:** The `generalize` function considers the
  current type context to avoid quantifying type variables that are
  still in use elsewhere.
  Feat: Add Forall type for polymorphism

Introduces the `Forall` type to support polymorphic functions and enable
let-polymorphism.

- `Forall(vars, body)`: Represents a universally quantified type where
  `vars` are the type variables bound by this quantification, and `body`
  is the type itself.
- `TypeChecker::generalize`: Wraps a type in `Forall` when a `def`
  boundary is encountered for function-typed values. This ensures that
  each use site of a polymorphic function gets its own instantiation.
- `TypeChecker::instantiate`: Replaces the type variables within a
  `Forall` type with fresh ones. This is performed at each call site of
  a polymorphic function.
- Updates `TypeChecker::unify` and `TypeChecker::apply_subst` to
  correctly handle `Forall` types, ensuring that bound variables within
  a `Forall` are not affected by global substitutions and that `Forall`
  types are instantiated before unification.
- Adds a new example script `examples/Propa.myc` to demonstrate basic
  usage.
- Includes a regression test
  `test_let_poly_non_series_callable_no_false_positive` to ensure that
  passing non-series callables to generic functions does not lead to
  type errors.
- Introduces `TypeChecker::bind_var` to handle lazy propagation of
  index-call constraints, crucial for correctly typing series lookups
  like `(s 0)`.
2026-03-28 22:49:44 +01:00
Brummel 8efd12add6 Add call hooks for series and push
Introduces `CallHooks` to enable extensions to the type inference and
AST finalization process. This allows for more dynamic and configurable
behavior without hardcoding symbol names in the compiler core.

Specifically, this commit adds:

- **`series_post_call`**: A hook for the `(series n)` function. It
  ensures that the return type is a fresh `TypeVar` when the element
  type is `Any`, allowing for proper type inference from subsequent
  `push` calls.
- **`series_finalize`**: A hook for `(series n)` that rewrites the AST
  node. It replaces the generic `series` call with a pre-configured
  factory closure that allocates the correct series storage type (e.g.,
  `ScalarSeries<f64>` for floats, `RecordSeries` for records). This
  avoids runtime dispatch and relies on type information captured during
  compilation.
- **`push_post_call`**: A hook for the `(push series val)` function. It
  unifies the series element `TypeVar` with the pushed value's type. It
  also handles numeric and record field promotion and updates the
  `TypeVar` binding if a promotion occurs.
2026-03-28 21:13:26 +01:00
Brummel 6cab8f649b Introduce numeric and record widening
This commit introduces implicit numeric widening from Int to Float and a
corresponding record promotion mechanism.

When pushing values into a series, if the series' element type is a
TypeVar,
and the pushed value is of a different numeric type (e.g., Int and
Float),
the TypeVar will be unified with the wider type (Float). This ensures
that
operations on series elements handle type differences gracefully.

The record promotion handles cases where two records are involved, and
their
fields have compatible types, either identical or through numeric
widening.
This allows for more flexible type inference in complex structures.
2026-03-28 14:52:24 +01:00
Brummel 350b7b49b6 Fix: Apply substitutions to upvalue types
When an identifier is used as an upvalue within a nested scope (e.g., a
`while` loop), the type checker needs to apply the global substitution
map to resolve `TypeVar`s that might have been determined in outer
scopes. This ensures that the correct type is used even if
`ctx.set_type` couldn't propagate the change directly through the
upvalue address.

This fix also includes a regression test to specifically cover this
scenario with series and closures.
2026-03-28 14:22:25 +01:00
Brummel d7d1aef8ed Refactor type checker for series and overloads
Introduce `unify_matched_overload` to handle type variable propagation
for overloaded functions. This ensures that when an overload is chosen,
its concrete parameter types are unified with the actual argument types.
This is crucial for resolving type variables nested within closures
called through overloaded functions.

Additionally, this commit:
- Allows `series` to infer schema type from `push` calls, simplifying
  its signature.
- Adds a fallback to `ValueSeries` in `rtl::series` if schema injection
  fails.
- Updates `StaticType::TypeVar` to return `Any` when accessed,
  simplifying field access logic.
- Adjusts tests to reflect the simplified `series` signature.
2026-03-28 14:03:48 +01:00
Brummel d2cba2d55d Refactor: Simplify series creation and infer element type
The `series` constructor now only accepts the `lookback` limit. The
element type is inferred by the type checker and implicitly added as a
schema argument during compilation. This simplifies the API and
centralizes type inference.

This change also includes:
- Updates to example scripts (`HMA.myc`, `sma.myc`, `soa_series.myc`) to
  reflect the new `series` signature.
- Modifications to the `TypeChecker` to handle the inferred schema
  injection.
- An addition of a regression test for type inference through nested
  closures with `series`.
- Removal of `#[allow(dead_code)]` from several `TypeChecker` methods as
  they are now used.
- Update to `rtl/prelude.myc` macro `cache`.
- Update to `rtl/series/mod.rs` to reflect new signature.
- Update to `ast/types.rs` to allow `series` to be indexed with an
  integer to retrieve its element type.
2026-03-28 13:47:15 +01:00
Brummel e595e747d4 Add type inference infrastructure
Introduces a `TypeChecker` struct with logic for Hindley-Milner type
inference.
This includes:
- `var_counter` for generating unique type variable IDs.
- `subst` for the global substitution map.
- `fresh_var` to create new type variables.
- `apply_subst` to resolve type variables recursively.
- `occurs` to check for cycles during unification.
- `unify` to merge types and extend the substitution.

The `StaticType` enum is extended with a `TypeVar(u32)` variant to
represent unresolved type variables.
The `Display` and `is_assignable_from` implementations for `StaticType`
are updated to handle `TypeVar`.
2026-03-28 13:08:15 +01:00
Brummel 0e8cd0832f Refactor global variable access in VM and optimizer
Replaces `Rc<RefCell<Vec<Value>>>` with a new `GlobalStore` struct for
accessing global variables. This provides a more structured way to
manage global values and allows for future optimizations like sharing
immutable RTL portions across environments. The `GlobalStore` also
includes an `rtl_len` field to distinguish between RTL and user global
slots, enabling debug-time checks for writes to immutable RTL slots.
2026-03-27 23:40:42 +01:00
Brummel 1379ab366a Refactor module loading to improve clarity
The module loading logic has been refactored to enhance readability and
maintainability. Key changes include:

*   **Path Handling**: Simplified path construction using `join` for
    better clarity and consistency.
*   **Error Reporting**: Improved error messages during parsing by
    utilizing `parser.diagnostics.format_errors()`.
*   **Module Loading Logic**:
    *   The `loaded_modules` set now uses `insert()` to both add new
        modules and efficiently check for duplicates, returning `false`
        if the module was already loaded.
    *   The recursive call to `collect_dependencies` is now placed
        before processing the current file's AST, ensuring a topological
        order of dependency loading.
*   **Helper Function Scope**: `extract_use_directives` is now a static
    method as it doesn't depend on the `ModuleLoader` instance.
2026-03-27 16:16:45 +01:00
Brummel 1f0208af95 Add module loader and related tests
Introduce `ModuleLoader` to handle `#use` directives and dependency
resolution. This involves adding `tempfile` dependency, modifying
`Cargo.toml` and `Cargo.lock`, creating a new `module_loader.rs` file,
and updating `environment.rs` to use the new module.

Also, add comprehensive tests for `Diagnostics::format_errors`,
`CompilationResult`, and the new `ModuleLoader` functionality. These
tests cover various scenarios including empty diagnostics, multiple
errors, error formatting, compilation success/failure, and complex
dependency loading with topological ordering and search path resolution.
2026-03-27 15:08:28 +01:00
Brummel 4f05562e0c Introduce CompilationResult struct
This commit introduces the `CompilationResult` struct to encapsulate the
outcome of a compilation pass. It holds either a successfully compiled
`TypedNode` or a `Diagnostics` object containing errors. Helper methods
for creating success or error results and for converting to a `Result`
are also included. This improves error handling and clarity in the
compilation process.
2026-03-27 13:25:12 +01:00
Brummel 9c5506b83e Implement unhygienic macro expansion for ~ident
This commit introduces support for unhygienic macro expansion using the
`~ident` syntax. When an identifier is prefixed with a tilde (`~`)
within a macro template, it is no longer subject to hygienic renaming.
Instead, it directly refers to a binding in the call site's environment.

This allows macros to interact with variables defined outside the
macro's scope, such as:
- Modifying call-site variables.
- Capturing call-site variables as upvalues in closures.
- Defining new variables that are visible in the call site.

A new test case `test_macro_tilde_nonparam_assign` has been added to
verify this functionality. Previously, unhygienic escapes were
implicitly handled by `SyntaxKind::Identifier` if they were not macro
parameters. This change makes this behavior explicit and correctly
handles non-parameter identifiers by returning a bare symbol.
2026-03-27 10:06:50 +01:00
Brummel 903c77a665 Update series syntax and binder scope handling
Refine the BNF for `series` to explicitly include the `lookback_limit`
and `schema`.
Introduce scope management within the `bind` function for `if/else`
branches to ensure correct context handling during compilation.
Add `Again` and `GetField` node kinds to the `Specializer`.
Improve lexer to ignore invisible characters within identifiers,
demonstrated by a new test case.
2026-03-26 16:04:45 +01:00
Brummel 0088a644eb Refactor stack allocator to reuse freed slots
Introduce `free_slots` in `StackAllocator` to keep track of physical
slots that have been freed. When mapping a new virtual slot, the
allocator first attempts to reuse a slot from the `free_slots` vector
before allocating a new one.

This change also includes a new function `collect_scope_locals` that
identifies non-captured local variables defined within a block. After
these expressions are lowered, the allocator reclaims the physical slots
associated with these locals, making them available for reuse by
subsequent blocks.

A new test `test_slot_reuse_non_overlapping_scopes` is added to verify
that distinct scopes correctly reuse stack slots, ensuring optimal stack
usage.
2026-03-26 14:01:46 +01:00
Brummel 78813e7197 Refactor: Optimize block handling in optimizer
The optimizer now correctly handles empty blocks by collapsing them into
Nop nodes. It also unwraps blocks containing a single expression, making
the AST more concise. This change improves AST simplification by
ensuring that redundant block structures are removed.
2026-03-26 13:44:38 +01:00
Brummel 273dc83d68 Refactor if-else binding scope management
The explicit scope management within the `if`/`else` binding logic was
redundant.
The `bind` function recursively handles scope creation and destruction
for
expressions, making manual scope manipulation here unnecessary and
error-prone.
2026-03-26 12:19:33 +01:00
Brummel e757b453a4 feat: Add AST emitter and comment support
Introduces a new AST emitter module responsible for serializing AST
nodes back into Myc source code. This emitter preserves leading comments
and whitespace, enabling a round-trip guarantee for the parser and
emitter.

The documentation in `docs/BNF.md` has been updated to reflect the new
syntax rules for comments, including single-line comments (`;`) and
documentation comments (`;;`). The rules clarify that comments must be
whole lines and that inline comments are disallowed.

The lexer and AST node structures have been updated to accommodate
`CommentLine` variants, allowing for different types of comments
(regular, documentation, and blank lines) to be stored and processed.

A new test suite `tests/comment_roundtrip.rs` has been added to verify
the round-trip property of the parser and emitter across all example
`.myc` files. This test ensures that parsing source code, emitting it,
and then parsing the emitted code again results in the same output
string.

The `ast.rs` binary now includes a `--emit` flag that uses the new
emitter to output the parsed source code, facilitating debugging and
testing of the emitter itself.
2026-03-25 19:15:40 +01:00
Brummel ee89d2330d feat: Add comments to AST nodes
This commit introduces support for comments within the AST nodes.
Comments are now parsed by the lexer and stored within the `Token`
struct.
These comments are then propagated through various compiler phases,
including
the `Node` struct, ensuring they are preserved in the Abstract Syntax
Tree.
This change enhances the AST's ability to retain source code
information,
which can be valuable for debugging and analysis.
2026-03-25 18:36:53 +01:00
Brummel a5c3f3da04 feat: Add bidirectional type inference for lambdas
This commit introduces bidirectional type inference, enabling the
compiler to infer lambda parameter types based on the context of their
usage. This is particularly useful for functions like `pipe`, where a
lambda's signature can be deduced from the types of the streams it
operates on.

Key changes include:

- **`extract_lambda_param_hints` function:** This new helper function in
  `type_checker.rs` is responsible for extracting expected parameter
  types for a lambda based on the callee's signature and already known
  argument types.
- **`check_lambda_with_param_hints` function:** This function allows
  type-checking a lambda node using provided parameter type hints,
  preserving upvalue types from the enclosing scope.
- **Call expression type checking:** The `check_call` function now
  phases its argument type checking. Non-lambda arguments are typed
  first, and then lambda arguments are typed using hints derived from
  `extract_lambda_param_hints`.
- **`pipe_arg_hint_resolver`:** This new resolver for the `pipe`
  function's `PolymorphicFn` type allows it to provide specific type
  hints for its lambda argument based on the types of its stream inputs
  (single stream, vector of streams, or tuple of streams).
- **`StaticType::PolymorphicFn` update:** The `PolymorphicFn` enum
  variant has been extended to include `resolve_arg_hints`, enabling
  functions to provide lambda parameter hints during bidirectional type
  inference.
- **New tests:** Added tests to verify the correct inference of lambda
  parameters for `pipe` with vector and tuple inputs, ensuring that
  inner stream types are correctly propagated. Also, a test to confirm
  `pipe` with an optional return still produces `Stream(Float)`.
2026-03-23 10:51:06 +01:00
Brummel 1875cfdc9b Remove unused pipe node definitions
The `Pipe` node and its associated logic have been removed from the AST.
This commit cleans up the code by removing all references to this
defunct node in the analyzer, binder, captures, dumper, lowering,
macros, optimizer, and type checker. The parser no longer recognizes the
`pipe` keyword.
2026-03-23 10:22:12 +01:00
Brummel 09ae98728f Refactor Value enum for Quote node
Replaces `Value::Object(Rc<dyn Object>)` for SyntaxNodes with a
dedicated `Value::Quote(Rc<SyntaxNode>)`. This provides better type
safety and clarity when dealing with AST nodes as values.
Refactor Value enum for Quote node

This commit introduces a new `Value::Quote` variant to represent quoted
AST nodes directly, replacing the generic `Value::Object` for this
purpose.

This change simplifies the handling of quoted nodes by:
- Directly storing an `Rc<SyntaxNode>` instead of relying on dynamic
  downcasting from `Rc<dyn Object>`.
- Streamlining macro expansion logic by removing the need to check for
  `SyntaxNode` within `Value::Object`.
- Improving type safety and explicitness in the `Value` enum.
2026-03-22 20:53:30 +01:00
Brummel 843ee7dfed Refactor: Use Value::Closure enum variant
Previously, compiled closures were stored as `Value::Object` and then
downcasted. This commit introduces a dedicated `Value::Closure` enum
variant to represent compiled closures. This improves type safety and
simplifies handling of closures throughout the compiler and VM.

This change involves:
- Updating type definitions to use `Value::Closure`.
- Adjusting downcasting logic to directly access the `Closure` struct.
- Modifying `run_with_args` and `run_with_args_observed` to expect
  `Value::Closure` for tail-call targets.
- Refining the handling of closures in the `Optimizer` and `Inliner` for
  better type clarity.
2026-03-22 19:41:23 +01:00
Brummel 6c37b0c64f Introduce closure AST node
The `Closure` struct has been moved from `ast/vm.rs` to a new module
`ast/closure.rs`. This improves the organization of the AST nodes. The
`Closure` struct represents a compiled function body along with its
captured upvalues, which is a key feature for Myc Script.
2026-03-22 19:37:04 +01:00
Brummel 007446a167 Update various types to use their own definitions
This commit refactors several modules to use the defined types from
`ast::types` and `ast::nodes` directly, rather than using fully
qualified paths. This improves code readability and reduces redundancy.

Specifically, the following changes were made:

- In `analyzer.rs`, `crate::ast::types::Identity` and
  `crate::ast::types::Purity` are now used directly.
- In `binder.rs`, `crate::ast::types::NodeIdentity`,
  `crate::ast::types::SourceLocation`,
  `crate::ast::types::RecordLayout`, and `crate::ast::types::Value` are
  now used directly.
- In `macros.rs`, types like `Address`, `VirtualId`, `NodeIdentity`,
  `SourceLocation`, `StaticType`, and `Purity` are now used directly.
- In `optimizer/engine.rs`, `Address<VirtualId>` is now used directly.
- In `type_checker.rs`, `BoundPhase`, `Signature`, `Keyword`, and
  `RecordLayout` are now used directly.
- In `environment.rs`, `CompilerScope`, `LocalInfo`, `CapturePass`,
  `AnalyzedPhase`, `NativeFunction`, and `Closure` are now used
  directly.
- In `nodes.rs`, `RecordLayout`, `Keyword`, `Purity`, and `StaticType`
  are now used directly.
- In `parser.rs`, `SourceLocation` and `NodeIdentity` are now used
  directly.
- In `rtl/math.rs`, `NativeFunction`, `Purity`, `Signature`,
  `StaticType`, `Value`, `RefCell`, and `Rc` are now used directly.
- In `rtl/streams.rs`, `ScalarValue`, `SeriesMember`, `Object`,
  `PipeFn`, `Value`, `VM`, `RingBuffer`, `RecordSeries`, `SeriesView`,
  `build_map_stream`, and `build_pipeline_node` are now used directly.
- In `rtl/type_registry.rs`, `RecordLayout`, `Keyword`, `Purity`,
  `Signature`, `StaticType`, and `Value` are now used directly.
- In `vm.rs`, `RecordSeries`, `SeriesView`, `build_map_stream`,
  `build_pipeline_node`, `StreamNode`, `Object`, and `PipeFn` are now
  used directly.
- In `utils/tester.rs`, `TypedNode` is now used directly.
2026-03-22 18:30:56 +01:00
Brummel 1cbc656554 Refactor: Move compiler node definitions to src/ast/nodes
The `bound_nodes.rs` file has been removed and its contents have been
moved to `src/ast/nodes.rs`. This consolidates all AST node definitions
into a single module, improving organization and maintainability.

The `compiler` modules now import these definitions from
`crate::ast::nodes` instead of `crate::ast::compiler::bound_nodes`.
2026-03-22 17:58:49 +01:00
Brummel 49ad76e7c3 Refactor: Remove integration tests and organize into modules
This commit refactors the test suite by removing the monolithic
`integration_test.rs` file.
The tests have been categorized and moved into dedicated modules within
the `tests/` directory:

- `tests/parser.rs`: Contains tests for parsing various literal values.
- `tests/destructuring.rs`: Houses tests related to destructuring
  syntax.
- `tests/closures.rs`: Includes tests for closure behavior and related
  optimizations.
- `tests/optimizer.rs`: Contains tests specifically targeting optimizer
  logic and regressions.
- `tests/records.rs`: Holds tests for record syntax and associated
  optimizations.
- `tests/rtl.rs`: Contains tests for runtime library operators and
  functions.
- `tests/pipeline.rs`: Tests for pipeline functionality.
- `tests/macros.rs`: Tests for macro expansion and related issues.
- `tests/error_recovery.rs`: Includes tests for compiler error handling
  and recovery mechanisms.
- `tests/examples.rs`: Verifies the execution of example scripts.

This reorganization improves test discoverability and maintainability.
The `lib.rs` file has also been updated to reflect these changes by
removing the reference to the old `integration_test` module.
The `type_checker.rs` file has had some tests removed, as they are now
covered by the more specific tests in `tests/error_recovery.rs`.
2026-03-21 15:56:07 +01:00
Brummel bc287d27dd Add destructuring support to dead-def elimination
Introduce `collect_pattern_addrs` to gather all bound addresses from a
destructuring pattern. This enables the optimizer to remove unused
destructuring definitions, similar to how simple unused definitions are
handled. Added integration tests to verify this behavior and other
optimizer robustness scenarios.
2026-03-21 15:35:28 +01:00
Brummel 6264e21f24 Remove unused BoundKind enum
The `BoundKind` enum was declared but never used. This commit removes it
to clean up the codebase.
2026-03-21 14:16:18 +01:00
Brummel e65402364d Refactor: Use new NodeKind and clean up Binder definitions
The Binder and related types have been refactored to use the new
`NodeKind` enum instead of the previous `BoundKind`. This commit updates
all references to use the new structure, ensuring consistency across the
compiler's AST representation.

Key changes include:

- Replacing `BoundKind` with `NodeKind` in the Binder's `bind` and
  `visit` methods.
- Updating pattern matching and field access to reflect the new enum
  variants (e.g., `NodeKind::Def` instead of `BoundKind::Define`).
- Adjusting identifier bindings to use the new `IdentifierBinding` enum.
- Reflecting changes in `DefBinding`, `AssignBinding`, and
  `LambdaBinding` structures.
- Ensuring all newly created nodes use `NodeKind` and the appropriate
  metadata.
2026-03-21 14:12:14 +01:00
Brummel 99fef2fc86 Refactor AssignBinding and add GetField node
The `AssignBinding` struct now uses `Option<Address<L>>` to
differentiate between simple assignments and destructuring assignments.
For destructuring, the addresses are managed by the `Identifier` nodes
within the target pattern.

A new `GetField` node kind has been introduced to represent optimized
field access, which is generated during the lowering phase for the
`RuntimePhase`. This change aids in more efficient code generation for
accessing fields.
2026-03-21 12:51:39 +01:00
Brummel 72244d9da7 Add generic NodeKind enum
This commit introduces a new `NodeKind` enum that serves as a unified
representation for AST nodes across different compilation phases. It
replaces the separate `SyntaxKind` and `BoundKind` enums, allowing
phase-specific information to be attached through generic type
parameters.

This change simplifies the AST structure and makes it easier to manage
node information consistently throughout the compilation process. The
`NodeKind` enum now holds all possible AST node variants, with
phase-specific data encapsulated within `CompilerPhase` trait
implementations.
2026-03-21 12:43:46 +01:00
Michael Schimmel 1a7bb5d3e6 Optimize Clone for BoundKind and VM GetField
This commit reduces unnecessary cloning for fields like `addr`, `kind`,
and `field` within `BoundKind` and `VM::GetField`. This improves
performance by avoiding redundant memory allocations.
2026-03-13 19:55:48 +01:00
Michael Schimmel 0dfcfac7b3 Refactor AST substitution logic
This commit refactors the AST substitution logic to correctly handle
nested expansions and improve the inlining of lambda expressions.

The changes include:
- Extracting the core value from potentially expanded AST nodes before
  checking their kind.
- Ensuring that lambda expressions with empty upvalues are correctly
  substituted.
- Adding support for inlining global get expressions as AST
  substitutions.
- Improving the `UsageInfo` collection to correctly track assigned
  values.
2026-03-13 19:51:56 +01:00
Michael Schimmel e5d82ee2b6 Refactor bound node types for clarity
Introduce generic `CompilerPhase` trait to unify different stages of the
bound AST. Rename `LocalSlot` to `VirtualId` and introduce `StackOffset`
for clearer distinction between compile-time and run-time addressing.
Update type aliases and implementations to reflect these changes.
2026-03-13 19:20:44 +01:00
Michael Schimmel b87a6d7ada Refactor closure instantiation and inlining
This commit makes several changes related to how closures are handled:

- **Dumper:** Removes redundant introspection of closure ASTs, as this
  is no longer relevant.
- **Optimizer:** Updates `try_inline` to accept `ExecNode` for
  parameters and adds a check to ensure the `function_node` is a
  `Lambda` before attempting inlining.
- **Environment:** Simplifies closure creation by passing an `ExecNode`
  for parameters and ensuring the correct `stack_size` is used.
- **VM:** Adjusts `Closure` to store an `ExecNode` for parameters and
  updates `VM::unpack` to accept an `ExecNode`.
2026-03-13 18:00:58 +01:00