Refactor Binder to support recursion and add stdlib operators
This commit introduces two main changes:
1. **Binder Refactoring**: The `Binder` has been refactored to support
recursive definitions by pre-declaring names in the scope before
binding their values. This ensures that a name is visible to itself
when its definition is being processed.
2. **Stdlib Operator Implementation**: Several standard library
operators, including `+`, `-`, `*`, `/`, `>`, and `<`, have been
implemented. These operators now correctly handle both `Int` and
`Float` types for numerical operations and comparisons.
Additionally, the display formatting for `Value::List` and
`Value::Record` has been improved for better readability. The
default source code in `main.rs` has also been updated to include a
Fibonacci example, demonstrating the new recursive capabilities.
This commit is contained in:
+48
-1
@@ -37,7 +37,6 @@ impl Environment {
|
||||
}
|
||||
|
||||
fn register_stdlib(&self) {
|
||||
// Simple math for testing
|
||||
self.register_native("+", StaticType::Any, |args| {
|
||||
let mut acc = 0.0;
|
||||
for arg in args {
|
||||
@@ -46,11 +45,59 @@ impl Environment {
|
||||
}
|
||||
if acc.fract() == 0.0 { Value::Int(acc as i64) } else { Value::Float(acc) }
|
||||
});
|
||||
|
||||
self.register_native("-", StaticType::Any, |args| {
|
||||
if args.is_empty() { return Value::Void; }
|
||||
let mut acc = match args[0] {
|
||||
Value::Int(i) => i as f64,
|
||||
Value::Float(f) => f,
|
||||
_ => return Value::Void,
|
||||
};
|
||||
if args.len() == 1 {
|
||||
acc = -acc;
|
||||
} else {
|
||||
for arg in &args[1..] {
|
||||
if let Value::Int(i) = arg { acc -= *i as f64; }
|
||||
else if let Value::Float(f) = arg { acc -= f; }
|
||||
}
|
||||
}
|
||||
if acc.fract() == 0.0 { Value::Int(acc as i64) } else { Value::Float(acc) }
|
||||
});
|
||||
|
||||
self.register_native("*", StaticType::Any, |args| {
|
||||
let mut acc = 1.0;
|
||||
for arg in args {
|
||||
if let Value::Int(i) = arg { acc *= i as f64; }
|
||||
else if let Value::Float(f) = arg { acc *= f; }
|
||||
}
|
||||
if acc.fract() == 0.0 { Value::Int(acc as i64) } else { Value::Float(acc) }
|
||||
});
|
||||
|
||||
self.register_native("/", StaticType::Any, |args| {
|
||||
if args.len() != 2 { return Value::Void; }
|
||||
let a = match args[0] { Value::Int(i) => i as f64, Value::Float(f) => f, _ => return Value::Void };
|
||||
let b = match args[1] { Value::Int(i) => i as f64, Value::Float(f) => f, _ => return Value::Void };
|
||||
Value::Float(a / b)
|
||||
});
|
||||
|
||||
self.register_native(">", StaticType::Any, |args| {
|
||||
if args.len() != 2 { return Value::Void; }
|
||||
match (&args[0], &args[1]) {
|
||||
(Value::Int(a), Value::Int(b)) => Value::Bool(a > b),
|
||||
(Value::Int(a), Value::Float(b)) => Value::Bool((*a as f64) > *b),
|
||||
(Value::Float(a), Value::Int(b)) => Value::Bool(*a > (*b as f64)),
|
||||
(Value::Float(a), Value::Float(b)) => Value::Bool(a > b),
|
||||
_ => Value::Bool(false),
|
||||
}
|
||||
});
|
||||
|
||||
self.register_native("<", StaticType::Any, |args| {
|
||||
if args.len() != 2 { return Value::Void; }
|
||||
match (&args[0], &args[1]) {
|
||||
(Value::Int(a), Value::Int(b)) => Value::Bool(a < b),
|
||||
(Value::Int(a), Value::Float(b)) => Value::Bool((*a as f64) < *b),
|
||||
(Value::Float(a), Value::Int(b)) => Value::Bool(*a < (*b as f64)),
|
||||
(Value::Float(a), Value::Float(b)) => Value::Bool(a < b),
|
||||
_ => Value::Bool(false),
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user