From 95fc6832fd8b97257640731b24efacf4828fb0c0 Mon Sep 17 00:00:00 2001 From: Kai Schmidt Date: Fri, 29 Nov 2024 12:46:12 -0800 Subject: [PATCH] add epsilon constant --- changelog.md | 2 ++ src/lex.rs | 46 +++++++++++++++++++++++++++++++++++++++---- src/primitive/defs.rs | 4 ++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index 3ab823f97..0895b088d 100644 --- a/changelog.md +++ b/changelog.md @@ -30,6 +30,8 @@ This version is not yet released. If you are reading this on the website, then t - Stabilize [`last ⊣`](https://uiua.org/docs/last) - Getting the last row is a very common operation - Negative indices to [`pick ⊡`](https://uiua.org/docs/pick) and [`select ⊏`](https://uiua.org/docs/select) now always use a fill value if available +- Add an `ε` shadowable constant for the machine epsilon + - You can type it as `Epsilon` - Add [`&ep`](https://uiua.org/docs/&ep) and [`&epf`](https://uiua.org/docs/&epf) system functions for easier printing to stderr - Change [`backward 𝄈`](https://uiua.org/docs/backward)'s glyph to `𝄈`. Code using `˜` will continue to work and will be formatted as `𝄈`. - Add the experimental [`or ∨`](https://uiua.org/docs/or) function diff --git a/src/lex.rs b/src/lex.rs index 40be0da2f..354908865 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -1,7 +1,7 @@ //! The Uiua lexer use std::{ - collections::VecDeque, + collections::{BTreeMap, VecDeque}, error::Error, fmt, hash::Hash, @@ -1615,7 +1615,7 @@ pub fn is_custom_glyph(c: &str) -> bool { } pub(crate) fn canonicalize_ident(ident: &str) -> Ident { - canonicalize_subscripts(&canonicalize_exclams(ident)) + canonicalize_special(canonicalize_subscripts(canonicalize_exclams(ident))) } /// Rewrite the identifier with the same number of exclamation points @@ -1640,9 +1640,9 @@ fn place_exclams(ident: &str, count: usize) -> Ident { } /// Rewrite the identifier with numerals preceded by `__` replaced with subscript characters -fn canonicalize_subscripts(ident: &str) -> Ident { +fn canonicalize_subscripts(ident: Ident) -> Ident { if !ident.contains('_') { - return ident.into(); + return ident; } // This hasty canonicalization is okay because the stricter // rules about the syntax are handled in the lexer @@ -1657,6 +1657,44 @@ fn canonicalize_subscripts(ident: &str) -> Ident { .collect() } +thread_local! { + static SPECIAL: BTreeMap<&'static str, &'static str> = [ + ("Alpha", "α"), + ("Beta", "β"), + ("Gamma", "γ"), + ("Delta", "δ"), + ("Epsilon", "ε"), + ("Zeta", "ζ"), + ("Iota", "ι"), + ("Kappa", "κ"), + ("Lambda", "λ"), + ("Mu", "μ"), + ("Nu", "ν"), + ("Xi", "ξ"), + ("Omicron", "ο"), + ("Rho", "ρ"), + ("Sigma", "σ"), + ("Upsilon", "υ"), + ("Phi", "φ"), + ("Chi", "χ"), + ("Psi", "ψ"), + ("Omega", "ω"), + ].into() +} + +fn canonicalize_special(ident: Ident) -> Ident { + let end = ident + .find(|c: char| "!‼₋".contains(c) || SUBSCRIPT_DIGITS.contains(&c)) + .unwrap_or(ident.len()); + if let Some(replacement) = SPECIAL.with(|map| map.get(&ident[..end]).copied()) { + let mut new = Ident::from(replacement); + new.push_str(&ident[end..]); + new + } else { + ident + } +} + fn pick_subscript(neg: bool, n: Option, overflow: bool) -> Subscript { if overflow { return Subscript::TooLarge; diff --git a/src/primitive/defs.rs b/src/primitive/defs.rs index fbc5ba09a..ea93b7d90 100644 --- a/src/primitive/defs.rs +++ b/src/primitive/defs.rs @@ -154,6 +154,10 @@ constant!( ("W", Math, WILDCARD_NAN), /// The maximum integer that can be represented exactly ("MaxInt", Math, 2f64.powi(53)), + /// The machine epsilon for Uiua numbers + /// + /// It is the difference between 1 and the next larger representable number. + ("ε", Math, f64::EPSILON), /// A string identifying the operating system ("Os", System, std::env::consts::OS), /// A string identifying family of the operating system