8000 bug(emitter): preserve ANLU calls when their return values are discarded · Issue #191 · Mnehmos/mnehmos.nls.lang · GitHub
[go: up one dir, main page]

Skip to content

bug(emitter): preserve ANLU calls when their return values are discarded #191

Closed

Description

@Mnehmos

Audited on master at 5630d74ec9cd912d4e2f325349f1943cbc15bcc6. This is a scoped implementation item under #147, based on the typed control/dataflow/effect audit. Proposed syntax below is illustrative unless explicitly marked as a current reproducer.

Problem and current evidence

Python silently drops a valid call used only for its effects or failure behavior. nlsc/emitter.py:574–632 only emits assignments/output bindings, and nlsc/emitter.py:413–420 turns other steps into comments. TypeScript does emit unbound expression statements via nlsc/emitter_typescript.py:288–302.

Current reproducer:

@module discarded_call
[reject]
PURPOSE: Always raise when called
GUARDS:
  - False -> ValueError("called")
RETURNS: 0

[probe]
PURPOSE: Call reject
LOGIC:
  1. [reject]()
DEPENDS: [reject]
RETURNS: 0

Validation succeeds. Generated Python contains # [reject](), and probe() returns 0 instead of raising. Payment/logging/notification calls can likewise disappear simply because the caller does not bind a result.

Implementation hints

  • Add a real expression-statement / discarded-call node. Its output is unused; its execution, effects, and errors remain semantically required.
  • For the immediate patch, recognize complete supported calls independently of output_binding, using a parser with balanced arguments. Do not make arbitrary English executable.
  • Route conditional and unconditional discarded calls through the same mechanism. Preserve source order and execute exactly once per reached step.
  • In the later IR migration, retain these nodes during dead-value elimination unless the operation is proven removable under the full effect/failure contract.
  • Do not require users to add meaningless temporary variables as a workaround.

Acceptance criteria

  • The reproducer raises ValueError("called") under Python.
  • A local fake operation appending to an event log is invoked once with and without an output binding.
  • A false conditional does not invoke its discarded call; a true conditional invokes it once.
  • Returned values remain discardable, and void operations do not need fake bindings.
  • Backend tests compare ordered events and normalized errors, not just source substrings.

The failure here is call execution itself; the separate error-contract item addresses TypeScript's undefined ValueError class.

Implementation ordering

Can begin immediately; integrate with the checked IR work under #147. Add the regression fixtures before implementation.

Activity

  1. added
    bugSomething isn't working
    emitterCode generation targets
    on Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingemitterCode generation targetspriority-highImportant, address soon

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0