From aa1edf8c80de8e0e1b4761d8a102b3c85fb390c1 Mon Sep 17 00:00:00 2001 From: Tim Fennis Date: Mon, 2 Mar 2026 20:33:26 +0100 Subject: [PATCH 1/5] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Decouple=20Environment?= =?UTF-8?q?=20from=20stdlib=20registration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ndc_lib/src/interpreter/environment.rs | 12 ++++-------- ndc_lib/src/interpreter/mod.rs | 3 ++- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/ndc_lib/src/interpreter/environment.rs b/ndc_lib/src/interpreter/environment.rs index fe2cf08a..f9638cd1 100644 --- a/ndc_lib/src/interpreter/environment.rs +++ b/ndc_lib/src/interpreter/environment.rs @@ -50,21 +50,17 @@ impl Environment { } #[must_use] - pub fn new_with_stdlib(writer: Box) -> Self { + pub fn new(writer: Box) -> Self { let root = RootEnvironment { output: writer, global_functions: Default::default(), }; - let mut env = Self { + Self { root: Rc::new(RefCell::new(root)), parent: None, values: Default::default(), - }; - - crate::stdlib::register(&mut env); - - env + } } pub fn get_global_identifiers(&self) -> Vec<(String, StaticType)> { @@ -181,7 +177,7 @@ impl Environment { impl Default for Environment { fn default() -> Self { - Self::new_with_stdlib(Box::new(stdout())) + Self::new(Box::new(stdout())) } } diff --git a/ndc_lib/src/interpreter/mod.rs b/ndc_lib/src/interpreter/mod.rs index cd479a26..62d2512e 100644 --- a/ndc_lib/src/interpreter/mod.rs +++ b/ndc_lib/src/interpreter/mod.rs @@ -30,7 +30,8 @@ impl Interpreter { where T: InterpreterOutput + 'static, { - let environment = Environment::new_with_stdlib(Box::new(dest)); + let mut environment = Environment::new(Box::new(dest)); + crate::stdlib::register(&mut environment); let global_identifiers = environment.get_global_identifiers(); Self { From 0377043001744174a908adeb9e89de7703a5584f Mon Sep 17 00:00:00 2001 From: Tim Fennis Date: Mon, 2 Mar 2026 20:51:39 +0100 Subject: [PATCH 2/5] =?UTF-8?q?=E2=9C=A8=20Extract=20stdlib=20into=20ndc?= =?UTF-8?q?=5Fstdlib=20crate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 34 ++-- Cargo.toml | 3 +- benches/Cargo.toml | 1 + benches/src/benchmark.rs | 5 +- ndc_bin/Cargo.toml | 1 + ndc_bin/src/docs.rs | 4 +- ndc_bin/src/main.rs | 5 +- ndc_bin/src/repl.rs | 4 +- ndc_lib/Cargo.toml | 14 +- ndc_lib/src/interpreter/mod.rs | 10 +- ndc_lib/src/interpreter/value.rs | 18 +- ndc_lib/src/lib.rs | 5 +- ndc_lib/src/stdlib/serde.rs | 142 -------------- ndc_lsp/Cargo.toml | 2 +- ndc_lsp/src/backend.rs | 6 +- ndc_macros/src/convert.rs | 20 +- ndc_macros/src/function.rs | 178 +++++++++--------- ndc_macros/src/lib.rs | 2 +- ndc_stdlib/Cargo.toml | 26 +++ {ndc_lib/src/stdlib => ndc_stdlib/src}/aoc.rs | 8 +- {ndc_lib/src/stdlib => ndc_stdlib/src}/cmp.rs | 4 +- .../src/stdlib => ndc_stdlib/src}/crypto.rs | 0 .../src/stdlib => ndc_stdlib/src}/deque.rs | 4 +- .../src/stdlib => ndc_stdlib/src}/file.rs | 6 +- .../src/stdlib => ndc_stdlib/src}/hash_map.rs | 10 +- .../src/stdlib => ndc_stdlib/src}/heap.rs | 6 +- .../stdlib/mod.rs => ndc_stdlib/src/lib.rs | 9 +- .../src/stdlib => ndc_stdlib/src}/list.rs | 6 +- .../src/stdlib => ndc_stdlib/src}/math.rs | 20 +- .../src/stdlib => ndc_stdlib/src}/rand.rs | 8 +- .../src/stdlib => ndc_stdlib/src}/regex.rs | 2 +- .../src/stdlib => ndc_stdlib/src}/sequence.rs | 16 +- ndc_stdlib/src/serde.rs | 134 +++++++++++++ .../src/stdlib => ndc_stdlib/src}/string.rs | 6 +- .../src/stdlib => ndc_stdlib/src}/value.rs | 8 +- tests/Cargo.toml | 2 +- tests/src/programs.rs | 4 +- 37 files changed, 382 insertions(+), 351 deletions(-) delete mode 100644 ndc_lib/src/stdlib/serde.rs create mode 100644 ndc_stdlib/Cargo.toml rename {ndc_lib/src/stdlib => ndc_stdlib/src}/aoc.rs (80%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/cmp.rs (96%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/crypto.rs (100%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/deque.rs (97%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/file.rs (96%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/hash_map.rs (97%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/heap.rs (90%) rename ndc_lib/src/stdlib/mod.rs => ndc_stdlib/src/lib.rs (71%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/list.rs (97%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/math.rs (97%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/rand.rs (92%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/regex.rs (98%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/sequence.rs (98%) create mode 100644 ndc_stdlib/src/serde.rs rename {ndc_lib/src/stdlib => ndc_stdlib/src}/string.rs (98%) rename {ndc_lib/src/stdlib => ndc_stdlib/src}/value.rs (96%) diff --git a/Cargo.lock b/Cargo.lock index 154414a5..37acd212 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,6 +168,7 @@ version = "0.0.0" dependencies = [ "criterion", "ndc_lib", + "ndc_stdlib", "rand", "rand_chacha", ] @@ -1250,6 +1251,7 @@ dependencies = [ "ndc_lexer", "ndc_lib", "ndc_lsp", + "ndc_stdlib", "owo-colors", "rustyline", "strsim", @@ -1275,22 +1277,13 @@ dependencies = [ "anyhow", "derive_builder", "derive_more", - "factorial", "itertools 0.14.0", - "md5", "ndc_lexer", - "ndc_macros", "ndc_parser", "num", - "once_cell", "ordered-float", - "rand", - "regex", "ryu", "self_cell", - "serde_json", - "sha1", - "tap", "thiserror", ] @@ -1299,8 +1292,8 @@ name = "ndc_lsp" version = "0.2.1" dependencies = [ "ndc_lexer", - "ndc_lib", "ndc_parser", + "ndc_stdlib", "tokio", "tower-lsp", ] @@ -1326,6 +1319,25 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ndc_stdlib" +version = "0.2.1" +dependencies = [ + "anyhow", + "factorial", + "itertools 0.14.0", + "md5", + "ndc_lib", + "ndc_macros", + "num", + "once_cell", + "rand", + "regex", + "serde_json", + "sha1", + "tap", +] + [[package]] name = "nibble_vec" version = "0.1.0" @@ -2050,7 +2062,7 @@ dependencies = [ name = "tests" version = "0.2.1" dependencies = [ - "ndc_lib", + "ndc_stdlib", "owo-colors", ] diff --git a/Cargo.toml b/Cargo.toml index 3d9b5934..22e7b22a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "3" -members = ["ndc_macros", "ndc_bin", "ndc_lib", "ndc_lsp", "ndc_lexer", "ndc_parser", "benches", "tests"] +members = ["ndc_macros", "ndc_bin", "ndc_lib", "ndc_lsp", "ndc_lexer", "ndc_parser", "ndc_stdlib", "benches", "tests"] [workspace.package] edition = "2024" @@ -22,6 +22,7 @@ ndc_lib = { path = "ndc_lib" } ndc_parser = { path = "ndc_parser" } ndc_lsp = { path = "ndc_lsp" } ndc_macros = { path = "ndc_macros" } +ndc_stdlib = { path = "ndc_stdlib" } num = "0.4.3" once_cell = "1.21.3" ordered-float = "5.1.0" diff --git a/benches/Cargo.toml b/benches/Cargo.toml index 14ca4abb..4c7ecc06 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -5,6 +5,7 @@ license.workspace = true [dependencies] ndc_lib.workspace = true +ndc_stdlib.workspace = true rand.workspace = true criterion.workspace = true rand_chacha.workspace = true diff --git a/benches/src/benchmark.rs b/benches/src/benchmark.rs index 5f81f20a..322133e0 100644 --- a/benches/src/benchmark.rs +++ b/benches/src/benchmark.rs @@ -1,5 +1,6 @@ use criterion::{Criterion, criterion_group, criterion_main}; -use ndc_lib::interpreter::{Interpreter, InterpreterError}; +use ndc_lib::interpreter::InterpreterError; +use ndc_stdlib::new_interpreter; use rand::{RngExt, SeedableRng}; use rand_chacha::ChaCha8Rng; use std::fs; @@ -8,7 +9,7 @@ use std::time::Duration; fn run_string(input: &str) -> Result { let buf: Vec = vec![]; - let mut interpreter = Interpreter::new(buf); + let mut interpreter = new_interpreter(buf); interpreter.run_str(std::hint::black_box(input)) } diff --git a/ndc_bin/Cargo.toml b/ndc_bin/Cargo.toml index d9649483..bdacdfcc 100644 --- a/ndc_bin/Cargo.toml +++ b/ndc_bin/Cargo.toml @@ -16,6 +16,7 @@ strsim.workspace = true miette = { version = "7.6.0", features = ["fancy"] } ndc_lexer.workspace = true ndc_lib.workspace = true +ndc_stdlib.workspace = true ndc_lsp.workspace = true owo-colors.workspace = true rustyline.workspace = true diff --git a/ndc_bin/src/docs.rs b/ndc_bin/src/docs.rs index 9b9ba97d..b379784c 100644 --- a/ndc_bin/src/docs.rs +++ b/ndc_bin/src/docs.rs @@ -1,5 +1,5 @@ -use ndc_lib::interpreter::Interpreter; use ndc_lib::interpreter::function::{Parameter, TypeSignature}; +use ndc_stdlib::new_interpreter; use std::cmp::Ordering; use std::fmt::Write; use strsim::normalized_damerau_levenshtein; @@ -13,7 +13,7 @@ fn string_match(needle: &str, haystack: &str) -> bool { } pub fn docs(query: Option<&str>) -> anyhow::Result<()> { - let interpreter = Interpreter::new(Vec::new()); // Discard the output + let interpreter = new_interpreter(Vec::new()); // Discard the output let functions = interpreter.environment().borrow().get_all_functions(); let matched_functions = functions diff --git a/ndc_bin/src/main.rs b/ndc_bin/src/main.rs index d77ac8cf..5d9ffaa2 100644 --- a/ndc_bin/src/main.rs +++ b/ndc_bin/src/main.rs @@ -5,7 +5,8 @@ use anyhow::{Context, anyhow}; use clap::{Parser, Subcommand}; use highlighter::{AndycppHighlighter, AndycppHighlighterState}; use miette::{NamedSource, highlighters::HighlighterState}; -use ndc_lib::interpreter::{Interpreter, InterpreterError}; +use ndc_lib::interpreter::InterpreterError; +use ndc_stdlib::new_interpreter; use std::path::PathBuf; use std::process; use std::{fs, io::Write}; @@ -118,7 +119,7 @@ fn main() -> anyhow::Result<()> { let string = fs::read_to_string(path)?; let stdout = std::io::stdout(); - let mut interpreter = Interpreter::new(stdout); + let mut interpreter = new_interpreter(stdout); match into_miette_result(interpreter.run_str(&string)) { // we can just ignore successful runs because we have print statements Ok(_final_value) => {} diff --git a/ndc_bin/src/repl.rs b/ndc_bin/src/repl.rs index 96791985..62998d53 100644 --- a/ndc_bin/src/repl.rs +++ b/ndc_bin/src/repl.rs @@ -1,7 +1,7 @@ #![allow(clippy::print_stdout, clippy::print_stderr)] use itertools::Itertools; use miette::highlighters::HighlighterState; -use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::new_interpreter; use rustyline::Helper; use rustyline::config::Configurer; use rustyline::error::ReadlineError; @@ -36,7 +36,7 @@ pub fn run() -> anyhow::Result<()> { rl.set_helper(Some(h)); let stdout = std::io::stdout(); - let mut interpreter = Interpreter::new(stdout); + let mut interpreter = new_interpreter(stdout); loop { match rl.readline("λ ") { Ok(line) => { diff --git a/ndc_lib/Cargo.toml b/ndc_lib/Cargo.toml index 9fbe449b..8f82daf7 100644 --- a/ndc_lib/Cargo.toml +++ b/ndc_lib/Cargo.toml @@ -9,27 +9,15 @@ ahash = { workspace = true, optional = true } anyhow.workspace = true derive_more.workspace = true derive_builder.workspace = true -factorial.workspace = true itertools.workspace = true ndc_lexer.workspace = true -ndc_macros.workspace = true ndc_parser.workspace = true num.workspace = true -once_cell.workspace = true ordered-float.workspace = true -rand.workspace = true -regex.workspace = true ryu.workspace = true self_cell.workspace = true -serde_json.workspace = true -tap.workspace = true thiserror.workspace = true -# Crypto -md5 = { version = "0.8.0", optional = true } -sha1 = { version = "0.10.6", optional = true } - [features] -default = ["ahash", "crypto"] +default = ["ahash"] ahash = ["dep:ahash"] -crypto = ["dep:md5", "dep:sha1"] diff --git a/ndc_lib/src/interpreter/mod.rs b/ndc_lib/src/interpreter/mod.rs index 62d2512e..2ef63636 100644 --- a/ndc_lib/src/interpreter/mod.rs +++ b/ndc_lib/src/interpreter/mod.rs @@ -11,7 +11,7 @@ use ndc_lexer::{Lexer, TokenLocation}; pub mod environment; pub mod evaluate; pub mod function; -pub(crate) mod heap; +pub mod heap; pub mod int; pub mod iterator; pub mod num; @@ -30,10 +30,12 @@ impl Interpreter { where T: InterpreterOutput + 'static, { - let mut environment = Environment::new(Box::new(dest)); - crate::stdlib::register(&mut environment); - let global_identifiers = environment.get_global_identifiers(); + Self::from_env(Environment::new(Box::new(dest))) + } + #[must_use] + pub fn from_env(environment: Environment) -> Self { + let global_identifiers = environment.get_global_identifiers(); Self { environment: Rc::new(RefCell::new(environment)), analyser: Analyser::from_scope_tree(ScopeTree::from_global_scope(global_identifiers)), diff --git a/ndc_lib/src/interpreter/value.rs b/ndc_lib/src/interpreter/value.rs index 27bc7df1..2d871737 100644 --- a/ndc_lib/src/interpreter/value.rs +++ b/ndc_lib/src/interpreter/value.rs @@ -29,18 +29,18 @@ pub enum Value { } impl Value { - pub(crate) fn function(function: Function) -> Self { + pub fn function(function: Function) -> Self { Self::Function(Rc::new(function)) } - pub(crate) fn string>(string: S) -> Self { + pub fn string>(string: S) -> Self { Self::Sequence(Sequence::String(Rc::new(RefCell::new(string.into())))) } - pub(crate) fn list>>(data: V) -> Self { + pub fn list>>(data: V) -> Self { Self::Sequence(Sequence::List(Rc::new(RefCell::new(data.into())))) } - pub(crate) fn collect_list(i: I) -> Self + pub fn collect_list(i: I) -> Self where I: Iterator, V: Into, @@ -48,23 +48,23 @@ impl Value { Self::list(i.map(Into::into).collect::>()) } - pub(crate) fn tuple>>(data: V) -> Self { + pub fn tuple>>(data: V) -> Self { Self::Sequence(Sequence::Tuple(Rc::new(data.into()))) } - pub(crate) fn unit() -> Self { + pub fn unit() -> Self { Self::Sequence(Sequence::Tuple(Rc::new(vec![]))) } - pub(crate) fn none() -> Self { + pub fn none() -> Self { Self::Option(None) } - pub(crate) fn some(value: Self) -> Self { + pub fn some(value: Self) -> Self { Self::Option(Some(Box::new(value))) } - pub(crate) fn number>(source: T) -> Self { + pub fn number>(source: T) -> Self { Self::Number(source.into()) } diff --git a/ndc_lib/src/lib.rs b/ndc_lib/src/lib.rs index 389b0757..f4ea1ad3 100644 --- a/ndc_lib/src/lib.rs +++ b/ndc_lib/src/lib.rs @@ -1,4 +1,3 @@ -mod compare; -mod hash_map; +pub mod compare; +pub mod hash_map; pub mod interpreter; -pub mod stdlib; diff --git a/ndc_lib/src/stdlib/serde.rs b/ndc_lib/src/stdlib/serde.rs deleted file mode 100644 index 1e318f36..00000000 --- a/ndc_lib/src/stdlib/serde.rs +++ /dev/null @@ -1,142 +0,0 @@ -use ndc_macros::export_module; -use std::rc::Rc; -use std::{cell::RefCell, str::FromStr}; - -use crate::hash_map::HashMap; -use crate::interpreter::sequence::Sequence; -use crate::interpreter::value::Value; -use anyhow::Context; -use num::BigInt; -use num::ToPrimitive; -use serde_json::{Map, Number, Value as JsonValue, json}; - -impl TryFrom for JsonValue { - type Error = anyhow::Error; - - fn try_from(value: Value) -> Result { - match value { - Value::Option(Some(value)) => Self::try_from(*value), - Value::Option(None) => Ok(Self::Null), - Value::Number(number) => match number { - crate::interpreter::num::Number::Int(int) => match int { - crate::interpreter::int::Int::Int64(i) => Ok(json!(i)), - // Ehrmm.. - crate::interpreter::int::Int::BigInt(big_int) => { - Number::from_str(&big_int.to_string()) - .map(JsonValue::Number) - .context("Cannot convert bigint to string") - } - }, - crate::interpreter::num::Number::Float(f) => Ok(json!(f)), - crate::interpreter::num::Number::Rational(ratio) => Ok(json!(ratio.to_f64())), - crate::interpreter::num::Number::Complex(complex) => { - Ok(json!(format!("{complex}"))) - } - }, - Value::Bool(b) => Ok(json!(b)), - Value::Sequence(s) => match s { - Sequence::String(s) => Ok(json!(&*s.borrow())), - Sequence::List(values) => Ok(Self::Array( - values - .borrow() - .iter() - .map(|v| v.clone().try_into()) - .collect::, _>>()?, - )), - Sequence::Tuple(values) => match values.len() { - 0 => Ok(Self::Null), - _ => Ok(Self::Array( - values - .iter() - .map(|v| v.clone().try_into()) - .collect::, _>>()?, - )), - }, - Sequence::Map(values, _) => Ok(Self::Object( - values - .borrow() - .iter() - .map(|(key, value)| { - Self::try_from(value.clone()).map(|value| (key.to_string(), value)) - }) - .collect::, _>>()?, - )), - Sequence::Iterator(i) => { - let mut i = i.borrow_mut(); - let mut out = Vec::new(); - for value in i.by_ref() { - out.push(Self::try_from(value)?); - } - Ok(Self::Array(out)) - } - Sequence::MaxHeap(h) => Ok(Self::Array( - h.borrow() - .iter() - .map(|h| Self::try_from(h.0.clone())) - .collect::, _>>()?, - )), - Sequence::MinHeap(h) => Ok(Self::Array( - h.borrow() - .iter() - .map(|h| Self::try_from(h.0.0.clone())) - .collect::, _>>()?, - )), - Sequence::Deque(d) => Ok(Self::Array( - d.borrow() - .iter() - .map(|v| Self::try_from(v.clone())) - .collect::, _>>()?, - )), - }, - Value::Function(_) => Err(anyhow::anyhow!("Unable to serialize function")), - } - } -} - -impl TryFrom for Value { - type Error = anyhow::Error; - - fn try_from(value: JsonValue) -> Result { - Ok(match value { - JsonValue::Null => Self::unit(), - JsonValue::Bool(b) => Self::Bool(b), - JsonValue::Number(n) => n.as_str().parse::().map(Self::from).or_else(|_| { - n.as_f64() - .map(Self::from) - .context("Cannot parse number as int or float") - })?, - JsonValue::String(s) => Self::string(s), - JsonValue::Array(a) => Self::list( - a.into_iter() - .map(TryInto::try_into) - .collect::, _>>()?, - ), - JsonValue::Object(o) => Self::Sequence(Sequence::Map( - Rc::new(RefCell::new( - o.into_iter() - .map(|(key, value)| { - value.try_into().map(|value| (Self::string(key), value)) - }) - .collect::, _>>()?, - )), - None, - )), - }) - } -} - -#[export_module] -mod inner { - use crate::interpreter::value::Value; - - /// Converts a JSON string to a value - pub fn json_decode(input: &str) -> anyhow::Result { - serde_json::from_str::(input)?.try_into() - } - - /// Converts the input value to JSON - pub fn json_encode(input: Value) -> anyhow::Result { - let v: JsonValue = input.try_into()?; - Ok(v.to_string()) - } -} diff --git a/ndc_lsp/Cargo.toml b/ndc_lsp/Cargo.toml index 1399d3c1..ca7c7dc1 100644 --- a/ndc_lsp/Cargo.toml +++ b/ndc_lsp/Cargo.toml @@ -7,6 +7,6 @@ version.workspace = true [dependencies] tokio = { version = "1.49.0", features = ["full"] } ndc_lexer.workspace = true -ndc_lib.workspace = true +ndc_stdlib.workspace = true tower-lsp.workspace = true ndc_parser.workspace = true diff --git a/ndc_lsp/src/backend.rs b/ndc_lsp/src/backend.rs index 075023c4..60435c23 100644 --- a/ndc_lsp/src/backend.rs +++ b/ndc_lsp/src/backend.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use ndc_lexer::{Lexer, Span, TokenLocation}; use ndc_parser::{Expression, ExpressionLocation, ForBody, ForIteration, Lvalue}; -use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::new_interpreter; use tokio::sync::Mutex; use tower_lsp::jsonrpc::Result as JsonRPCResult; use tower_lsp::lsp_types::{ @@ -80,7 +80,7 @@ impl Backend { // The interpreter uses Rc internally (non-Send), so it must be fully dropped // before the next await point. let hints = { - let mut interpreter = Interpreter::new(Vec::new()); + let mut interpreter = new_interpreter(Vec::new()); match interpreter.analyse_str(text) { Ok(expressions) => { let mut hints = Vec::new(); @@ -151,7 +151,7 @@ impl LanguageServer for Backend { &self, _params: CompletionParams, ) -> Result, tower_lsp::jsonrpc::Error> { - let interpreter = Interpreter::new(Vec::new()); + let interpreter = new_interpreter(Vec::new()); let env = interpreter.environment(); let functions = env.borrow().get_all_functions(); diff --git a/ndc_macros/src/convert.rs b/ndc_macros/src/convert.rs index db1d9202..e280e83d 100644 --- a/ndc_macros/src/convert.rs +++ b/ndc_macros/src/convert.rs @@ -28,7 +28,7 @@ impl TypeConverter for MutRefString { } fn static_type(&self) -> TokenStream { - quote! { crate::interpreter::function::StaticType::String } + quote! { ndc_lib::interpreter::function::StaticType::String } } fn convert( @@ -42,7 +42,7 @@ impl TypeConverter for MutRefString { param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::String(#temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::String(#temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::String but wasn't"); }; let #argument_var_name = &mut *#temp_var.try_borrow_mut()?; @@ -73,7 +73,7 @@ impl TypeConverter for InternalMap { param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Map(#temp_var, _)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Map(#temp_var, _)) = #argument_var_name else { panic!("Value #position needed to be Sequence::Map but wasn't"); }; @@ -89,7 +89,7 @@ impl TypeConverter for InternalString { } fn static_type(&self) -> TokenStream { - quote! { crate::interpreter::function::StaticType::String } + quote! { ndc_lib::interpreter::function::StaticType::String } } fn convert( @@ -103,7 +103,7 @@ impl TypeConverter for InternalString { param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::String(#temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::String(#temp_var)) = #argument_var_name else { panic!("Value #position needed to be Sequence::List but wasn't"); }; @@ -122,8 +122,8 @@ impl TypeConverter for InternalList { fn static_type(&self) -> TokenStream { // TODO: just hardcoding Any here is lazy quote! { - crate::interpreter::function::StaticType::List(Box::new( - crate::interpreter::function::StaticType::Any + ndc_lib::interpreter::function::StaticType::List(Box::new( + ndc_lib::interpreter::function::StaticType::Any )) } } @@ -139,7 +139,7 @@ impl TypeConverter for InternalList { param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::List(#temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::List(#temp_var)) = #argument_var_name else { panic!("Value #position needed to be Sequence::List but wasn't"); }; @@ -164,11 +164,11 @@ impl TypeConverter for InternalList { // argument_var_name: syn::Ident, // ) -> Vec { // vec![Argument { -// param_type: quote! { crate::interpreter::function::StaticType::Tuple }, +// param_type: quote! { ndc_lib::interpreter::function::StaticType::Tuple }, // param_name: quote! { #original_name }, // argument: quote! { #argument_var_name }, // initialize_code: quote! { -// let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Tuple(#temp_var)) = #argument_var_name else { +// let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Tuple(#temp_var)) = #argument_var_name else { // panic!("Value #position needed to be Sequence::Tuple but wasn't"); // }; // diff --git a/ndc_macros/src/function.rs b/ndc_macros/src/function.rs index 6a3da976..7567909c 100644 --- a/ndc_macros/src/function.rs +++ b/ndc_macros/src/function.rs @@ -122,7 +122,7 @@ fn map_return_type(output: &syn::ReturnType) -> TokenStream { match output { syn::ReturnType::Default => { // in case return type is not specified (for closures rust defaults to type inference which doesn't help us here) - quote! { crate::interpreter::function::StaticType::Tuple(vec![]) } + quote! { ndc_lib::interpreter::function::StaticType::Tuple(vec![]) } } syn::ReturnType::Type(_, ty) => map_type(ty), } @@ -135,13 +135,13 @@ fn map_type(ty: &syn::Type) -> TokenStream { syn::Type::Tuple(t) => { let inner = t.elems.iter().map(map_type); quote::quote! { - crate::interpreter::function::StaticType::Tuple(vec![ + ndc_lib::interpreter::function::StaticType::Tuple(vec![ #(#inner),* ]) } } syn::Type::Infer(_) => { - quote::quote! { crate::interpreter::function::StaticType::Any } + quote::quote! { ndc_lib::interpreter::function::StaticType::Any } } _ => { panic!("unmapped type: {ty:?}"); @@ -155,29 +155,29 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { match segment.ident.to_string().as_str() { "i32" | "i64" | "isize" | "u32" | "u64" | "usize" | "BigInt" => { - quote::quote! { crate::interpreter::function::StaticType::Int } + quote::quote! { ndc_lib::interpreter::function::StaticType::Int } } "f32" | "f64" => { - quote::quote! { crate::interpreter::function::StaticType::Float } + quote::quote! { ndc_lib::interpreter::function::StaticType::Float } } "bool" => { - quote::quote! { crate::interpreter::function::StaticType::Bool } + quote::quote! { ndc_lib::interpreter::function::StaticType::Bool } } "String" | "str" => { - quote::quote! { crate::interpreter::function::StaticType::String } + quote::quote! { ndc_lib::interpreter::function::StaticType::String } } "Vec" | "List" => match &segment.arguments { syn::PathArguments::AngleBracketed(args) => { let inner = args.args.first().expect("Vec<> requires inner type"); if let syn::GenericArgument::Type(inner_ty) = inner { let mapped = map_type(inner_ty); - quote::quote! { crate::interpreter::function::StaticType::List(Box::new(#mapped)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::List(Box::new(#mapped)) } } else { panic!("Vec inner not a type"); } } _ => { - quote::quote! { crate::interpreter::function::StaticType::List(Box::new(crate::interpreter::function::StaticType::Any)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::List(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } }, "VecDeque" | "Deque" => match &segment.arguments { @@ -185,14 +185,14 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { let inner = args.args.first().expect("VecDeque<> requires inner type"); if let syn::GenericArgument::Type(inner_ty) = inner { let mapped = map_type(inner_ty); - quote::quote! { crate::interpreter::function::StaticType::Deque(Box::new(#mapped)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::Deque(Box::new(#mapped)) } } else { panic!("VecDeque inner not a type"); } } _ => quote::quote! { - crate::interpreter::function::StaticType::Deque(Box::new( - crate::interpreter::function::StaticType::Any + ndc_lib::interpreter::function::StaticType::Deque(Box::new( + ndc_lib::interpreter::function::StaticType::Any )) }, }, @@ -215,7 +215,7 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { }; let key_mapped = map_type(key_ty); let val_mapped = map_type(val_ty); - quote::quote! { crate::interpreter::function::StaticType::Map { key: Box::new(#key_mapped), value: Box::new(#val_mapped) } } + quote::quote! { ndc_lib::interpreter::function::StaticType::Map { key: Box::new(#key_mapped), value: Box::new(#val_mapped) } } } _ => temp_create_map_any(), }, @@ -224,14 +224,14 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { let inner = args.args.first().expect("MinHeap requires inner"); if let syn::GenericArgument::Type(inner_ty) = inner { let mapped = map_type(inner_ty); - quote::quote! { crate::interpreter::function::StaticType::MinHeap(Box::new(#mapped)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::MinHeap(Box::new(#mapped)) } } else { panic!("MinHeap inner invalid"); } } _ => quote::quote! { - crate::interpreter::function::StaticType::MinHeap(Box::new( - crate::interpreter::function::StaticType::Any + ndc_lib::interpreter::function::StaticType::MinHeap(Box::new( + ndc_lib::interpreter::function::StaticType::Any )) }, }, @@ -240,7 +240,7 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { let inner = args.args.first().expect("MaxHeap requires inner"); if let syn::GenericArgument::Type(inner_ty) = inner { let mapped = map_type(inner_ty); - quote::quote! { crate::interpreter::function::StaticType::MaxHeap(Box::new(#mapped)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::MaxHeap(Box::new(#mapped)) } } else { panic!("MaxHeap inner invalid"); } @@ -252,13 +252,13 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { let inner = args.args.first().expect("Iterator requires inner"); if let syn::GenericArgument::Type(inner_ty) = inner { let mapped = map_type(inner_ty); - quote::quote! { crate::interpreter::function::StaticType::Iterator(Box::new(#mapped)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::Iterator(Box::new(#mapped)) } } else { panic!("Iterator inner invalid"); } } _ => { - quote::quote! { crate::interpreter::function::StaticType::Iterator(Box::new(crate::interpreter::function::StaticType::Any)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::Iterator(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } }, "Option" => match &segment.arguments { @@ -266,7 +266,7 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { let inner = args.args.first().expect("Option requires inner type"); if let syn::GenericArgument::Type(inner_ty) = inner { let mapped = map_type(inner_ty); - quote::quote! { crate::interpreter::function::StaticType::Option(Box::new(#mapped)) } + quote::quote! { ndc_lib::interpreter::function::StaticType::Option(Box::new(#mapped)) } } else { panic!("Option inner invalid"); } @@ -283,9 +283,9 @@ fn map_type_path(p: &syn::TypePath) -> TokenStream { } _ => panic!("Result without angle bracketed args"), }, - "Number" => quote::quote! { crate::interpreter::function::StaticType::Number }, + "Number" => quote::quote! { ndc_lib::interpreter::function::StaticType::Number }, "Value" | "EvaluationResult" => { - quote::quote! { crate::interpreter::function::StaticType::Any } + quote::quote! { ndc_lib::interpreter::function::StaticType::Any } } unmatched => panic!("Cannot map type string '{unmatched}' to StaticType"), } @@ -334,7 +334,7 @@ fn wrap_single( let return_expr = match function.sig.output { syn::ReturnType::Default => quote! { - return Ok(crate::interpreter::value::Value::unit()); + return Ok(ndc_lib::interpreter::value::Value::unit()); }, syn::ReturnType::Type(_, typ) => match &*typ { // If the function returns a result we unpack it using the question mark operator @@ -342,11 +342,11 @@ fn wrap_single( return result; }, ty @ syn::Type::Path(_) if path_ends_with(ty, "Result") => quote! { - let value = result.map_err(|err| crate::interpreter::function::FunctionCarrier::IntoEvaluationError(Box::new(err)))?; - return Ok(crate::interpreter::value::Value::from(value)); + let value = result.map_err(|err| ndc_lib::interpreter::function::FunctionCarrier::IntoEvaluationError(Box::new(err)))?; + return Ok(ndc_lib::interpreter::value::Value::from(value)); }, _ => quote! { - let result = crate::interpreter::value::Value::from(result); + let result = ndc_lib::interpreter::value::Value::from(result); return Ok(result); }, }, @@ -364,9 +364,9 @@ fn wrap_single( // } let function_declaration = quote! { pub fn #identifier ( - values: &mut [crate::interpreter::value::Value], - environment: &std::rc::Rc> - ) -> crate::interpreter::evaluate::EvaluationResult { + values: &mut [ndc_lib::interpreter::value::Value], + environment: &std::rc::Rc> + ) -> ndc_lib::interpreter::evaluate::EvaluationResult { // Define the inner function that has the rust type signature #[inline] #inner @@ -384,11 +384,11 @@ fn wrap_single( }; let function_registration = quote! { - let func = crate::interpreter::function::FunctionBuilder::default() - .body(crate::interpreter::function::FunctionBody::GenericFunction { + let func = ndc_lib::interpreter::function::FunctionBuilder::default() + .body(ndc_lib::interpreter::function::FunctionBody::GenericFunction { function: #identifier, - type_signature: crate::interpreter::function::TypeSignature::Exact(vec![ - #( crate::interpreter::function::Parameter::new(#param_names, #param_types,) ),* + type_signature: ndc_lib::interpreter::function::TypeSignature::Exact(vec![ + #( ndc_lib::interpreter::function::Parameter::new(#param_names, #param_types,) ),* ]), return_type: #return_type, }) @@ -409,10 +409,10 @@ fn wrap_single( fn into_param_type(ty: &syn::Type) -> TokenStream { match ty { ty if path_ends_with(ty, "Vec") => { - quote! { crate::interpreter::function::StaticType::List(Box::new(crate::interpreter::function::StaticType::Any)) } + quote! { ndc_lib::interpreter::function::StaticType::List(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } ty if path_ends_with(ty, "VecDeque") => { - quote! { crate::interpreter::function::StaticType::Deque(Box::new(crate::interpreter::function::StaticType::Any)) } + quote! { ndc_lib::interpreter::function::StaticType::Deque(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } ty if path_ends_with(ty, "DefaultMap") || path_ends_with(ty, "DefaultMapMut") @@ -421,42 +421,42 @@ fn into_param_type(ty: &syn::Type) -> TokenStream { temp_create_map_any() } ty if path_ends_with(ty, "MinHeap") => { - quote! { crate::interpreter::function::StaticType::MinHeap(Box::new(crate::interpreter::function::StaticType::Any)) } + quote! { ndc_lib::interpreter::function::StaticType::MinHeap(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } ty if path_ends_with(ty, "MaxHeap") => { - quote! { crate::interpreter::function::StaticType::MaxHeap(Box::new(crate::interpreter::function::StaticType::Any)) } + quote! { ndc_lib::interpreter::function::StaticType::MaxHeap(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } ty if path_ends_with(ty, "ListRepr") => { - quote! { crate::interpreter::function::StaticType::List(Box::new(crate::interpreter::function::StaticType::Any)) } + quote! { ndc_lib::interpreter::function::StaticType::List(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } ty if path_ends_with(ty, "MapRepr") => temp_create_map_any(), syn::Type::Reference(syn::TypeReference { elem, .. }) => into_param_type(elem), syn::Type::Path(syn::TypePath { path, .. }) => match path { - _ if path.is_ident("i64") => quote! { crate::interpreter::function::StaticType::Int }, - _ if path.is_ident("usize") => quote! { crate::interpreter::function::StaticType::Int }, - _ if path.is_ident("f64") => quote! { crate::interpreter::function::StaticType::Float }, - _ if path.is_ident("bool") => quote! { crate::interpreter::function::StaticType::Bool }, + _ if path.is_ident("i64") => quote! { ndc_lib::interpreter::function::StaticType::Int }, + _ if path.is_ident("usize") => quote! { ndc_lib::interpreter::function::StaticType::Int }, + _ if path.is_ident("f64") => quote! { ndc_lib::interpreter::function::StaticType::Float }, + _ if path.is_ident("bool") => quote! { ndc_lib::interpreter::function::StaticType::Bool }, _ if path.is_ident("Value") => { - quote! { crate::interpreter::function::StaticType::Any } + quote! { ndc_lib::interpreter::function::StaticType::Any } } _ if path.is_ident("Number") => { - quote! { crate::interpreter::function::StaticType::Number } + quote! { ndc_lib::interpreter::function::StaticType::Number } } _ if path.is_ident("Sequence") => { - quote! { crate::interpreter::function::StaticType::Sequence(Box::new(crate::interpreter::function::StaticType::Any)) } + quote! { ndc_lib::interpreter::function::StaticType::Sequence(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } _ if path.is_ident("Callable") => { quote! { - crate::interpreter::function::StaticType::Function { + ndc_lib::interpreter::function::StaticType::Function { parameters: None, - return_type: Box::new(crate::interpreter::function::StaticType::Any) + return_type: Box::new(ndc_lib::interpreter::function::StaticType::Any) } } } _ => panic!("Don't know how to convert Path into StaticType\n\n{path:?}"), }, syn::Type::ImplTrait(_) => { - quote! { crate::interpreter::function::StaticType::Iterator(Box::new(crate::interpreter::function::StaticType::Any)) } + quote! { ndc_lib::interpreter::function::StaticType::Iterator(Box::new(ndc_lib::interpreter::function::StaticType::Any)) } } x => panic!("Don't know how to convert {x:?} into StaticType"), } @@ -488,15 +488,15 @@ fn create_temp_variable( return vec![Argument { param_type: quote! { // TODO: how are we going to figure out the exact type of function here - crate::interpreter::function::StaticType::Function { + ndc_lib::interpreter::function::StaticType::Function { parameters: None, - return_type: Box::new(crate::interpreter::function::StaticType::Any) + return_type: Box::new(ndc_lib::interpreter::function::StaticType::Any) } }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Function(#temp_var) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Function(#temp_var) = #argument_var_name else { panic!("Value #position needed to be a Sequence::Map but wasn't"); }; let #argument_var_name = &Callable { @@ -515,7 +515,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Map(#rc_temp_var, _default)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Map(#rc_temp_var, _default)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::Map but wasn't"); }; let #argument_var_name = &*#rc_temp_var.borrow(); @@ -531,7 +531,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Map(#rc_temp_var, _default)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Map(#rc_temp_var, _default)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::Map but wasn't"); }; let #argument_var_name = &mut *#rc_temp_var.try_borrow_mut()?; @@ -547,7 +547,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Map(#rc_temp_var, default)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Map(#rc_temp_var, default)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::Map but wasn't"); }; let #argument_var_name = (&*#rc_temp_var.borrow(), default.to_owned()); @@ -563,7 +563,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Map(#rc_temp_var, default)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Map(#rc_temp_var, default)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::Map but wasn't"); }; let #argument_var_name = (&mut *#rc_temp_var.try_borrow_mut()?, default.to_owned()); @@ -576,11 +576,11 @@ fn create_temp_variable( let rc_temp_var = syn::Ident::new(&format!("temp_{argument_var_name}"), identifier.span()); return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::List(Box::new(crate::interpreter::function::StaticType::Any)) }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::List(Box::new(ndc_lib::interpreter::function::StaticType::Any)) }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::List(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::List(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::List but wasn't"); }; let #argument_var_name = &mut *#rc_temp_var.try_borrow_mut()?; @@ -596,7 +596,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Deque(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Deque(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::List but wasn't"); }; let #argument_var_name = &mut *#rc_temp_var.try_borrow_mut()?; @@ -612,7 +612,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Deque(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Deque(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::List but wasn't"); }; let #argument_var_name = &*#rc_temp_var.try_borrow()?; @@ -628,7 +628,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::MaxHeap(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::MaxHeap(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::MaxHeap but wasn't"); }; let #argument_var_name = &mut *#rc_temp_var.try_borrow_mut()?; @@ -644,7 +644,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::MaxHeap(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::MaxHeap(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::MaxHeap but wasn't"); }; let #argument_var_name = &*#rc_temp_var.try_borrow()?; @@ -660,7 +660,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::MinHeap(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::MinHeap(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::MinHeap but wasn't"); }; let #argument_var_name = &mut *#rc_temp_var.try_borrow_mut()?; @@ -676,7 +676,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::MinHeap(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::MinHeap(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::MinHeap but wasn't"); }; let #argument_var_name = &*#rc_temp_var.try_borrow()?; @@ -688,11 +688,11 @@ fn create_temp_variable( let rc_temp_var = syn::Ident::new(&format!("temp_{argument_var_name}"), identifier.span()); return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::String }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::String }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::String(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::String(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::String but wasn't"); }; let #rc_temp_var = #rc_temp_var.borrow(); @@ -704,19 +704,19 @@ fn create_temp_variable( else if is_ref_of_bigint(ty) { let big_int = syn::Ident::new(&format!("temp_{argument_var_name}"), identifier.span()); return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::Int }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::Int }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let #big_int = if let crate::interpreter::value::Value::Number(crate::interpreter::num::Number::Int(crate::interpreter::int::Int::Int64(smol))) = #argument_var_name { + let #big_int = if let ndc_lib::interpreter::value::Value::Number(ndc_lib::interpreter::num::Number::Int(ndc_lib::interpreter::int::Int::Int64(smol))) = #argument_var_name { Some(num::BigInt::from(*smol)) } else { None }; let #argument_var_name = match #argument_var_name { - crate::interpreter::value::Value::Number(crate::interpreter::num::Number::Int(crate::interpreter::int::Int::BigInt(big))) => big, - crate::interpreter::value::Value::Number(crate::interpreter::num::Number::Int(crate::interpreter::int::Int::Int64(smoll))) => #big_int.as_ref().unwrap(), + ndc_lib::interpreter::value::Value::Number(ndc_lib::interpreter::num::Number::Int(ndc_lib::interpreter::int::Int::BigInt(big))) => big, + ndc_lib::interpreter::value::Value::Number(ndc_lib::interpreter::num::Number::Int(ndc_lib::interpreter::int::Int::Int64(smoll))) => #big_int.as_ref().unwrap(), _ => panic!("Value #position need to be an Int but wasn't"), } }, @@ -725,7 +725,7 @@ fn create_temp_variable( // If we need an owned Value else if path_ends_with(ty, "Value") && !is_ref(ty) { return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::Any }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::Any }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { @@ -738,11 +738,11 @@ fn create_temp_variable( let rc_temp_var = syn::Ident::new(&format!("temp_{argument_var_name}"), identifier.span()); return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::List(Box::new(crate::interpreter::function::StaticType::Any)) }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::List(Box::new(ndc_lib::interpreter::function::StaticType::Any)) }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::List(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::List(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::List but wasn't"); }; let #argument_var_name = &mut *#rc_temp_var.borrow_mut(); @@ -755,22 +755,22 @@ fn create_temp_variable( syn::Ident::new(&format!("temp_{argument_var_name}"), identifier.span()); return vec![ Argument { - param_type: quote! { crate::interpreter::function::StaticType::List(Box::new(crate::interpreter::function::StaticType::Any)) }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::List(Box::new(ndc_lib::interpreter::function::StaticType::Any)) }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::List(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::List(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::List but wasn't"); }; let #argument_var_name = &*#rc_temp_var.borrow(); }, }, // Argument { - // param_type: quote! { crate::interpreter::function::StaticType::Tuple }, + // param_type: quote! { ndc_lib::interpreter::function::StaticType::Tuple }, // param_name: quote! { #original_name }, // argument: quote! { #argument_var_name }, // initialize_code: quote! { - // let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Tuple(#rc_temp_var)) = #argument_var_name else { + // let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Tuple(#rc_temp_var)) = #argument_var_name else { // panic!("Value #position needed to be a Sequence::List but wasn't"); // }; // let #argument_var_name = &#rc_temp_var; @@ -781,11 +781,11 @@ fn create_temp_variable( // The pattern is &BigRational else if path_ends_with(ty, "BigRational") && is_ref(ty) { return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::Rational }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::Rational }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Number(crate::interpreter::num::Number::Rational(#argument_var_name)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Number(ndc_lib::interpreter::num::Number::Rational(#argument_var_name)) = #argument_var_name else { panic!("Value #position needs to be Rational but wasn't"); }; @@ -796,11 +796,11 @@ fn create_temp_variable( // The pattern is BigRational else if path_ends_with(ty, "BigRational") && !is_ref(ty) { return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::Rational }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::Rational }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Number(crate::interpreter::num::Number::Rational(#argument_var_name)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Number(ndc_lib::interpreter::num::Number::Rational(#argument_var_name)) = #argument_var_name else { panic!("VValue #position needs to be Rational but wasn't"); }; @@ -811,11 +811,11 @@ fn create_temp_variable( // The pattern is Complex64 else if path_ends_with(ty, "Complex64") && !is_ref(ty) { return vec![Argument { - param_type: quote! { crate::interpreter::function::StaticType::Complex }, + param_type: quote! { ndc_lib::interpreter::function::StaticType::Complex }, param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Number(crate::interpreter::num::Number::Complex(#argument_var_name)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Number(ndc_lib::interpreter::num::Number::Complex(#argument_var_name)) = #argument_var_name else { panic!("Value #position needs to be Complex64 but wasn't"); }; @@ -830,7 +830,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let #argument_var_name = #path :: try_from(#argument_var_name).map_err(|err| crate::interpreter::function::FunctionCallError::ConvertToNativeTypeError(format!("{err}")))? + let #argument_var_name = #path :: try_from(#argument_var_name).map_err(|err| ndc_lib::interpreter::function::FunctionCallError::ConvertToNativeTypeError(format!("{err}")))? }, }]; } @@ -841,7 +841,7 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let #argument_var_name = <#type_ref as TryFrom<&mut crate::interpreter::value::Value>> :: try_from(#argument_var_name).map_err(|err| crate::interpreter::function::FunctionCallError::ConvertToNativeTypeError(format!("{err}")))? + let #argument_var_name = <#type_ref as TryFrom<&mut ndc_lib::interpreter::value::Value>> :: try_from(#argument_var_name).map_err(|err| ndc_lib::interpreter::function::FunctionCallError::ConvertToNativeTypeError(format!("{err}")))? }, }]; } @@ -856,11 +856,11 @@ fn create_temp_variable( param_name: quote! { #original_name }, argument: quote! { #argument_var_name }, initialize_code: quote! { - let crate::interpreter::value::Value::Sequence(crate::interpreter::sequence::Sequence::Iterator(#rc_temp_var)) = #argument_var_name else { + let ndc_lib::interpreter::value::Value::Sequence(ndc_lib::interpreter::sequence::Sequence::Iterator(#rc_temp_var)) = #argument_var_name else { panic!("Value #position needed to be a Sequence::Iterator but wasn't"); }; - let #argument_var_name = crate::interpreter::iterator::RcIter::new(Rc::clone(#rc_temp_var)); + let #argument_var_name = ndc_lib::interpreter::iterator::RcIter::new(Rc::clone(#rc_temp_var)); }, }]; } else { @@ -874,9 +874,9 @@ fn create_temp_variable( // TODO: just adding Any as type here is lazy AF but CBA fixing generics pub fn temp_create_map_any() -> TokenStream { quote! { - crate::interpreter::function::StaticType::Map { - key: Box::new(crate::interpreter::function::StaticType::Any), - value: Box::new(crate::interpreter::function::StaticType::Any) + ndc_lib::interpreter::function::StaticType::Map { + key: Box::new(ndc_lib::interpreter::function::StaticType::Any), + value: Box::new(ndc_lib::interpreter::function::StaticType::Any) } } } diff --git a/ndc_macros/src/lib.rs b/ndc_macros/src/lib.rs index b1b8e5c0..1a9b4ccf 100644 --- a/ndc_macros/src/lib.rs +++ b/ndc_macros/src/lib.rs @@ -43,7 +43,7 @@ pub fn export_module(_attr: TokenStream, item: TokenStream) -> TokenStream { } let register_function = quote! { - pub fn register(env: &mut crate::interpreter::environment::Environment) { + pub fn register(env: &mut ndc_lib::interpreter::environment::Environment) { #(#registrations)* } }; diff --git a/ndc_stdlib/Cargo.toml b/ndc_stdlib/Cargo.toml new file mode 100644 index 00000000..8da35e51 --- /dev/null +++ b/ndc_stdlib/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "ndc_stdlib" +edition.workspace = true +version.workspace = true + +[dependencies] +anyhow.workspace = true +factorial.workspace = true +itertools.workspace = true +ndc_lib = { workspace = true } +ndc_macros.workspace = true +num.workspace = true +once_cell.workspace = true +rand.workspace = true +regex.workspace = true +serde_json = { workspace = true } +tap.workspace = true + +# Crypto +md5 = { version = "0.8.0", optional = true } +sha1 = { version = "0.10.6", optional = true } + +[features] +default = ["ahash", "crypto"] +ahash = ["ndc_lib/ahash"] +crypto = ["dep:md5", "dep:sha1"] diff --git a/ndc_lib/src/stdlib/aoc.rs b/ndc_stdlib/src/aoc.rs similarity index 80% rename from ndc_lib/src/stdlib/aoc.rs rename to ndc_stdlib/src/aoc.rs index 2d0430ad..d04a179b 100644 --- a/ndc_lib/src/stdlib/aoc.rs +++ b/ndc_stdlib/src/aoc.rs @@ -4,10 +4,10 @@ mod inner { use std::cell::RefCell; use std::rc::Rc; - use crate::hash_map::HashMap; - use crate::interpreter::iterator::mut_seq_to_iterator; - use crate::interpreter::sequence::Sequence; - use crate::interpreter::value::Value; + use ndc_lib::hash_map::HashMap; + use ndc_lib::interpreter::iterator::mut_seq_to_iterator; + use ndc_lib::interpreter::sequence::Sequence; + use ndc_lib::interpreter::value::Value; /// Counts the occurrences of each item in a sequence and returns a map with the frequencies. #[function(return_type = HashMap<_, _>)] diff --git a/ndc_lib/src/stdlib/cmp.rs b/ndc_stdlib/src/cmp.rs similarity index 96% rename from ndc_lib/src/stdlib/cmp.rs rename to ndc_stdlib/src/cmp.rs index 47feef7b..a9a160f9 100644 --- a/ndc_lib/src/stdlib/cmp.rs +++ b/ndc_stdlib/src/cmp.rs @@ -2,8 +2,8 @@ mod inner { use anyhow::anyhow; - use crate::compare::FallibleOrd; - use crate::interpreter::value::Value; + use ndc_lib::compare::FallibleOrd; + use ndc_lib::interpreter::value::Value; use std::cmp::Ordering; /// Produces an error if the argument is not true. diff --git a/ndc_lib/src/stdlib/crypto.rs b/ndc_stdlib/src/crypto.rs similarity index 100% rename from ndc_lib/src/stdlib/crypto.rs rename to ndc_stdlib/src/crypto.rs diff --git a/ndc_lib/src/stdlib/deque.rs b/ndc_stdlib/src/deque.rs similarity index 97% rename from ndc_lib/src/stdlib/deque.rs rename to ndc_stdlib/src/deque.rs index 02afff20..23e52af5 100644 --- a/ndc_lib/src/stdlib/deque.rs +++ b/ndc_stdlib/src/deque.rs @@ -2,8 +2,8 @@ use ndc_macros::export_module; #[export_module] mod inner { - use crate::interpreter::sequence::Sequence; - use crate::interpreter::value::Value; + use ndc_lib::interpreter::sequence::Sequence; + use ndc_lib::interpreter::value::Value; use std::cell::RefCell; use std::collections::VecDeque; use std::rc::Rc; diff --git a/ndc_lib/src/stdlib/file.rs b/ndc_stdlib/src/file.rs similarity index 96% rename from ndc_lib/src/stdlib/file.rs rename to ndc_stdlib/src/file.rs index 277b4bd7..0388ebbc 100644 --- a/ndc_lib/src/stdlib/file.rs +++ b/ndc_stdlib/src/file.rs @@ -1,8 +1,8 @@ -use crate::interpreter::environment::Environment; -use crate::interpreter::function::{ +use ndc_lib::interpreter::environment::Environment; +use ndc_lib::interpreter::function::{ FunctionBody, FunctionBuilder, FunctionCarrier, StaticType, TypeSignature, }; -use crate::interpreter::value::Value; +use ndc_lib::interpreter::value::Value; use ndc_macros::export_module; use std::fs::read_to_string; diff --git a/ndc_lib/src/stdlib/hash_map.rs b/ndc_stdlib/src/hash_map.rs similarity index 97% rename from ndc_lib/src/stdlib/hash_map.rs rename to ndc_stdlib/src/hash_map.rs index 4d448ad0..890fcae1 100644 --- a/ndc_lib/src/stdlib/hash_map.rs +++ b/ndc_stdlib/src/hash_map.rs @@ -1,8 +1,8 @@ -use crate::hash_map; -use crate::hash_map::HashMap; -use crate::hash_map::HashMapExt; -use crate::interpreter::sequence::{DefaultMap, MapRepr, Sequence}; -use crate::interpreter::value::Value; +use ndc_lib::hash_map; +use ndc_lib::hash_map::HashMap; +use ndc_lib::hash_map::HashMapExt; +use ndc_lib::interpreter::sequence::{DefaultMap, MapRepr, Sequence}; +use ndc_lib::interpreter::value::Value; use std::cell::RefCell; use std::rc::Rc; diff --git a/ndc_lib/src/stdlib/heap.rs b/ndc_stdlib/src/heap.rs similarity index 90% rename from ndc_lib/src/stdlib/heap.rs rename to ndc_stdlib/src/heap.rs index 9c6a2d5e..5c9385e9 100644 --- a/ndc_lib/src/stdlib/heap.rs +++ b/ndc_stdlib/src/heap.rs @@ -2,9 +2,9 @@ use ndc_macros::export_module; #[export_module] mod inner { - use crate::interpreter::heap::{MaxHeap, MinHeap}; - use crate::interpreter::sequence::Sequence; - use crate::interpreter::value::Value; + use ndc_lib::interpreter::heap::{MaxHeap, MinHeap}; + use ndc_lib::interpreter::sequence::Sequence; + use ndc_lib::interpreter::value::Value; use std::cell::RefCell; use std::rc::Rc; diff --git a/ndc_lib/src/stdlib/mod.rs b/ndc_stdlib/src/lib.rs similarity index 71% rename from ndc_lib/src/stdlib/mod.rs rename to ndc_stdlib/src/lib.rs index 2c82bb1c..d83aa5e9 100644 --- a/ndc_lib/src/stdlib/mod.rs +++ b/ndc_stdlib/src/lib.rs @@ -1,4 +1,5 @@ -use crate::interpreter::environment::Environment; +use ndc_lib::interpreter::environment::{Environment, InterpreterOutput}; +use ndc_lib::interpreter::Interpreter; pub mod aoc; pub mod cmp; @@ -39,3 +40,9 @@ pub fn register(env: &mut Environment) { string::register(env); value::register(env); } + +pub fn new_interpreter(dest: T) -> Interpreter { + let mut environment = Environment::new(Box::new(dest)); + register(&mut environment); + Interpreter::from_env(environment) +} diff --git a/ndc_lib/src/stdlib/list.rs b/ndc_stdlib/src/list.rs similarity index 97% rename from ndc_lib/src/stdlib/list.rs rename to ndc_stdlib/src/list.rs index 66fc5b74..5fca0b70 100644 --- a/ndc_lib/src/stdlib/list.rs +++ b/ndc_stdlib/src/list.rs @@ -1,8 +1,8 @@ #[ndc_macros::export_module] mod inner { - use crate::interpreter::iterator::mut_seq_to_iterator; - use crate::interpreter::sequence::{ListRepr, Sequence}; - use crate::interpreter::value::Value; + use ndc_lib::interpreter::iterator::mut_seq_to_iterator; + use ndc_lib::interpreter::sequence::{ListRepr, Sequence}; + use ndc_lib::interpreter::value::Value; use itertools::Itertools; use std::rc::Rc; diff --git a/ndc_lib/src/stdlib/math.rs b/ndc_stdlib/src/math.rs similarity index 97% rename from ndc_lib/src/stdlib/math.rs rename to ndc_stdlib/src/math.rs index 40f028cf..1fd0a502 100644 --- a/ndc_lib/src/stdlib/math.rs +++ b/ndc_stdlib/src/math.rs @@ -1,7 +1,7 @@ -use crate::interpreter::environment::Environment; -use crate::interpreter::num::{BinaryOperatorError, Number}; -use crate::interpreter::sequence::Sequence; -use crate::interpreter::value::Value; +use ndc_lib::interpreter::environment::Environment; +use ndc_lib::interpreter::num::{BinaryOperatorError, Number}; +use ndc_lib::interpreter::sequence::Sequence; +use ndc_lib::interpreter::value::Value; use factorial::Factorial; use ndc_macros::export_module; use num::ToPrimitive; @@ -52,8 +52,8 @@ mod inner { use std::ops::Sub; use super::FallibleSum; - use crate::interpreter::int::Int; - use crate::interpreter::num::Number; + use ndc_lib::interpreter::int::Int; + use ndc_lib::interpreter::num::Number; use anyhow::Context; use num::{BigInt, BigRational, BigUint, Integer, complex::Complex64}; @@ -209,11 +209,11 @@ mod inner { pub mod f64 { use super::{Environment, Number, ToPrimitive, f64}; - use crate::interpreter::function::{ + use ndc_lib::interpreter::function::{ FunctionBody, FunctionBuilder, FunctionCarrier, Parameter, StaticType, TypeSignature, }; - use crate::interpreter::num::BinaryOperatorError; - use crate::interpreter::value::Value; + use ndc_lib::interpreter::num::BinaryOperatorError; + use ndc_lib::interpreter::value::Value; use std::cmp::Ordering; use std::ops::Not; @@ -475,7 +475,7 @@ pub mod f64 { ($method:ident,$docs:literal) => { let function = FunctionBuilder::default() .body( - $crate::interpreter::function::FunctionBody::NumericUnaryOp { + ndc_lib::interpreter::function::FunctionBody::NumericUnaryOp { body: |num: Number| match num { Number::Int(i) => Number::Float(f64::from(i).$method()), Number::Float(f) => Number::Float(f.$method()), diff --git a/ndc_lib/src/stdlib/rand.rs b/ndc_stdlib/src/rand.rs similarity index 92% rename from ndc_lib/src/stdlib/rand.rs rename to ndc_stdlib/src/rand.rs index 6f5fa2ea..9bb043b1 100644 --- a/ndc_lib/src/stdlib/rand.rs +++ b/ndc_stdlib/src/rand.rs @@ -19,10 +19,10 @@ pub fn random_n( #[export_module] mod inner { - use crate::interpreter::iterator::mut_seq_to_iterator; - use crate::interpreter::num::Number; - use crate::interpreter::sequence::Sequence; - use crate::interpreter::value::Value; + use ndc_lib::interpreter::iterator::mut_seq_to_iterator; + use ndc_lib::interpreter::num::Number; + use ndc_lib::interpreter::sequence::Sequence; + use ndc_lib::interpreter::value::Value; use itertools::Itertools; /// Randomly shuffles the elements of the list in place. diff --git a/ndc_lib/src/stdlib/regex.rs b/ndc_stdlib/src/regex.rs similarity index 98% rename from ndc_lib/src/stdlib/regex.rs rename to ndc_stdlib/src/regex.rs index 5ea2aeee..7a4362a7 100644 --- a/ndc_lib/src/stdlib/regex.rs +++ b/ndc_stdlib/src/regex.rs @@ -1,4 +1,4 @@ -use crate::interpreter::value::Value; +use ndc_lib::interpreter::value::Value; use once_cell::sync::Lazy; use regex::Regex; diff --git a/ndc_lib/src/stdlib/sequence.rs b/ndc_stdlib/src/sequence.rs similarity index 98% rename from ndc_lib/src/stdlib/sequence.rs rename to ndc_stdlib/src/sequence.rs index d56fdd72..b2efeafd 100644 --- a/ndc_lib/src/stdlib/sequence.rs +++ b/ndc_stdlib/src/sequence.rs @@ -1,8 +1,8 @@ #![allow(clippy::ptr_arg)] -use crate::interpreter::iterator::{MutableValueIntoIterator, mut_seq_to_iterator}; -use crate::interpreter::sequence::Sequence; -use crate::{ +use ndc_lib::interpreter::iterator::{MutableValueIntoIterator, mut_seq_to_iterator}; +use ndc_lib::interpreter::sequence::Sequence; +use ndc_lib::{ compare::FallibleOrd, interpreter::{evaluate::EvaluationResult, function::Callable, value::Value}, }; @@ -79,8 +79,8 @@ fn try_sort_by( #[export_module] mod inner { - use crate::interpreter::iterator::{Repeat, ValueIterator}; - use crate::interpreter::{function::FunctionCarrier, iterator::mut_value_to_iterator}; + use ndc_lib::interpreter::iterator::{Repeat, ValueIterator}; + use ndc_lib::interpreter::{function::FunctionCarrier, iterator::mut_value_to_iterator}; use std::cell::RefCell; #[function(name = "in")] @@ -832,8 +832,8 @@ pub mod extra { use anyhow::anyhow; use itertools::izip; - use crate::interpreter::function::{FunctionBuilder, StaticType}; - use crate::interpreter::{ + use ndc_lib::interpreter::function::{FunctionBuilder, StaticType}; + use ndc_lib::interpreter::{ environment::Environment, function::FunctionBody, iterator::mut_value_to_iterator, value::Value, }; @@ -844,7 +844,7 @@ pub mod extra { .name("zip".to_string()) .documentation("Combines multiple sequences (or iterables) into a single sequence of tuples, where the ith tuple contains the ith element from each input sequence.\n\nIf the input sequences are of different lengths, the resulting sequence is truncated to the length of the shortest input.".to_string()) .body(FunctionBody::generic( - crate::interpreter::function::TypeSignature::Variadic, + ndc_lib::interpreter::function::TypeSignature::Variadic, StaticType::List(Box::new(StaticType::Tuple(vec![StaticType::Any, StaticType::Any]))), |args, _env| match args { [_] => { diff --git a/ndc_stdlib/src/serde.rs b/ndc_stdlib/src/serde.rs new file mode 100644 index 00000000..d095a0df --- /dev/null +++ b/ndc_stdlib/src/serde.rs @@ -0,0 +1,134 @@ +use ndc_macros::export_module; +use std::rc::Rc; +use std::{cell::RefCell, str::FromStr}; + +use ndc_lib::hash_map::HashMap; +use ndc_lib::interpreter::sequence::Sequence; +use ndc_lib::interpreter::value::Value; +use anyhow::Context; +use num::BigInt; +use num::ToPrimitive; +use serde_json::{Map, Number, Value as JsonValue, json}; + +fn value_to_json(value: Value) -> Result { + match value { + Value::Option(Some(value)) => value_to_json(*value), + Value::Option(None) => Ok(JsonValue::Null), + Value::Number(number) => match number { + ndc_lib::interpreter::num::Number::Int(int) => match int { + ndc_lib::interpreter::int::Int::Int64(i) => Ok(json!(i)), + ndc_lib::interpreter::int::Int::BigInt(big_int) => { + Number::from_str(&big_int.to_string()) + .map(JsonValue::Number) + .context("Cannot convert bigint to string") + } + }, + ndc_lib::interpreter::num::Number::Float(f) => Ok(json!(f)), + ndc_lib::interpreter::num::Number::Rational(ratio) => Ok(json!(ratio.to_f64())), + ndc_lib::interpreter::num::Number::Complex(complex) => { + Ok(json!(format!("{complex}"))) + } + }, + Value::Bool(b) => Ok(json!(b)), + Value::Sequence(s) => match s { + Sequence::String(s) => Ok(json!(&*s.borrow())), + Sequence::List(values) => Ok(JsonValue::Array( + values + .borrow() + .iter() + .map(|v| value_to_json(v.clone())) + .collect::, _>>()?, + )), + Sequence::Tuple(values) => match values.len() { + 0 => Ok(JsonValue::Null), + _ => Ok(JsonValue::Array( + values + .iter() + .map(|v| value_to_json(v.clone())) + .collect::, _>>()?, + )), + }, + Sequence::Map(values, _) => Ok(JsonValue::Object( + values + .borrow() + .iter() + .map(|(key, value)| { + value_to_json(value.clone()).map(|value| (key.to_string(), value)) + }) + .collect::, _>>()?, + )), + Sequence::Iterator(i) => { + let mut i = i.borrow_mut(); + let mut out = Vec::new(); + for value in i.by_ref() { + out.push(value_to_json(value)?); + } + Ok(JsonValue::Array(out)) + } + Sequence::MaxHeap(h) => Ok(JsonValue::Array( + h.borrow() + .iter() + .map(|h| value_to_json(h.0.clone())) + .collect::, _>>()?, + )), + Sequence::MinHeap(h) => Ok(JsonValue::Array( + h.borrow() + .iter() + .map(|h| value_to_json(h.0.0.clone())) + .collect::, _>>()?, + )), + Sequence::Deque(d) => Ok(JsonValue::Array( + d.borrow() + .iter() + .map(|v| value_to_json(v.clone())) + .collect::, _>>()?, + )), + }, + Value::Function(_) => Err(anyhow::anyhow!("Unable to serialize function")), + } +} + +fn json_to_value(value: JsonValue) -> Result { + Ok(match value { + JsonValue::Null => Value::unit(), + JsonValue::Bool(b) => Value::Bool(b), + JsonValue::Number(n) => n.as_str().parse::().map(Value::from).or_else(|_| { + n.as_f64() + .map(Value::from) + .context("Cannot parse number as int or float") + })?, + JsonValue::String(s) => Value::string(s), + JsonValue::Array(a) => Value::list( + a.into_iter() + .map(json_to_value) + .collect::, _>>()?, + ), + JsonValue::Object(o) => Value::Sequence(Sequence::Map( + Rc::new(RefCell::new( + o.into_iter() + .map(|(key, value)| { + json_to_value(value).map(|value| (Value::string(key), value)) + }) + .collect::, _>>()?, + )), + None, + )), + }) +} + +#[export_module] +mod inner { + use ndc_lib::interpreter::value::Value; + + /// Converts a JSON string to a value + pub fn json_decode(input: &str) -> anyhow::Result { + let json: JsonValue = serde_json::from_str(input)?; + json_to_value(json) + } + + /// Converts the input value to JSON + pub fn json_encode(input: Value) -> anyhow::Result { + let v = value_to_json(input)?; + Ok(v.to_string()) + } +} diff --git a/ndc_lib/src/stdlib/string.rs b/ndc_stdlib/src/string.rs similarity index 98% rename from ndc_lib/src/stdlib/string.rs rename to ndc_stdlib/src/string.rs index 9c3b4d3f..0819e0b9 100644 --- a/ndc_lib/src/stdlib/string.rs +++ b/ndc_stdlib/src/string.rs @@ -1,8 +1,8 @@ use ndc_macros::export_module; -use crate::interpreter::iterator::mut_seq_to_iterator; -use crate::interpreter::sequence::{Sequence, StringRepr}; -use crate::interpreter::value::Value; +use ndc_lib::interpreter::iterator::mut_seq_to_iterator; +use ndc_lib::interpreter::sequence::{Sequence, StringRepr}; +use ndc_lib::interpreter::value::Value; use std::rc::Rc; use anyhow::{Context, anyhow}; diff --git a/ndc_lib/src/stdlib/value.rs b/ndc_stdlib/src/value.rs similarity index 96% rename from ndc_lib/src/stdlib/value.rs rename to ndc_stdlib/src/value.rs index b8f8c80a..eebca82e 100644 --- a/ndc_lib/src/stdlib/value.rs +++ b/ndc_stdlib/src/value.rs @@ -3,10 +3,10 @@ use std::fmt::Write; #[export_module] mod inner { - use crate::interpreter::function::Callable; - use crate::interpreter::heap::{MaxHeap, MinHeap}; - use crate::interpreter::sequence::Sequence; - use crate::interpreter::value::Value; + use ndc_lib::interpreter::function::Callable; + use ndc_lib::interpreter::heap::{MaxHeap, MinHeap}; + use ndc_lib::interpreter::sequence::Sequence; + use ndc_lib::interpreter::value::Value; use std::cell::RefCell; use std::rc::Rc; diff --git a/tests/Cargo.toml b/tests/Cargo.toml index b030f322..8c39be99 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -4,7 +4,7 @@ edition.workspace = true version.workspace = true [dev-dependencies] -ndc_lib.workspace = true +ndc_stdlib.workspace = true owo-colors.workspace = true [[test]] diff --git a/tests/src/programs.rs b/tests/src/programs.rs index 648a44a3..2c99b9d7 100644 --- a/tests/src/programs.rs +++ b/tests/src/programs.rs @@ -1,4 +1,4 @@ -use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::new_interpreter; use owo_colors::OwoColorize; use std::fs; use std::path::PathBuf; @@ -23,7 +23,7 @@ fn run_ndc_test(path: PathBuf) -> Result<(), std::io::Error> { print!("Running {path:?}..."); - let mut interpreter = Interpreter::new(Vec::new()); + let mut interpreter = new_interpreter(Vec::new()); let interpreter_result = interpreter.run_str(&contents); let program_had_error = interpreter_result.is_err(); From 7aae196084c88b880ac67a067b7aadcfb9d9cbec Mon Sep 17 00:00:00 2001 From: Tim Fennis Date: Mon, 2 Mar 2026 20:59:11 +0100 Subject: [PATCH 3/5] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Replace=20new=5Finterp?= =?UTF-8?q?reter()=20with=20WithStdlib=20extension=20trait?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 2 ++ benches/src/benchmark.rs | 5 +++-- ndc_bin/src/docs.rs | 5 +++-- ndc_bin/src/main.rs | 6 +++--- ndc_bin/src/repl.rs | 5 +++-- ndc_lib/src/interpreter/mod.rs | 6 ++++++ ndc_lsp/Cargo.toml | 1 + ndc_lsp/src/backend.rs | 7 ++++--- ndc_stdlib/src/lib.rs | 15 ++++++++++----- tests/Cargo.toml | 1 + tests/src/programs.rs | 5 +++-- 11 files changed, 39 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37acd212..e5cafc1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1292,6 +1292,7 @@ name = "ndc_lsp" version = "0.2.1" dependencies = [ "ndc_lexer", + "ndc_lib", "ndc_parser", "ndc_stdlib", "tokio", @@ -2062,6 +2063,7 @@ dependencies = [ name = "tests" version = "0.2.1" dependencies = [ + "ndc_lib", "ndc_stdlib", "owo-colors", ] diff --git a/benches/src/benchmark.rs b/benches/src/benchmark.rs index 322133e0..1963a0b0 100644 --- a/benches/src/benchmark.rs +++ b/benches/src/benchmark.rs @@ -1,6 +1,7 @@ use criterion::{Criterion, criterion_group, criterion_main}; use ndc_lib::interpreter::InterpreterError; -use ndc_stdlib::new_interpreter; +use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::WithStdlib; use rand::{RngExt, SeedableRng}; use rand_chacha::ChaCha8Rng; use std::fs; @@ -9,7 +10,7 @@ use std::time::Duration; fn run_string(input: &str) -> Result { let buf: Vec = vec![]; - let mut interpreter = new_interpreter(buf); + let mut interpreter = Interpreter::new(buf).with_stdlib(); interpreter.run_str(std::hint::black_box(input)) } diff --git a/ndc_bin/src/docs.rs b/ndc_bin/src/docs.rs index b379784c..a1a45b0f 100644 --- a/ndc_bin/src/docs.rs +++ b/ndc_bin/src/docs.rs @@ -1,5 +1,6 @@ use ndc_lib::interpreter::function::{Parameter, TypeSignature}; -use ndc_stdlib::new_interpreter; +use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::WithStdlib; use std::cmp::Ordering; use std::fmt::Write; use strsim::normalized_damerau_levenshtein; @@ -13,7 +14,7 @@ fn string_match(needle: &str, haystack: &str) -> bool { } pub fn docs(query: Option<&str>) -> anyhow::Result<()> { - let interpreter = new_interpreter(Vec::new()); // Discard the output + let interpreter = Interpreter::new(Vec::new()).with_stdlib(); // Discard the output let functions = interpreter.environment().borrow().get_all_functions(); let matched_functions = functions diff --git a/ndc_bin/src/main.rs b/ndc_bin/src/main.rs index 5d9ffaa2..05a97d3c 100644 --- a/ndc_bin/src/main.rs +++ b/ndc_bin/src/main.rs @@ -5,8 +5,8 @@ use anyhow::{Context, anyhow}; use clap::{Parser, Subcommand}; use highlighter::{AndycppHighlighter, AndycppHighlighterState}; use miette::{NamedSource, highlighters::HighlighterState}; -use ndc_lib::interpreter::InterpreterError; -use ndc_stdlib::new_interpreter; +use ndc_lib::interpreter::{Interpreter, InterpreterError}; +use ndc_stdlib::WithStdlib; use std::path::PathBuf; use std::process; use std::{fs, io::Write}; @@ -119,7 +119,7 @@ fn main() -> anyhow::Result<()> { let string = fs::read_to_string(path)?; let stdout = std::io::stdout(); - let mut interpreter = new_interpreter(stdout); + let mut interpreter = Interpreter::new(stdout).with_stdlib(); match into_miette_result(interpreter.run_str(&string)) { // we can just ignore successful runs because we have print statements Ok(_final_value) => {} diff --git a/ndc_bin/src/repl.rs b/ndc_bin/src/repl.rs index 62998d53..ec71d900 100644 --- a/ndc_bin/src/repl.rs +++ b/ndc_bin/src/repl.rs @@ -1,7 +1,8 @@ #![allow(clippy::print_stdout, clippy::print_stderr)] use itertools::Itertools; use miette::highlighters::HighlighterState; -use ndc_stdlib::new_interpreter; +use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::WithStdlib; use rustyline::Helper; use rustyline::config::Configurer; use rustyline::error::ReadlineError; @@ -36,7 +37,7 @@ pub fn run() -> anyhow::Result<()> { rl.set_helper(Some(h)); let stdout = std::io::stdout(); - let mut interpreter = new_interpreter(stdout); + let mut interpreter = Interpreter::new(stdout).with_stdlib(); loop { match rl.readline("λ ") { Ok(line) => { diff --git a/ndc_lib/src/interpreter/mod.rs b/ndc_lib/src/interpreter/mod.rs index 2ef63636..a106c4a2 100644 --- a/ndc_lib/src/interpreter/mod.rs +++ b/ndc_lib/src/interpreter/mod.rs @@ -42,6 +42,12 @@ impl Interpreter { } } + pub fn configure(&mut self, f: F) { + f(&mut self.environment.borrow_mut()); + let global_identifiers = self.environment.borrow().get_global_identifiers(); + self.analyser = Analyser::from_scope_tree(ScopeTree::from_global_scope(global_identifiers)); + } + #[must_use] pub fn environment(self) -> Rc> { self.environment diff --git a/ndc_lsp/Cargo.toml b/ndc_lsp/Cargo.toml index ca7c7dc1..f8d20249 100644 --- a/ndc_lsp/Cargo.toml +++ b/ndc_lsp/Cargo.toml @@ -7,6 +7,7 @@ version.workspace = true [dependencies] tokio = { version = "1.49.0", features = ["full"] } ndc_lexer.workspace = true +ndc_lib.workspace = true ndc_stdlib.workspace = true tower-lsp.workspace = true ndc_parser.workspace = true diff --git a/ndc_lsp/src/backend.rs b/ndc_lsp/src/backend.rs index 60435c23..5fa0c96b 100644 --- a/ndc_lsp/src/backend.rs +++ b/ndc_lsp/src/backend.rs @@ -2,7 +2,8 @@ use std::collections::HashMap; use ndc_lexer::{Lexer, Span, TokenLocation}; use ndc_parser::{Expression, ExpressionLocation, ForBody, ForIteration, Lvalue}; -use ndc_stdlib::new_interpreter; +use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::WithStdlib; use tokio::sync::Mutex; use tower_lsp::jsonrpc::Result as JsonRPCResult; use tower_lsp::lsp_types::{ @@ -80,7 +81,7 @@ impl Backend { // The interpreter uses Rc internally (non-Send), so it must be fully dropped // before the next await point. let hints = { - let mut interpreter = new_interpreter(Vec::new()); + let mut interpreter = Interpreter::new(Vec::new()).with_stdlib(); match interpreter.analyse_str(text) { Ok(expressions) => { let mut hints = Vec::new(); @@ -151,7 +152,7 @@ impl LanguageServer for Backend { &self, _params: CompletionParams, ) -> Result, tower_lsp::jsonrpc::Error> { - let interpreter = new_interpreter(Vec::new()); + let interpreter = Interpreter::new(Vec::new()).with_stdlib(); let env = interpreter.environment(); let functions = env.borrow().get_all_functions(); diff --git a/ndc_stdlib/src/lib.rs b/ndc_stdlib/src/lib.rs index d83aa5e9..bf89f81f 100644 --- a/ndc_stdlib/src/lib.rs +++ b/ndc_stdlib/src/lib.rs @@ -1,4 +1,4 @@ -use ndc_lib::interpreter::environment::{Environment, InterpreterOutput}; +use ndc_lib::interpreter::environment::Environment; use ndc_lib::interpreter::Interpreter; pub mod aoc; @@ -41,8 +41,13 @@ pub fn register(env: &mut Environment) { value::register(env); } -pub fn new_interpreter(dest: T) -> Interpreter { - let mut environment = Environment::new(Box::new(dest)); - register(&mut environment); - Interpreter::from_env(environment) +pub trait WithStdlib: Sized { + fn with_stdlib(self) -> Self; +} + +impl WithStdlib for Interpreter { + fn with_stdlib(mut self) -> Self { + self.configure(register); + self + } } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 8c39be99..5228def1 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -4,6 +4,7 @@ edition.workspace = true version.workspace = true [dev-dependencies] +ndc_lib.workspace = true ndc_stdlib.workspace = true owo-colors.workspace = true diff --git a/tests/src/programs.rs b/tests/src/programs.rs index 2c99b9d7..87d2d539 100644 --- a/tests/src/programs.rs +++ b/tests/src/programs.rs @@ -1,4 +1,5 @@ -use ndc_stdlib::new_interpreter; +use ndc_lib::interpreter::Interpreter; +use ndc_stdlib::WithStdlib; use owo_colors::OwoColorize; use std::fs; use std::path::PathBuf; @@ -23,7 +24,7 @@ fn run_ndc_test(path: PathBuf) -> Result<(), std::io::Error> { print!("Running {path:?}..."); - let mut interpreter = new_interpreter(Vec::new()); + let mut interpreter = Interpreter::new(Vec::new()).with_stdlib(); let interpreter_result = interpreter.run_str(&contents); let program_had_error = interpreter_result.is_err(); From 3a4ecd4935391b364b04ba6089590b87582e0676 Mon Sep 17 00:00:00 2001 From: Tim Fennis Date: Mon, 2 Mar 2026 21:01:53 +0100 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=8E=A8=20cargo=20fmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- benches/src/benchmark.rs | 2 +- ndc_bin/src/docs.rs | 2 +- ndc_lib/src/interpreter/environment.rs | 2 +- ndc_lib/src/interpreter/evaluate/index.rs | 12 +++++++----- ndc_lib/src/interpreter/evaluate/mod.rs | 6 +++--- ndc_lib/src/interpreter/function.rs | 2 +- ndc_lib/src/interpreter/mod.rs | 2 +- ndc_lib/src/interpreter/num.rs | 2 +- ndc_lib/src/interpreter/semantic/analyser.rs | 14 ++++++++++---- ndc_lsp/src/backend.rs | 2 +- ndc_macros/src/function.rs | 12 +++++++++--- ndc_stdlib/src/lib.rs | 2 +- ndc_stdlib/src/list.rs | 2 +- ndc_stdlib/src/math.rs | 4 ++-- ndc_stdlib/src/rand.rs | 2 +- ndc_stdlib/src/sequence.rs | 4 ++-- ndc_stdlib/src/serde.rs | 6 ++---- 17 files changed, 45 insertions(+), 33 deletions(-) diff --git a/benches/src/benchmark.rs b/benches/src/benchmark.rs index 1963a0b0..fba47fa5 100644 --- a/benches/src/benchmark.rs +++ b/benches/src/benchmark.rs @@ -1,6 +1,6 @@ use criterion::{Criterion, criterion_group, criterion_main}; -use ndc_lib::interpreter::InterpreterError; use ndc_lib::interpreter::Interpreter; +use ndc_lib::interpreter::InterpreterError; use ndc_stdlib::WithStdlib; use rand::{RngExt, SeedableRng}; use rand_chacha::ChaCha8Rng; diff --git a/ndc_bin/src/docs.rs b/ndc_bin/src/docs.rs index a1a45b0f..0e5e04d4 100644 --- a/ndc_bin/src/docs.rs +++ b/ndc_bin/src/docs.rs @@ -1,5 +1,5 @@ -use ndc_lib::interpreter::function::{Parameter, TypeSignature}; use ndc_lib::interpreter::Interpreter; +use ndc_lib::interpreter::function::{Parameter, TypeSignature}; use ndc_stdlib::WithStdlib; use std::cmp::Ordering; use std::fmt::Write; diff --git a/ndc_lib/src/interpreter/environment.rs b/ndc_lib/src/interpreter/environment.rs index f9638cd1..c14a57ac 100644 --- a/ndc_lib/src/interpreter/environment.rs +++ b/ndc_lib/src/interpreter/environment.rs @@ -1,7 +1,7 @@ use crate::interpreter::function::{Function, StaticType}; -use ndc_parser::ResolvedVar; use crate::interpreter::value::Value; +use ndc_parser::ResolvedVar; use std::cell::RefCell; use std::fmt; use std::fmt::Formatter; diff --git a/ndc_lib/src/interpreter/evaluate/index.rs b/ndc_lib/src/interpreter/evaluate/index.rs index 23acdc42..cb31813d 100644 --- a/ndc_lib/src/interpreter/evaluate/index.rs +++ b/ndc_lib/src/interpreter/evaluate/index.rs @@ -9,14 +9,12 @@ //! | Backward index | -10 | -9 | -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 | //! +----------------+-----+----+----+----+----+----+----+----+----+----+ -use ndc_parser::{Expression, ExpressionLocation}; use super::{EvaluationError, EvaluationResult, IntoEvaluationResult, evaluate_expression}; use crate::interpreter::environment::Environment; -use crate::{ - interpreter::{function::FunctionCarrier, sequence::Sequence, value::Value}, -}; +use crate::interpreter::{function::FunctionCarrier, sequence::Sequence, value::Value}; use itertools::Itertools; use ndc_lexer::Span; +use ndc_parser::{Expression, ExpressionLocation}; use std::cell::RefCell; use std::cmp::min; use std::ops::IndexMut; @@ -300,7 +298,11 @@ pub fn set_at_index( Offset::Range(from_usize, to_usize) => { let tail = list.drain(from_usize..).collect::>(); - list.extend(rhs.try_into_vec().expect("this must succeed, but not sure why").into_iter()); + list.extend( + rhs.try_into_vec() + .expect("this must succeed, but not sure why") + .into_iter(), + ); list.extend_from_slice(&tail[(to_usize - from_usize)..]); } diff --git a/ndc_lib/src/interpreter/evaluate/mod.rs b/ndc_lib/src/interpreter/evaluate/mod.rs index 7fdc973b..9a41c094 100644 --- a/ndc_lib/src/interpreter/evaluate/mod.rs +++ b/ndc_lib/src/interpreter/evaluate/mod.rs @@ -1,6 +1,3 @@ -use ndc_parser::{ - Binding, Expression, ExpressionLocation, ForBody, ForIteration, LogicalOperator, Lvalue, -}; use crate::hash_map::HashMap; use crate::interpreter::environment::Environment; use crate::interpreter::function::{Function, FunctionBody, FunctionCarrier, StaticType}; @@ -12,6 +9,9 @@ use crate::interpreter::value::Value; use index::{Offset, evaluate_as_index, get_at_index, set_at_index}; use itertools::Itertools; use ndc_lexer::Span; +use ndc_parser::{ + Binding, Expression, ExpressionLocation, ForBody, ForIteration, LogicalOperator, Lvalue, +}; use std::cell::RefCell; use std::fmt; use std::rc::Rc; diff --git a/ndc_lib/src/interpreter/function.rs b/ndc_lib/src/interpreter/function.rs index 47aea37e..a8e93a1a 100644 --- a/ndc_lib/src/interpreter/function.rs +++ b/ndc_lib/src/interpreter/function.rs @@ -1,4 +1,3 @@ -use ndc_parser::{ExpressionLocation, ResolvedVar}; use crate::hash_map::{DefaultHasher, HashMap}; use crate::interpreter::environment::Environment; use crate::interpreter::evaluate::{ @@ -9,6 +8,7 @@ use crate::interpreter::sequence::Sequence; use crate::interpreter::value::Value; use derive_builder::Builder; use ndc_lexer::Span; +use ndc_parser::{ExpressionLocation, ResolvedVar}; pub use ndc_parser::{Parameter, StaticType, TypeSignature}; use std::cell::{BorrowError, BorrowMutError, RefCell}; use std::fmt; diff --git a/ndc_lib/src/interpreter/mod.rs b/ndc_lib/src/interpreter/mod.rs index a106c4a2..61ab1875 100644 --- a/ndc_lib/src/interpreter/mod.rs +++ b/ndc_lib/src/interpreter/mod.rs @@ -1,13 +1,13 @@ use std::cell::RefCell; use std::rc::Rc; -use ndc_parser::ExpressionLocation; use crate::interpreter::environment::{Environment, InterpreterOutput}; use crate::interpreter::evaluate::{EvaluationError, evaluate_expression}; use crate::interpreter::function::FunctionCarrier; use crate::interpreter::semantic::analyser::{Analyser, ScopeTree}; use crate::interpreter::value::Value; use ndc_lexer::{Lexer, TokenLocation}; +use ndc_parser::ExpressionLocation; pub mod environment; pub mod evaluate; pub mod function; diff --git a/ndc_lib/src/interpreter/num.rs b/ndc_lib/src/interpreter/num.rs index ee211a4d..75cae747 100644 --- a/ndc_lib/src/interpreter/num.rs +++ b/ndc_lib/src/interpreter/num.rs @@ -4,11 +4,11 @@ use std::hash::{Hash, Hasher}; use std::num::TryFromIntError; use std::ops::{Add, Div, Mul, Neg, Not, Rem, Sub}; -use ndc_parser::BinaryOperator; use crate::interpreter::evaluate::EvaluationError; use crate::interpreter::function::StaticType; use crate::interpreter::int::Int; use ndc_lexer::Span; +use ndc_parser::BinaryOperator; use num::bigint::TryFromBigIntError; use num::complex::{Complex64, ComplexFloat}; use num::{BigInt, BigRational, Complex, FromPrimitive, Signed, ToPrimitive, Zero}; diff --git a/ndc_lib/src/interpreter/semantic/analyser.rs b/ndc_lib/src/interpreter/semantic/analyser.rs index 68704aa4..8d78ead7 100644 --- a/ndc_lib/src/interpreter/semantic/analyser.rs +++ b/ndc_lib/src/interpreter/semantic/analyser.rs @@ -1,9 +1,9 @@ -use ndc_parser::{ - Binding, Expression, ExpressionLocation, ForBody, ForIteration, Lvalue, ResolvedVar, -}; use crate::interpreter::function::StaticType; use itertools::Itertools; use ndc_lexer::Span; +use ndc_parser::{ + Binding, Expression, ExpressionLocation, ForBody, ForIteration, Lvalue, ResolvedVar, +}; use std::fmt::{Debug, Formatter}; pub struct Analyser { @@ -347,7 +347,13 @@ impl Analyser { self.scope_tree.new_scope(); // TODO: when we give type parameters to all instances of sequence we can correctly infer StaticType::Any in this position - self.resolve_lvalue_declarative(l_value, sequence_type.sequence_element_type().unwrap_or(StaticType::Any), span)?; + self.resolve_lvalue_declarative( + l_value, + sequence_type + .sequence_element_type() + .unwrap_or(StaticType::Any), + span, + )?; do_destroy = true; // TODO: why is this correct } ForIteration::Guard(expr) => { diff --git a/ndc_lsp/src/backend.rs b/ndc_lsp/src/backend.rs index 5fa0c96b..af6ff24e 100644 --- a/ndc_lsp/src/backend.rs +++ b/ndc_lsp/src/backend.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; use ndc_lexer::{Lexer, Span, TokenLocation}; -use ndc_parser::{Expression, ExpressionLocation, ForBody, ForIteration, Lvalue}; use ndc_lib::interpreter::Interpreter; +use ndc_parser::{Expression, ExpressionLocation, ForBody, ForIteration, Lvalue}; use ndc_stdlib::WithStdlib; use tokio::sync::Mutex; use tower_lsp::jsonrpc::Result as JsonRPCResult; diff --git a/ndc_macros/src/function.rs b/ndc_macros/src/function.rs index 7567909c..32ee9327 100644 --- a/ndc_macros/src/function.rs +++ b/ndc_macros/src/function.rs @@ -433,9 +433,15 @@ fn into_param_type(ty: &syn::Type) -> TokenStream { syn::Type::Reference(syn::TypeReference { elem, .. }) => into_param_type(elem), syn::Type::Path(syn::TypePath { path, .. }) => match path { _ if path.is_ident("i64") => quote! { ndc_lib::interpreter::function::StaticType::Int }, - _ if path.is_ident("usize") => quote! { ndc_lib::interpreter::function::StaticType::Int }, - _ if path.is_ident("f64") => quote! { ndc_lib::interpreter::function::StaticType::Float }, - _ if path.is_ident("bool") => quote! { ndc_lib::interpreter::function::StaticType::Bool }, + _ if path.is_ident("usize") => { + quote! { ndc_lib::interpreter::function::StaticType::Int } + } + _ if path.is_ident("f64") => { + quote! { ndc_lib::interpreter::function::StaticType::Float } + } + _ if path.is_ident("bool") => { + quote! { ndc_lib::interpreter::function::StaticType::Bool } + } _ if path.is_ident("Value") => { quote! { ndc_lib::interpreter::function::StaticType::Any } } diff --git a/ndc_stdlib/src/lib.rs b/ndc_stdlib/src/lib.rs index bf89f81f..41270177 100644 --- a/ndc_stdlib/src/lib.rs +++ b/ndc_stdlib/src/lib.rs @@ -1,5 +1,5 @@ -use ndc_lib::interpreter::environment::Environment; use ndc_lib::interpreter::Interpreter; +use ndc_lib::interpreter::environment::Environment; pub mod aoc; pub mod cmp; diff --git a/ndc_stdlib/src/list.rs b/ndc_stdlib/src/list.rs index 5fca0b70..f5d25483 100644 --- a/ndc_stdlib/src/list.rs +++ b/ndc_stdlib/src/list.rs @@ -1,9 +1,9 @@ #[ndc_macros::export_module] mod inner { + use itertools::Itertools; use ndc_lib::interpreter::iterator::mut_seq_to_iterator; use ndc_lib::interpreter::sequence::{ListRepr, Sequence}; use ndc_lib::interpreter::value::Value; - use itertools::Itertools; use std::rc::Rc; use anyhow::anyhow; diff --git a/ndc_stdlib/src/math.rs b/ndc_stdlib/src/math.rs index 1fd0a502..211fb1d1 100644 --- a/ndc_stdlib/src/math.rs +++ b/ndc_stdlib/src/math.rs @@ -1,8 +1,8 @@ +use factorial::Factorial; use ndc_lib::interpreter::environment::Environment; use ndc_lib::interpreter::num::{BinaryOperatorError, Number}; use ndc_lib::interpreter::sequence::Sequence; use ndc_lib::interpreter::value::Value; -use factorial::Factorial; use ndc_macros::export_module; use num::ToPrimitive; use std::ops::{Add, Mul}; @@ -52,9 +52,9 @@ mod inner { use std::ops::Sub; use super::FallibleSum; + use anyhow::Context; use ndc_lib::interpreter::int::Int; use ndc_lib::interpreter::num::Number; - use anyhow::Context; use num::{BigInt, BigRational, BigUint, Integer, complex::Complex64}; /// Returns the sign of a number. diff --git a/ndc_stdlib/src/rand.rs b/ndc_stdlib/src/rand.rs index 9bb043b1..66bb1ffd 100644 --- a/ndc_stdlib/src/rand.rs +++ b/ndc_stdlib/src/rand.rs @@ -19,11 +19,11 @@ pub fn random_n( #[export_module] mod inner { + use itertools::Itertools; use ndc_lib::interpreter::iterator::mut_seq_to_iterator; use ndc_lib::interpreter::num::Number; use ndc_lib::interpreter::sequence::Sequence; use ndc_lib::interpreter::value::Value; - use itertools::Itertools; /// Randomly shuffles the elements of the list in place. pub fn shuffle(list: &mut [Value]) { diff --git a/ndc_stdlib/src/sequence.rs b/ndc_stdlib/src/sequence.rs index b2efeafd..64d3f26e 100644 --- a/ndc_stdlib/src/sequence.rs +++ b/ndc_stdlib/src/sequence.rs @@ -1,13 +1,13 @@ #![allow(clippy::ptr_arg)] +use anyhow::anyhow; +use itertools::Itertools; use ndc_lib::interpreter::iterator::{MutableValueIntoIterator, mut_seq_to_iterator}; use ndc_lib::interpreter::sequence::Sequence; use ndc_lib::{ compare::FallibleOrd, interpreter::{evaluate::EvaluationResult, function::Callable, value::Value}, }; -use anyhow::anyhow; -use itertools::Itertools; use ndc_macros::export_module; use std::cmp::Ordering; use std::rc::Rc; diff --git a/ndc_stdlib/src/serde.rs b/ndc_stdlib/src/serde.rs index d095a0df..01939ee6 100644 --- a/ndc_stdlib/src/serde.rs +++ b/ndc_stdlib/src/serde.rs @@ -2,10 +2,10 @@ use ndc_macros::export_module; use std::rc::Rc; use std::{cell::RefCell, str::FromStr}; +use anyhow::Context; use ndc_lib::hash_map::HashMap; use ndc_lib::interpreter::sequence::Sequence; use ndc_lib::interpreter::value::Value; -use anyhow::Context; use num::BigInt; use num::ToPrimitive; use serde_json::{Map, Number, Value as JsonValue, json}; @@ -25,9 +25,7 @@ fn value_to_json(value: Value) -> Result { }, ndc_lib::interpreter::num::Number::Float(f) => Ok(json!(f)), ndc_lib::interpreter::num::Number::Rational(ratio) => Ok(json!(ratio.to_f64())), - ndc_lib::interpreter::num::Number::Complex(complex) => { - Ok(json!(format!("{complex}"))) - } + ndc_lib::interpreter::num::Number::Complex(complex) => Ok(json!(format!("{complex}"))), }, Value::Bool(b) => Ok(json!(b)), Value::Sequence(s) => match s { From e6184def9b94c8d199545c0d3c8247ad83dc5051 Mon Sep 17 00:00:00 2001 From: Tim Fennis Date: Mon, 2 Mar 2026 21:09:05 +0100 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=92=85=20minor=20style=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ndc_bin/src/docs.rs | 4 +++- ndc_lib/src/interpreter/value.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ndc_bin/src/docs.rs b/ndc_bin/src/docs.rs index 0e5e04d4..3cad915e 100644 --- a/ndc_bin/src/docs.rs +++ b/ndc_bin/src/docs.rs @@ -14,7 +14,9 @@ fn string_match(needle: &str, haystack: &str) -> bool { } pub fn docs(query: Option<&str>) -> anyhow::Result<()> { - let interpreter = Interpreter::new(Vec::new()).with_stdlib(); // Discard the output + let interpreter = Interpreter::new(Vec::new()) // Discard the output + .with_stdlib(); + let functions = interpreter.environment().borrow().get_all_functions(); let matched_functions = functions diff --git a/ndc_lib/src/interpreter/value.rs b/ndc_lib/src/interpreter/value.rs index 2d871737..451b50de 100644 --- a/ndc_lib/src/interpreter/value.rs +++ b/ndc_lib/src/interpreter/value.rs @@ -93,7 +93,7 @@ impl Value { } Self::Sequence(Sequence::String(string)) => match Rc::try_unwrap(string) { // This implementation is peak retard, we don't want collect_vec here - // ^-- WTF: is this comment, we collect_vec here anyways? + // ^-- WTF: is this comment, we collect_vec here anyway? Ok(string) => Some(string.into_inner().chars().map(Self::from).collect_vec()), Err(string) => Some(string.borrow().chars().map(Self::from).collect_vec()), },