From 25f004844a9dd45e677081a153da4f6950829c24 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Mon, 9 Mar 2020 11:22:56 +0100 Subject: [PATCH] self: now reject capitalized entrypoint annotation --- gitlab-pages/docs/reference/current.md | 4 +- src/bin/expect_tests/contract_tests.ml | 2 +- .../5-self_ast_typed/contract_passes.ml | 52 +++++++++---------- .../negative/self_type_annotation.ligo | 2 +- src/test/contracts/self_type_annotation.ligo | 2 +- src/test/contracts/self_with_entrypoint.ligo | 4 +- .../contracts/self_without_entrypoint.ligo | 2 +- 7 files changed, 32 insertions(+), 36 deletions(-) diff --git a/gitlab-pages/docs/reference/current.md b/gitlab-pages/docs/reference/current.md index 45e3c6f35..642bbb6fe 100644 --- a/gitlab-pages/docs/reference/current.md +++ b/gitlab-pages/docs/reference/current.md @@ -324,8 +324,8 @@ let main = (p : unit) : address => Tezos.self_address; ## Self Typecast the currently running contract with an entrypoint annotation. -If your are using entrypoints: use "%Bar" for constructor Bar -If you are not using entrypoints: use "%Default" +If your are using entrypoints: use "%bar" for constructor Bar +If you are not using entrypoints: use "%default" diff --git a/src/bin/expect_tests/contract_tests.ml b/src/bin/expect_tests/contract_tests.ml index fa784525d..49b1563d7 100644 --- a/src/bin/expect_tests/contract_tests.ml +++ b/src/bin/expect_tests/contract_tests.ml @@ -1322,7 +1322,7 @@ let%expect_test _ = run_ligo_bad [ "compile-contract" ; bad_contract "self_bad_entrypoint_format.ligo" ; "main" ] ; [%expect {| - ligo: in file "self_bad_entrypoint_format.ligo", line 8, characters 52-58. bad entrypoint format: entrypoint "Toto" is badly formatted. We expect "%Bar" for entrypoint Bar and "%Default" when no entrypoint used {"location":"in file \"self_bad_entrypoint_format.ligo\", line 8, characters 52-58","hint":"try %Toto"} + ligo: in file "self_bad_entrypoint_format.ligo", line 8, characters 52-58. bad entrypoint format: entrypoint "Toto" is badly formatted. We expect "%bar" for entrypoint Bar and "%default" when no entrypoint used {"location":"in file \"self_bad_entrypoint_format.ligo\", line 8, characters 52-58"} If you're not sure how to fix this error, you can diff --git a/src/passes/5-self_ast_typed/contract_passes.ml b/src/passes/5-self_ast_typed/contract_passes.ml index 3d93c359c..c16898146 100644 --- a/src/passes/5-self_ast_typed/contract_passes.ml +++ b/src/passes/5-self_ast_typed/contract_passes.ml @@ -7,17 +7,6 @@ type contract_pass_data = { } module Errors = struct - let corner_case loc message = - let title () = "corner case" in - let content () = "we don't have a good error message for this case. we are -striving find ways to better report them and find the use-cases that generate -them. please report this to the developers." in - let data = [ - ("location" , fun () -> loc) ; - ("message" , fun () -> message) ; - ] in - error ~data title content - let bad_self_type expected got loc () = let title = thunk "bad self type" in let message () = Format.asprintf "expected %a but got %a" Ast_typed.PP.type_expression expected Ast_typed.PP.type_expression got in @@ -28,10 +17,25 @@ them. please report this to the developers." in let bad_format_entrypoint_ann ep loc () = let title = thunk "bad entrypoint format" in - let message () = Format.asprintf "entrypoint \"%s\" is badly formatted. We expect \"%%Bar\" for entrypoint Bar and \"%%Default\" when no entrypoint used" ep in + let message () = Format.asprintf "entrypoint \"%s\" is badly formatted. We expect \"%%bar\" for entrypoint Bar and \"%%default\" when no entrypoint used" ep in + let data = [ + ("location" , fun () -> Format.asprintf "%a" Location.pp loc) ; + ] in + error ~data title message () + + let entrypoint_annotation_not_literal loc () = + let title = thunk "entrypoint annotation must be a string literal" in + let message () = Format.asprintf "" in + let data = [ + ("location" , fun () -> Format.asprintf "%a" Location.pp loc) ; + ] in + error ~data title message () + + let unmatched_entrypoint loc () = + let title = thunk "No constructor matches the entrypoint annotation" in + let message () = Format.asprintf "" in let data = [ ("location" , fun () -> Format.asprintf "%a" Location.pp loc) ; - ("hint" , fun () -> Format.asprintf "try %%%s" ep) ] in error ~data title message () @@ -39,7 +43,10 @@ end let check_entrypoint_annotation_format ep exp = match String.split_on_char '%' ep with - | [ "" ; ep'] -> ok @@ ep' + | [ "" ; ep'] -> + let cap = String.capitalize_ascii ep' in + if String.equal cap ep' then fail @@ Errors.bad_format_entrypoint_ann ep exp.location + else ok cap | _ -> fail @@ Errors.bad_format_entrypoint_ann ep exp.location @@ -52,25 +59,14 @@ let self_typing : contract_pass_data -> expression -> (bool * contract_pass_data match e.expression_content , e.type_expression with | E_constant {cons_name=C_SELF ; arguments=[entrypoint_exp]}, {type_content = T_operator (TC_contract t) ; type_meta=_} -> let%bind entrypoint = match entrypoint_exp.expression_content with - | E_literal (Literal_string ep) -> check_entrypoint_annotation_format ep entrypoint_exp - | E_variable v -> ( - match Ast_typed.Environment.get_opt v e.environment with - | Some {type_value = _; source_environment = _ ; definition = ED_declaration {expr ; free_variables = _}} -> ( - match expr.expression_content with - | E_literal (Literal_string ep) -> check_entrypoint_annotation_format ep entrypoint_exp - | _ -> fail @@ Errors.corner_case __LOC__ "SELF argument do not resolve to a string" - ) - | _ -> fail @@ Errors.corner_case __LOC__ "SELD argument not found in the environment" - ) - | _ -> fail @@ Errors.corner_case __LOC__ "SELF argument is not a string or a variable" in + | E_literal (Literal_string ep) -> check_entrypoint_annotation_format ep entrypoint_exp + | _ -> fail @@ Errors.entrypoint_annotation_not_literal entrypoint_exp.location in let%bind entrypoint_t = match dat.contract_type.parameter.type_content with - | T_sum cmap -> trace_option (simple_error "No constructor matches the entrypoint annotation") + | T_sum cmap -> trace_option (Errors.unmatched_entrypoint entrypoint_exp.location) @@ Stage_common.Types.CMap.find_opt (Constructor entrypoint) cmap | t -> ok {dat.contract_type.parameter with type_content = t} in let%bind () = trace_strong (bad_self_err ()) @@ Ast_typed.assert_type_expression_eq (entrypoint_t , t) in ok (true, dat, e) - | E_constant {cons_name=C_SELF ; arguments=[_]}, {type_content=_ ; type_meta=_} -> - fail (bad_self_err ()) | _ -> ok (true,dat,e) diff --git a/src/test/contracts/negative/self_type_annotation.ligo b/src/test/contracts/negative/self_type_annotation.ligo index d292c17a0..375fbf0af 100644 --- a/src/test/contracts/negative/self_type_annotation.ligo +++ b/src/test/contracts/negative/self_type_annotation.ligo @@ -5,6 +5,6 @@ type return is list (operation) * storage function main (const p : parameter; const s : storage) : return is block { - const self_contract: contract(int) = Tezos.self ("%Default"); + const self_contract: contract(int) = Tezos.self ("%default"); } with ((nil: list(operation)), s) \ No newline at end of file diff --git a/src/test/contracts/self_type_annotation.ligo b/src/test/contracts/self_type_annotation.ligo index 12a74ae5b..3bd607aa1 100644 --- a/src/test/contracts/self_type_annotation.ligo +++ b/src/test/contracts/self_type_annotation.ligo @@ -5,6 +5,6 @@ type return is list (operation) * storage function main (const p : parameter; const s : storage) : return is block { - const self_contract: contract(parameter) = Tezos.self("%Default") ; + const self_contract: contract(parameter) = Tezos.self("%default") ; } with ((nil: list(operation)), s) \ No newline at end of file diff --git a/src/test/contracts/self_with_entrypoint.ligo b/src/test/contracts/self_with_entrypoint.ligo index d690c0187..aede1b5b5 100644 --- a/src/test/contracts/self_with_entrypoint.ligo +++ b/src/test/contracts/self_with_entrypoint.ligo @@ -5,8 +5,8 @@ type return is list (operation) * storage function main (const p : parameter; const s : storage) : return is block { - const v : string = "%Toto" ; - const self_contract: contract(int) = Tezos.self(v) ; + // const v : string = "%toto" ; + const self_contract: contract(int) = Tezos.self("%toto") ; const op : operation = Tezos.transaction (2, 300tz, self_contract) ; } with (list [op], s) \ No newline at end of file diff --git a/src/test/contracts/self_without_entrypoint.ligo b/src/test/contracts/self_without_entrypoint.ligo index ce5fa7d74..04701cf1d 100644 --- a/src/test/contracts/self_without_entrypoint.ligo +++ b/src/test/contracts/self_without_entrypoint.ligo @@ -5,7 +5,7 @@ type return is list (operation) * storage function main (const p : parameter; const s : storage) : return is block { - const self_contract: contract(int) = Tezos.self("%Default") ; + const self_contract: contract(int) = Tezos.self("%default") ; const op : operation = Tezos.transaction (2, 300tz, self_contract) ; } with (list [op], s) \ No newline at end of file