feat: use ere (compile-time regex compilation)

This commit is contained in:
2026-02-07 17:00:06 +08:00
parent 216930027d
commit e8a28a6d2f
4 changed files with 55 additions and 20 deletions

View File

@@ -62,6 +62,7 @@ rnix = "0.12"
rowan = "0.15"
nix-js-macros = { path = "../nix-js-macros" }
ere = "0.2.4"
[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

View File

@@ -1,7 +1,6 @@
use anyhow::Result;
use nix_js::context::Context;
use nix_js::error::Source;
use regex::Regex;
use rustyline::DefaultEditor;
use rustyline::error::ReadlineError;
@@ -10,7 +9,7 @@ fn main() -> Result<()> {
let mut rl = DefaultEditor::new()?;
let mut context = Context::new()?;
let re = Regex::new(r"^\s*([a-zA-Z_][a-zA-Z0-9_'-]*)\s*=(.*)$").unwrap();
const RE: ere::Regex<3> = ere::compile_regex!("^[ \t]*([a-zA-Z_][a-zA-Z0-9_'-]*)[ \t]*(.*)$");
loop {
let readline = rl.readline("nix-js-repl> ");
match readline {
@@ -19,18 +18,16 @@ fn main() -> Result<()> {
continue;
}
let _ = rl.add_history_entry(line.as_str());
if let Some(_caps) = re.captures(&line) {
if let Some([Some(_), Some(_ident), Some(_expr)]) = RE.exec(&line) {
eprintln!("Error: binding not implemented yet");
continue;
/* let ident = caps.get(1).unwrap().as_str();
let expr = caps.get(2).unwrap().as_str().trim();
if expr.is_empty() {
eprintln!("Error: missing expression after '='");
continue;
}
if let Err(err) = context.add_binding(ident, expr) {
eprintln!("Error: {}", err);
} */
// if expr.is_empty() {
// eprintln!("Error: missing expression after '='");
// continue;
// }
// if let Err(err) = context.add_binding(ident, expr) {
// eprintln!("Error: {}", err);
// }
} else {
let src = Source::new_repl(line)?;
match context.eval_shallow(src) {

View File

@@ -5,10 +5,8 @@ use core::ops::Deref;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::ops::DerefMut;
use std::sync::LazyLock;
use derive_more::{Constructor, IsVariant, Unwrap};
use regex::Regex;
/// Represents a Nix symbol, which is used as a key in attribute sets.
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Constructor)]
@@ -23,10 +21,10 @@ impl<T: Into<String>> From<T> for Symbol {
/// Formats a string slice as a Nix symbol, quoting it if necessary.
pub fn format_symbol<'a>(sym: impl Into<Cow<'a, str>>) -> Cow<'a, str> {
let sym = sym.into();
if REGEX.is_match(&sym) {
if Symbol::NORMAL_REGEX.test(&sym) {
sym
} else {
Cow::Owned(format!(r#""{sym}""#))
Cow::Owned(escape_quote_string(&sym))
}
}
@@ -40,13 +38,11 @@ impl Display for Symbol {
}
}
static REGEX: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_'-]*$").expect("hardcoded regex is always valid")
});
impl Symbol {
const NORMAL_REGEX: ere::Regex<1> = ere::compile_regex!("^[a-zA-Z_][a-zA-Z0-9_'-]*$");
/// Checks if the symbol is a "normal" identifier that doesn't require quotes.
fn normal(&self) -> bool {
REGEX.is_match(self)
Self::NORMAL_REGEX.test(self)
}
}