non-evaluator attribute requires manual propagation across entire call chain

Open
#4,904 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
haskell
Domain
compilers

Research direction

Start by finding the original PR or issue that introduced the non-evaluator attribute, then survey its use outside mir-semantics, including the EXPERIMENT-no-llvm-kompile-updated branch. Trace how the Haskell backend sends call chains and requires clauses to the LLVM backend; done means identifying the root cause, choosing a solution direction, and implementing and verifying it.

Written by the indexing model from the issue text.

Description

area:haskell-backend area:llvm-backend priority:p2 status:icebox type:feature

Problem

The non-evaluator attribute marks a function so it is not evaluated by the LLVM backend. However, in practice, marking a single function as non-evaluator is not enough — every function in the call chain above it must also be manually marked, otherwise the Haskell backend will still send the caller to the LLVM backend, which then encounters a non-evaluator function it cannot handle.

Example:

syntax Int ::= A(Int) [function, non-evaluator]
syntax Int ::= B(Int) [function]

rule B(X) => A(X) +Int 1
  • A is marked non-evaluator
  • B is not marked non-evaluator
  • When the Haskell backend simplifies B(42), since B is not non-evaluator, it sends B(42) to the LLVM backend
  • The LLVM backend attempts to evaluate, unfolds the rule, and encounters A(42) — but A is non-evaluator and the LLVM backend cannot handle it correctly
  • Workaround: manually add non-evaluator to B as well. But then all callers of B also need it, and so on — propagating up the entire call chain

The same issue occurs when a requires clause references a non-evaluator function.

This was discovered in the mir-semantics project (EXPERIMENT-no-llvm-kompile-updated branch), which has many functions unsuitable for LLVM backend execution.

Expected Behavior

non-evaluator should not require manual propagation. Possible directions:

  • The compiler automatically analyzes the call graph and propagates the attribute
  • The Haskell backend recognizes when a term contains non-evaluator functions and handles them itself
  • The LLVM backend gracefully returns unevaluated terms when encountering non-evaluator functions

Suggested First Steps

Before choosing a solution, some investigation is needed:

  1. Find the original PR/issue that introduced non-evaluator to understand the design intent
  2. Survey non-evaluator usage in projects other than mir-semantics — do they encounter the same propagation problem?
  3. Assess the semantics of non-evaluator in concrete execution (pure LLVM backend) scenarios (currently a potential concern, no observed issues yet)

Acceptance Criteria

  • Research non-evaluator introduction history and usage across projects
  • Identify root cause and solution direction
  • Implement and verify
Dominant language
Python
Stars
591
Forks
163
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from runtimeverification/k

All issues in runtimeverification/k

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.