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:
+1
-2
@@ -1,6 +1,5 @@
|
||||
use crate::ast::compiler::optimizer::Purity;
|
||||
use crate::ast::environment::Environment;
|
||||
use crate::ast::types::{Signature, StaticType, Value};
|
||||
use crate::ast::types::{Purity, Signature, StaticType, Value};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn register(env: &Environment) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::ast::compiler::optimizer::Purity;
|
||||
use crate::ast::environment::Environment;
|
||||
use crate::ast::types::{Signature, StaticType, Value};
|
||||
use crate::ast::types::{Purity, Signature, StaticType, Value};
|
||||
use chrono::{NaiveDate, NaiveDateTime};
|
||||
|
||||
pub fn register(env: &Environment) {
|
||||
|
||||
+19
-20
@@ -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,
|
||||
)),
|
||||
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
use crate::ast::compiler::optimizer::Purity;
|
||||
use crate::ast::environment::Environment;
|
||||
use crate::ast::types::{Signature, StaticType, Value};
|
||||
use crate::ast::types::{Purity, Signature, StaticType, Value};
|
||||
use std::f64::consts;
|
||||
|
||||
pub fn register(env: &Environment) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::ast::types::{Keyword, Signature, StaticType, Value};
|
||||
use crate::ast::types::{Keyword, Purity, Signature, StaticType, Value};
|
||||
use std::any::TypeId;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@@ -68,7 +68,7 @@ impl TypeRegistry {
|
||||
}
|
||||
}
|
||||
};
|
||||
Value::Function(Rc::new(closure))
|
||||
Value::make_function(Purity::Impure, closure)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,8 @@ impl RecordBuilder {
|
||||
F: Fn(Vec<Value>) -> Value + 'static,
|
||||
{
|
||||
let key = Keyword::intern(name);
|
||||
self.fields.push((key, Value::Function(Rc::new(func))));
|
||||
self.fields
|
||||
.push((key, Value::make_function(Purity::Impure, func)));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -217,7 +218,7 @@ mod tests {
|
||||
let greet_fn = &r.values[idx];
|
||||
|
||||
if let Value::Function(f) = greet_fn {
|
||||
let res = f(vec![]);
|
||||
let res = (f.func)(vec![]);
|
||||
if let Value::Text(s) = res {
|
||||
assert_eq!(&*s, "Hello Alice");
|
||||
} else {
|
||||
@@ -249,7 +250,7 @@ mod tests {
|
||||
});
|
||||
|
||||
if let Value::Function(f) = factory_val {
|
||||
let instance = f(vec![Value::Text("Bob".into()), Value::Int(40)]);
|
||||
let instance = (f.func)(vec![Value::Text("Bob".into()), Value::Int(40)]);
|
||||
if let Value::Record(r) = instance {
|
||||
let idx = r
|
||||
.keys
|
||||
@@ -259,7 +260,7 @@ mod tests {
|
||||
let greet_fn = &r.values[idx];
|
||||
|
||||
if let Value::Function(gf) = greet_fn {
|
||||
let res = gf(vec![]);
|
||||
let res = (gf.func)(vec![]);
|
||||
if let Value::Text(s) = res {
|
||||
assert_eq!(&*s, "Hello Bob");
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user