Skip to content

Commit 5e83a35

Browse files
refactor(parser): centralize SSA name parsing in SsaName helper
1 parent 9f8ffa9 commit 5e83a35

4 files changed

Lines changed: 51 additions & 36 deletions

File tree

compiler/src/modules/parser/types.rs

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,13 @@ impl SSAChunk {
190190
// prev_slots[i]: slot of name i at version-1, if any.
191191
let mut ps: Vec<Option<u16>> = vec![None; n];
192192
for (i, name) in self.names.iter().enumerate() {
193-
if let Some(pos) = name.rfind('_')
194-
&& let Ok(ver) = name[pos+1..].parse::<u32>()
195-
&& ver > 0 {
196-
let prev = s!(str &name[..pos], "_", int ver - 1);
197-
if let Some(&j) = self.name_index.get(&prev) {
198-
ps[i] = Some(j);
199-
}
193+
if let Some(parsed) = SsaName::parse(name)
194+
&& parsed.version > 0
195+
{
196+
let prev = s!(str parsed.bare, "_", int parsed.version as i64 - 1);
197+
if let Some(&j) = self.name_index.get(&prev) {
198+
ps[i] = Some(j);
199+
}
200200
}
201201
}
202202

@@ -255,16 +255,40 @@ pub(crate) struct JoinNode {
255255
pub(super) then: Option<HashMap<String, u32>>,
256256
}
257257

258+
/* Parsed view of a `<bare>_<digits>` SSA-suffixed name. Returned by
259+
`SsaName::parse` and used everywhere callers need the bare prefix
260+
and/or the numeric version, instead of re-doing the rfind('_') +
261+
ascii-digit + parse dance inline. */
262+
pub struct SsaName<'a> {
263+
pub bare: &'a str,
264+
pub version: u32,
265+
}
266+
267+
impl<'a> SsaName<'a> {
268+
/* Returns Some(parts) when `name` matches `<bare>_<digits>`; None
269+
for synthetic temps (`#cmp`, `#match`) and any non-SSA name. */
270+
pub fn parse(name: &'a str) -> Option<Self> {
271+
let pos = name.rfind('_')?;
272+
if pos + 1 >= name.len() { return None; }
273+
let suffix = &name[pos + 1..];
274+
if !suffix.bytes().all(|b| b.is_ascii_digit()) { return None; }
275+
let version = suffix.parse().ok()?;
276+
Some(Self { bare: &name[..pos], version })
277+
}
278+
279+
/* Convenience for callers that want a (bare, version) pair for
280+
every name, falling back to (name, 0) when no SSA suffix is
281+
present. */
282+
pub fn parse_or_bare(name: &'a str) -> (&'a str, u32) {
283+
Self::parse(name)
284+
.map(|s| (s.bare, s.version))
285+
.unwrap_or((name, 0))
286+
}
287+
}
288+
258289
/* Strips `_<digits>` SSA suffix for user-facing diagnostics; returns input unchanged if absent. */
259290
pub fn ssa_strip(name: &str) -> &str {
260-
if let Some(pos) = name.rfind('_')
261-
&& pos + 1 < name.len()
262-
&& name[pos + 1..].bytes().all(|b| b.is_ascii_digit())
263-
{
264-
&name[..pos]
265-
} else {
266-
name
267-
}
291+
SsaName::parse(name).map(|s| s.bare).unwrap_or(name)
268292
}
269293

270294
/* Diagnostic with byte offsets; line/col computed at render time (UTF-8 safe). */

compiler/src/modules/vm/builtins/attr.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,7 @@ impl<'a> VM<'a> {
153153
Some(v) if !v.is_undef() => *v,
154154
_ => continue,
155155
};
156-
let bare = match name.rfind('_') {
157-
Some(p) if name[p + 1..].chars().all(|c| c.is_ascii_digit()) =>
158-
name[..p].to_string(),
159-
_ => name.clone(),
160-
};
156+
let bare = crate::modules::parser::ssa_strip(name).to_string();
161157
// User assignment overrides the builtin entry of the same name.
162158
out.insert(bare, v);
163159
}
@@ -191,11 +187,8 @@ impl<'a> VM<'a> {
191187
// scratch — never user-visible.
192188
if name.starts_with('#') { continue; }
193189
// Strip SSA version suffix.
194-
let (bare, ver) = match name.rfind('_') {
195-
Some(p) if name[p + 1..].chars().all(|c| c.is_ascii_digit()) =>
196-
(&name[..p], name[p + 1..].parse::<i64>().unwrap_or(0)),
197-
_ => (name.as_str(), 0),
198-
};
190+
let (bare, ver) = crate::modules::parser::SsaName::parse_or_bare(name);
191+
let ver = ver as i64;
199192
// Skip unmodified builtins: if the global registration for this
200193
// name points at the *same* Val we'd return, the user never
201194
// rebound it locally — exclude from locals().

compiler/src/modules/vm/init.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,12 @@ impl<'a> VM<'a> {
8282
// re-parsing each name on every miss.
8383
let mut name_versions: super::NameVersionIndex = crate::util::fx::FxHashMap::default();
8484
for (si, sname) in chunk.names.iter().enumerate() {
85-
if let Some(p) = sname.rfind('_')
86-
&& let Ok(v) = sname[p+1..].parse::<i64>() {
87-
name_versions
88-
.entry(sname[..p].to_string())
89-
.or_default()
90-
.push((v, si));
91-
}
85+
if let Some(parsed) = crate::modules::parser::SsaName::parse(sname) {
86+
name_versions
87+
.entry(parsed.bare.to_string())
88+
.or_default()
89+
.push((parsed.version as i64, si));
90+
}
9291
}
9392
self.chunk_name_versions.insert(chunk as *const _, name_versions);
9493
for class_body in chunk.classes.iter() {

compiler/src/modules/vm/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ impl<'a> VM<'a> {
237237
// we explicitly require the suffix-bearing form here, not
238238
// ssa_strip's "fall through to bare on missing suffix" shape.
239239
let canon = body.names.iter().enumerate()
240-
.find(|(_, n)| n.rfind('_').map(|p| &n[..p]) == Some(base.as_str()))
240+
.find(|(_, n)| crate::modules::parser::SsaName::parse(n).map(|s| s.bare) == Some(base.as_str()))
241241
.map(|(i, _)| body.alias_groups.get(i).and_then(|g| g.first().copied()).unwrap_or(i as u16) as usize)?;
242242
Some((canon, canon))
243243
}).collect()
@@ -284,9 +284,8 @@ impl<'a> VM<'a> {
284284
if canon != slot { return None; }
285285
if param_bm.get(slot).copied().unwrap_or(false) { return None; }
286286
if written.contains(&slot) { return None; }
287-
let p = name.rfind('_')?;
288-
name[p+1..].parse::<u32>().ok()?;
289-
Some((name[..p].to_string(), slot))
287+
let parsed = crate::modules::parser::SsaName::parse(name)?;
288+
Some((parsed.bare.to_string(), slot))
290289
}).collect()
291290
}).collect();
292291

0 commit comments

Comments
 (0)