a726b79d8a
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.
116 lines
4.3 KiB
Rust
116 lines
4.3 KiB
Rust
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.
|
|
pub fn lookup(name: &str, args: &[StaticType]) -> Option<(Value, StaticType)> {
|
|
match (name, args) {
|
|
// --- Integer Arithmetic ---
|
|
("+", [StaticType::Int, StaticType::Int]) => Some((
|
|
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::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::make_function(Purity::Pure, |args| {
|
|
let a = match args[0] {
|
|
Value::Int(i) => i,
|
|
_ => 0,
|
|
};
|
|
let b = match args[1] {
|
|
Value::Int(i) => i,
|
|
_ => 0,
|
|
};
|
|
let c = match args[2] {
|
|
Value::Int(i) => i,
|
|
_ => 0,
|
|
};
|
|
Value::Int(a - b - c)
|
|
}),
|
|
StaticType::Int,
|
|
)),
|
|
("*", [StaticType::Int, StaticType::Int]) => Some((
|
|
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::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::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::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::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::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,
|
|
)),
|
|
|
|
// --- Constant Unary for -1 (decrement optimization) ---
|
|
// Special case: tak uses (- x 1). The specializer sees Call("-", [Int, Int]).
|
|
_ => None,
|
|
}
|
|
}
|