From 6d421ab4b13e037ab5fb1d184a8df11cac97d4b0 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Fri, 31 Jan 2020 17:13:22 -0800 Subject: [PATCH 1/3] Add Map.add to test suite --- src/test/contracts/map.ligo | 1 + src/test/contracts/map.mligo | 4 +++- src/test/contracts/map.religo | 2 ++ src/test/integration_tests.ml | 5 +++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/test/contracts/map.ligo b/src/test/contracts/map.ligo index 797bb1a8b..f6c63598b 100644 --- a/src/test/contracts/map.ligo +++ b/src/test/contracts/map.ligo @@ -20,6 +20,7 @@ function set_ (var n : int ; var m : foobar) : foobar is block { m[23] := n ; } with m +function add (var n : int ; var m : foobar) : foobar is set_(n,m) function rm (var m : foobar) : foobar is block { remove 42 from map m diff --git a/src/test/contracts/map.mligo b/src/test/contracts/map.mligo index 15f45ead1..7b13f406c 100644 --- a/src/test/contracts/map.mligo +++ b/src/test/contracts/map.mligo @@ -11,6 +11,8 @@ let set_2 (n: int) (m: foobar) : foobar = Map.update 23 (Some n) m let set_ (t: int * foobar) : foobar = set_2 t.0 t.1 +let add (n,m: int * foobar) : foobar = Map.add 23 n m + let rm (m: foobar) : foobar = Map.remove 42 m (* Dummy test so that we can add the same test for PascaLIGO *) @@ -30,7 +32,7 @@ let gf (m: foobar) : int = Map.find 23 m let get (m: foobar) : int option = Map.find_opt 42 m let get_ (m: foobar) : int option = Map.find_opt 42 m -let mem (km: int * foobar) : bool = Map.mem km.0 km.1 +let mem (k,m: int * foobar) : bool = Map.mem k m let iter_op (m : foobar) : unit = let assert_eq = fun (i: int * int) -> assert (i.0 = i.1) diff --git a/src/test/contracts/map.religo b/src/test/contracts/map.religo index 6faacb700..74ec39dcf 100644 --- a/src/test/contracts/map.religo +++ b/src/test/contracts/map.religo @@ -10,6 +10,8 @@ let map2: foobar = Map.literal([(23, 0), (42, 0)]); let set_ = (n: int, m: foobar): foobar => Map.update(23, Some(n), m); +let add = (n: int, m: foobar) : foobar => Map.add(23, n, m); + let rm = (m: foobar): foobar => Map.remove(42, m); /* Dummy test so that we can add the same test for PascaLIGO */ diff --git a/src/test/integration_tests.ml b/src/test/integration_tests.ml index 58b492fc2..e944b7c91 100644 --- a/src/test/integration_tests.ml +++ b/src/test/integration_tests.ml @@ -974,6 +974,11 @@ let map_ type_f path : unit result = let make_expected = fun n -> ez [(23 , n) ; (42 , 0)] in expect_eq_n_pos_small program "set_" make_input make_expected in + let%bind () = + let input = (e_pair (e_int 23) (ez [(42, 42)])) in + let expected = ez [(23, 23) ; (42, 42)] in + expect_eq program "add" input expected + in let%bind () = let input = ez [(23, 23) ; (42, 42)] in let expected = ez [23, 23] in From 477d2e1b12f5d4d7f37134ce1886c4a29712b870 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Fri, 31 Jan 2020 17:22:51 -0800 Subject: [PATCH 2/3] Add map reference page to docs --- gitlab-pages/docs/reference/map.md | 334 +++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 gitlab-pages/docs/reference/map.md diff --git a/gitlab-pages/docs/reference/map.md b/gitlab-pages/docs/reference/map.md new file mode 100644 index 000000000..9d764b824 --- /dev/null +++ b/gitlab-pages/docs/reference/map.md @@ -0,0 +1,334 @@ +--- +id: map-reference +title: Map +--- + +## Map.find_opt(k: a', m: (a',b') map) : b' option + +Retrieve the value associated with a particular key. This version returns an option +which can either shift logic in response to a missing value or throw an error. + + + +```pascaligo +const my_balance : option(move) = moves[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)]; +``` + + + +```cameligo +let my_balance : move option = Map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves +``` + + + +```reasonligo +let my_balance : option(move) = + Map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves); +``` + + +## Map.find(k: a', m: (a', b') map) : b' + +Forcefully retrieve the value associated with a particular key. If that value +doesn't exist, this function throws an error. + + + +```pascaligo +const my_balance : move = get_force(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves); +``` + + + +```cameligo +let my_balance : move = Map.find ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) moves +``` + + + +```reasonligo +let my_balance : move = + Map.find("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves); +``` + + + +## Map.update(k: a', v: b', m: (a', b') map) : (a', b') map + +Change the value associated with a particular key, if that value doesn't already +exist add it. + + + + + +The values of a PascaLIGO map can be updated using the ordinary assignment syntax: + +```pascaligo + +function set_ (var m: moveset) : moveset is + block { + m[("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address)] := (4,9); + } with m +``` + + + +We can update a map in CameLIGO using the `Map.update` built-in: + +```cameligo + +let updated_map: moveset = Map.update ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) (Some (4,9)) moves +``` + + + +We can update a map in ReasonLIGO using the `Map.update` built-in: + +```reasonligo + +let updated_map: moveset = Map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves); +``` + + + +## Map.add(k: a', v: b', m: (a', b') map) : (a', b') map + + + + +```pascaligo +function patch_ (var m: foobar) : foobar is block { + patch m with map [0 -> 5; 1 -> 6; 2 -> 7] +} with m +``` + + +```cameligo + +``` + + + + + +## Map.remove(k: a', m: (a', b') map) : (a', b') map + +Remove a key and its associated value from the map. + + + + +```pascaligo +function rm (var m : foobar) : foobar is block { + remove 42 from map m +} with m +``` + + +```cameligo +let rm (m: foobar) : foobar = Map.remove 42 m +``` + + +```reasonligo +let rm = (m: foobar): foobar => Map.remove(42, m); +``` + + + +## Map.iter(iterator_function: (a', b') -> unit, m: (a', b') map) : unit + +Run a function returning unit over the contents of a map's key-value pairs. +For example an assertion. + + + +```pascaligo +function iter_op (const m : moveset) : unit is + block { + function aggregate (const i : address ; const j : move) : unit is block + { if j.1 > 1 then skip else failwith("fail") } with unit + } with map_iter(aggregate, m); +``` + + +```cameligo +let iter_op (m : moveset) : unit = + let assert_eq = fun (i,j: address * move) -> assert (j.0 > 1) + in Map.iter assert_eq m +``` + + +```reasonligo +let iter_op = (m: moveset): unit => { + let assert_eq = ((i,j): (address, move)) => assert (j[0] > 1); + Map.iter(assert_eq, m); +}; +``` + + + +## Map.map(mapping_function: (a', b') -> b', m: (a', b') map) : (a', b') map + +Update the values associated with every key in the map according to some update +rule `mapping_function`. + + + +```pascaligo +function map_op (const m : moveset) : moveset is + block { + function increment (const i : address ; const j : move) : move is (j.0, j.1 + 1); + } with map_map (increment, m); +``` + + +```cameligo +let map_op (m : moveset) : moveset = + let increment = fun (i,j: address * move) -> (j.0, j.1 + 1) + in Map.map increment m +``` + + +```reasonligo +let map_op = (m: moveset): moveset => { + let increment = ((i,j): (address, move)) => (j[0], j[1] + 1); + Map.map(increment, m); +}; +``` + + +## Map.fold(folding_function: (b', (a', b')) -> b', m: (a', b') map, initial: b') : b' + +Combine every value in the map together according to a fold rule `folding_function`. + + + +```pascaligo +function fold_op (const m : moveset) : int is + block { + function aggregate (const j : int; const cur : address * (int * int)) : int is j + cur.1.1 + } with map_fold(aggregate, m, 5) +``` + + +```cameligo +let fold_op (m : moveset) : moveset = + let aggregate = fun (i,j: int * (address * (int * int))) -> i + j.1.1 + in Map.fold aggregate m 5 +``` + + +```reasonligo +let fold_op = (m: moveset): moveset => { + let aggregate = ((i,j): (int, (address, (int,int)))) => i + j[1][1]; + Map.fold(aggregate, m, 5); +}; + +``` + + + + +## Map.mem(k: a', m: (a', b') map) : bool + +Test whether a particular key `k` exists in a given map `m`. + + + + +```pascaligo +function mem (const k: int; const m: foobar) : bool is map_mem(k, m) +``` + +```cameligo +let mem (k,m: int * foobar) : bool = Map.mem k m +``` + + +```reasonligo +let mem = (km: (int, foobar)): bool => Map.mem(km[0], km[1]); +``` + + + +## Map.empty() : (a', b') map + +Create an empty map. + + + + +```pascaligo +const empty_map : foobar = map end +``` + +```cameligo +let empty_map : foobar = Map.empty +``` + + +```reasonligo +let empty_map: foobar = Map.empty; +``` + + + +## Map.literal(key_value_pair_list: (a', b') list) : (a', b') map + +Constructs a map from a list of key-value pair tuples. + + + + + +```pascaligo +const moves: moveset = map + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2); + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3); +end +``` + + + +```cameligo +let moves: moveset = Map.literal + [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ; + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ; + ] +``` + + + +```reasonligo +let moves : moveset = + Map.literal([ + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)), + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)), + ]); +``` + + +## Map.size(m: (a', b') map) : nat + +Get the size of a given map `m`. + + + + +```pascaligo +function size_ (const m : foobar) : nat is + block {skip} with (size(m)) +``` + +```cameligo +let size_ (m: foobar) : nat = Map.size m +``` + +```reasonligo +let size_ = (m: foobar): nat => Map.size(m); +``` + + From b6a6eea5d2e38393c940d314363f88d4d779477c Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Mon, 10 Feb 2020 20:51:48 -0800 Subject: [PATCH 3/3] Add map reference page to doc tests and fix bugs --- gitlab-pages/docs/reference/map.md | 88 +++++++++++++++++++++++++----- src/test/md_file_tests.ml | 1 + 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/gitlab-pages/docs/reference/map.md b/gitlab-pages/docs/reference/map.md index 9d764b824..08e1a457f 100644 --- a/gitlab-pages/docs/reference/map.md +++ b/gitlab-pages/docs/reference/map.md @@ -3,6 +3,61 @@ id: map-reference title: Map --- +## Defining A Map Type + + + +```pascaligo +type move is int * int +type moveset is map(address, move) +``` + + +```cameligo +type move = int * int +type moveset = (address, move) map +``` + + +```reasonligo +type move = (int, int); +type moveset = map(address, move); +``` + + + +## Creating A Map + + + + +```pascaligo +const moves: moveset = map + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address) -> (1, 2); + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address) -> (0, 3); +end +``` + + + +```cameligo +let moves: moveset = Map.literal + [ (("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address), (1, 2)) ; + (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (0, 3)) ; + ] +``` + + + +```reasonligo +let moves : moveset = + Map.literal([ + ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx": address, (1, 2)), + ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, (0, 3)), + ]); +``` + + ## Map.find_opt(k: a', m: (a',b') map) : b' option Retrieve the value associated with a particular key. This version returns an option @@ -99,17 +154,20 @@ let updated_map: moveset = Map.update(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": a ```pascaligo -function patch_ (var m: foobar) : foobar is block { - patch m with map [0 -> 5; 1 -> 6; 2 -> 7] +function set_ (var n : int ; var m : map(int, int)) : map(int, int) is block { + m[23] := n ; } with m ``` ```cameligo - +let add (n,m: int * (int, int) map) : foobar = Map.add 23 n m ``` +```reasonligo +let add = (n: int, m: map(int, int)) : foobar => Map.add(23, n, m); +``` @@ -121,19 +179,19 @@ Remove a key and its associated value from the map. ```pascaligo -function rm (var m : foobar) : foobar is block { +function rm (var m : map(int, int)) : map(int, int) is block { remove 42 from map m } with m ``` ```cameligo -let rm (m: foobar) : foobar = Map.remove 42 m +let rm (m: (int, int) map) : (int, int) map = Map.remove 42 m ``` ```reasonligo -let rm = (m: foobar): foobar => Map.remove(42, m); +let rm = (m: map(int, int)): map(int, int) => Map.remove(42, m); ``` @@ -240,16 +298,16 @@ Test whether a particular key `k` exists in a given map `m`. ```pascaligo -function mem (const k: int; const m: foobar) : bool is map_mem(k, m) +function mem (const k: int; const m: map(int, int)) : bool is map_mem(k, m) ``` ```cameligo -let mem (k,m: int * foobar) : bool = Map.mem k m +let mem (k,m: int * (int, int) map) : bool = Map.mem k m ``` ```reasonligo -let mem = (km: (int, foobar)): bool => Map.mem(km[0], km[1]); +let mem = ((k,m): (int, map(int,int))): bool => Map.mem(k, m); ``` @@ -262,16 +320,16 @@ Create an empty map. ```pascaligo -const empty_map : foobar = map end +const empty_map : map(int, int) = map end ``` ```cameligo -let empty_map : foobar = Map.empty +let empty_map : (int, int) map = Map.empty ``` ```reasonligo -let empty_map: foobar = Map.empty; +let empty_map: map(int, int) = Map.empty; ``` @@ -319,16 +377,16 @@ Get the size of a given map `m`. ```pascaligo -function size_ (const m : foobar) : nat is +function size_ (const m : map(int, int)) : nat is block {skip} with (size(m)) ``` ```cameligo -let size_ (m: foobar) : nat = Map.size m +let size_ (m: (int, int) map) : nat = Map.size m ``` ```reasonligo -let size_ = (m: foobar): nat => Map.size(m); +let size_ = (m: map(int, int)): nat => Map.size(m); ``` diff --git a/src/test/md_file_tests.ml b/src/test/md_file_tests.ml index 86aefeb89..a65ba74a5 100644 --- a/src/test/md_file_tests.ml +++ b/src/test/md_file_tests.ml @@ -122,6 +122,7 @@ let md_files = [ "/gitlab-pages/docs/advanced/timestamps-addresses.md"; "/gitlab-pages/docs/api/cli-commands.md"; "/gitlab-pages/docs/api/cheat-sheet.md"; + "/gitlab-pages/docs/reference/map.md"; ] let md_root = "../../gitlab-pages/docs/language-basics/"