feat: Add StaticType and type checking

This commit introduces `StaticType` and enhances the `Binder` to perform
basic type checking during the binding phase.

Key changes include:

- **`StaticType` enum:** Represents static types such as `Any`, `Void`,
  `Bool`, `Int`, `Float`, `Text`, `List`, `Record`, and `Function`.
- **`Node<K, T>`:** The generic `Node` now includes a `ty` field to
  store its inferred static type.
- **Binder enhancements:**
    - `CompilerScope` now stores `LocalInfo` containing the variable's
      slot and `StaticType`.
    - `FunctionCompiler` stores upvalues with their associated
      `StaticType`.
    - `Binder::bind` now returns `Node<BoundKind, StaticType>`,
      propagating type information.
    - Type checking is added for `If` conditions and `Assign`
      operations.
    - `Def` nodes now infer and store the type of the defined variable.
- **`Value::static_type()`:** A new method to determine the `StaticType`
  of a `Value`.
- **Environment modifications:** `global_names` now stores `(u32,
  StaticType)` to associate global variables with their types.
- **Parser modifications:** The `ty` field of nodes is initialized to
  `()` by default.
- **VM modifications:** `VM::run` and `VM::eval` now operate on
  `Node<BoundKind, StaticType>`.
- **Tests:** Added basic evaluation and type error tests.
  feat: Add StaticType and type checking

Introduces `StaticType` enum and integrates it into the AST. The binder
now performs type checking during compilation, ensuring that expressions
conform to expected types, especially for control flow structures like
`if`. This lays the groundwork for static type analysis and error
reporting.
This commit is contained in:
Michael Schimmel
2026-02-17 11:54:52 +01:00
parent 2c612adc49
commit 49a879045e
9 changed files with 243 additions and 106 deletions
+10 -10
View File
@@ -1,5 +1,5 @@
use std::sync::Arc;
use crate::ast::types::Value;
use crate::ast::types::{Value, StaticType};
use crate::ast::nodes::Node;
#[derive(Debug, Clone, Copy, PartialEq)]
@@ -20,35 +20,35 @@ pub enum BoundKind {
// Variable Update (Resolved)
Set {
addr: Address,
value: Box<Node<BoundKind>>,
value: Box<Node<BoundKind, StaticType>>,
},
If {
cond: Box<Node<BoundKind>>,
then_br: Box<Node<BoundKind>>,
else_br: Option<Box<Node<BoundKind>>>,
cond: Box<Node<BoundKind, StaticType>>,
then_br: Box<Node<BoundKind, StaticType>>,
else_br: Option<Box<Node<BoundKind, StaticType>>>,
},
// Global Definition (Locals are implicit by stack position)
DefGlobal {
global_index: u32,
value: Box<Node<BoundKind>>,
value: Box<Node<BoundKind, StaticType>>,
},
Lambda {
param_count: u32,
// The list of variables captured from enclosing scopes
upvalues: Vec<Address>,
body: Arc<Node<BoundKind>>,
body: Arc<Node<BoundKind, StaticType>>,
},
Call {
callee: Box<Node<BoundKind>>,
args: Vec<Node<BoundKind>>,
callee: Box<Node<BoundKind, StaticType>>,
args: Vec<Node<BoundKind, StaticType>>,
},
Block {
exprs: Vec<Node<BoundKind>>,
exprs: Vec<Node<BoundKind, StaticType>>,
},
// Extension points (need to be adapted for bound nodes if they use variables)