diff --git a/gitlab-pages/docs/reference/big_map.md b/gitlab-pages/docs/reference/big_map.md
index e20bdc48c..104751667 100644
--- a/gitlab-pages/docs/reference/big_map.md
+++ b/gitlab-pages/docs/reference/big_map.md
@@ -8,9 +8,13 @@ hide_table_of_contents: true
import Syntax from '@theme/Syntax';
import SyntaxTitle from '@theme/SyntaxTitle';
-A lazily deserialized map that's intended to store large amounts of data.
+A lazily deserialized map that's intended to store large amounts of data.
+Lazily means that storage is read or written per key on demand. Therefore
+there are no `map`, `fold`, and `iter` operations as in
+[Map](./map-reference).
-The gast costs of deserialized maps are higher than standard maps as data is lazily deserialized.
+The gast costs of big maps are higher than standard maps as data is lazily
+deserialized.
type big_map ('key, 'value)
@@ -47,15 +51,17 @@ type register = (address, move) big_map
The type of a big map from values of type `key` to
-values of type `value` is `big_map (key, value)`.
+values of type `value` is `big_map(key, value)`.
```reasonligo group=big_map
type move = (int, int);
-type register = big_map (address, move);
+type register = big_map(address, move);
```
+Be aware that a `big_map` cannot appear inside another `big_map`.
+
function empty : big_map ('key, 'value)
@@ -63,7 +69,7 @@ function empty : big_map ('key, 'value)
val empty : ('key, 'value) big_map
-let empty: big_map ('key, 'value)
+let empty: big_map('key, 'value)
Create an empty big_map.
@@ -91,7 +97,7 @@ let empty : register = Big_map.empty
```reasonligo group=big_map
-let empty : register = Big_map.empty
+let empty: register = Big_map.empty
```
@@ -141,7 +147,7 @@ let moves : register =
```reasonligo group=big_map
-let moves : register =
+let moves: register =
Big_map.literal ([
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address, (1,2)),
("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, (0,3))]);
@@ -156,7 +162,7 @@ function find_opt : 'key -> big_map ('key, 'value) -> option 'value
val find_opt : 'key -> ('key, 'value) big_map -> 'value option
-let find_opt : ('key, big_map ('key, 'value)) => option ('value)
+let find_opt: ('key, big_map ('key, 'value)) => option ('value)
Retrieve a value from a big map with the given key.
@@ -191,8 +197,8 @@ let my_balance : move option =
```reasonligo group=big_map
-let my_balance : option (move) =
- Big_map.find_opt ("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address, moves);
+let my_balance: option (move) =
+ Big_map.find_opt("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address, moves);
```
@@ -204,7 +210,7 @@ function update : 'key -> option 'value -> big_map ('key, 'value) -> big_map ('k
val update: 'key -> 'value option -> ('key, 'value) big_map -> ('key, 'value) big_map
-let update: ('key, option('value), big_map ('key, 'value)) => big_map ('key, 'value)
+let update: ('key, option('value), big_map('key, 'value)) => big_map('key, 'value)
Note: when `None` is used as a value, the value is removed from the big_map.
@@ -255,9 +261,9 @@ let updated_map : register =
```reasonligo group=big_map
-let updated_map : register =
+let updated_map: register =
Big_map.update
- (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some ((4,9)), moves);
+ (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), Some((4,9)), moves);
```
@@ -292,7 +298,7 @@ let add (m : register) : register =
```reasonligo group=big_map
let add = (m: register): register =>
Big_map.add
- (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" : address), (4,9), m);
+ (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), (4,9), m);
```
@@ -305,7 +311,7 @@ function remove: 'key -> big_map ('key, 'value) -> big_map ('key, 'value)
val remove: 'key -> ('key, 'value) big_map -> ('key, 'value) big_map
-let remove: ('key, big_map ('key, 'value)) => big_map ('key, 'value)
+let remove: ('key, big_map('key, 'value)) => big_map('key, 'value)
@@ -340,8 +346,8 @@ let updated_map : register =
```reasonligo group=big_map
-let updated_map : register =
- Big_map.remove (("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
+let updated_map: register =
+ Big_map.remove(("tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN": address), moves)
```
diff --git a/src/bin/expect_tests/contract_tests.ml b/src/bin/expect_tests/contract_tests.ml
index 3785881be..984a0163b 100644
--- a/src/bin/expect_tests/contract_tests.ml
+++ b/src/bin/expect_tests/contract_tests.ml
@@ -1344,4 +1344,56 @@ let%expect_test _ =
* Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
* Ask a question on our Discord: https://discord.gg/9rhYaEt
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
- * Check the changelog by running 'ligo changelog' |}]
+ * Check the changelog by running 'ligo changelog' |}];
+
+ run_ligo_bad ["compile-contract"; bad_contract "nested_bigmap_1.religo"; "main"];
+ [%expect {|
+ ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
+
+
+ If you're not sure how to fix this error, you can
+ do one of the following:
+
+ * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
+ * Ask a question on our Discord: https://discord.gg/9rhYaEt
+ * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
+ * Check the changelog by running 'ligo changelog' |}];
+
+ run_ligo_bad ["compile-contract"; bad_contract "nested_bigmap_2.religo"; "main"];
+ [%expect {|
+ ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
+
+
+ If you're not sure how to fix this error, you can
+ do one of the following:
+
+ * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
+ * Ask a question on our Discord: https://discord.gg/9rhYaEt
+ * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
+ * Check the changelog by running 'ligo changelog' |}];
+
+ run_ligo_bad ["compile-contract"; bad_contract "nested_bigmap_3.religo"; "main"];
+ [%expect {|
+ ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
+
+
+ If you're not sure how to fix this error, you can
+ do one of the following:
+
+ * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
+ * Ask a question on our Discord: https://discord.gg/9rhYaEt
+ * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
+ * Check the changelog by running 'ligo changelog' |}];
+
+ run_ligo_bad ["compile-contract"; bad_contract "nested_bigmap_4.religo"; "main"];
+ [%expect {|
+ ligo: It looks like you have nested a big map inside another big map. This is not supported. : {}
+
+
+ If you're not sure how to fix this error, you can
+ do one of the following:
+
+ * Visit our documentation: https://ligolang.org/docs/intro/what-and-why/
+ * Ask a question on our Discord: https://discord.gg/9rhYaEt
+ * Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
+ * Check the changelog by running 'ligo changelog' |}]
\ No newline at end of file
diff --git a/src/passes/3-self_ast_imperative/entrypoints_lenght_limit.ml b/src/passes/3-self_ast_imperative/entrypoints_length_limit.ml
similarity index 100%
rename from src/passes/3-self_ast_imperative/entrypoints_lenght_limit.ml
rename to src/passes/3-self_ast_imperative/entrypoints_length_limit.ml
diff --git a/src/passes/3-self_ast_imperative/self_ast_imperative.ml b/src/passes/3-self_ast_imperative/self_ast_imperative.ml
index a10968c0c..b0270ebd0 100644
--- a/src/passes/3-self_ast_imperative/self_ast_imperative.ml
+++ b/src/passes/3-self_ast_imperative/self_ast_imperative.ml
@@ -6,7 +6,7 @@ let all_expression_mapper = [
Literals.peephole_expression ;
]
let all_type_expression_mapper = [
- Entrypoints_lenght_limit.peephole_type_expression ;
+ Entrypoints_length_limit.peephole_type_expression ;
]
let all_exp = List.map (fun el -> Helpers.Expression el) all_expression_mapper
diff --git a/src/passes/9-self_ast_typed/no_nested_big_map.ml b/src/passes/9-self_ast_typed/no_nested_big_map.ml
new file mode 100644
index 000000000..e1a130ce9
--- /dev/null
+++ b/src/passes/9-self_ast_typed/no_nested_big_map.ml
@@ -0,0 +1,56 @@
+open Ast_typed
+open Trace
+
+type contract_pass_data = Contract_passes.contract_pass_data
+
+module Errors = struct
+ let no_nested_bigmap () =
+ let title = (thunk ("It looks like you have nested a big map inside another big map. This is not supported. ")) in
+ let message () = "" in
+ let data = [
+ (* ("location" , fun () -> Format.asprintf "%a" Location.pp loc) TODO once types have an actual location *)
+ ] in
+ error ~data title message ()
+end
+
+let rec check_no_nested_bigmap is_in_bigmap e =
+ match e.type_content with
+ | T_operator (TC_big_map (_, _)) when is_in_bigmap ->
+ fail @@ Errors.no_nested_bigmap
+ | T_operator (TC_big_map (key, value)) ->
+ let%bind _ = check_no_nested_bigmap false key in
+ let%bind _ = check_no_nested_bigmap true value in
+ ok ()
+ | T_operator (TC_contract t)
+ | T_operator (TC_option t)
+ | T_operator (TC_list t)
+ | T_operator (TC_set t) ->
+ let%bind _ = check_no_nested_bigmap is_in_bigmap t in
+ ok ()
+ | T_operator (TC_map (a, b)) ->
+ let%bind _ = check_no_nested_bigmap is_in_bigmap a in
+ let%bind _ = check_no_nested_bigmap is_in_bigmap b in
+ ok ()
+ | T_operator (TC_arrow (a, b)) ->
+ let%bind _ = check_no_nested_bigmap false a in
+ let%bind _ = check_no_nested_bigmap false b in
+ ok ()
+ | T_sum s ->
+ let es = CMap.to_list s in
+ let%bind _ = bind_map_list (fun l -> check_no_nested_bigmap is_in_bigmap l) es in
+ ok ()
+ | T_record elm ->
+ let es = LMap.to_list elm in
+ let%bind _ = bind_map_list (fun l -> check_no_nested_bigmap is_in_bigmap l) es in
+ ok ()
+ | T_arrow { type1; type2 } ->
+ let%bind _ = check_no_nested_bigmap false type1 in
+ let%bind _ = check_no_nested_bigmap false type2 in
+ ok ()
+ | T_variable _
+ | T_constant _ ->
+ ok ()
+
+let self_typing : contract_pass_data -> expression -> (bool * contract_pass_data * expression) result = fun dat el ->
+ let%bind _ = check_no_nested_bigmap false el.type_expression in
+ ok (true, dat, el)
diff --git a/src/passes/9-self_ast_typed/self_ast_typed.ml b/src/passes/9-self_ast_typed/self_ast_typed.ml
index 76bfbdf90..e8dfefdce 100644
--- a/src/passes/9-self_ast_typed/self_ast_typed.ml
+++ b/src/passes/9-self_ast_typed/self_ast_typed.ml
@@ -6,6 +6,7 @@ let all_passes = [
let contract_passes = [
Contract_passes.self_typing ;
+ No_nested_big_map.self_typing ;
]
let all_program =
diff --git a/src/test/contracts/negative/nested_bigmap_1.religo b/src/test/contracts/negative/nested_bigmap_1.religo
new file mode 100644
index 000000000..b86e549b1
--- /dev/null
+++ b/src/test/contracts/negative/nested_bigmap_1.religo
@@ -0,0 +1,10 @@
+type bar = big_map (nat, int);
+
+/* this should result in an error as nested big_maps are not supported: */
+type storage = big_map (int, bar);
+
+type return = (list (operation), storage);
+
+let main = ((ignore, store): (unit, storage)): return => {
+ ([]: list(operation), store)
+};
diff --git a/src/test/contracts/negative/nested_bigmap_2.religo b/src/test/contracts/negative/nested_bigmap_2.religo
new file mode 100644
index 000000000..d8061f912
--- /dev/null
+++ b/src/test/contracts/negative/nested_bigmap_2.religo
@@ -0,0 +1,9 @@
+/* this should result in an error as nested big_maps are not supported: */
+type storage = big_map (nat, big_map (int, string));
+
+type return = (list (operation), storage);
+
+let main = ((ignore, store): (unit, storage)): return => {
+ ([]: list(operation), store)
+};
+
\ No newline at end of file
diff --git a/src/test/contracts/negative/nested_bigmap_3.religo b/src/test/contracts/negative/nested_bigmap_3.religo
new file mode 100644
index 000000000..e8941f445
--- /dev/null
+++ b/src/test/contracts/negative/nested_bigmap_3.religo
@@ -0,0 +1,15 @@
+type bar = big_map (nat, int);
+
+type foo = {
+ a: int,
+ b: bar
+};
+
+/* this should result in an error as nested big_maps are not supported: */
+type storage = big_map(nat, foo);
+
+type return = (list (operation), storage);
+
+let main = ((ignore, store): (unit, storage)): return => {
+ ([]: list(operation), store)
+};
diff --git a/src/test/contracts/negative/nested_bigmap_4.religo b/src/test/contracts/negative/nested_bigmap_4.religo
new file mode 100644
index 000000000..653908636
--- /dev/null
+++ b/src/test/contracts/negative/nested_bigmap_4.religo
@@ -0,0 +1,9 @@
+/* this should result in an error as nested big_maps are not supported: */
+type storage = map (int, big_map (nat, big_map (int, string)));
+
+type return = (list (operation), storage);
+
+let main = ((ignore, store): (unit, storage)): return => {
+ ([]: list(operation), store)
+};
+
\ No newline at end of file