a42429012e
- crates/ → engrams/ (Rust engrams live here)
- el-compiler/ added: el self-hosting compiler as an el package
- src/{compiler,lexer,parser,codegen}.el
- bootstrap/el-compiler.elc (114KB, Rust-compiled seed)
- el.toml Cargo.toml workspace paths updated
- neuron-rs cross-repo path deps fixed (were pointing to products/ instead of foundation/)
87 lines
3.9 KiB
Rust
87 lines
3.9 KiB
Rust
//! Array operations: map, filter, reduce, find, any, all, length, push, pop,
|
|
//! sort, reverse, zip, enumerate.
|
|
|
|
use el_types::{Type, TypeEnv};
|
|
use super::fn_type;
|
|
|
|
pub fn register(env: &mut TypeEnv) {
|
|
let arr_int = Type::Array(Box::new(Type::Int));
|
|
let arr_str = Type::Array(Box::new(Type::String));
|
|
let arr_unk = Type::Array(Box::new(Type::Unknown));
|
|
|
|
// array_length([T]) -> Int
|
|
env.register_fn("array_length", fn_type(vec![arr_unk.clone()], Type::Int));
|
|
// array_push([T], T) -> [T]
|
|
env.register_fn("array_push", fn_type(vec![arr_unk.clone(), Type::Unknown], arr_unk.clone()));
|
|
// array_pop([T]) -> T?
|
|
env.register_fn("array_pop", fn_type(vec![arr_unk.clone()], Type::Optional(Box::new(Type::Unknown))));
|
|
// array_map([T], fn(T) -> U) -> [U]
|
|
let mapper = Type::Fn { params: vec![Type::Unknown], return_type: Box::new(Type::Unknown) };
|
|
env.register_fn("array_map", fn_type(vec![arr_unk.clone(), mapper.clone()], arr_unk.clone()));
|
|
// array_filter([T], fn(T) -> Bool) -> [T]
|
|
let predicate = Type::Fn { params: vec![Type::Unknown], return_type: Box::new(Type::Bool) };
|
|
env.register_fn("array_filter", fn_type(vec![arr_unk.clone(), predicate.clone()], arr_unk.clone()));
|
|
// array_reduce([T], U, fn(U, T) -> U) -> U
|
|
let reducer = Type::Fn { params: vec![Type::Unknown, Type::Unknown], return_type: Box::new(Type::Unknown) };
|
|
env.register_fn("array_reduce", fn_type(vec![arr_unk.clone(), Type::Unknown, reducer], Type::Unknown));
|
|
// array_find([T], fn(T) -> Bool) -> T?
|
|
env.register_fn("array_find", fn_type(vec![arr_unk.clone(), predicate.clone()], Type::Optional(Box::new(Type::Unknown))));
|
|
// array_any([T], fn(T) -> Bool) -> Bool
|
|
env.register_fn("array_any", fn_type(vec![arr_unk.clone(), predicate.clone()], Type::Bool));
|
|
// array_all([T], fn(T) -> Bool) -> Bool
|
|
env.register_fn("array_all", fn_type(vec![arr_unk.clone(), predicate], Type::Bool));
|
|
// array_sort([Int]) -> [Int]
|
|
env.register_fn("array_sort", fn_type(vec![arr_int.clone()], arr_int.clone()));
|
|
// array_reverse([T]) -> [T]
|
|
env.register_fn("array_reverse", fn_type(vec![arr_unk.clone()], arr_unk.clone()));
|
|
// array_zip([T], [U]) -> [[T]] (simplified: returns array of unknown)
|
|
env.register_fn("array_zip", fn_type(vec![arr_unk.clone(), arr_unk.clone()], arr_unk.clone()));
|
|
// array_enumerate([T]) -> [[T]] (returns pairs as arrays)
|
|
env.register_fn("array_enumerate", fn_type(vec![arr_unk.clone()], arr_unk.clone()));
|
|
// array_join([String], String) -> String
|
|
env.register_fn("array_join", fn_type(vec![arr_str.clone(), Type::String], Type::String));
|
|
// array_concat([T], [T]) -> [T]
|
|
env.register_fn("array_concat", fn_type(vec![arr_unk.clone(), arr_unk.clone()], arr_unk.clone()));
|
|
// array_slice([T], Int, Int) -> [T]
|
|
env.register_fn("array_slice", fn_type(vec![arr_unk.clone(), Type::Int, Type::Int], arr_unk));
|
|
// array_first([T]) -> T?
|
|
env.register_fn("array_first", fn_type(vec![arr_int.clone()], Type::Optional(Box::new(Type::Int))));
|
|
// array_last([T]) -> T?
|
|
env.register_fn("array_last", fn_type(vec![arr_int.clone()], Type::Optional(Box::new(Type::Int))));
|
|
// array_contains([String], String) -> Bool
|
|
env.register_fn("array_contains", fn_type(vec![arr_str, Type::String], Type::Bool));
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
fn env() -> TypeEnv {
|
|
let mut e = TypeEnv::with_builtins();
|
|
register(&mut e);
|
|
e
|
|
}
|
|
|
|
#[test]
|
|
fn test_array_length_registered() {
|
|
assert!(env().lookup_fn("array_length").is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn test_array_map_is_fn_type() {
|
|
let e = env();
|
|
let ty = e.lookup_fn("array_map").unwrap();
|
|
assert!(matches!(ty, Type::Fn { .. }));
|
|
}
|
|
|
|
#[test]
|
|
fn test_array_filter_registered() {
|
|
assert!(env().lookup_fn("array_filter").is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn test_array_push_registered() {
|
|
assert!(env().lookup_fn("array_push").is_some());
|
|
}
|
|
}
|