Skip to content

il2al: host function rules become two independent conditionals and ignore the new store s' #2279

Open

Description

@tamaroning

I came across this while looking at how il2al uses Either for nondeterminism.

The rules Step/call_ref-hostfunc-res and -div (added in #2210) can both apply:

rule Step/call_ref-hostfunc-res:
s; f; val^n (REF.FUNC_ADDR a) (CALL_REF yy) ~> s'; f; $lift_result(result)
----
-- if $funcinst((s; f))[a] = fi
-- Expand: fi.TYPE ~~ FUNC t_1^n -> t_2^m
-- if fi.CODE = _HOSTFUNC hf
-- if RES s' result <- $hostcall(_HOSTFUNC hf, s, val^n)
rule Step/call_ref-hostfunc-div:
s; f; val^n (REF.FUNC_ADDR a) (CALL_REF yy) ~> s; f; val^n (REF.FUNC_ADDR a) (CALL_REF yy)
----
-- if $funcinst((s; f))[a] = fi
-- Expand: fi.TYPE ~~ FUNC t_1^n -> t_2^m
-- if fi.CODE = _HOSTFUNC hf
-- if BOT <- $hostcall(_HOSTFUNC hf, s, val^n)

--prose gives:

13. If an element of $hostcall((_HOSTFUNC hf), s, val^n) is some RES, then:
  a. Let (RES s' result) be an element of $hostcall((_HOSTFUNC hf), s, val^n).
  b. Execute the sequence $lift_result(result).
14. If BOT is contained in $hostcall((_HOSTFUNC hf), s, val^n), then:
  ...
  1. Steps 13 and 14 are not alternatives, so when both apply the algorithm does both.
  2. s' is never used, so the store is not updated.

I would expect something like this, as for memory.grow (not sure how AL should update the whole store):

13. Either:
  a. Let (RES s' result) be an element of $hostcall((_HOSTFUNC hf), s, val^n).
  b. Update the store s to s'.
  c. Execute the sequence $lift_result(result).
14. Or:
  ...

It seems il2al produces Either only for rules without conditions (translate.ml#L1155).

Note: This might be low priority since neither the document nor the reference interpreter uses this algorithm.

Activity

  1. tamaroning commented on Oct 14, 2026

    @tamaroning
    ContributorAuthor

    @zilinc Since these rules came from #2210, I'd appreciate your thoughts on this.

  2. zilinc commented on Oct 15, 2026

    @zilinc
    Contributor

    I can totally believe that the the prose generator may give suboptimal or even wrong output at times. The AL pipeline is by and large by-demand, meaning that we try to ensure that it works for the things that will go into the official document. Since this part of prose isn't used in the official spec, it could be wrong. Unfortunately I think it will remain this way for the near future. Regarding if vs. either, I'm not entirely sure. From the SpecTec formulation, at least, it appears that there's a subtle difference. Here, algorithmically, the nondeterminism comes from the host function call, and "we" don't get to make the choice. Whereas for the grow instructions, "we" can decide which choice to make. So maybe AL is right here to generate "if".

  3. rossberg commented on Oct 15, 2026

    @rossberg
    Member

    Like @zilinc says, the prose backend obviously isn't prepared well for dealing with cases like this.

    I agree that something closer to your second formulation would be adequate, with the modification that the possible choices still somehow need to be conditioned on what is in the set of possible non-determinisitc behaviours, like in the first formulation. Something along the lines of

    1. Let hostresult be the result of $hostcall((_HOSTFUNC hf), s, val^n).
    2. Assert: hostresult is non-empty.
    3. Either, but only if some RES is contained in hostresult, then:
      a. Let (RES s' result) be an element of $hostcall((_HOSTFUNC hf), s, val^n).
      b. Update the store to s'.
      c. Execute the sequence $lift_result(result).
    4. Or, but only if BOT is contained in hostresult, then:
      ...

    @zilinc, I don't think there is a difference in the flavour of non-determinism here. In both this and other cases, some meta-level function expresses the entire set of possible behaviours, and then as a specification device, "execution" arbitrarily picks one.

  4. rossberg commented on Oct 15, 2026

    @rossberg
    Member

    Btw, I think the spec currently doesn't specify that the result of hf must be non-empty. I think it needs to be. (Theoretically, we could have a rule that traps in that case, but that wouldn't reflect any behaviour possible in reality.)

  5. rossberg commented on Oct 15, 2026

    @rossberg
    Member

    @zilinc, please see #2280.

  6. zilinc commented on Oct 16, 2026

    @zilinc
    Contributor

    @zilinc, I don't think there is a difference in the flavour of non-determinism here. In both this and other cases, some meta-level function expresses the entire set of possible behaviours, and then as a specification device, "execution" arbitrarily picks one.

    Oh yeah you're right. I misread the <- part.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions