Skip to content

Allow Translation of Nev Rule Ids back to Rules and their Line Numbers#790

Merged
mmarx merged 11 commits into
mainfrom
nev-rule-id
Jun 26, 2026
Merged

Allow Translation of Nev Rule Ids back to Rules and their Line Numbers#790
mmarx merged 11 commits into
mainfrom
nev-rule-id

Conversation

@monsterkrampe

Copy link
Copy Markdown
Member

This PR adds a function to nemo-wasm that allows to translate a rule id from Nev into the corresponding line number in the underlying Nemo program. For this to work, the PR also touches the handling of rule ids in the nemo crate.

@aannleax I'm not sure if you still wanted to clean things up here. For example, there is still a TODO in rule_translation.rs. If we cannot resolve this now then please create a technical debt issue for that. Once you are done, please mark the PR as ready :)

@monsterkrampe monsterkrampe added wasm issue related to compiling for the Web Assembly target tracing Issue related to tracing of derived facts labels Jun 26, 2026
@github-project-automation github-project-automation Bot moved this to Todo in nemo Jun 26, 2026
@aannleax

Copy link
Copy Markdown
Member

"If we cannot resolve this now then please create a technical debt issue for that."
I guess the issue exists already (#774), though its a bit vague.

@monsterkrampe

Copy link
Copy Markdown
Member Author

Ah, ok. Maybe putting a link to the issue in the TODO comment then would be nice :)

Comment thread nemo/Cargo.toml Outdated
nemo-physical = { path = "../nemo-physical", default-features = false }
log = { workspace = true }
nom = "7.1.1"
line-index = "0.1.1"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already use that in nemo-language-server, so it's now time to move this out into the top-level Cargo.toml and inherit the version both here and there.

@aannleax

aannleax commented Jun 26, 2026

Copy link
Copy Markdown
Member

This PR also introduces RuleIdTranslation, which basically translates rule indices from the original (before transformations) to the normalized program. Hence, we assume now that no program transformation changes the structure of derivation trees (which is true now).

Also, it properly sets the origins for the global, incermental import, and sparql merge transformations (which is also covered by unit tests now).

And finally, some small changes to the API and how the python and wasm code builds programs and ExecutionEngines.

@aannleax aannleax marked this pull request as ready for review June 26, 2026 14:11
@aannleax aannleax requested a review from mmarx June 26, 2026 14:12
Comment thread nemo-python/src/lib.rs Outdated
Comment thread nemo/src/execution/tracing/rule_translation.rs Outdated
Comment thread nemo/src/execution/tracing/rule_translation.rs Outdated
Comment thread nemo/src/execution/tracing/rule_translation.rs Outdated
Comment on lines +62 to +80
let norm_to_orig = normalized
.rules()
.iter()
.map(|rule| {
let origin_id = tracing_resolve_origin_id(handle, rule.id());
*orig_index_by_id.get(&origin_id).expect(
"a normalized rule has no corresponding original rule; a \
transformation created a rule without recording its origin",
)
})
.collect::<Vec<usize>>();

// Invert the mapping. As the transformations are one-to-one on rules, no
// two normalized rules map to the same original rule, so every insert is
// into a fresh slot (checked via the resulting length below).
let mut orig_to_norm = HashMap::with_capacity(norm_to_orig.len());
for (norm_index, &orig_index) in norm_to_orig.iter().enumerate() {
orig_to_norm.insert(orig_index, norm_index);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not build both mapping simultaneously?

let mut norm_to_orig = HashMap::with_capacity(normalized.rules().count());
let mut orig_to_norm = HashMap::with_capacity(original.rules().count());

for rule in normalized.rules() {
    let origin_id = tracing_resolve_origin_id(handle, rule.id());
    let origin_index = orig_index_by_id.get(&origin_id).expect("each normalized rule has a corresponding original rule");
    let prev = norm_to_orig.insert(rule.id(), origin_index);
    debug_assert!(prev.is_none(), "each normalized rule maps to exactly one original rule");
    let prev = orig_to_norm.insert(origin_index, rule.id());
    debug_assert!(prev.is_none(), "each original rules maps to exactly one normalized rule");
}

Comment thread nemo/src/rule_model/error.rs
Comment thread nemo/src/rule_model/pipeline.rs Outdated
Comment thread nemo/src/parser/span.rs Outdated
Comment thread nemo/src/parser/span.rs
Comment thread nemo/src/rule_model/pipeline.rs Outdated
@github-project-automation github-project-automation Bot moved this from Todo to In Progress in nemo Jun 26, 2026

@mmarx mmarx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, much better. I'd just prefer assert_matches!(…) over assert!(matches!(…)), since that gives much better error messages.

.unwrap();
let rule = transformed.rules().next().unwrap();

assert!(matches!(rule.origin(), Origin::Global(id) if id == original));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better use assert_matches! instead of assert!(matches!(…)), that'll give much better error messages in case of failure:

use std::assert_matches;

assert_matches!(rule.origin(), Origin::Global(id) if id == original)

let transformed = handle.transform(TransformationIncremental::new()).unwrap();
let rule = transformed.rules().next().unwrap();

assert!(matches!(rule.origin(), Origin::Incremental(id) if id == original));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see above)

let transformed = inlined.transform(TransformationMergeSparql).unwrap();
let rule = transformed.rules().next().unwrap();

assert!(matches!(rule.origin(), Origin::MergeSparql(id) if id == predecessor));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see above)

.unwrap();
let rule = transformed.rules().next().unwrap();

assert!(matches!(rule.origin(), Origin::Normalization(id) if id == original));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see above)

@mmarx mmarx enabled auto-merge June 26, 2026 17:44
@mmarx mmarx merged commit 73cf695 into main Jun 26, 2026
8 checks passed
@mmarx mmarx deleted the nev-rule-id branch June 26, 2026 17:56
@github-project-automation github-project-automation Bot moved this from In Progress to Done in nemo Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tracing Issue related to tracing of derived facts wasm issue related to compiling for the Web Assembly target

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants