Skip to content

JsLIGO: abstractor generate curried definitions

E. Rivas requested to merge er433/jsligo/curry into dev

Motivation and Context

We are interested in solving the tension between curried and uncurried syntax.


This MR tries to make JsLIGO abstractor to generate curried definitions, and explore its limitations.


  • JsLIGO abstractor (passes/04).
  • Build here and there to make compile contract work with curried contracts.
  • Contracts, tests, MD files (CameLIGO/PascaLIGO, Test.originate ~> Test.originate_uncurried; JsLIGO, uncurrying certain functions).

There's a considerable number of files updated in this MR, however, most of them are related to tests.

These were issues that got solutions implemented:

  1. Contracts need to be written as let main = ([p, s]: [parameter, storage]) => ... instead of let main = (p: parameter, s: storage) => ....

    Implemented solutions:

    • Make compile contract accept such functions and uncurry them, also for views. -> IMPLEMENTED (contracts now can be in curried form when using compile contract)
    • A modification/currying op. for Test.originate. -> IMPLEMENTED (Test.originate now takes a curried function, there's a Test.originate_uncurried)

    Other possible solutions:

    • These problems might be fixed anyway when we have a first-class contract.

Right now, the main remaining drawbacks:

  1. No control of partial applications: if let f = (x: int, y: int) => x + y, then f(4) is a valid application. This could be only checked at Ast_typed (or during 10-checking?), but at this point we are already in an IR where CameLIGO and JsLIGO are unified?

    Possible solutions: implement extra fields/cases that keep information about "multiparameter" functions? Need to make the typer aware of these?

  2. Possible we close more often over big_map/etc.? This is already an existing problem in CameLIGO (we've merged an error reporting thing in !2231 (merged) , but still no proper solution?).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Performance improvement (non-breaking change that improves performance)
  • None (change with no changelog)


Previously, multiparameter functions in JsLIGO were compiled to a function taking a tuple of parameters.

After this MR, multiparameter functions in JsLIGO are compiled to curried functions.

Contracts do still require taking a tuple (parameter, storage) (as in Michelson). However, LIGO will transform curried contracts to its uncurried form when using compile contract. The same is true for views, taking still tuples (argument, storage), but curried views will be uncurried automatically as well.

New functions are introduced at top-level:

  • val curry : ('a -> 'b -> 'c) -> ('a * 'b -> 'c)
  • val uncurry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c

For testing, Test.originate will take an curried contract of the form parameter -> storage -> operation list * storage. The old (uncurried) alternative is still available as Test.originate_uncurried.


  • Changes follow the existing coding style (use dune @fmt to check).
  • Tests for the changes have been added (for bug fixes / feature).
  • Documentation has been updated.
  • Changelog description has been added (if appropriate).
  • Start titles under ## Changelog section with #### (if appropriate).
  • There is no image or uploaded file in changelog
  • Examples in changed behaviour have been added to the changelog (for breaking change / feature).
Edited by E. Rivas

Merge request reports