diff --git a/src/compiler.rs b/src/compiler.rs index 15fd214..3dde67c 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -2228,6 +2228,7 @@ impl Expr { data: ExprData { ty: { let default_number_type_context_type = kast + .cache .interpreter .builtins .get("default_number_type") diff --git a/src/interpreter.rs b/src/interpreter.rs index 5b29ee9..08dca77 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -2,7 +2,6 @@ use super::*; #[derive(Clone)] pub struct State { - pub builtins: Parc>, pub contexts: Parc>, } @@ -18,13 +17,16 @@ pub struct CompletionCandidate { pub ty: Type, } -impl State { - #[allow(clippy::new_without_default)] +pub struct Cache { + pub builtins: HashMap, + pub set_natives: Parc>>, +} + +impl Cache { pub fn new() -> Self { let set_natives: Parc>> = Parc::new(Mutex::new(HashMap::new())); Self { - contexts: Parc::new(Mutex::new(contexts::State::default())), builtins: { let mut map = HashMap::::new(); @@ -175,6 +177,65 @@ impl State { })) }), ); + map.insert( + "list_iter".to_owned(), + Box::new({ + let set_natives = set_natives.clone(); + move |expected: Type| { + let set_natives = set_natives.clone(); + let elem_ty = Type::new_not_inferred(); + let ty = FnType { + arg: TypeShape::List(elem_ty).into(), + contexts: Contexts::new_not_inferred(), // TODO generator_handler + result: TypeShape::Unit.into(), + }; + expected.expect_inferred(TypeShape::Function(Box::new(ty.clone())))?; + Ok(Value::NativeFunction(NativeFunction { + name: "list_iter".to_owned(), + r#impl: (std::sync::Arc::new( + move |kast: Kast, _fn_ty: FnType, value: Value| { + let set_natives = set_natives.clone(); + async move { + let value = value.expect_list()?; + let generator_handler = set_natives + .lock() + .unwrap() + .get("generator_handler") + .ok_or_else(|| eyre!("generator_handler not set"))? + .clone(); + let generator_handler = kast + .instantiate( + generator_handler, + Value::Type(value.element_ty), + ) + .await? + .expect_type()?; + let handler = kast + .interpreter + .contexts + .lock() + .unwrap() + .get_runtime(generator_handler)? + .ok_or_else(|| eyre!("no handler"))? + .expect_tuple()?; + let handler = handler + .get_named("handle") + .ok_or_else(|| eyre!("wut"))?; + for elem in value.values { + kast.call(handler.clone(), elem).await?; + } + Ok(Value::Unit) + } + .boxed() + }, + ) + as std::sync::Arc) + .into(), + ty, + })) + } + }), + ); map.insert( "chars".to_owned(), Box::new({ @@ -271,6 +332,32 @@ impl State { } }), ); + map.insert( + "list_length".to_owned(), + Box::new(|expected: Type| { + let ty = FnType { + arg: TypeShape::List(Type::new_not_inferred()).into(), + contexts: Contexts::empty(), + result: TypeShape::Int32.into(), // TODO usize? + }; + expected.expect_inferred(TypeShape::Function(Box::new(ty.clone())))?; + Ok(Value::NativeFunction(NativeFunction { + name: "list_length".to_owned(), + r#impl: (std::sync::Arc::new(|_kast, _fn_ty, list: Value| { + async move { + let list = list.expect_list()?; + Ok(Value::Int32(list.values.len().try_into().map_err(|e| { + eyre!("list length doesnt fit in int32: {e}") + })?)) + } + .boxed() + }) + as std::sync::Arc) + .into(), + ty, + })) + }), + ); map.insert( "list_push".to_owned(), Box::new(|expected: Type| { @@ -532,13 +619,24 @@ impl State { })); }; } + // I am even worse in other things binary_op!(-, checked_sub); binary_op!(+, checked_add); binary_op!(*, checked_mul); binary_op!(/, checked_div); binary_op!(%, checked_rem); - Parc::new(map) + map }, + set_natives, + } + } +} + +impl State { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { + contexts: Parc::new(Mutex::new(contexts::State::default())), } } } @@ -1095,7 +1193,7 @@ impl Kast { .substitute_bindings(self, &mut RecurseCache::new()); let name = self.eval(name).await?.expect_string()?; tracing::trace!("native {name} :: {actual_type}"); - match self.interpreter.builtins.get(name.as_str()) { + match self.cache.interpreter.builtins.get(name.as_str()) { Some(builtin) => builtin(actual_type)?, None => eyre::bail!("native {name:?} not found"), } diff --git a/src/lib.rs b/src/lib.rs index edecebe..92e8771 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,7 @@ enum ImportMode { } struct Cache { + interpreter: interpreter::Cache, compiler: compiler::Cache, imports: Mutex>>, } @@ -100,6 +101,7 @@ struct Cache { impl Default for Cache { fn default() -> Self { Self { + interpreter: interpreter::Cache::new(), compiler: compiler::Cache::new(), imports: Default::default(), } diff --git a/std/lib.ks b/std/lib.ks index e2d15c9..b503b45 100644 --- a/std/lib.ks +++ b/std/lib.ks @@ -162,6 +162,12 @@ const push_char :: (string, char) -> string = native "push_char"; const list_push = forall[T] { native "list_push" :: (list[T], T) -> list[T] }; +const list_length = forall[T] { + native "list_length" :: list[T] -> int32 +}; +const list_iter = forall[T] { + native "list_iter" :: list[T] -> () with generator_handler[T] +}; #trait Iterator { # type Item;