From 56f47bf17681a727268ab15e8771998a76201cbb Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Thu, 25 Jun 2026 10:20:35 +0000 Subject: [PATCH] Decouple functions from fields namespace Surprisingly fields and functions share a namespace. There can't be a function called "len" if a field "len" is also present. This happens exactly in hyperion. ElfMmapEvent has a len field, so registering a function fails there. It's a footgun. Luckily with a simple fix. Put function and field names in separate lookup maps. The lexer knows to use the function lookup map if the name is followed by (. --- engine/src/scheme.rs | 85 ++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/engine/src/scheme.rs b/engine/src/scheme.rs index db21743..97b0a23 100644 --- a/engine/src/scheme.rs +++ b/engine/src/scheme.rs @@ -443,9 +443,17 @@ impl<'i, 's> LexWith<'i, &'s Scheme> for Identifier<'s> { let name = span(initial_input, input); - let field = scheme - .get(name) - .ok_or((LexErrorKind::UnknownIdentifier, name))?; + let field = if input.starts_with('(') { + scheme + .get_function(name) + .map(Identifier::Function) + .map_err(|_| (LexErrorKind::UnknownIdentifier, name))? + } else { + scheme + .get_field(name) + .map(Identifier::Field) + .map_err(|_| (LexErrorKind::UnknownIdentifier, name))? + }; Ok((field, input)) } @@ -628,7 +636,8 @@ struct FieldDefinition { pub struct SchemeBuilder { fields: Vec, functions: Vec<(IdentifierName, Box)>, - items: HashMap, + fields_map: HashMap, + functions_map: HashMap, list_types: HashMap, lists: Vec<(Type, Box)>, @@ -648,15 +657,10 @@ impl SchemeBuilder { ty: Type, optional: bool, ) -> Result<(), IdentifierRedefinitionError> { - match self.items.entry(name) { - Entry::Occupied(entry) => match entry.get() { - SchemeItem::Field(_) => Err(IdentifierRedefinitionError::Field( - FieldRedefinitionError(entry.key().to_string()), - )), - SchemeItem::Function(_) => Err(IdentifierRedefinitionError::Function( - FunctionRedefinitionError(entry.key().to_string()), - )), - }, + match self.fields_map.entry(name) { + Entry::Occupied(entry) => Err(IdentifierRedefinitionError::Field( + FieldRedefinitionError(entry.key().to_string()), + )), Entry::Vacant(entry) => { let index = self.fields.len(); self.fields.push(FieldDefinition { @@ -664,7 +668,7 @@ impl SchemeBuilder { ty, optional, }); - entry.insert(SchemeItem::Field(index)); + entry.insert(index); Ok(()) } } @@ -694,20 +698,15 @@ impl SchemeBuilder { name: N, function: impl FunctionDefinition + 'static, ) -> Result<(), IdentifierRedefinitionError> { - match self.items.entry(name.as_ref().into()) { - Entry::Occupied(entry) => match entry.get() { - SchemeItem::Field(_) => Err(IdentifierRedefinitionError::Field( - FieldRedefinitionError(entry.key().to_string()), - )), - SchemeItem::Function(_) => Err(IdentifierRedefinitionError::Function( - FunctionRedefinitionError(entry.key().to_string()), - )), - }, + match self.functions_map.entry(name.as_ref().into()) { + Entry::Occupied(entry) => Err(IdentifierRedefinitionError::Function( + FunctionRedefinitionError(entry.key().to_string()), + )), Entry::Vacant(entry) => { let index = self.functions.len(); self.functions .push((entry.key().clone(), Box::new(function))); - entry.insert(SchemeItem::Function(index)); + entry.insert(index); Ok(()) } } @@ -851,26 +850,16 @@ impl<'de> Deserialize<'de> for Scheme { } impl<'s> Scheme { - /// Returns the [`identifier`](enum@Identifier) with the specified `name`. - pub(crate) fn get(&'s self, name: &str) -> Option> { - self.inner.items.get(name).map(move |item| match *item { - SchemeItem::Field(index) => Identifier::Field(FieldRef { - scheme: self, - index, - }), - SchemeItem::Function(index) => Identifier::Function(FunctionRef { - scheme: self, - index, - }), - }) - } - /// Returns the [`field`](struct@Field) with the specified `name`. pub fn get_field(&'s self, name: &str) -> Result, UnknownFieldError> { - match self.get(name) { - Some(Identifier::Field(f)) => Ok(f), - _ => Err(UnknownFieldError), - } + self.inner + .fields_map + .get(name) + .map(move |item| FieldRef { + scheme: self, + index: *item, + }) + .ok_or(UnknownFieldError) } /// Iterates over fields registered in the [`scheme`](struct@Scheme). @@ -896,10 +885,14 @@ impl<'s> Scheme { /// Returns the [`function`](struct@Function) with the specified `name`. pub fn get_function(&'s self, name: &str) -> Result, UnknownFunctionError> { - match self.get(name) { - Some(Identifier::Function(f)) => Ok(f), - _ => Err(UnknownFunctionError), - } + self.inner + .functions_map + .get(name) + .map(move |item| FunctionRef { + scheme: self, + index: *item, + }) + .ok_or(UnknownFunctionError) } /// Iterates over functions registered in the [`scheme`](struct@Scheme).