Files
el/engrams/el-stdlib/src/array.rs
T
Will Anderson a42429012e rename crates/ to engrams/; add el-compiler el package with bootstrap artifact
- 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/)
2026-04-29 03:27:32 -05:00

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());
}
}