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:
+11
-1
@@ -39,6 +39,7 @@ impl<'a> Parser<'a> {
|
||||
callee: Box::new(self.make_id_node("quote", identity)),
|
||||
args: vec![expr],
|
||||
},
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
_ => self.parse_atom(),
|
||||
@@ -65,7 +66,7 @@ impl<'a> Parser<'a> {
|
||||
_ => return Err(format!("Unexpected token in atom: {:?} at {:?}", token.kind, token.location)),
|
||||
};
|
||||
|
||||
Ok(Node { identity, kind })
|
||||
Ok(Node { identity, kind, ty: () })
|
||||
}
|
||||
|
||||
fn parse_list(&mut self) -> Result<Node<UntypedKind>, String> {
|
||||
@@ -107,6 +108,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::If { cond, then_br, else_br },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -122,6 +124,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::Def { name, value },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -133,6 +136,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::Assign { target, value },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -144,6 +148,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::Block { exprs },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -157,6 +162,7 @@ impl<'a> Parser<'a> {
|
||||
params,
|
||||
body: Arc::new(body),
|
||||
},
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -188,6 +194,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::Call { callee: Box::new(callee), args },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -209,6 +216,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Node {
|
||||
identity: Arc::new(NodeIdentity { location: token.location }),
|
||||
kind: UntypedKind::Constant(Value::List(Arc::new(elements))),
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -241,6 +249,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Node {
|
||||
identity: Arc::new(NodeIdentity { location: token.location }),
|
||||
kind: UntypedKind::Constant(Value::Record(Arc::new(map))),
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -257,6 +266,7 @@ impl<'a> Parser<'a> {
|
||||
Node {
|
||||
identity,
|
||||
kind: UntypedKind::Identifier(Arc::from(name)),
|
||||
ty: (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user