Skip to content

Interfaces and module types: implement `extends`/`include`

E. Rivas requested to merge er433/interfaces/include into dev

Motivation and Context

We don't have a way of doing include in module type (like we do in module).

Description

This MR introduces include for module type in CameLIGO and it also implements extends for interfaces in JsLIGO.

In addition:

  • It makes JsLIGO support multiple interfaces in implements.
  • It makes JsLIGO's interfaces not filter.
  • It adds support to JsLIGO for optional item values in interfaces.

Component

  • compiler
  • website
  • webide
  • vscode-plugin
  • debugger

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)

Changelog

Here is an example showing include in module type:

module type FA0 = sig
  type t
  [@entry] val transfer : unit -> t -> operation list * t
end

module type FA0EXT = sig
  include FA0
  [@entry] val transfer2 : unit -> t -> operation list * t
end

module FA0Impl : FA0 = struct
  type t = unit
  [@entry] let transfer (_ : unit) (_ : t) : operation list * t = ([], ())
end

module FA0EXTImpl : FA0EXT = struct
  include FA0Impl

  [@entry] let transfer2 (_ : unit) (_ : t) : operation list * t = ([], ())
end

Here is an example showing JsLIGO's new features:

interface FABase {
  type t;
};

interface FA0 extends FABase {
  @entry const transfer : (_u : unit, s : t) => [list<operation>, t];
};

interface FA0Ext extends FA0 {
  @entry const other1 : (_u : unit, s : t) => [list<operation>, t];
};

interface FA1 extends FABase {
  @entry const other2 : (_u : unit, s : t) => [list<operation>, t];
};

namespace Impl implements FA0Ext, FA1 {
  type t = int;

  @entry const transfer = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
  @entry const other1 = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
  @entry const other2 = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
};

interface FAAll extends FA0Ext, FA1 {
  @entry const other3 : (_u : unit, s : t) => [list<operation>, t];
  @view const v1 : (_u : unit, s : t) => t;

  /* this one is optional, so it doesn't need to be implemented */
  @entry const juju? : (i : int, s : t) => [list<operation>, t];
};

namespace ImplAll implements FAAll {
  type t = int;

  @entry const transfer = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
  @entry const other1 = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
  @entry const other2 = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
  @entry const other3 = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
  @view const v1 = (_u : unit, s : t) : t => s;

  /* foo, other4 and v2 are not in FAAll, but still added, because filtering
     is not enabled */
  export const foo = (s : t) : t => s;
  @entry const other4 = (_u : unit, s : t) : [list<operation>, t] => [list([]), s];
  @view const v2 = (_u : unit, s : t) : t => s;
}

const test = do {
  let orig = Test.originate(contract_of(ImplAll), ImplAll.foo(42), 0tez);
  let p : parameter_of ImplAll = Other4();
  Test.transfer_exn(orig.addr, p, 1mutez);
}

Checklist:

  • If a new syntax has been introduced, put a message on slack ligo-lsp
  • 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