Skip to content

[#470] Added `UNPAIR n` instruction

Diogo Castro requested to merge diogo/#470-unpair-n into master

Description

This MR adds the new UNPAIR n instruction.

UNPAIR n takes a right-combed pair off the top of the stack, and splits it into n values.

UNPAIR 3 : [pair a b c] -> [a : b : c]

If the pair contains more than n elements, then the remaining elements are left "tupled".

UNPAIR 3 : [pair a b c d] -> [a : b : pair c d]

Implementation note: Usually, while typecheking an instruction, we insert the annotations in right stack elements, and then Helpers.wrapWithNotes extracts those annotations and wraps them in meta-instructions (like InstrWithNotes and InstrWithVarAnns).

Later, when interpreting an instruction, we rely on those meta-instructions to handle annotations.

-- handles annotations
runInstrImpl runner (InstrWithVarAnns vns i) inp = do
  runner i inp <&> \case
    StkEl v1 _ n1 :& StkEl v2 vn2 n2 :& r -> case vns of
      U.OneVarAnn vn      -> StkEl v1 vn n1 :& StkEl v2 vn2 n2 :& r
      U.TwoVarAnns vn vn' -> StkEl v1 vn n1 :& StkEl v2 vn' n2 :& r
    StkEl v _ n :& r -> case vns of
      U.OneVarAnn vn   -> StkEl v vn n :& r
      U.TwoVarAnns _ _ -> error "Input stack is exhausted but there is still a variable annotation."
    RNil -> error "Input stack is exhausted but there is still variables annotations."

-- does not need to handle annotations, they've already been handled by the meta-instr
runInstrImpl _ (AnnPAIR{}) ((StkEl a _ _) :& (StkEl b _ _) :& r) =
  pure $ starNotesStkEl (VPair (a, b)) :& r

However, this separation of concerns it a lot harder to do for UNPAIR n. All other instructions put a fixed number of values at the top of the stack (either 1 or 2 values), whereas UNPAIR n pushes a variable number of values. Thus, capturing all polymorphic Notes x and then later, in the interpreter, lining them up again with the stack elements, is not trivial.

IMO, it's much simpler to not use meta-instructions here, and simply handle the annotations in runInstrImpl _ UNPAIRN.

Please let me know what you think about this, and if there are other advantages to using meta-instructions that I may have overlooked.

Related issue(s)

Resolves part of #470 (closed)

Checklist for your Merge Request

Related changes (conditional)

  • Tests (see short guidelines)

    • If I added new functionality, I added tests covering it.
    • If I fixed a bug, I added a regression test to prevent the bug from silently reappearing again.
  • Documentation

    • I checked whether I should update the docs and did so if necessary:
    • I updated changelog files of all affected packages released to Hackage if my changes are externally visible.

Stylistic guide (mandatory)

Edited by Diogo Castro

Merge request reports