Refactor Purity enum and NativeFunction struct

Move `Purity` enum definition from `optimizer.rs` to `types.rs` and
create a `NativeFunction` struct to hold the function and its purity.
Update `Value::Function` to store `Rc<NativeFunction>` and
`Value::make_function`
helper to simplify creation.

This change allows tracking the purity of native functions, which is
useful
for optimization and static analysis.
This commit is contained in:
Michael Schimmel
2026-02-22 10:50:37 +01:00
parent b54a449369
commit a726b79d8a
9 changed files with 111 additions and 83 deletions
+19 -20
View File
@@ -1,5 +1,4 @@
use crate::ast::types::{StaticType, Value};
use std::rc::Rc;
use crate::ast::types::{Purity, StaticType, Value};
/// Looks up a specialized intrinsic function for the given operator and argument types.
/// Returns (Executable Value, Return Type) if a fast-path exists.
@@ -7,29 +6,29 @@ pub fn lookup(name: &str, args: &[StaticType]) -> Option<(Value, StaticType)> {
match (name, args) {
// --- Integer Arithmetic ---
("+", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Int(a + b)
} else {
Value::Int(0) // Should not happen if type checker works
}
})),
}),
StaticType::Int,
)),
("-", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Int(a - b)
} else {
Value::Int(0)
}
})),
}),
StaticType::Int,
)),
("-", [StaticType::Int, StaticType::Int, StaticType::Int]) => Some((
// Variadic optimization for 3 args (common in some Lisp dialects, though - usually is binary/unary)
// MyC's core.rs supports variadic subtraction.
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
let a = match args[0] {
Value::Int(i) => i,
_ => 0,
@@ -43,69 +42,69 @@ pub fn lookup(name: &str, args: &[StaticType]) -> Option<(Value, StaticType)> {
_ => 0,
};
Value::Int(a - b - c)
})),
}),
StaticType::Int,
)),
("*", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Int(a * b)
} else {
Value::Int(0)
}
})),
}),
StaticType::Int,
)),
// --- Integer Comparison ---
("<=", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Bool(a <= b)
} else {
Value::Bool(false)
}
})),
}),
StaticType::Bool,
)),
("<", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Bool(a < b)
} else {
Value::Bool(false)
}
})),
}),
StaticType::Bool,
)),
(">", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Bool(a > b)
} else {
Value::Bool(false)
}
})),
}),
StaticType::Bool,
)),
(">=", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Bool(a >= b)
} else {
Value::Bool(false)
}
})),
}),
StaticType::Bool,
)),
("=", [StaticType::Int, StaticType::Int]) => Some((
Value::Function(Rc::new(|args| {
Value::make_function(Purity::Pure, |args| {
if let (Value::Int(a), Value::Int(b)) = (&args[0], &args[1]) {
Value::Bool(a == b)
} else {
Value::Bool(false)
}
})),
}),
StaticType::Bool,
)),