diff --git a/src/bin/orcx.rs b/src/bin/orcx.rs index 2fa1289..fd922f6 100644 --- a/src/bin/orcx.rs +++ b/src/bin/orcx.rs @@ -8,7 +8,6 @@ use std::process; use clap::Parser; use itertools::Itertools; use orchidlang::facade::{Environment, PreMacro}; -use orchidlang::interner::InternedDisplay; use orchidlang::systems::stl::StlConfig; use orchidlang::systems::{io_system, AsynchConfig, IOStream}; use orchidlang::{ast, interpreted, interpreter, Interner, Sym, VName}; @@ -70,36 +69,34 @@ pub fn to_vname(data: &str, i: &Interner) -> VName { data.split("::").map(|s| i.i(s)).collect::>() } -fn print_for_debug(e: &ast::Expr, i: &Interner) { +fn print_for_debug(e: &ast::Expr) { print!( "code: {}\nglossary: {}", - e.bundle(i), + e, (e.value.collect_names().into_iter()) - .map(|t| i.extern_vec(t).join("::")) + .map(|t| t.iter().join("::")) .join(", ") ) } /// A little utility to step through the resolution of a macro set -pub fn macro_debug(premacro: PreMacro, sym: Sym, i: &Interner) { +pub fn macro_debug(premacro: PreMacro, sym: Sym) { let (mut code, location) = (premacro.consts.get(&sym)) .unwrap_or_else(|| { panic!( "Symbol {} not found\nvalid symbols: \n\t{}\n", - i.extern_vec(sym).join("::"), - (premacro.consts.keys()) - .map(|t| i.extern_vec(*t).join("::")) - .join("\n\t") + sym.iter().join("::"), + (premacro.consts.keys()).map(|t| t.iter().join("::")).join("\n\t") ) }) .clone(); println!( "Debugging macros in {} defined at {}. Initial state: ", - i.extern_vec(sym).join("::"), + sym.iter().join("::"), location ); - print_for_debug(&code, i); + print_for_debug(&code); let mut steps = premacro.step(sym).enumerate(); loop { let (cmd, _) = cmd_prompt("\ncmd> ").unwrap(); @@ -108,12 +105,12 @@ pub fn macro_debug(premacro: PreMacro, sym: Sym, i: &Interner) { if let Some((idx, c)) = steps.next() { code = c; print!("Step {idx}: "); - print_for_debug(&code, i); + print_for_debug(&code); } else { print!("Halted") }, - "p" | "print" => print_for_debug(&code, i), - "d" | "dump" => print!("Rules: {}", premacro.repo.bundle(i)), + "p" | "print" => print_for_debug(&code), + "d" | "dump" => print!("Rules: {}", premacro.repo), "q" | "quit" => return, "h" | "help" => print!( "Available commands: @@ -146,22 +143,22 @@ pub fn main() { .add_system(StlConfig { impure: true }) .add_system(asynch) .add_system(io); - let premacro = i.unwrap(env.load_dir(&dir, &main)); + let premacro = env.load_dir(&dir, &main).unwrap(); if args.dump_repo { - println!("Parsed rules: {}", premacro.repo.bundle(&i)); + println!("Parsed rules: {}", premacro.repo); return; } if !args.macro_debug.is_empty() { let sym = i.i(&to_vname(&args.macro_debug, &i)); - return macro_debug(premacro, sym, &i); + return macro_debug(premacro, sym); } - let mut proc = i.unwrap(premacro.build_process(Some(args.macro_limit))); + let mut proc = premacro.build_process(Some(args.macro_limit)).unwrap(); let main = interpreted::Clause::Constant(i.i(&main)).wrap(); - let ret = i.unwrap(proc.run(main, None)); + let ret = proc.run(main, None).unwrap(); let interpreter::Return { gas, state, inert } = ret; drop(proc); if inert { - println!("Settled at {}", state.expr().clause.bundle(&i)); + println!("Settled at {}", state.expr().clause); if let Some(g) = gas { println!("Remaining gas: {g}") } diff --git a/src/error/import_all.rs b/src/error/import_all.rs index a3f87c6..6dd344b 100644 --- a/src/error/import_all.rs +++ b/src/error/import_all.rs @@ -1,8 +1,10 @@ use std::rc::Rc; +use itertools::Itertools; + use super::ProjectError; use crate::representations::location::Location; -use crate::{Interner, VName}; +use crate::VName; /// Error produced for the statement `import *` #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -16,11 +18,11 @@ impl ProjectError for ImportAll { fn description(&self) -> &str { "a top-level glob import was used" } - fn message(&self, i: &Interner) -> String { - format!("{} imports *", i.extern_all(&self.offender_mod).join("::")) + fn message(&self) -> String { + format!("{} imports *", self.offender_mod.iter().join("::")) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { Location::File(self.offender_file.clone()) } } diff --git a/src/error/no_targets.rs b/src/error/no_targets.rs index 836deff..3b98dca 100644 --- a/src/error/no_targets.rs +++ b/src/error/no_targets.rs @@ -3,7 +3,6 @@ use super::{ErrorPosition, ProjectError}; use crate::parse_layer; use crate::utils::iter::box_empty; use crate::utils::BoxedIter; -use crate::Interner; /// Error produced when [parse_layer] is called without targets. This function /// produces an error instead of returning a straightforward empty tree because @@ -17,7 +16,7 @@ impl ProjectError for NoTargets { "No targets were specified for layer parsing" } - fn positions(&self, _i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { box_empty() } } diff --git a/src/error/not_exported.rs b/src/error/not_exported.rs index 6d2587a..007366e 100644 --- a/src/error/not_exported.rs +++ b/src/error/not_exported.rs @@ -21,21 +21,23 @@ impl ProjectError for NotExported { fn description(&self) -> &str { "An import refers to a symbol that exists but isn't exported" } - fn positions(&self, i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { Box::new( [ ErrorPosition { - location: Location::File(Rc::new(i.extern_all(&self.file))), + location: Location::File(Rc::new(Interner::extern_all(&self.file))), message: Some(format!( "{} isn't exported", - i.extern_all(&self.subpath).join("::") + Interner::extern_all(&self.subpath).join("::") )), }, ErrorPosition { - location: Location::File(Rc::new(i.extern_all(&self.referrer_file))), + location: Location::File(Rc::new(Interner::extern_all( + &self.referrer_file, + ))), message: Some(format!( "{} cannot see this symbol", - i.extern_all(&self.referrer_subpath).join("::") + Interner::extern_all(&self.referrer_subpath).join("::") )), }, ] diff --git a/src/error/not_found.rs b/src/error/not_found.rs index 758dafe..d335959 100644 --- a/src/error/not_found.rs +++ b/src/error/not_found.rs @@ -37,7 +37,7 @@ impl NotFound { ) -> Self { let last_mod = orig.walk_ref(&path[..e.pos], false).expect("error occured on next step"); - let mut whole_path = prefix.iter().chain(path.iter()).copied(); + let mut whole_path = prefix.iter().chain(path.iter()).cloned(); if let Some(file) = &last_mod.extra.file { Self { source: Some(source.to_vec()), @@ -57,14 +57,14 @@ impl ProjectError for NotFound { fn description(&self) -> &str { "an import refers to a nonexistent module" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "module {} in {} was not found", - i.extern_all(&self.subpath).join("::"), - i.extern_all(&self.file).join("/"), + Interner::extern_all(&self.subpath).join("::"), + Interner::extern_all(&self.file).join("/"), ) } - fn one_position(&self, i: &Interner) -> crate::Location { - Location::File(Rc::new(i.extern_all(&self.file))) + fn one_position(&self) -> crate::Location { + Location::File(Rc::new(Interner::extern_all(&self.file))) } } diff --git a/src/error/parse_error_with_tokens.rs b/src/error/parse_error_with_tokens.rs index 044bca6..55525f5 100644 --- a/src/error/parse_error_with_tokens.rs +++ b/src/error/parse_error_with_tokens.rs @@ -3,10 +3,8 @@ use std::rc::Rc; use itertools::Itertools; use super::{ErrorPosition, ProjectError}; -use crate::interner::InternedDisplay; use crate::parse::Entry; use crate::utils::BoxedIter; -use crate::Interner; /// Produced by stages that parse text when it fails. pub struct ParseErrorWithTokens { @@ -21,14 +19,14 @@ impl ProjectError for ParseErrorWithTokens { fn description(&self) -> &str { self.error.description() } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "Failed to parse code: {}\nTokenized source for context:\n{}", - self.error.message(i), - self.tokens.iter().map(|t| t.to_string_i(i)).join(" "), + self.error.message(), + self.tokens.iter().map(|t| t.to_string()).join(" "), ) } - fn positions(&self, i: &Interner) -> BoxedIter { - self.error.positions(i) + fn positions(&self) -> BoxedIter { + self.error.positions() } } diff --git a/src/error/project_error.rs b/src/error/project_error.rs index 0f5a235..bfb4a46 100644 --- a/src/error/project_error.rs +++ b/src/error/project_error.rs @@ -1,10 +1,10 @@ +use std::fmt::Debug; +use std::fmt::Display; use std::rc::Rc; -use crate::interner::InternedDisplay; use crate::representations::location::Location; use crate::utils::iter::box_once; use crate::utils::BoxedIter; -use crate::Interner; /// A point of interest in resolving the error, such as the point where /// processing got stuck, a command that is likely to be incorrect @@ -21,17 +21,17 @@ pub trait ProjectError { /// A general description of this type of error fn description(&self) -> &str; /// A formatted message that includes specific parameters - fn message(&self, _i: &Interner) -> String { + fn message(&self) -> String { self.description().to_string() } /// Code positions relevant to this error. If you don't implement this, you /// must implement [ProjectError::one_position] - fn positions(&self, i: &Interner) -> BoxedIter { - box_once(ErrorPosition { location: self.one_position(i), message: None }) + fn positions(&self) -> BoxedIter { + box_once(ErrorPosition { location: self.one_position(), message: None }) } /// Short way to provide a single location. If you don't implement this, you /// must implement [ProjectError::positions] - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { unimplemented!() } /// Convert the error into an `Rc` to be able to @@ -44,15 +44,11 @@ pub trait ProjectError { } } -impl InternedDisplay for dyn ProjectError { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { +impl Display for dyn ProjectError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let description = self.description(); - let message = self.message(i); - let positions = self.positions(i); + let message = self.message(); + let positions = self.positions(); writeln!(f, "Project error: {description}\n{message}")?; for ErrorPosition { location, message } in positions { writeln!( @@ -65,6 +61,12 @@ impl InternedDisplay for dyn ProjectError { } } +impl Debug for dyn ProjectError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{self}") + } +} + /// Alias for a result with an error of [Rc] of [ProjectError] trait object. /// This is the type of result most commonly returned by pre-run operations. pub type ProjectResult = Result>; diff --git a/src/error/too_many_supers.rs b/src/error/too_many_supers.rs index 9c1d67e..c87ee0d 100644 --- a/src/error/too_many_supers.rs +++ b/src/error/too_many_supers.rs @@ -20,15 +20,15 @@ impl ProjectError for TooManySupers { "an import path starts with more `super` segments than the current \ module's absolute path" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "path {} in {} contains too many `super` steps.", - i.extern_all(&self.path).join("::"), - i.extern_all(&self.offender_mod).join("::") + Interner::extern_all(&self.path).join("::"), + Interner::extern_all(&self.offender_mod).join("::") ) } - fn one_position(&self, i: &Interner) -> Location { - Location::File(Rc::new(i.extern_all(&self.offender_file))) + fn one_position(&self) -> Location { + Location::File(Rc::new(Interner::extern_all(&self.offender_file))) } } diff --git a/src/error/unexpected_directory.rs b/src/error/unexpected_directory.rs index 9251fdc..637f5b5 100644 --- a/src/error/unexpected_directory.rs +++ b/src/error/unexpected_directory.rs @@ -15,14 +15,14 @@ impl ProjectError for UnexpectedDirectory { "A stage that deals specifically with code encountered a path that refers \ to a directory" } - fn one_position(&self, i: &Interner) -> crate::Location { - Location::File(Rc::new(i.extern_all(&self.path))) + fn one_position(&self) -> crate::Location { + Location::File(Rc::new(Interner::extern_all(&self.path))) } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "{} was expected to be a file but a directory was found", - i.extern_all(&self.path).join("/") + Interner::extern_all(&self.path).join("/") ) } } diff --git a/src/error/visibility_mismatch.rs b/src/error/visibility_mismatch.rs index cf6f913..04b8caf 100644 --- a/src/error/visibility_mismatch.rs +++ b/src/error/visibility_mismatch.rs @@ -16,13 +16,13 @@ impl ProjectError for VisibilityMismatch { fn description(&self) -> &str { "Some occurences of a namespace are exported but others are not" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "{} is opened multiple times with different visibilities", - i.extern_all(&self.namespace).join("::") + Interner::extern_all(&self.namespace).join("::") ) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { Location::File(self.file.clone()) } } diff --git a/src/facade/environment.rs b/src/facade/environment.rs index 72402b5..9059740 100644 --- a/src/facade/environment.rs +++ b/src/facade/environment.rs @@ -65,7 +65,7 @@ impl<'a> Environment<'a> { ) -> ProjectResult> { let i = self.i; let CompiledEnv { prelude, systems, tree } = self.compile()?; - let file_cache = file_loader::mk_dir_cache(dir.to_path_buf(), i); + let file_cache = file_loader::mk_dir_cache(dir.to_path_buf()); let vname_tree = parse_layer( iter::once(target), &|path| file_cache.find(path), diff --git a/src/facade/pre_macro.rs b/src/facade/pre_macro.rs index 4da51d2..b4438a1 100644 --- a/src/facade/pre_macro.rs +++ b/src/facade/pre_macro.rs @@ -42,11 +42,12 @@ impl<'a> PreMacro<'a> { repo, consts: (consts.into_iter()) .map(|(name, expr)| { - let location = (i.r(name).split_last()) + let location = (name.split_last()) .and_then(|(_, path)| { let origin = (tree.0.walk_ref(path, false)) .expect("path sourced from symbol names"); - origin.extra.file.as_ref().map(|path| i.extern_all(&path[..])) + (origin.extra.file.as_ref()) + .map(|path| Interner::extern_all(&path[..])) }) .map(|p| Location::File(Rc::new(p))) .unwrap_or(Location::Unknown); @@ -73,7 +74,7 @@ impl<'a> PreMacro<'a> { return Err( MacroTimeout { location: source_location.clone(), - symbol: *name, + symbol: name.clone(), limit, } .rc(), @@ -85,7 +86,7 @@ impl<'a> PreMacro<'a> { repo.pass(source).unwrap_or_else(|| source.clone()) }; let runtree = ast_to_interpreted(&unmatched).map_err(|e| e.rc())?; - symbols.insert(*name, runtree); + symbols.insert(name.clone(), runtree); } Ok(Process { symbols, @@ -118,15 +119,15 @@ impl ProjectError for MacroTimeout { "Macro execution has not halted" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "Macro execution during the processing of {} took more than {} steps", - i.extern_vec(self.symbol).join("::"), + self.symbol.extern_vec().join("::"), self.limit ) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } diff --git a/src/facade/process.rs b/src/facade/process.rs index 4e68bfe..41fee33 100644 --- a/src/facade/process.rs +++ b/src/facade/process.rs @@ -38,9 +38,9 @@ impl<'a> Process<'a> { let sym = self.symbols.get(&key).expect("symbol must exist"); sym.search_all(&mut |s: &ExprInst| { let expr = s.expr(); - if let interpreted::Clause::Constant(sym) = expr.clause { - if !self.symbols.contains_key(&sym) { - errors.push((sym, expr.location.clone())) + if let interpreted::Clause::Constant(sym) = &expr.clause { + if !self.symbols.contains_key(sym) { + errors.push((sym.clone(), expr.location.clone())) } } None::<()> @@ -53,8 +53,10 @@ impl<'a> Process<'a> { /// produced pub fn validate_refs(&self) -> ProjectResult<()> { for key in self.symbols.keys() { - if let Some((symbol, location)) = self.unbound_refs(*key).pop() { - return Err(MissingSymbol { location, referrer: *key, symbol }.rc()); + if let Some((symbol, location)) = self.unbound_refs(key.clone()).pop() { + return Err( + MissingSymbol { location, referrer: key.clone(), symbol }.rc(), + ); } } Ok(()) @@ -74,15 +76,15 @@ impl ProjectError for MissingSymbol { that macro execution didn't correctly halt." } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "The symbol {} referenced in {} does not exist", - i.extern_vec(self.symbol).join("::"), - i.extern_vec(self.referrer).join("::") + self.symbol.extern_vec().join("::"), + self.referrer.extern_vec().join("::") ) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } diff --git a/src/facade/system.rs b/src/facade/system.rs index c2263c8..9db03c0 100644 --- a/src/facade/system.rs +++ b/src/facade/system.rs @@ -52,14 +52,14 @@ impl ProjectError for MissingSystemCode { fn description(&self) -> &str { "A system tried to import a path that doesn't exist" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "Path {} is not defined by {} or any system before it", - i.extern_all(&self.path).join("::"), + Interner::extern_all(&self.path).join("::"), self.system.join("::") ) } - fn positions(&self, _i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { box_empty() } } diff --git a/src/foreign/cps_box.rs b/src/foreign/cps_box.rs index de2a358..6607a19 100644 --- a/src/foreign/cps_box.rs +++ b/src/foreign/cps_box.rs @@ -108,7 +108,7 @@ impl Atomic for CPSBox { } /// Like [init_cps] but wrapped in a [ConstTree] for init-time usage -pub fn mk_const(argc: usize, payload: T) -> ConstTree { +pub fn const_cps(argc: usize, payload: T) -> ConstTree { ConstTree::xfn(CPSFn::new(argc, payload)) } diff --git a/src/interner/mod.rs b/src/interner/mod.rs index 5b86a87..6e276e1 100644 --- a/src/interner/mod.rs +++ b/src/interner/mod.rs @@ -5,9 +5,9 @@ mod monotype; mod multitype; mod token; -mod traits; +// mod traits; pub use monotype::TypedInterner; pub use multitype::Interner; pub use token::Tok; -pub use traits::{DisplayBundle, InternedDisplay, InternedInto}; +// pub use traits::{DisplayBundle, InternedDisplay, InternedInto}; diff --git a/src/interner/monotype.rs b/src/interner/monotype.rs index 535c1a0..1524621 100644 --- a/src/interner/monotype.rs +++ b/src/interner/monotype.rs @@ -1,7 +1,7 @@ use std::borrow::Borrow; use std::cell::RefCell; use std::hash::{BuildHasher, Hash}; -use std::num::NonZeroU32; +use std::rc::Rc; use hashbrown::HashMap; @@ -11,20 +11,19 @@ use super::token::Tok; /// Lasso but much simpler, in part because not much can be known about the /// type. pub struct TypedInterner { - tokens: RefCell>>, - values: RefCell>, + tokens: RefCell, Tok>>, } impl TypedInterner { /// Create a fresh interner instance - pub fn new() -> Self { - Self { - tokens: RefCell::new(HashMap::new()), - values: RefCell::new(Vec::new()), - } + pub fn new() -> Rc { + Rc::new(Self { tokens: RefCell::new(HashMap::new()) }) } /// Intern an object, returning a token - pub fn i>(&self, q: &Q) -> Tok + pub fn i>( + self: &Rc, + q: &Q, + ) -> Tok where T: Borrow, { @@ -34,65 +33,11 @@ impl TypedInterner { .raw_entry_mut() .from_hash(hash, |k| >::borrow(k) == q); let kv = raw_entry.or_insert_with(|| { - let mut values = self.values.borrow_mut(); - let uniq_key: NonZeroU32 = - (values.len() as u32 + 1u32).try_into().expect("can never be zero"); - let keybox = Box::new(q.to_owned()); - let keyref = Box::leak(keybox); - values.push((keyref, true)); - let token = Tok::::from_id(uniq_key); - (keyref, token) + let keyrc = Rc::new(q.to_owned()); + let token = Tok::::new(keyrc.clone(), Rc::downgrade(self)); + (keyrc, token) }); - *kv.1 - } - - /// Resolve a token, obtaining a reference to the held object. - /// It is illegal to use a token obtained from one interner with - /// another. - pub fn r(&self, t: Tok) -> &T { - let values = self.values.borrow(); - let key = t.into_usize() - 1; - values[key].0.borrow() - } - - /// Intern a static reference without allocating the data on the heap - #[allow(unused)] - pub fn intern_static(&self, tref: &'static T) -> Tok { - let mut tokens = self.tokens.borrow_mut(); - let token = *tokens - .raw_entry_mut() - .from_key(tref) - .or_insert_with(|| { - let mut values = self.values.borrow_mut(); - let uniq_key: NonZeroU32 = - (values.len() as u32 + 1u32).try_into().expect("can never be zero"); - values.push((tref, false)); - let token = Tok::::from_id(uniq_key); - (tref, token) - }) - .1; - token - } -} - -impl Default for TypedInterner { - fn default() -> Self { - Self::new() - } -} - -impl Drop for TypedInterner { - fn drop(&mut self) { - // make sure all values leaked by us are dropped - // FIXME: with the new hashmap logic we can actually store Rc-s - // which negates the need for unsafe here - let mut values = self.values.borrow_mut(); - for (item, owned) in values.drain(..) { - if !owned { - continue; - } - let _ = unsafe { Box::from_raw((item as *const T).cast_mut()) }; - } + kv.1.clone() } } diff --git a/src/interner/multitype.rs b/src/interner/multitype.rs index 1885b9f..e43446b 100644 --- a/src/interner/multitype.rs +++ b/src/interner/multitype.rs @@ -8,7 +8,7 @@ use hashbrown::HashMap; use super::monotype::TypedInterner; use super::token::Tok; -use super::InternedDisplay; +// use super::InternedDisplay; /// A collection of interners based on their type. Allows to intern any object /// that implements [ToOwned]. Objects of the same type are stored together in a @@ -32,57 +32,33 @@ impl Interner { interner.i(q) } - /// Resolve a token to a reference - pub fn r(&self, t: Tok) -> &T { - let mut interners = self.interners.borrow_mut(); - let interner = get_interner(&mut interners); - // TODO: figure this out - unsafe { (interner.r(t) as *const T).as_ref().unwrap() } - } - - /// Fully resolve an interned list of interned things - /// TODO: make this generic over containers - pub fn extern_vec( - &self, - t: Tok>>, - ) -> Vec { - let mut interners = self.interners.borrow_mut(); - let v_int = get_interner(&mut interners); - let t_int = get_interner(&mut interners); - let v = v_int.r(t); - v.iter().map(|t| t_int.r(*t)).cloned().collect() - } - /// Fully resolve a list of interned things. - pub fn extern_all( - &self, - s: &[Tok], - ) -> Vec { - s.iter().map(|t| self.r(*t)).cloned().collect() + pub fn extern_all(s: &[Tok]) -> Vec { + s.iter().map(|t| (**t).clone()).collect() } - /// A variant of `unwrap` using [InternedDisplay] to circumvent `unwrap`'s - /// dependencyon [Debug]. For clarity, [expect] should be preferred. - pub fn unwrap(&self, result: Result) -> T { - result.unwrap_or_else(|e| { - println!("Unwrapped Error: {}", e.bundle(self)); - panic!("Unwrapped an error"); - }) - } + // /// A variant of `unwrap` using [InternedDisplay] to circumvent `unwrap`'s + // /// dependencyon [Debug]. For clarity, [expect] should be preferred. + // pub fn unwrap(&self, result: Result) -> T { + // result.unwrap_or_else(|e| { + // println!("Unwrapped Error: {}", e.bundle(self)); + // panic!("Unwrapped an error"); + // }) + // } - /// A variant of `expect` using [InternedDisplay] to circumvent `expect`'s - /// depeendency on [Debug]. - pub fn expect( - &self, - result: Result, - msg: &str, - ) -> T { - result.unwrap_or_else(|e| { - println!("Expectation failed: {msg}"); - println!("Error: {}", e.bundle(self)); - panic!("Expected an error"); - }) - } + // /// A variant of `expect` using [InternedDisplay] to circumvent `expect`'s + // /// depeendency on [Debug]. + // pub fn expect( + // &self, + // result: Result, + // msg: &str, + // ) -> T { + // result.unwrap_or_else(|e| { + // println!("Expectation failed: {msg}"); + // println!("Error: {}", e.bundle(self)); + // panic!("Expected an error"); + // }) + // } } impl Default for Interner { @@ -98,7 +74,7 @@ fn get_interner( let boxed = interners .raw_entry_mut() .from_key(&TypeId::of::()) - .or_insert_with(|| (TypeId::of::(), Rc::new(TypedInterner::::new()))) + .or_insert_with(|| (TypeId::of::(), TypedInterner::::new())) .1 .clone(); boxed.downcast().expect("the typeid is supposed to protect from this") diff --git a/src/interner/token.rs b/src/interner/token.rs index 8ff7c11..05652b1 100644 --- a/src/interner/token.rs +++ b/src/interner/token.rs @@ -1,66 +1,94 @@ use std::cmp::PartialEq; -use std::fmt::Debug; +use std::fmt::{Debug, Display}; use std::hash::Hash; -use std::marker::PhantomData; -use std::num::NonZeroU32; +use std::num::NonZeroUsize; +use std::ops::Deref; +use std::rc::{Rc, Weak}; + +use super::TypedInterner; /// A number representing an object of type `T` stored in some interner. It is a /// logic error to compare tokens obtained from different interners, or to use a /// token with an interner other than the one that created it, but this is /// currently not enforced. -pub struct Tok { - id: NonZeroU32, - phantom_data: PhantomData, +#[derive(Clone)] +pub struct Tok { + data: Rc, + interner: Weak>, } -impl Tok { - /// Wrap an ID number into a token - pub fn from_id(id: NonZeroU32) -> Self { - Self { id, phantom_data: PhantomData } +impl Tok { + /// Create a new token. Used exclusively by the interner + pub(crate) fn new(data: Rc, interner: Weak>) -> Self { + Self { data, interner } } /// Take the ID number out of a token - pub fn into_id(self) -> NonZeroU32 { - self.id + pub fn id(&self) -> NonZeroUsize { + ((self.data.as_ref() as *const T as usize).try_into()) + .expect("Pointer can always be cast to nonzero") } /// Cast into usize - pub fn into_usize(self) -> usize { - let zero: u32 = self.id.into(); - zero as usize + pub fn usize(&self) -> usize { + self.id().into() + } + /// + pub fn assert_comparable(&self, other: &Self) { + let iref = self.interner.as_ptr() as usize; + assert!( + iref == other.interner.as_ptr() as usize, + "Tokens must come from the same interner" + ); + } +} + +impl Tok>> { + /// Extern all elements of the vector in a new vector + pub fn extern_vec(&self) -> Vec { + self.iter().map(|t| (**t).clone()).collect() } } -impl Debug for Tok { +impl Deref for Tok { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.data.as_ref() + } +} + +impl Debug for Tok { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Token({})", self.id) + write!(f, "Token({})", self.id()) } } -impl Copy for Tok {} -impl Clone for Tok { - fn clone(&self) -> Self { - Self { id: self.id, phantom_data: PhantomData } +impl Display for Tok { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", *self) } } -impl Eq for Tok {} -impl PartialEq for Tok { +impl Eq for Tok {} +impl PartialEq for Tok { fn eq(&self, other: &Self) -> bool { - self.id == other.id + self.assert_comparable(other); + self.id() == other.id() } } -impl Ord for Tok { +impl Ord for Tok { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.id.cmp(&other.id) + self.assert_comparable(other); + self.id().cmp(&other.id()) } } -impl PartialOrd for Tok { +impl PartialOrd for Tok { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Hash for Tok { +impl Hash for Tok { fn hash(&self, state: &mut H) { - state.write_u32(self.id.into()) + state.write_usize(self.usize()) } } diff --git a/src/interpreter/apply.rs b/src/interpreter/apply.rs index f5df076..8d16c91 100644 --- a/src/interpreter/apply.rs +++ b/src/interpreter/apply.rs @@ -108,7 +108,7 @@ pub fn apply( if let Some(sym) = ctx.symbols.get(name) { Ok((Clause::Apply { f: sym.clone(), x }, (ctx.gas, false))) } else { - Err(RuntimeError::MissingSymbol(*name, loc.clone())) + Err(RuntimeError::MissingSymbol(name.clone(), loc.clone())) }, Clause::P(Primitive::Atom(atom)) => { // take a step in expanding atom diff --git a/src/interpreter/error.rs b/src/interpreter/error.rs index 3066297..27fe8e2 100644 --- a/src/interpreter/error.rs +++ b/src/interpreter/error.rs @@ -1,7 +1,7 @@ +use std::fmt::Display; use std::rc::Rc; use crate::foreign::ExternError; -use crate::interner::InternedDisplay; use crate::representations::interpreted::ExprInst; use crate::{Location, Sym}; @@ -22,12 +22,8 @@ impl From> for RuntimeError { } } -impl InternedDisplay for RuntimeError { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &crate::Interner, - ) -> std::fmt::Result { +impl Display for RuntimeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Extern(e) => write!(f, "Error in external function: {e}"), Self::NonFunctionApplication(expr) => { @@ -37,7 +33,7 @@ impl InternedDisplay for RuntimeError { write!( f, "{}, called at {loc} is not loaded", - i.extern_vec(*sym).join("::") + sym.extern_vec().join("::") ) }, } diff --git a/src/interpreter/run.rs b/src/interpreter/run.rs index e48f1c7..5664d68 100644 --- a/src/interpreter/run.rs +++ b/src/interpreter/run.rs @@ -30,8 +30,9 @@ pub fn run(expr: ExprInst, mut ctx: Context) -> Result { i = clause.clone(); }, Clause::Constant(c) => { - let symval = (ctx.symbols.get(c)) - .ok_or_else(|| RuntimeError::MissingSymbol(*c, loc.clone()))?; + let symval = (ctx.symbols.get(c)).ok_or_else(|| { + RuntimeError::MissingSymbol(c.clone(), loc.clone()) + })?; ctx.gas = ctx.gas.map(|g| g - 1); // cost of lookup i = symval.expr().clause.clone(); }, diff --git a/src/parse/errors.rs b/src/parse/errors.rs index fbab4a1..c0dceb2 100644 --- a/src/parse/errors.rs +++ b/src/parse/errors.rs @@ -5,9 +5,8 @@ use itertools::Itertools; use super::{Entry, Lexeme}; use crate::error::{ErrorPosition, ProjectError}; -use crate::interner::InternedDisplay; use crate::utils::BoxedIter; -use crate::{Interner, Location, Tok}; +use crate::{Location, Tok}; #[derive(Debug)] pub struct LineNeedsPrefix { @@ -17,10 +16,10 @@ impl ProjectError for LineNeedsPrefix { fn description(&self) -> &str { "This linetype requires a prefix" } - fn message(&self, i: &Interner) -> String { - format!("{} cannot appear at the beginning of a line", self.entry.bundle(i)) + fn message(&self) -> String { + format!("{} cannot appear at the beginning of a line", self.entry) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.entry.location() } } @@ -35,13 +34,13 @@ impl ProjectError for UnexpectedEOL { "The line ended abruptly" } - fn message(&self, _i: &Interner) -> String { + fn message(&self) -> String { "The line ends unexpectedly here. In Orchid, all line breaks outside \ parentheses start a new declaration" .to_string() } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.entry.location() } } @@ -53,7 +52,7 @@ impl ProjectError for ExpectedEOL { fn description(&self) -> &str { "Expected the end of the line" } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } @@ -64,8 +63,8 @@ pub struct ExpectedName { } impl ExpectedName { pub fn expect(entry: &Entry) -> Result, Rc> { - match entry.lexeme { - Lexeme::Name(n) => Ok(n), + match &entry.lexeme { + Lexeme::Name(n) => Ok(n.clone()), _ => Err(Self { entry: entry.clone() }.rc()), } } @@ -75,18 +74,18 @@ impl ProjectError for ExpectedName { "A name was expected here, but something else was found" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { if self.entry.is_keyword() { format!( "{} is a restricted keyword and cannot be used as a name", - self.entry.bundle(i) + self.entry ) } else { - format!("Expected a name, found {}", self.entry.bundle(i)) + format!("Expected a name, found {}", self.entry) } } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.entry.location() } } @@ -111,22 +110,19 @@ impl ProjectError for Expected { fn description(&self) -> &str { "A concrete token was expected but something else was found" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { let list = match &self.expected[..] { &[] => return "Unsatisfiable expectation".to_string(), - [only] => only.to_string_i(i), - [a, b] => format!("either {} or {}", a.bundle(i), b.bundle(i)), - [variants @ .., last] => format!( - "any of {} or {}", - variants.iter().map(|l| l.to_string_i(i)).join(", "), - last.bundle(i) - ), + [only] => only.to_string(), + [a, b] => format!("either {a} or {b}"), + [variants @ .., last] => + format!("any of {} or {last}", variants.iter().join(", ")), }; let or_name = if self.or_name { " or a name" } else { "" }; - format!("Expected {}{} but found {}", list, or_name, self.found.bundle(i)) + format!("Expected {list}{or_name} but found {}", self.found) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.found.location() } } @@ -139,11 +135,11 @@ impl ProjectError for ReservedToken { "A token reserved for future use was found in the code" } - fn message(&self, i: &Interner) -> String { - format!("{} is a reserved token", self.entry.bundle(i)) + fn message(&self) -> String { + format!("{} is a reserved token", self.entry) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.entry.location() } } @@ -157,11 +153,11 @@ impl ProjectError for BadTokenInRegion { "A token was found in a region where it should not appear" } - fn message(&self, i: &Interner) -> String { - format!("{} cannot appear in {}", self.entry.bundle(i), self.region) + fn message(&self) -> String { + format!("{} cannot appear in {}", self.entry, self.region) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.entry.location() } } @@ -175,11 +171,11 @@ impl ProjectError for NotFound { "A specific lexeme was expected but not found in the given range" } - fn message(&self, _i: &Interner) -> String { + fn message(&self) -> String { format!("{} was expected", self.expected) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } @@ -191,7 +187,7 @@ impl ProjectError for LeadingNS { fn description(&self) -> &str { ":: can only follow a name token" } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } @@ -203,10 +199,10 @@ impl ProjectError for MisalignedParen { fn description(&self) -> &str { "Parentheses (), [] and {} must always pair up" } - fn message(&self, i: &Interner) -> String { - format!("This {} has no pair", self.entry.bundle(i)) + fn message(&self) -> String { + format!("This {} has no pair", self.entry) } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.entry.location() } } @@ -218,7 +214,7 @@ impl ProjectError for NamespacedExport { fn description(&self) -> &str { "Exports can only refer to unnamespaced names in the local namespace" } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } @@ -230,7 +226,7 @@ impl ProjectError for GlobExport { fn description(&self) -> &str { "Exports can only refer to concrete names, globstars are not allowed" } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } @@ -244,7 +240,7 @@ impl ProjectError for LexError { fn description(&self) -> &str { "An error occured during tokenization" } - fn positions(&self, _i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { let file = self.file.clone(); Box::new(self.errors.iter().map(move |s| ErrorPosition { location: Location::Range { diff --git a/src/parse/lexer.rs b/src/parse/lexer.rs index f940475..07f1716 100644 --- a/src/parse/lexer.rs +++ b/src/parse/lexer.rs @@ -1,10 +1,11 @@ -use std::fmt; +use std::fmt::{self, Display}; use std::ops::Range; use std::rc::Rc; use chumsky::prelude::*; use chumsky::text::keyword; use chumsky::Parser; +use itertools::Itertools; use ordered_float::NotNan; use super::context::Context; @@ -12,7 +13,7 @@ use super::decls::SimpleParser; use super::number::print_nat16; use super::{comment, name, number, placeholder, string}; use crate::ast::{PHClass, Placeholder}; -use crate::interner::{InternedDisplay, Interner, Tok}; +use crate::interner::Tok; use crate::representations::Literal; use crate::Location; @@ -51,13 +52,9 @@ impl Entry { } } -impl InternedDisplay for Entry { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { - self.lexeme.fmt_i(f, i) +impl Display for Entry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.lexeme.fmt(f) } } @@ -120,15 +117,11 @@ pub enum Lexeme { Placeh(Placeholder), } -impl InternedDisplay for Lexeme { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { +impl Display for Lexeme { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Literal(l) => write!(f, "{:?}", l), - Self::Name(token) => write!(f, "{}", i.r(*token)), + Self::Name(token) => write!(f, "{}", **token), Self::Walrus => write!(f, ":="), Self::Arrow(prio) => write!(f, "={}=>", print_nat16(*prio)), Self::NS => write!(f, "::"), @@ -151,10 +144,10 @@ impl InternedDisplay for Lexeme { Self::Const => write!(f, "const"), Self::Macro => write!(f, "macro"), Self::Placeh(Placeholder { name, class }) => match *class { - PHClass::Scalar => write!(f, "${}", i.r(*name)), + PHClass::Scalar => write!(f, "${}", **name), PHClass::Vec { nonzero, prio } => { if nonzero { write!(f, "...") } else { write!(f, "..") }?; - write!(f, "${}", i.r(*name))?; + write!(f, "${}", **name)?; if prio != 0 { write!(f, ":{}", prio)?; }; @@ -182,13 +175,9 @@ impl Lexeme { #[derive(Clone, PartialEq, Eq, Hash)] pub struct LexedText(pub Vec); -impl InternedDisplay for LexedText { - fn fmt_i(&self, f: &mut fmt::Formatter<'_>, i: &Interner) -> fmt::Result { - for tok in self.0.iter() { - tok.fmt_i(f, i)?; - f.write_str(" ")? - } - Ok(()) +impl Display for LexedText { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0.iter().join(" ")) } } diff --git a/src/parse/multiname.rs b/src/parse/multiname.rs index 26dfe7a..140a5b3 100644 --- a/src/parse/multiname.rs +++ b/src/parse/multiname.rs @@ -43,8 +43,8 @@ fn parse_multiname_branch( let comma = ctx.interner().i(","); let (subnames, cursor) = parse_multiname_rec(cursor, ctx.clone())?; let (delim, cursor) = cursor.trim().pop()?; - match delim.lexeme { - Lexeme::Name(n) if n == comma => { + match &delim.lexeme { + Lexeme::Name(n) if n == &comma => { let (tail, cont) = parse_multiname_branch(cursor, ctx)?; Ok((box_chain!(subnames, tail), cont)) }, @@ -74,7 +74,7 @@ fn parse_multiname_rec( loop { let head; (head, cursor) = cursor.trim().pop()?; - match head.lexeme { + match &head.lexeme { Lexeme::Name(n) => names.push(n), Lexeme::RP('[') => break, _ => { @@ -87,7 +87,10 @@ fn parse_multiname_rec( }, } } - Ok((Box::new(names.into_iter().map(Subresult::new_named)), cursor)) + Ok(( + Box::new(names.into_iter().map(|n| Subresult::new_named(n.clone()))), + cursor, + )) }, Lexeme::Name(n) if *n == star => Ok((box_once(Subresult::new_glob()), cursor)), @@ -96,10 +99,10 @@ fn parse_multiname_rec( if cursor.get(0).ok().map(|e| &e.lexeme) == Some(&Lexeme::NS) { let cursor = cursor.step()?; let (out, cursor) = parse_multiname_rec(cursor, ctx)?; - let out = Box::new(out.map(|sr| sr.push_front(*n))); + let out = Box::new(out.map(|sr| sr.push_front(n.clone()))); Ok((out, cursor)) } else { - Ok((box_once(Subresult::new_named(*n)), cursor)) + Ok((box_once(Subresult::new_named(n.clone())), cursor)) } }, _ => Err( diff --git a/src/parse/sourcefile.rs b/src/parse/sourcefile.rs index b64d268..fbfd579 100644 --- a/src/parse/sourcefile.rs +++ b/src/parse/sourcefile.rs @@ -201,14 +201,14 @@ fn parse_exprv( }, Lexeme::Placeh(ph) => { output.push(Expr { - value: Clause::Placeh(*ph), + value: Clause::Placeh(ph.clone()), location: current.location(), }); cursor = cursor.step()?; }, Lexeme::Name(n) => { let location = cursor.location(); - let mut fullname = vec![*n]; + let mut fullname = vec![n.clone()]; while cursor.get(1).ok().map(|e| &e.lexeme) == Some(&Lexeme::NS) { fullname.push(ExpectedName::expect(cursor.get(2)?)?); cursor = cursor.step()?.step()?; diff --git a/src/pipeline/file_loader.rs b/src/pipeline/file_loader.rs index 6530bdd..7180e28 100644 --- a/src/pipeline/file_loader.rs +++ b/src/pipeline/file_loader.rs @@ -24,10 +24,10 @@ impl ProjectError for FileLoadingError { fn description(&self) -> &str { "Neither a file nor a directory could be read from the requested path" } - fn one_position(&self, _i: &Interner) -> crate::Location { + fn one_position(&self) -> crate::Location { Location::File(Rc::new(self.path.clone())) } - fn message(&self, _i: &Interner) -> String { + fn message(&self) -> String { format!("File: {}\nDirectory: {}", self.file, self.dir) } } @@ -89,9 +89,9 @@ pub fn load_file(root: &Path, path: &[impl AsRef]) -> IOResult { } /// Generates a cached file loader for a directory -pub fn mk_dir_cache(root: PathBuf, i: &Interner) -> Cache { +pub fn mk_dir_cache(root: PathBuf) -> Cache<'static, VName, IOResult> { Cache::new(move |vname: VName, _this| -> IOResult { - let path = vname.iter().map(|t| i.r(*t).as_str()).collect::>(); + let path = vname.iter().map(|t| t.as_str()).collect::>(); load_file(&root, &path) }) } @@ -130,12 +130,11 @@ pub fn load_embed(path: &str, ext: &str) -> IOResult { } /// Generates a cached file loader for a [RustEmbed] -pub fn mk_embed_cache<'a, T: 'static + RustEmbed>( - ext: &'a str, - i: &'a Interner, -) -> Cache<'a, Vec, IOResult> { +pub fn mk_embed_cache( + ext: &str, +) -> Cache<'_, Vec, IOResult> { Cache::new(move |vname: VName, _this| -> IOResult { - let path = i.extern_all(&vname).join("/"); + let path = Interner::extern_all(&vname).join("/"); load_embed::(&path, ext) }) } diff --git a/src/pipeline/import_abs_path.rs b/src/pipeline/import_abs_path.rs index e2fad06..ebc796e 100644 --- a/src/pipeline/import_abs_path.rs +++ b/src/pipeline/import_abs_path.rs @@ -12,10 +12,9 @@ pub fn import_abs_path( // path of module within file let mod_pathv = mod_stack.iter().rev_vec_clone(); // path of module within compilation - let abs_pathv = src_path - .iter() - .copied() - .chain(mod_pathv.iter().copied()) + let abs_pathv = (src_path.iter()) + .chain(mod_pathv.iter()) + .cloned() .collect::>(); // preload-target path relative to module // preload-target path within compilation diff --git a/src/pipeline/import_resolution/apply_aliases.rs b/src/pipeline/import_resolution/apply_aliases.rs index edebc18..2c4470e 100644 --- a/src/pipeline/import_resolution/apply_aliases.rs +++ b/src/pipeline/import_resolution/apply_aliases.rs @@ -17,7 +17,7 @@ fn resolve_rec( Some(alias.clone()) } else if let Some((foot, body)) = namespace.split_last() { let mut new_beginning = resolve_rec(body, alias_map)?; - new_beginning.push(*foot); + new_beginning.push(foot.clone()); Some(new_beginning) } else { None @@ -61,7 +61,7 @@ fn apply_aliases_rec( ModMember::Item(expr) => ModMember::Item(process_expr(expr, alias_map, injected_as)), ModMember::Sub(module) => { - let subpath = path.push(*name); + let subpath = path.push(name.clone()); let new_mod = if !updated(&subpath.iter().rev_vec_clone()) { module.clone() } else { @@ -70,7 +70,7 @@ fn apply_aliases_rec( ModMember::Sub(new_mod) }, }; - (*name, ModEntry { exported: *exported, member }) + (name.clone(), ModEntry { exported: *exported, member }) }) .collect::>(); let rules = (module.extra.rules.iter()) @@ -94,7 +94,7 @@ fn apply_aliases_rec( rules, exports: (module.extra.exports.iter()) .map(|(k, v)| { - (*k, resolve(v, alias_map, injected_as).unwrap_or(v.clone())) + (k.clone(), resolve(v, alias_map, injected_as).unwrap_or(v.clone())) }) .collect(), file: module.extra.file.clone(), diff --git a/src/pipeline/import_resolution/collect_aliases.rs b/src/pipeline/import_resolution/collect_aliases.rs index 66e2f8c..f95daed 100644 --- a/src/pipeline/import_resolution/collect_aliases.rs +++ b/src/pipeline/import_resolution/collect_aliases.rs @@ -105,13 +105,13 @@ fn collect_aliases_rec( if !updated(&mod_path_v) { return Ok(()); }; - for (&name, target_mod_name) in module.extra.imports_from.iter() { - let target_sym_v = pushed(target_mod_name, name); + for (name, target_mod_name) in module.extra.imports_from.iter() { + let target_sym_v = pushed(target_mod_name, name.clone()); assert_visible(&mod_path_v, &target_sym_v, project)?; - let sym_path_v = pushed(&mod_path_v, name); + let sym_path_v = pushed(&mod_path_v, name.clone()); let target_mod = (project.0.walk_ref(target_mod_name, false)) .expect("checked above in assert_visible"); - let target_sym = (target_mod.extra.exports.get(&name)) + let target_sym = (target_mod.extra.exports.get(name)) .ok_or_else(|| { let file_len = target_mod.extra.file.as_ref().unwrap_or(target_mod_name).len(); @@ -125,10 +125,10 @@ fn collect_aliases_rec( .clone(); alias_map.link(sym_path_v, target_sym); } - for (&name, entry) in module.items.iter() { + for (name, entry) in module.items.iter() { let submodule = unwrap_or!(&entry.member => ModMember::Sub; continue); collect_aliases_rec( - path.push(name), + path.push(name.clone()), submodule, project, alias_map, diff --git a/src/pipeline/parse_layer.rs b/src/pipeline/parse_layer.rs index 8ad5798..6a2acd1 100644 --- a/src/pipeline/parse_layer.rs +++ b/src/pipeline/parse_layer.rs @@ -30,8 +30,8 @@ pub fn parse_layer<'a>( module.extra.exports.get(item).cloned() }; let injected_names = |path: Tok>>| { - let module = environment.0.walk_ref(&i.r(path)[..], false).ok()?; - Some(Rc::new(module.extra.exports.keys().copied().collect())) + let module = environment.0.walk_ref(&path, false).ok()?; + Some(Rc::new(module.extra.exports.keys().cloned().collect())) }; let source = source_loader::load_source(targets, prelude, i, loader, &|path| { diff --git a/src/pipeline/project_tree/build_tree.rs b/src/pipeline/project_tree/build_tree.rs index f7d8227..01f588d 100644 --- a/src/pipeline/project_tree/build_tree.rs +++ b/src/pipeline/project_tree/build_tree.rs @@ -76,7 +76,8 @@ fn source_to_module( let imports_from = (imports.iter()) .map(|imp| -> ProjectResult<_> { let mut imp_path_v = imp.path.clone(); - imp_path_v.push(imp.name.expect("glob imports had just been resolved")); + imp_path_v + .push(imp.name.clone().expect("glob imports had just been resolved")); let mut abs_path = absolute_path(&path_v, &imp_path_v, i) .expect("should have failed in preparsing"); let name = abs_path.pop().ok_or_else(|| { @@ -92,19 +93,19 @@ fn source_to_module( .collect::, _>>()?; let exports = (data.iter()) .flat_map(|ent| { - let mk_ent = |name| (name, pushed(&path_v, name)); + let mk_ent = |name: Tok| (name.clone(), pushed(&path_v, name)); match ent { - FileEntry::Export(names) => Box::new(names.iter().copied().map(mk_ent)), + FileEntry::Export(names) => Box::new(names.iter().cloned().map(mk_ent)), FileEntry::Exported(mem) => match mem { - Member::Constant(constant) => box_once(mk_ent(constant.name)), - Member::Module(ns) => box_once(mk_ent(ns.name)), + Member::Constant(constant) => box_once(mk_ent(constant.name.clone())), + Member::Module(ns) => box_once(mk_ent(ns.name.clone())), Member::Rule(rule) => { let mut names = Vec::new(); for e in rule.pattern.iter() { e.search_all(&mut |e| { if let Clause::Name(n) = &e.value { if let Some([name]) = n.strip_prefix(&path_v[..]) { - names.push((*name, n.clone())) + names.push((name.clone(), n.clone())) } } None::<()> @@ -134,7 +135,7 @@ fn source_to_module( panic!("Preparsed should include entries for all submodules") ); let module = match source_to_module( - path.push(ns.name), + path.push(ns.name.clone()), new_prep, ns.body, i, @@ -144,7 +145,7 @@ fn source_to_module( Ok(t) => t, }; let member = ModMember::Sub(module); - Some(Ok((ns.name, ModEntry { exported, member }))) + Some(Ok((ns.name.clone(), ModEntry { exported, member }))) }, Member::Constant(Constant { name, value }) => { let member = ModMember::Item(value); @@ -184,7 +185,7 @@ fn files_to_module( let path_v = path.iter().rev_vec_clone(); if files.len() == 1 && files[0].path.len() == lvl { return source_to_module( - path, + path.clone(), &files[0].loaded.preparsed.0, files[0].parsed.clone(), i, @@ -192,18 +193,19 @@ fn files_to_module( ); } let items = (files.into_iter()) - .group_by(|f| f.path[lvl]) + .group_by(|f| f.path[lvl].clone()) .into_iter() .map(|(namespace, files)| -> ProjectResult<_> { - let subpath = path.push(namespace); + let subpath = path.push(namespace.clone()); let files_v = files.collect::>(); let module = files_to_module(subpath, files_v, i)?; let member = ModMember::Sub(module); Ok((namespace, ModEntry { exported: true, member })) }) .collect::, _>>()?; - let exports: HashMap<_, _> = - items.keys().copied().map(|name| (name, pushed(&path_v, name))).collect(); + let exports: HashMap<_, _> = (items.keys()) + .map(|name| (name.clone(), pushed(&path_v, name.clone()))) + .collect(); Ok(Module { items, imports: vec![], @@ -223,7 +225,7 @@ pub fn build_tree( injected: &impl InjectedOperatorsFn, ) -> ProjectResult> { assert!(!files.is_empty(), "A tree requires at least one module"); - let ops_cache = collect_ops::mk_cache(&files, i, injected); + let ops_cache = collect_ops::mk_cache(&files, injected); let mut entries = files .iter() .map(|(path, loaded)| { diff --git a/src/pipeline/project_tree/collect_ops/exported_ops.rs b/src/pipeline/project_tree/collect_ops/exported_ops.rs index 5b08aae..a6827b0 100644 --- a/src/pipeline/project_tree/collect_ops/exported_ops.rs +++ b/src/pipeline/project_tree/collect_ops/exported_ops.rs @@ -4,7 +4,7 @@ use hashbrown::HashSet; use trait_set::trait_set; use crate::error::{NotFound, ProjectError, ProjectResult}; -use crate::interner::{Interner, Tok}; +use crate::interner::Tok; use crate::pipeline::source_loader::LoadedSourceTable; use crate::representations::tree::WalkErrorKind; use crate::utils::{split_max_prefix, Cache}; @@ -28,22 +28,21 @@ fn coprefix( pub fn collect_exported_ops( path: Sym, loaded: &LoadedSourceTable, - i: &Interner, injected: &impl InjectedOperatorsFn, ) -> OpsResult { - let injected = injected(path).unwrap_or_else(|| Rc::new(HashSet::new())); - let path_s = &i.r(path)[..]; - match split_max_prefix(path_s, &|n| loaded.contains_key(n)) { + let injected = + injected(path.clone()).unwrap_or_else(|| Rc::new(HashSet::new())); + match split_max_prefix(&path, &|n| loaded.contains_key(n)) { None => { let ops = (loaded.keys()) .filter_map(|modname| { - if path_s.len() == coprefix(path_s.iter(), modname.iter()) { - Some(modname[path_s.len()]) + if path.len() == coprefix(path.iter(), modname.iter()) { + Some(modname[path.len()].clone()) } else { None } }) - .chain(injected.iter().copied()) + .chain(injected.iter().cloned()) .collect::>(); Ok(Rc::new(ops)) }, @@ -64,8 +63,8 @@ pub fn collect_exported_ops( )?; let out = (module.items.iter()) .filter(|(_, v)| v.exported) - .map(|(k, _)| *k) - .chain(injected.iter().copied()) + .map(|(k, _)| k.clone()) + .chain(injected.iter().cloned()) .collect::>(); Ok(Rc::new(out)) }, @@ -74,8 +73,7 @@ pub fn collect_exported_ops( pub fn mk_cache<'a>( loaded: &'a LoadedSourceTable, - i: &'a Interner, injected: &'a impl InjectedOperatorsFn, ) -> ExportedOpsCache<'a> { - Cache::new(|path, _this| collect_exported_ops(path, loaded, i, injected)) + Cache::new(|path, _this| collect_exported_ops(path, loaded, injected)) } diff --git a/src/pipeline/project_tree/collect_ops/ops_for.rs b/src/pipeline/project_tree/collect_ops/ops_for.rs index 49d5d72..28e90d2 100644 --- a/src/pipeline/project_tree/collect_ops/ops_for.rs +++ b/src/pipeline/project_tree/collect_ops/ops_for.rs @@ -16,7 +16,7 @@ fn tree_all_ops( module: &Module, ops: &mut HashSet>, ) { - ops.extend(module.items.keys().copied()); + ops.extend(module.items.keys().cloned()); for ent in module.items.values() { if let ModMember::Sub(m) = &ent.member { tree_all_ops(m, ops); @@ -40,16 +40,14 @@ pub fn collect_ops_for( let mut ret = HashSet::new(); tree_all_ops(tree, &mut ret); tree.visit_all_imports(&mut |modpath, _m, import| -> ProjectResult<()> { - if let Some(n) = import.name { - ret.insert(n); + if let Some(n) = &import.name { + ret.insert(n.clone()); } else { - let path = i.expect( - import_abs_path(file, modpath, &import.path, i), - "This error should have been caught during loading", - ); - ret.extend(ops_cache.find(&i.i(&path))?.iter().copied()); + let path = import_abs_path(file, modpath, &import.path, i) + .expect("This error should have been caught during loading"); + ret.extend(ops_cache.find(&i.i(&path))?.iter().cloned()); } Ok(()) })?; - Ok(Rc::new(ret.into_iter().filter(|t| is_op(i.r(*t))).collect())) + Ok(Rc::new(ret.into_iter().filter(|t| is_op(&**t)).collect())) } diff --git a/src/pipeline/project_tree/normalize_imports.rs b/src/pipeline/project_tree/normalize_imports.rs index 4a3d4b3..eecca6d 100644 --- a/src/pipeline/project_tree/normalize_imports.rs +++ b/src/pipeline/project_tree/normalize_imports.rs @@ -25,8 +25,8 @@ fn member_rec( &preparsed.items[&name].member => ModMember::Sub; unreachable!("This name must point to a namespace") ); - let new_body = - entv_rec(mod_stack.push(name), subprep, body, path, ops_cache, i); + let new_stack = mod_stack.push(name.clone()); + let new_body = entv_rec(new_stack, subprep, body, path, ops_cache, i); Member::Module(ModuleBlock { name, body: new_body }) }, any => any, @@ -58,16 +58,12 @@ fn entv_rec( .into_iter() .flat_map(|import| { if let Import { name: None, path } = import { - let p = i.expect( - import_abs_path(mod_path, mod_stack, &path, i), - "Should have emerged in preparsing", - ); - let names = i.expect( - ops_cache.find(&i.i(&p)), - "Should have emerged in second parsing", - ); + let p = import_abs_path(mod_path, mod_stack.clone(), &path, i) + .expect("Should have emerged in preparsing"); + let names = (ops_cache.find(&i.i(&p))) + .expect("Should have emerged in second parsing"); let imports = (names.iter()) - .map(|&n| Import { name: Some(n), path: path.clone() }) + .map(|n| Import { name: Some(n.clone()), path: path.clone() }) .collect::>(); Box::new(imports.into_iter()) as BoxedIter } else { @@ -77,10 +73,10 @@ fn entv_rec( .collect(), ), FileEntry::Exported(mem) => FileEntry::Exported(member_rec( - mod_stack, preparsed, mem, mod_path, ops_cache, i, + mod_stack.clone(), preparsed, mem, mod_path, ops_cache, i, )), FileEntry::Internal(mem) => FileEntry::Internal(member_rec( - mod_stack, preparsed, mem, mod_path, ops_cache, i, + mod_stack.clone(), preparsed, mem, mod_path, ops_cache, i, )), any => any, }) diff --git a/src/pipeline/project_tree/parse_file.rs b/src/pipeline/project_tree/parse_file.rs index d030ef9..ab70ce1 100644 --- a/src/pipeline/project_tree/parse_file.rs +++ b/src/pipeline/project_tree/parse_file.rs @@ -28,16 +28,14 @@ pub fn parse_file( let ld = &loaded[path]; // let ops_cache = collect_ops::mk_cache(loaded, i); let ops = collect_ops_for(path, loaded, ops_cache, i)?; - let ops_vec = ops.iter().map(|t| i.r(*t)).cloned().collect::>(); + let ops_vec = ops.iter().map(|t| (**t).clone()).collect::>(); let ctx = parse::ParsingContext { interner: i, ops: &ops_vec, - file: Rc::new(i.extern_all(path)), + file: Rc::new(Interner::extern_all(path)), }; - let entries = i.expect( - parse::parse2(ld.text.as_str(), ctx), - "This error should have been caught during loading", - ); + let entries = parse::parse2(ld.text.as_str(), ctx) + .expect("This error should have been caught during loading"); let with_prelude = add_prelude(entries, path, prelude); let impnormalized = normalize_imports(&ld.preparsed.0, with_prelude, path, ops_cache, i); diff --git a/src/pipeline/project_tree/prefix.rs b/src/pipeline/project_tree/prefix.rs index 60719e3..8bbf63b 100644 --- a/src/pipeline/project_tree/prefix.rs +++ b/src/pipeline/project_tree/prefix.rs @@ -15,12 +15,13 @@ fn member_rec( i: &Interner, ) -> Member { let prefix = (path.iter()) - .copied() + .cloned() .chain(mod_stack.iter().rev_vec_clone().into_iter()) .collect::>(); match data { Member::Module(ModuleBlock { name, body }) => { - let new_body = entv_rec(mod_stack.push(name), body, path, ops_cache, i); + let new_stack = mod_stack.push(name.clone()); + let new_body = entv_rec(new_stack, body, path, ops_cache, i); Member::Module(ModuleBlock { name, body: new_body }) }, Member::Constant(constant) => Member::Constant(Constant { @@ -49,15 +50,15 @@ fn entv_rec( ops_cache: &ExportedOpsCache, i: &Interner, ) -> Vec { - data - .into_iter() - .map(|fe| match fe { - FileEntry::Exported(mem) => - FileEntry::Exported(member_rec(mod_stack, mem, path, ops_cache, i)), - FileEntry::Internal(mem) => - FileEntry::Internal(member_rec(mod_stack, mem, path, ops_cache, i)), - // XXX should [FileEntry::Export] be prefixed? - any => any, + (data.into_iter()) + .map(|fe| { + let (mem, wrapper): (Member, fn(Member) -> FileEntry) = match fe { + FileEntry::Exported(mem) => (mem, FileEntry::Exported), + FileEntry::Internal(mem) => (mem, FileEntry::Internal), + // XXX should [FileEntry::Export] be prefixed? + any => return any, + }; + wrapper(member_rec(mod_stack.clone(), mem, path, ops_cache, i)) }) .collect() } diff --git a/src/pipeline/source_loader/load_source.rs b/src/pipeline/source_loader/load_source.rs index 8b59ef4..746f265 100644 --- a/src/pipeline/source_loader/load_source.rs +++ b/src/pipeline/source_loader/load_source.rs @@ -44,7 +44,7 @@ fn load_abs_path_rec( return Err(UnexpectedDirectory { path: filename.to_vec() }.rc()) }); let preparsed = preparse( - filename.iter().map(|t| i.r(*t)).cloned().collect(), + Interner::extern_all(filename), text.as_str(), prelude, i, @@ -87,7 +87,7 @@ fn load_abs_path_rec( // recurse on all files and folders within for item in coll.iter() { let abs_subpath = (abs_path.iter()) - .copied() + .cloned() .chain(iter::once(i.i(item))) .collect::>(); load_abs_path_rec( diff --git a/src/pipeline/source_loader/preparse.rs b/src/pipeline/source_loader/preparse.rs index 1628508..c9bc3a7 100644 --- a/src/pipeline/source_loader/preparse.rs +++ b/src/pipeline/source_loader/preparse.rs @@ -39,12 +39,12 @@ fn to_module(src: &[FileEntry], prelude: &[FileEntry]) -> Module<(), ()> { FileEntry::Internal(Member::Module(ns)) => { let member = ModMember::Sub(to_module(&ns.body, prelude)); let entry = ModEntry { exported: false, member }; - Some((ns.name, entry)) + Some((ns.name.clone(), entry)) }, FileEntry::Exported(Member::Module(ns)) => { let member = ModMember::Sub(to_module(&ns.body, prelude)); let entry = ModEntry { exported: true, member }; - Some((ns.name, entry)) + Some((ns.name.clone(), entry)) }, _ => None, }) @@ -57,12 +57,12 @@ fn to_module(src: &[FileEntry], prelude: &[FileEntry]) -> Module<(), ()> { | FileEntry::Exported(Member::Module(_)) => (), FileEntry::Export(tokv) => for tok in tokv { - add_export(&mut items, *tok) + add_export(&mut items, tok.clone()) }, FileEntry::Internal(Member::Constant(Constant { name, .. })) => - add_intern(&mut items, *name), + add_intern(&mut items, name.clone()), FileEntry::Exported(Member::Constant(Constant { name, .. })) => - add_export(&mut items, *name), + add_export(&mut items, name.clone()), FileEntry::Internal(Member::Rule(rule)) => { let names = rule.collect_single_names(); for name in names { diff --git a/src/representations/ast.rs b/src/representations/ast.rs index e4cfa43..92e62de 100644 --- a/src/representations/ast.rs +++ b/src/representations/ast.rs @@ -3,6 +3,7 @@ //! These structures are produced by the pipeline, processed by the macro //! executor, and then converted to other usable formats. +use std::fmt::Display; use std::hash::Hash; use std::rc::Rc; @@ -15,7 +16,7 @@ use super::interpreted; use super::location::Location; use super::namelike::{NameLike, VName}; use super::primitive::Primitive; -use crate::interner::{InternedDisplay, Interner, Tok}; +use crate::interner::Tok; use crate::utils::map_rc; /// A [Clause] with associated metadata @@ -74,7 +75,7 @@ impl Expr { pub fn prefix( &self, prefix: &[Tok], - except: &impl Fn(Tok) -> bool, + except: &impl Fn(&Tok) -> bool, ) -> Self { Self { value: self.value.prefix(prefix, except), @@ -83,15 +84,9 @@ impl Expr { } } -impl InternedDisplay for Expr { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { - let Expr { value, .. } = self; - value.fmt_i(f, i)?; - Ok(()) +impl Display for Expr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.value.fmt(f) } } @@ -110,7 +105,7 @@ pub enum PHClass { } /// Properties of a placeholder that matches unknown tokens in macros -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Placeholder { /// Identifier to pair placeholders in the pattern and template pub name: Tok, @@ -118,21 +113,15 @@ pub struct Placeholder { pub class: PHClass, } -impl InternedDisplay for Placeholder { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { - let name = i.r(self.name); +impl Display for Placeholder { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let name = &self.name; match self.class { PHClass::Scalar => write!(f, "${name}"), - PHClass::Vec { nonzero, prio } => - if nonzero { - write!(f, "...${name}:{prio}") - } else { - write!(f, "..${name}:{prio}") - }, + PHClass::Vec { nonzero, prio } => { + if nonzero { write!(f, "...") } else { write!(f, "..") }?; + write!(f, "${name}:{prio}") + }, } } } @@ -307,11 +296,11 @@ impl Clause { pub fn prefix( &self, prefix: &[Tok], - except: &impl Fn(Tok) -> bool, + except: &impl Fn(&Tok) -> bool, ) -> Self { self .map_names(&|name| { - if except(name[0]) { + if except(&name[0]) { return None; } let mut new = prefix.to_vec(); @@ -322,46 +311,27 @@ impl Clause { } } -fn fmt_expr_seq<'a, N: NameLike>( - it: &mut impl Iterator>, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, -) -> std::fmt::Result { - for item in Itertools::intersperse(it.map(Some), None) { - match item { - Some(expr) => expr.fmt_i(f, i), - None => f.write_str(" "), - }? - } - Ok(()) -} - -impl InternedDisplay for Clause { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { +impl Display for Clause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::P(p) => write!(f, "{:?}", p), - Self::Name(name) => write!(f, "{}", name.to_strv(i).join("::")), + Self::Name(name) => write!(f, "{}", name.to_strv().join("::")), Self::S(del, items) => { - f.write_str(&del.to_string())?; - fmt_expr_seq(&mut items.iter(), f, i)?; - f.write_str(match del { + let body = items.iter().join(" "); + let led = match del { '(' => ")", '[' => "]", '{' => "}", _ => "CLOSING_DELIM", - }) + }; + write!(f, "{del}{body}{led}") }, Self::Lambda(arg, body) => { - f.write_str("\\")?; - fmt_expr_seq(&mut arg.iter(), f, i)?; - f.write_str(".")?; - fmt_expr_seq(&mut body.iter(), f, i) + let args = arg.iter().join(" "); + let bodys = body.iter().join(" "); + write!(f, "\\{args}.{bodys}") }, - Self::Placeh(ph) => ph.fmt_i(f, i), + Self::Placeh(ph) => ph.fmt(f), } } } @@ -382,7 +352,7 @@ impl Rule { pub fn prefix( &self, prefix: &[Tok], - except: &impl Fn(Tok) -> bool, + except: &impl Fn(&Tok) -> bool, ) -> Self { Self { prio: self.prio, @@ -401,7 +371,7 @@ impl Rule { e.search_all(&mut |e| { if let Clause::Name(ns_name) = &e.value { if ns_name.len() == 1 { - names.push(ns_name[0]) + names.push(ns_name[0].clone()) } } None::<()> @@ -411,22 +381,15 @@ impl Rule { } } -impl InternedDisplay for Rule { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { - for e in self.pattern.iter() { - e.fmt_i(f, i)?; - write!(f, " ")?; - } - write!(f, "={}=>", self.prio)?; - for e in self.template.iter() { - write!(f, " ")?; - e.fmt_i(f, i)?; - } - Ok(()) +impl Display for Rule { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{} ={}=> {}", + self.pattern.iter().join(" "), + self.prio, + self.template.iter().join(" ") + ) } } @@ -439,13 +402,8 @@ pub struct Constant { pub value: Expr, } -impl InternedDisplay for Constant { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { - write!(f, "{} := ", i.r(self.name))?; - self.value.fmt_i(f, i) +impl Display for Constant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} := {}", *self.name, self.value) } } diff --git a/src/representations/ast_to_postmacro.rs b/src/representations/ast_to_postmacro.rs index 16e47b1..a7ec1a4 100644 --- a/src/representations/ast_to_postmacro.rs +++ b/src/representations/ast_to_postmacro.rs @@ -4,7 +4,7 @@ use super::location::Location; use super::{ast, postmacro}; use crate::error::ProjectError; use crate::utils::Substack; -use crate::{Interner, Sym}; +use crate::Sym; #[derive(Debug, Clone)] pub enum ErrorKind { @@ -44,13 +44,13 @@ impl ProjectError for Error { } } - fn message(&self, _i: &Interner) -> String { + fn message(&self) -> String { match self.kind { ErrorKind::BadGroup(char) => format!("{} block found in the code", char), _ => self.description().to_string(), } } - fn one_position(&self, _i: &Interner) -> Location { + fn one_position(&self) -> Location { self.location.clone() } } @@ -60,7 +60,7 @@ pub fn expr(expr: &ast::Expr) -> Result { expr_rec(expr, Context::new()) } -#[derive(Clone, Copy)] +#[derive(Clone)] struct Context<'a> { names: Substack<'a, Sym>, } @@ -89,7 +89,7 @@ fn exprv_rec<'a>( if rest.is_empty() { return expr_rec(&v[0], ctx); } - let f = exprv_rec(location, rest, ctx)?; + let f = exprv_rec(location, rest, ctx.clone())?; let x = expr_rec(last, ctx)?; let value = postmacro::Clause::Apply(Rc::new(f), Rc::new(x)); Ok(postmacro::Expr { value, location: Location::Unknown }) @@ -116,7 +116,7 @@ fn expr_rec<'a>( return Err(Error::new(ErrorKind::Placeholder, location)), _ => return Err(Error::new(ErrorKind::InvalidArg, location)), }; - let body_ctx = ctx.w_name(*name); + let body_ctx = ctx.w_name(name.clone()); let body = exprv_rec(location, b.as_ref(), body_ctx)?; postmacro::Clause::Lambda(Rc::new(body)) }, @@ -127,7 +127,7 @@ fn expr_rec<'a>( .map(|(lvl, _)| lvl); match lvl_opt { Some(lvl) => postmacro::Clause::LambdaArg(lvl), - None => postmacro::Clause::Constant(*name), + None => postmacro::Clause::Constant(name.clone()), } }, ast::Clause::S(paren, entries) => { diff --git a/src/representations/const_tree.rs b/src/representations/const_tree.rs index b177423..8ffc427 100644 --- a/src/representations/const_tree.rs +++ b/src/representations/const_tree.rs @@ -94,7 +94,7 @@ fn from_const_tree_rec( let mut items = HashMap::new(); let path_v = path.iter().rev_vec_clone(); for (name, item) in consts { - items.insert(name, ModEntry { + items.insert(name.clone(), ModEntry { exported: true, member: match item { ConstTree::Const(c) => ModMember::Item(c), @@ -103,8 +103,9 @@ fn from_const_tree_rec( }, }); } - let exports = - items.keys().map(|name| (*name, pushed(&path_v, *name))).collect(); + let exports = (items.keys()) + .map(|name| (name.clone(), pushed(&path_v, name.clone()))) + .collect(); Module { items, imports: vec![], diff --git a/src/representations/interpreted.rs b/src/representations/interpreted.rs index 731a5c7..7fcdfc1 100644 --- a/src/representations/interpreted.rs +++ b/src/representations/interpreted.rs @@ -3,7 +3,7 @@ //! This code may be generated to minimize the number of states external //! functions have to define use std::cell::RefCell; -use std::fmt::Debug; +use std::fmt::{Debug, Display}; use std::ops::{Deref, DerefMut}; use std::rc::Rc; @@ -13,8 +13,6 @@ use super::location::Location; use super::path_set::PathSet; use super::primitive::Primitive; use super::Literal; -use crate::interner::InternedDisplay; -use crate::utils::sym2string; use crate::Sym; // TODO: implement Debug, Eq and Hash with cycle detection @@ -36,19 +34,11 @@ impl Debug for Expr { } } -impl InternedDisplay for Expr { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &crate::interner::Interner, - ) -> std::fmt::Result { +impl Display for Expr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.location { - Location::Unknown => self.clause.fmt_i(f, i), - loc => { - write!(f, "{}:(", loc)?; - self.clause.fmt_i(f, i)?; - write!(f, ")") - }, + Location::Unknown => write!(f, "{}", self.clause), + loc => write!(f, "{}:({})", loc, self.clause), } } } @@ -151,20 +141,16 @@ impl ExprInst { impl Debug for ExprInst { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.0.try_borrow() { - Ok(expr) => write!(f, "{:?}", expr), + Ok(expr) => write!(f, "{expr:?}"), Err(_) => write!(f, ""), } } } -impl InternedDisplay for ExprInst { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &crate::interner::Interner, - ) -> std::fmt::Result { +impl Display for ExprInst { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.0.try_borrow() { - Ok(expr) => expr.fmt_i(f, i), + Ok(expr) => write!(f, "{expr}"), Err(_) => write!(f, ""), } } @@ -208,32 +194,17 @@ impl Clause { } } -impl InternedDisplay for Clause { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &crate::interner::Interner, - ) -> std::fmt::Result { +impl Display for Clause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Clause::P(p) => write!(f, "{p:?}"), Clause::LambdaArg => write!(f, "arg"), - Clause::Apply { f: fun, x } => { - write!(f, "(")?; - fun.fmt_i(f, i)?; - write!(f, " ")?; - x.fmt_i(f, i)?; - write!(f, ")") - }, - Clause::Lambda { args, body } => { - write!(f, "\\")?; - match args { - Some(path) => write!(f, "{path:?}")?, - None => write!(f, "_")?, - } - write!(f, ".")?; - body.fmt_i(f, i) + Clause::Apply { f: fun, x } => write!(f, "({fun} {x})"), + Clause::Lambda { args, body } => match args { + Some(path) => write!(f, "\\{path:?}.{body}"), + None => write!(f, "\\_.{body}"), }, - Clause::Constant(t) => write!(f, "{}", sym2string(*t, i)), + Clause::Constant(t) => write!(f, "{}", t.extern_vec().join("::")), } } } diff --git a/src/representations/namelike.rs b/src/representations/namelike.rs index 17ec97f..700a138 100644 --- a/src/representations/namelike.rs +++ b/src/representations/namelike.rs @@ -20,17 +20,17 @@ pub type Sym = Tok>>; /// handled together in datastructures pub trait NameLike: 'static + Clone + Eq + Hash { /// Fully resolve the name for printing - fn to_strv(&self, i: &Interner) -> Vec; + fn to_strv(&self) -> Vec; } impl NameLike for Sym { - fn to_strv(&self, i: &Interner) -> Vec { - i.extern_vec(*self) + fn to_strv(&self) -> Vec { + self.extern_vec() } } impl NameLike for VName { - fn to_strv(&self, i: &Interner) -> Vec { - i.extern_all(self) + fn to_strv(&self) -> Vec { + Interner::extern_all(self) } } diff --git a/src/representations/postmacro_to_interpreted.rs b/src/representations/postmacro_to_interpreted.rs index 0dc8b9d..499a4ae 100644 --- a/src/representations/postmacro_to_interpreted.rs +++ b/src/representations/postmacro_to_interpreted.rs @@ -40,7 +40,8 @@ fn collect_paths_cls_rec( pub fn clause(cls: &postmacro::Clause) -> interpreted::Clause { match cls { - postmacro::Clause::Constant(name) => interpreted::Clause::Constant(*name), + postmacro::Clause::Constant(name) => + interpreted::Clause::Constant(name.clone()), postmacro::Clause::P(p) => interpreted::Clause::P(p.clone()), postmacro::Clause::Apply(f, x) => interpreted::Clause::Apply { f: expr(f.as_ref()), x: expr(x.as_ref()) }, diff --git a/src/representations/project.rs b/src/representations/project.rs index c2de388..034eaf3 100644 --- a/src/representations/project.rs +++ b/src/representations/project.rs @@ -76,11 +76,11 @@ fn collect_consts_rec( match &entry.member { ModMember::Item(expr) => { let mut name = path.iter().rev_vec_clone(); - name.push(*key); + name.push(key.clone()); bag.insert(i.i(&name), expr.clone()); }, ModMember::Sub(module) => - collect_consts_rec(path.push(*key), bag, module, i), + collect_consts_rec(path.push(key.clone()), bag, module, i), } } } diff --git a/src/representations/sourcefile.rs b/src/representations/sourcefile.rs index 54629ca..8516b08 100644 --- a/src/representations/sourcefile.rs +++ b/src/representations/sourcefile.rs @@ -30,8 +30,8 @@ impl Import { /// name if this is a specific import pub fn nonglob_path(&self) -> Vec> { let mut path_vec = self.path.clone(); - if let Some(n) = self.name { - path_vec.push(n) + if let Some(n) = &self.name { + path_vec.push(n.clone()) } path_vec } @@ -98,10 +98,10 @@ pub fn normalize_namespaces( other => Either::Right(other), }); // Combine namespace blocks with the same name - namespaces.sort_unstable_by_key(|(_, ns)| ns.name); + namespaces.sort_unstable_by_key(|(_, ns)| ns.name.clone()); let mut lumped = namespaces .into_iter() - .group_by(|(_, ns)| ns.name) + .group_by(|(_, ns)| ns.name.clone()) .into_iter() .map(|(name, grp)| { let mut any_exported = false; @@ -119,10 +119,10 @@ pub fn normalize_namespaces( .flat_map(|ns| ns.body.into_iter()); // Apply the function to the contents of these blocks too let body = normalize_namespaces(Box::new(grp_src)).map_err(|mut e| { - e.push(name); + e.push(name.clone()); e })?; - let member = Member::Module(ModuleBlock { name, body }); + let member = Member::Module(ModuleBlock { name: name.clone(), body }); match (any_exported, any_internal) { (true, true) => Err(vec![name]), (true, false) => Ok(FileEntry::Exported(member)), @@ -161,11 +161,11 @@ pub fn absolute_path( Ok(new_abs.to_vec()) } else { let new_rel = - iter::once(i.i("self")).chain(tail.iter().copied()).collect::>(); + iter::once(i.i("self")).chain(tail.iter().cloned()).collect::>(); absolute_path(new_abs, &new_rel, i) } } else if *head == i.i("self") { - Ok(abs_location.iter().chain(tail.iter()).copied().collect()) + Ok(abs_location.iter().chain(tail.iter()).cloned().collect()) } else { Ok(rel_path.to_vec()) } diff --git a/src/representations/tree.rs b/src/representations/tree.rs index 860a9d4..d60158c 100644 --- a/src/representations/tree.rs +++ b/src/representations/tree.rs @@ -96,11 +96,11 @@ impl Module { callback: &mut impl FnMut(ModPath, &Self, &Import) -> Result<(), E>, ) -> Result<(), E> { for import in self.imports.iter() { - callback(path, self, import)? + callback(path.clone(), self, import)? } for (name, entry) in self.items.iter() { if let ModMember::Sub(module) = &entry.member { - module.visit_all_imports_rec(path.push(*name), callback)? + module.visit_all_imports_rec(path.push(name.clone()), callback)? } } Ok(()) diff --git a/src/rule/matcher_vectree/build.rs b/src/rule/matcher_vectree/build.rs index 82da1de..27df048 100644 --- a/src/rule/matcher_vectree/build.rs +++ b/src/rule/matcher_vectree/build.rs @@ -64,7 +64,7 @@ fn mk_vec(pattern: &[RuleExpr]) -> VecMatcher { let (r_sep, r_side) = right.split_at(r_sep_size); let l_sep_size = scal_cnt(left.iter().rev()); let (l_side, l_sep) = left.split_at(left.len() - l_sep_size); - let main = VecMatcher::Placeh { key, nonzero }; + let main = VecMatcher::Placeh { key: key.clone(), nonzero }; match (left, right) { (&[], &[]) => VecMatcher::Placeh { key, nonzero }, (&[], _) => VecMatcher::Scan { @@ -102,13 +102,13 @@ fn mk_vec(pattern: &[RuleExpr]) -> VecMatcher { fn mk_scalar(pattern: &RuleExpr) -> ScalMatcher { match &pattern.value { Clause::P(p) => ScalMatcher::P(p.clone()), - Clause::Name(n) => ScalMatcher::Name(*n), + Clause::Name(n) => ScalMatcher::Name(n.clone()), Clause::Placeh(Placeholder { name, class }) => { debug_assert!( !matches!(class, PHClass::Vec { .. }), "Scalar matcher cannot be built from vector pattern" ); - ScalMatcher::Placeh(*name) + ScalMatcher::Placeh(name.clone()) }, Clause::S(c, body) => ScalMatcher::S(*c, Box::new(mk_any(body))), Clause::Lambda(arg, body) => @@ -122,7 +122,7 @@ mod test { use super::mk_any; use crate::ast::{Clause, PHClass, Placeholder}; - use crate::interner::{InternedDisplay, Interner}; + use crate::interner::Interner; #[test] fn test_scan() { @@ -158,6 +158,6 @@ mod test { .into_expr(), ]; let matcher = mk_any(&pattern); - println!("{}", matcher.bundle(&i)); + println!("{matcher}"); } } diff --git a/src/rule/matcher_vectree/scal_match.rs b/src/rule/matcher_vectree/scal_match.rs index 103c422..f3ba8cc 100644 --- a/src/rule/matcher_vectree/scal_match.rs +++ b/src/rule/matcher_vectree/scal_match.rs @@ -12,7 +12,7 @@ pub fn scal_match<'a>( (ScalMatcher::P(p1), Clause::P(p2)) if p1 == p2 => Some(State::new()), (ScalMatcher::Name(n1), Clause::Name(n2)) if n1 == n2 => Some(State::new()), (ScalMatcher::Placeh(key), _) => - Some(State::from([(*key, StateEntry::Scalar(expr))])), + Some(State::from([(key.clone(), StateEntry::Scalar(expr))])), (ScalMatcher::S(c1, b_mat), Clause::S(c2, body)) if c1 == c2 => any_match(b_mat, &body[..]), (ScalMatcher::Lambda(arg_mat, b_mat), Clause::Lambda(arg, body)) => { diff --git a/src/rule/matcher_vectree/shared.rs b/src/rule/matcher_vectree/shared.rs index 73365a2..cc3c882 100644 --- a/src/rule/matcher_vectree/shared.rs +++ b/src/rule/matcher_vectree/shared.rs @@ -1,13 +1,15 @@ -use std::fmt::Write; +use std::fmt::{Display, Write}; use std::rc::Rc; +use itertools::Itertools; + use super::any_match::any_match; use super::build::mk_any; -use crate::interner::{InternedDisplay, Interner, Tok}; +use crate::interner::Tok; use crate::representations::Primitive; use crate::rule::matcher::{Matcher, RuleExpr}; use crate::rule::state::State; -use crate::utils::{sym2string, unwrap_or, Side}; +use crate::utils::Side; use crate::Sym; pub enum ScalMatcher { @@ -63,115 +65,64 @@ impl Matcher for AnyMatcher { } } -// ################ InternedDisplay ################ - -fn disp_scalv( - scalv: &[ScalMatcher], - f: &mut std::fmt::Formatter<'_>, - i: &Interner, -) -> std::fmt::Result { - let (head, tail) = unwrap_or!(scalv.split_first(); return Ok(())); - head.fmt_i(f, i)?; - for s in tail.iter() { - write!(f, " ")?; - s.fmt_i(f, i)?; - } - Ok(()) -} +// ################ Display ################ -impl InternedDisplay for ScalMatcher { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { +impl Display for ScalMatcher { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::P(p) => write!(f, "{:?}", p), - Self::Placeh(n) => write!(f, "${}", i.r(*n)), - Self::Name(n) => write!(f, "{}", sym2string(*n, i)), + Self::Placeh(n) => write!(f, "${n}"), + Self::Name(n) => write!(f, "{}", n.extern_vec().join("::")), Self::S(c, body) => { - f.write_char(*c)?; - body.fmt_i(f, i)?; - f.write_char(match c { + let pair = match c { '(' => ')', '[' => ']', '{' => '}', _ => unreachable!(), - }) + }; + write!(f, "{c}{body}{pair}") }, Self::Lambda(arg, body) => { - f.write_char('\\')?; - arg.fmt_i(f, i)?; - f.write_char('.')?; - body.fmt_i(f, i) + write!(f, "\\{arg}.{body}") }, } } } -impl InternedDisplay for VecMatcher { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { +impl Display for VecMatcher { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Placeh { key, nonzero } => { if *nonzero { f.write_char('.')?; }; - write!(f, "..${}", i.r(*key)) + write!(f, "..${key}") }, - Self::Scan { left, sep, right, direction } => { - let arrow = match direction { - Side::Left => " <== ", - Side::Right => " ==> ", - }; - write!(f, "Scan{{")?; - left.fmt_i(f, i)?; - f.write_str(arrow)?; - disp_scalv(sep, f, i)?; - f.write_str(arrow)?; - right.fmt_i(f, i)?; - write!(f, "}}") + Self::Scan { left, sep, right, direction } => match direction { + Side::Left => + write!(f, "Scan{{{left} <== {} <== {right}}}", sep.iter().join(" ")), + Side::Right => + write!(f, "Scan{{{left} ==> {} ==> {right}}}", sep.iter().join(" ")), }, Self::Middle { left, left_sep, mid, right_sep, right, .. } => { - write!(f, "Middle{{")?; - left.fmt_i(f, i)?; - f.write_str("|")?; - disp_scalv(left_sep, f, i)?; - f.write_str("|")?; - mid.fmt_i(f, i)?; - f.write_str("|")?; - disp_scalv(right_sep, f, i)?; - f.write_str("|")?; - right.fmt_i(f, i)?; - write!(f, "}}") + let left_sep_s = left_sep.iter().join(" "); + let right_sep_s = right_sep.iter().join(" "); + write!(f, "Middle{{{left}|{left_sep_s}|{mid}|{right_sep_s}|{right}}}") }, } } } -impl InternedDisplay for AnyMatcher { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { +impl Display for AnyMatcher { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Scalar(s) => { - write!(f, "(")?; - disp_scalv(s, f, i)?; - write!(f, ")") + write!(f, "({})", s.iter().join(" ")) }, Self::Vec { left, mid, right } => { - write!(f, "[")?; - disp_scalv(left, f, i)?; - write!(f, "|")?; - mid.fmt_i(f, i)?; - write!(f, "|")?; - disp_scalv(right, f, i)?; - write!(f, "]") + let lefts = left.iter().join(" "); + let rights = right.iter().join(" "); + write!(f, "[{lefts}|{mid}|{rights}]") }, } } @@ -191,12 +142,8 @@ impl Matcher for VectreeMatcher { self.0.apply(source) } } -impl InternedDisplay for VectreeMatcher { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { - self.0.fmt_i(f, i) +impl Display for VectreeMatcher { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) } } diff --git a/src/rule/matcher_vectree/vec_match.rs b/src/rule/matcher_vectree/vec_match.rs index e8b5ced..1697da6 100644 --- a/src/rule/matcher_vectree/vec_match.rs +++ b/src/rule/matcher_vectree/vec_match.rs @@ -17,7 +17,7 @@ pub fn vec_match<'a>( if *nonzero && seq.is_empty() { return None; } - return Some(State::from([(*key, StateEntry::Vec(seq))])); + return Some(State::from([(key.clone(), StateEntry::Vec(seq))])); }, VecMatcher::Scan { left, sep, right, direction } => { if seq.len() < sep.len() { diff --git a/src/rule/prepare_rule.rs b/src/rule/prepare_rule.rs index 38d2fad..7948430 100644 --- a/src/rule/prepare_rule.rs +++ b/src/rule/prepare_rule.rs @@ -64,16 +64,16 @@ fn check_rec_expr( let typ = (*class).into(); // in a template, the type must be known and identical // outside template (in pattern) the type must be unknown - if let Some(known) = types.insert(*name, typ) { + if let Some(known) = types.insert(name.clone(), typ) { if !in_template { - Err(RuleError::Multiple(*name)) + Err(RuleError::Multiple(name.clone())) } else if known != typ { - Err(RuleError::ArityMismatch(*name)) + Err(RuleError::ArityMismatch(name.clone())) } else { Ok(()) } } else if in_template { - Err(RuleError::Missing(*name)) + Err(RuleError::Missing(name.clone())) } else { Ok(()) } diff --git a/src/rule/repository.rs b/src/rule/repository.rs index 8133777..e2f5e9c 100644 --- a/src/rule/repository.rs +++ b/src/rule/repository.rs @@ -1,4 +1,4 @@ -use std::fmt::{Debug, Write}; +use std::fmt::{Debug, Display}; use std::format; use std::rc::Rc; @@ -11,7 +11,7 @@ use super::prepare_rule::prepare_rule; use super::state::apply_exprv; use super::{update_first_seq, RuleError, VectreeMatcher}; use crate::ast::Rule; -use crate::interner::{InternedDisplay, Interner}; +use crate::interner::Interner; use crate::Sym; #[derive(Debug)] @@ -21,18 +21,10 @@ pub struct CachedRule { template: Vec, } -impl InternedDisplay for CachedRule { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { - for item in self.pattern.iter() { - item.fmt_i(f, i)?; - f.write_char(' ')?; - } - write!(f, "is matched by ")?; - self.matcher.fmt_i(f, i) +impl Display for CachedRule { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let patterns = self.pattern.iter().join(" "); + write!(f, "{patterns} is matched by {}", self.matcher) } } @@ -152,22 +144,14 @@ fn fmt_hex(num: f64) -> String { format!("0x{:x}p{}", mantissa as i64, exponent as i64) } -impl InternedDisplay for Repository { - fn fmt_i( - &self, - f: &mut std::fmt::Formatter<'_>, - i: &Interner, - ) -> std::fmt::Result { +impl Display for Repository { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "Repository[")?; - for (item, deps, p) in self.cache.iter() { - write!( - f, - " priority: {}\tdependencies: [{}]\n ", - fmt_hex(f64::from(*p)), - deps.iter().map(|t| i.extern_vec(*t).join("::")).join(", ") - )?; - item.fmt_i(f, i)?; - writeln!(f)?; + for (rule, deps, p) in self.cache.iter() { + let prio = fmt_hex(f64::from(*p)); + let deps = deps.iter().map(|t| t.extern_vec().join("::")).join(", "); + writeln!(f, " priority: {prio}\tdependencies: [{deps}]")?; + writeln!(f, " {rule}")?; } write!(f, "]") } diff --git a/src/rule/rule_error.rs b/src/rule/rule_error.rs index 13b351b..0be7d9f 100644 --- a/src/rule/rule_error.rs +++ b/src/rule/rule_error.rs @@ -1,16 +1,16 @@ -use std::fmt; +use std::fmt::{self, Display}; use std::rc::Rc; use hashbrown::HashSet; use crate::ast::{self, search_all_slcs, PHClass, Placeholder, Rule}; use crate::error::{ErrorPosition, ProjectError}; -use crate::interner::{InternedDisplay, Interner, Tok}; +use crate::interner::Tok; use crate::utils::BoxedIter; use crate::{Location, Sym}; /// Various reasons why a substitution rule may be invalid -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum RuleError { /// A key is present in the template but not the pattern Missing(Tok), @@ -33,25 +33,17 @@ impl RuleError { } } -impl InternedDisplay for RuleError { - fn fmt_i(&self, f: &mut fmt::Formatter<'_>, i: &Interner) -> fmt::Result { - match *self { - Self::Missing(key) => { - write!(f, "Key {:?} not in match pattern", i.r(key)) - }, - Self::ArityMismatch(key) => write!( - f, - "Key {:?} used inconsistently with and without ellipsis", - i.r(key) - ), - Self::Multiple(key) => { - write!(f, "Key {:?} appears multiple times in match pattern", i.r(key)) - }, +impl Display for RuleError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Missing(key) => write!(f, "Key {key} not in match pattern"), + Self::ArityMismatch(key) => + write!(f, "Key {key} used inconsistently with and without ellipsis"), + Self::Multiple(key) => + write!(f, "Key {key} appears multiple times in match pattern"), Self::VecNeighbors(left, right) => write!( f, - "Keys {:?} and {:?} are two vectorials right next to each other", - i.r(left), - i.r(right) + "Keys {left} and {right} are two vectorials right next to each other" ), } } @@ -83,13 +75,13 @@ impl ProjectError for Missing { fn description(&self) -> &str { "A key appears in the template but not the pattern of a rule" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "The key {} appears in the template but not the pattern of this rule", - i.r(self.name) + self.name ) } - fn positions(&self, _i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { Box::new( (self.locations.iter()) .cloned() @@ -124,10 +116,10 @@ impl ProjectError for Multiple { fn description(&self) -> &str { "A key appears multiple times in the pattern of a rule" } - fn message(&self, i: &Interner) -> String { - format!("The key {} appears multiple times in this pattern", i.r(self.name)) + fn message(&self) -> String { + format!("The key {} appears multiple times in this pattern", self.name) } - fn positions(&self, _i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { Box::new( (self.locations.iter()) .cloned() @@ -162,13 +154,13 @@ impl ProjectError for ArityMismatch { fn description(&self) -> &str { "A key appears with different arities in a rule" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "The key {} appears multiple times with different arities in this rule", - i.r(self.name) + self.name ) } - fn positions(&self, _i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { Box::new((self.locations.iter()).cloned().map(|(location, class)| { ErrorPosition { location, @@ -199,12 +191,12 @@ impl VecNeighbors { search_all_slcs(&rule.template[..], &mut |ev| { for pair in ev.windows(2) { let (a, b) = (&pair[0], &pair[1]); - let a_vec = matches!(a.value, ast::Clause::Placeh( + let a_vec = matches!(&a.value, ast::Clause::Placeh( Placeholder{ class: PHClass::Vec { .. }, name } - ) if name == n1); - let b_vec = matches!(b.value, ast::Clause::Placeh( + ) if name == &n1); + let b_vec = matches!(&b.value, ast::Clause::Placeh( Placeholder{ class: PHClass::Vec { .. }, name } - ) if name == n2); + ) if name == &n2); if a_vec && b_vec { locations.insert(a.location.clone()); locations.insert(b.location.clone()); @@ -219,14 +211,13 @@ impl ProjectError for VecNeighbors { fn description(&self) -> &str { "Two vectorial placeholders appear next to each other" } - fn message(&self, i: &Interner) -> String { + fn message(&self) -> String { format!( "The keys {} and {} appear next to each other with a vectorial arity", - i.r(self.n1), - i.r(self.n2) + self.n1, self.n2 ) } - fn positions(&self, _i: &Interner) -> BoxedIter { + fn positions(&self) -> BoxedIter { Box::new( (self.locations.iter()) .cloned() diff --git a/src/rule/vec_attrs.rs b/src/rule/vec_attrs.rs index aee13ba..86798b7 100644 --- a/src/rule/vec_attrs.rs +++ b/src/rule/vec_attrs.rs @@ -5,13 +5,11 @@ use crate::interner::Tok; /// Returns the name, priority and nonzero of the expression if it is /// a vectorial placeholder pub fn vec_attrs(expr: &RuleExpr) -> Option<(Tok, u64, bool)> { - if let Clause::Placeh(Placeholder { - class: PHClass::Vec { prio, nonzero }, - name, - }) = expr.value - { - Some((name, prio, nonzero)) - } else { - None + match expr.value.clone() { + Clause::Placeh(Placeholder { + class: PHClass::Vec { prio, nonzero }, + name, + }) => Some((name, prio, nonzero)), + _ => None, } } diff --git a/src/systems/stl/inspect.rs b/src/systems/stl/inspect.rs index 9ce82c0..09381d7 100644 --- a/src/systems/stl/inspect.rs +++ b/src/systems/stl/inspect.rs @@ -1,7 +1,6 @@ use std::fmt::Debug; use crate::foreign::{Atomic, AtomicReturn}; -use crate::interner::InternedDisplay; use crate::interpreter::Context; use crate::representations::interpreted::ExprInst; use crate::{atomic_defaults, write_fn_step, ConstTree, Interner}; @@ -19,7 +18,7 @@ struct Inspect1 { impl Atomic for Inspect1 { atomic_defaults!(); fn run(&self, ctx: Context) -> crate::foreign::AtomicResult { - println!("{}", self.expr_inst.bundle(ctx.interner)); + println!("{}", self.expr_inst); Ok(AtomicReturn { clause: self.expr_inst.expr().clause.clone(), gas: ctx.gas.map(|g| g - 1), diff --git a/src/systems/stl/mod.rs b/src/systems/stl/mod.rs index b5c0974..784fcbb 100644 --- a/src/systems/stl/mod.rs +++ b/src/systems/stl/mod.rs @@ -9,6 +9,7 @@ mod num; mod panic; mod stl_system; mod str; +mod state; pub use arithmetic_error::ArithmeticError; pub use bin::Binary; pub use num::Numeric; diff --git a/src/systems/stl/state.rs b/src/systems/stl/state.rs new file mode 100644 index 0000000..3fa1238 --- /dev/null +++ b/src/systems/stl/state.rs @@ -0,0 +1,61 @@ +use std::cell::RefCell; +use std::rc::Rc; + +use crate::foreign::cps_box::{const_cps, init_cps, CPSBox}; +use crate::foreign::Atomic; +use crate::interpreted::ExprInst; +use crate::interpreter::HandlerTable; +use crate::systems::codegen::call; +use crate::{atomic_inert, define_fn, ConstTree, Interner}; + +#[derive(Debug, Clone)] +pub struct State(Rc>); +atomic_inert!(State, "a state"); + +#[derive(Debug, Clone)] +struct NewStateCmd; + +#[derive(Debug, Clone)] +struct SetStateCmd(State); + +#[derive(Debug, Clone)] +struct GetStateCmd(State); + +define_fn! { SetState = |x| Ok(init_cps(2, SetStateCmd(x.try_into()?))) } +define_fn! { GetState = |x| Ok(init_cps(2, GetStateCmd(x.try_into()?))) } + +fn new_state_handler(cmd: &CPSBox) -> Result { + let (_, default, handler) = cmd.unpack2(); + let state = State(Rc::new(RefCell::new(default.clone()))); + Ok(call(handler.clone(), [state.atom_exi()]).wrap()) +} + +fn set_state_handler(cmd: &CPSBox) -> Result { + let (SetStateCmd(state), value, handler) = cmd.unpack2(); + *state.0.as_ref().borrow_mut() = value.clone(); + Ok(handler.clone()) +} + +fn get_state_handler(cmd: &CPSBox) -> Result { + let (GetStateCmd(state), handler) = cmd.unpack1(); + Ok(call(handler.clone(), [state.0.as_ref().borrow().clone()]).wrap()) +} + +pub fn state_handlers() -> HandlerTable<'static> { + let mut handlers = HandlerTable::new(); + handlers.register(new_state_handler); + handlers.register(get_state_handler); + handlers.register(set_state_handler); + handlers +} + +pub fn state_lib(i: &Interner) -> ConstTree { + ConstTree::namespace( + [i.i("state")], + ConstTree::tree([ + (i.i("new_state"), const_cps(2, NewStateCmd)), + (i.i("get_state"), ConstTree::xfn(GetState)), + (i.i("set_state"), ConstTree::xfn(SetState)), + ]), + ) +} diff --git a/src/systems/stl/stl_system.rs b/src/systems/stl/stl_system.rs index 3c00f9f..82e9bdd 100644 --- a/src/systems/stl/stl_system.rs +++ b/src/systems/stl/stl_system.rs @@ -8,10 +8,10 @@ use super::conv::conv; use super::inspect::inspect; use super::num::num; use super::panic::panic; +use super::state::{state_handlers, state_lib}; use super::str::str; use crate::facade::{IntoSystem, System}; use crate::interner::Interner; -use crate::interpreter::HandlerTable; use crate::pipeline::file_loader::embed_to_map; use crate::sourcefile::{FileEntry, Import}; @@ -33,7 +33,8 @@ struct StlEmbed; impl IntoSystem<'static> for StlConfig { fn into_system(self, i: &Interner) -> System<'static> { - let pure_fns = conv(i) + bool(i) + str(i) + num(i) + bin(i) + panic(i); + let pure_fns = + conv(i) + bool(i) + str(i) + num(i) + bin(i) + panic(i) + state_lib(i); let mk_impure_fns = || inspect(i); let fns = if self.impure { pure_fns + mk_impure_fns() } else { pure_fns }; System { @@ -44,7 +45,7 @@ impl IntoSystem<'static> for StlConfig { path: vec![i.i("std"), i.i("prelude")], name: None, }])], - handlers: HandlerTable::new(), + handlers: state_handlers(), } } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index dc2bb45..b54a04c 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,7 +2,6 @@ mod cache; mod delete_cell; mod event_poller; mod iter_find; -mod print_nname; mod pushed; mod rc_to_owned; mod replace_first; @@ -15,7 +14,6 @@ pub mod thread_pool; mod unwrap_or; pub use cache::Cache; -pub use print_nname::sym2string; pub use pushed::pushed; pub use rc_to_owned::{map_rc, rc_to_owned}; pub use replace_first::replace_first; diff --git a/src/utils/print_nname.rs b/src/utils/print_nname.rs deleted file mode 100644 index d3301ca..0000000 --- a/src/utils/print_nname.rs +++ /dev/null @@ -1,9 +0,0 @@ -use itertools::Itertools; - -use crate::interner::Interner; -use crate::Sym; - -/// Print symbols to :: delimited strings -pub fn sym2string(t: Sym, i: &Interner) -> String { - i.r(t).iter().map(|t| i.r(*t)).join("::") -}