Refactor regex compilation and use is_some_and
This commit introduces several improvements: - Pre-compiles regular expressions in `ast/tester.rs` to avoid redundant compilation, improving performance. - Replaces `.extension().map_or(false, |ext| ext == "myc")` with the more concise and readable `.extension().is_some_and(|ext| ext == "myc")`. - Simplifies upvalue capture logic by using `.or_default()` instead of `.or_insert_with(HashSet::new)`. - Adds a `Default` implementation for `TracingObserver`. - Optimizes string literal parsing in `highlight_myc` to correctly handle escape sequences. - Uses `saturating_sub` for bracket depth to prevent underflow.
This commit is contained in:
@@ -35,7 +35,7 @@ impl UpvalueAnalyzer {
|
||||
// Captured from an outer scope!
|
||||
if let Some(lambda_id) = ¤t_lambda {
|
||||
capture_map.entry(decl_id.clone())
|
||||
.or_insert_with(HashSet::new)
|
||||
.or_default()
|
||||
.insert(lambda_id.clone());
|
||||
}
|
||||
}
|
||||
|
||||
+22
-21
@@ -21,14 +21,15 @@ pub fn run_functional_tests() -> Vec<TestResult> {
|
||||
let mut results = Vec::new();
|
||||
let entries = fs::read_dir("examples").unwrap();
|
||||
let env = Environment::new();
|
||||
let output_re = Regex::new(r";; Output: (.*)").unwrap();
|
||||
|
||||
for entry in entries.filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
if path.extension().map_or(false, |ext| ext == "myc") {
|
||||
if path.extension().is_some_and(|ext| ext == "myc") {
|
||||
let content = fs::read_to_string(&path).unwrap();
|
||||
let name = path.file_name().unwrap().to_string_lossy().to_string();
|
||||
|
||||
let expected_output = Regex::new(r";; Output: (.*)").unwrap()
|
||||
let expected_output = output_re
|
||||
.captures(&content)
|
||||
.map(|m| m.get(1).unwrap().as_str().trim().to_string());
|
||||
|
||||
@@ -55,15 +56,15 @@ pub fn run_benchmarks(update: bool) -> Vec<BenchmarkResult> {
|
||||
let entries = fs::read_dir("examples").unwrap();
|
||||
let env = Environment::new();
|
||||
let is_release = !cfg!(debug_assertions);
|
||||
let baseline_re = Regex::new(r";; Benchmark: ([\d\.]+\w+)").unwrap();
|
||||
|
||||
for entry in entries.filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
if path.extension().map_or(false, |ext| ext == "myc") {
|
||||
if path.extension().is_some_and(|ext| ext == "myc") {
|
||||
let content = fs::read_to_string(&path).unwrap();
|
||||
let name = path.file_name().unwrap().to_string_lossy().to_string();
|
||||
|
||||
let baseline_pattern = Regex::new(r";; Benchmark: ([\d\.]+\w+)").unwrap();
|
||||
let baseline_match = baseline_pattern.captures(&content);
|
||||
let baseline_match = baseline_re.captures(&content);
|
||||
|
||||
// Measure
|
||||
let mut runs = Vec::new();
|
||||
@@ -80,24 +81,21 @@ pub fn run_benchmarks(update: bool) -> Vec<BenchmarkResult> {
|
||||
let updated_content = if let Some(m) = baseline_match {
|
||||
content.replace(m.get(0).unwrap().as_str(), &format!(";; Benchmark: {}", new_val))
|
||||
} else {
|
||||
format!(";; Benchmark: {}
|
||||
{}", new_val, content)
|
||||
format!(";; Benchmark: {}\n{}", new_val, content)
|
||||
};
|
||||
fs::write(&path, updated_content).unwrap();
|
||||
results.push(BenchmarkResult { name, median, baseline: None, diff_pct: None, status: format!("UPDATED: {}", new_val) });
|
||||
} else if let Some(m) = baseline_match {
|
||||
let baseline_str = m.get(1).unwrap().as_str();
|
||||
let baseline = parse_duration(baseline_str).unwrap();
|
||||
let diff = (median.as_nanos() as f64 / baseline.as_nanos() as f64) - 1.0;
|
||||
|
||||
let threshold = if is_release { 0.10 } else { 0.25 };
|
||||
let status = if median > baseline && diff > threshold { "FAILED" } else { "OK" };
|
||||
|
||||
results.push(BenchmarkResult { name, median, baseline: Some(baseline), diff_pct: Some(diff * 100.0), status: status.to_string() });
|
||||
} else {
|
||||
if let Some(m) = baseline_match {
|
||||
let baseline_str = m.get(1).unwrap().as_str();
|
||||
let baseline = parse_duration(baseline_str).unwrap();
|
||||
let diff = (median.as_nanos() as f64 / baseline.as_nanos() as f64) - 1.0;
|
||||
|
||||
let threshold = if is_release { 0.10 } else { 0.25 };
|
||||
let status = if median > baseline && diff > threshold { "FAILED" } else { "OK" };
|
||||
|
||||
results.push(BenchmarkResult { name, median, baseline: Some(baseline), diff_pct: Some(diff * 100.0), status: status.to_string() });
|
||||
} else {
|
||||
results.push(BenchmarkResult { name, median, baseline: None, diff_pct: None, status: "MISSING BASELINE".to_string() });
|
||||
}
|
||||
results.push(BenchmarkResult { name, median, baseline: None, diff_pct: None, status: "MISSING BASELINE".to_string() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,8 +110,11 @@ fn format_duration(d: Duration) -> String {
|
||||
}
|
||||
|
||||
fn parse_duration(s: &str) -> Option<Duration> {
|
||||
let re = Regex::new(r"([\d\.]+)(\w+)").unwrap();
|
||||
let caps = re.captures(s)?;
|
||||
use lazy_static::lazy_static;
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"([\d\.]+)(\w+)").unwrap();
|
||||
}
|
||||
let caps = RE.captures(s)?;
|
||||
let val: f64 = caps[1].parse().ok()?;
|
||||
let unit = &caps[2];
|
||||
match unit {
|
||||
|
||||
@@ -53,6 +53,12 @@ impl TracingObserver {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TracingObserver {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl VMObserver for TracingObserver {
|
||||
const ACTIVE: bool = true;
|
||||
|
||||
|
||||
+5
-5
@@ -46,7 +46,7 @@ impl Default for CompilerApp {
|
||||
.map(|entries| {
|
||||
entries
|
||||
.filter_map(|e| e.ok())
|
||||
.filter(|e| e.path().extension().map_or(false, |ext| ext == "myc"))
|
||||
.filter(|e| e.path().extension().is_some_and(|ext| ext == "myc"))
|
||||
.filter_map(|e| {
|
||||
let path = e.path();
|
||||
let name = e.file_name().into_string().ok()?;
|
||||
@@ -184,7 +184,7 @@ impl CompilerApp {
|
||||
if let Ok(entries) = std::fs::read_dir("examples") {
|
||||
self.examples = entries
|
||||
.filter_map(|e| e.ok())
|
||||
.filter(|e| e.path().extension().map_or(false, |ext| ext == "myc"))
|
||||
.filter(|e| e.path().extension().is_some_and(|ext| ext == "myc"))
|
||||
.filter_map(|e| {
|
||||
let path = e.path();
|
||||
let name = e.file_name().into_string().ok()?;
|
||||
@@ -445,8 +445,8 @@ fn highlight_myc(ctx: &egui::Context, code: &str) -> egui::text::LayoutJob {
|
||||
while let Some(next) = chars.next() {
|
||||
text.push(next);
|
||||
if next == '"' { break; }
|
||||
if next == '\\' {
|
||||
if let Some(escaped) = chars.next() { text.push(escaped); }
|
||||
if next == '\\' && let Some(escaped) = chars.next() {
|
||||
text.push(escaped);
|
||||
}
|
||||
}
|
||||
color = color_str;
|
||||
@@ -463,7 +463,7 @@ fn highlight_myc(ctx: &egui::Context, code: &str) -> egui::text::LayoutJob {
|
||||
bracket_depth += 1;
|
||||
}
|
||||
')' | ']' | '}' => {
|
||||
if bracket_depth > 0 { bracket_depth -= 1; }
|
||||
bracket_depth = bracket_depth.saturating_sub(1);
|
||||
color = color_bracket[bracket_depth % 3];
|
||||
}
|
||||
'0'..='9' => {
|
||||
|
||||
Reference in New Issue
Block a user