Merge branch '129-allow-passing-timestamp-literals' into 'dev'

Resolve "Allow passing timestamp literals"

Closes #129

See merge request ligolang/ligo!298
This commit is contained in:
John David Pressman 2020-01-03 21:46:46 +00:00
commit d3fa06d62a
7 changed files with 86 additions and 14 deletions

View File

@ -19,6 +19,8 @@ const today: timestamp = now;
```
<!--END_DOCUSAURUS_CODE_TABS-->
> When running code with ligo CLI, the option `--predecessor-timestamp` allows you to control what `now` returns.
### Timestamp arithmetic
In LIGO, timestamps can be added with `int`(s), this enables you to set e.g. time constraints for your smart contracts like this:
@ -30,6 +32,8 @@ In LIGO, timestamps can be added with `int`(s), this enables you to set e.g. tim
const today: timestamp = now;
const one_day: int = 86400;
const in_24_hrs: timestamp = today + one_day;
const some_date: timestamp = ("2000-01-01T10:10:10Z" : timestamp);
const one_day_later: timestamp = some_date + one_day;
```
<!--END_DOCUSAURUS_CODE_TABS-->

View File

@ -90,7 +90,7 @@ let predecessor_timestamp =
let open Arg in
let info =
let docv = "PREDECESSOR_TIMESTAMP" in
let doc = "$(docv) is the pedecessor_timestamp the michelson interpreter transaction will use (e.g. '2000-01-01T10:10:10Z')" in
let doc = "$(docv) is the pedecessor_timestamp (now value) the michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')" in
info ~docv ~doc ["predecessor-timestamp"] in
value @@ opt (some string) None info
@ -156,7 +156,7 @@ let measure_contract =
(Term.ret term , Term.info ~doc cmdname)
let compile_parameter =
let f source_file entry_point expression syntax display_format michelson_format =
let f source_file entry_point expression syntax amount sender source predecessor_timestamp display_format michelson_format =
toplevel ~display_format @@
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
let%bind typed_prg,state = Compile.Of_simplified.compile simplified in
@ -174,11 +174,12 @@ let compile_parameter =
let%bind compiled_param = Compile.Of_mini_c.aggregate_and_compile_expression mini_c_prg mini_c_param in
let%bind () = Compile.Of_typed.assert_equal_contract_type Check_parameter entry_point typed_prg typed_param in
let%bind () = Compile.Of_michelson.assert_equal_contract_type Check_parameter michelson_prg compiled_param in
let%bind value = Run.evaluate_expression compiled_param.expr compiled_param.expr_ty in
let%bind options = Run.make_dry_run_options {predecessor_timestamp ; amount ; sender ; source } in
let%bind value = Run.evaluate_expression ~options compiled_param.expr compiled_param.expr_ty in
ok @@ Format.asprintf "%a\n" (Main.Display.michelson_pp michelson_format) value
in
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ expression "PARAMETER" 2 $ syntax $ display_format $ michelson_code_format) in
Term.(const f $ source_file 0 $ entry_point 1 $ expression "PARAMETER" 2 $ syntax $ amount $ sender $ source $ predecessor_timestamp $ display_format $ michelson_code_format) in
let cmdname = "compile-parameter" in
let doc = "Subcommand: compile parameters to a michelson expression. The resulting michelson expression can be passed as an argument in a transaction which calls a contract." in
(Term.ret term , Term.info ~doc cmdname)
@ -213,7 +214,7 @@ let interpret =
let compile_storage =
let f source_file entry_point expression syntax display_format michelson_format =
let f source_file entry_point expression syntax amount sender source predecessor_timestamp display_format michelson_format =
toplevel ~display_format @@
let%bind simplified = Compile.Of_source.compile source_file (Syntax_name syntax) in
let%bind typed_prg,state = Compile.Of_simplified.compile simplified in
@ -231,11 +232,12 @@ let compile_storage =
let%bind compiled_param = Compile.Of_mini_c.compile_expression mini_c_param in
let%bind () = Compile.Of_typed.assert_equal_contract_type Check_storage entry_point typed_prg typed_param in
let%bind () = Compile.Of_michelson.assert_equal_contract_type Check_storage michelson_prg compiled_param in
let%bind value = Run.evaluate_expression compiled_param.expr compiled_param.expr_ty in
let%bind options = Run.make_dry_run_options {predecessor_timestamp ; amount ; sender ; source } in
let%bind value = Run.evaluate_expression ~options compiled_param.expr compiled_param.expr_ty in
ok @@ Format.asprintf "%a\n" (Main.Display.michelson_pp michelson_format) value
in
let term =
Term.(const f $ source_file 0 $ entry_point 1 $ expression "STORAGE" 2 $ syntax $ display_format $ michelson_code_format) in
Term.(const f $ source_file 0 $ entry_point 1 $ expression "STORAGE" 2 $ syntax $ amount $ sender $ source $ predecessor_timestamp $ display_format $ michelson_code_format) in
let cmdname = "compile-storage" in
let doc = "Subcommand: compile an initial storage in ligo syntax to a michelson expression. The resulting michelson expression can be passed as an argument in a transaction which originates a contract." in
(Term.ret term , Term.info ~doc cmdname)

View File

@ -30,6 +30,10 @@ let%expect_test _ =
()
let%expect_test _ =
run_ligo_good [ "compile-storage" ; contract "timestamp.ligo" ; "main" ; "now" ; "--predecessor-timestamp" ; "2042-01-01T00:00:00Z" ] ;
[%expect {| "2042-01-01T00:00:01Z" |}]
let%expect_test _ =
run_ligo_good [ "compile-contract" ; contract "coase.ligo" ; "main" ] ;
[%expect {|
@ -936,3 +940,7 @@ let%expect_test _ =
let%expect_test _ =
run_ligo_bad [ "compile-contract" ; contract "bad_address_format.religo" ; "main" ] ;
[%expect {| ligo: in file "bad_address_format.religo", line 2, characters 25-47. Badly formatted address "KT1badaddr": {"location":"in file \"bad_address_format.religo\", line 2, characters 25-47"} |}]
let%expect_test _ =
run_ligo_bad [ "compile-contract" ; contract "bad_timestamp.ligo" ; "main" ] ;
[%expect {| ligo: in file "bad_timestamp.ligo", line 5, characters 29-43. Badly formatted timestamp "badtimestamp": {"location":"in file \"bad_timestamp.ligo\", line 5, characters 29-43"} |}]

View File

@ -176,6 +176,9 @@ let%expect_test _ =
contract.
OPTIONS
--amount=AMOUNT (absent=0)
AMOUNT is the amount the michelson interpreter will use.
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
(absent=human-readable)
DISPLAY_FORMAT is the format that will be used by the CLI.
@ -194,11 +197,23 @@ let%expect_test _ =
compile-contract for the resulting Michelson. Available formats
are 'text' (default), 'json' and 'hex'.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value) the
michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
syntaxes are "pascaligo" and "cameligo". By default, the syntax is
guessed from the extension (.ligo and .mligo, respectively).
--sender=SENDER
SENDER is the sender the michelson interpreter transaction will
use.
--source=SOURCE
SOURCE is the source the michelson interpreter transaction will
use.
--version
Show version information. |} ] ;
@ -226,6 +241,9 @@ let%expect_test _ =
STORAGE_EXPRESSION is the expression that will be compiled.
OPTIONS
--amount=AMOUNT (absent=0)
AMOUNT is the amount the michelson interpreter will use.
--format=DISPLAY_FORMAT, --display-format=DISPLAY_FORMAT
(absent=human-readable)
DISPLAY_FORMAT is the format that will be used by the CLI.
@ -244,11 +262,23 @@ let%expect_test _ =
compile-contract for the resulting Michelson. Available formats
are 'text' (default), 'json' and 'hex'.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value) the
michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
syntaxes are "pascaligo" and "cameligo". By default, the syntax is
guessed from the extension (.ligo and .mligo, respectively).
--sender=SENDER
SENDER is the sender the michelson interpreter transaction will
use.
--source=SOURCE
SOURCE is the source the michelson interpreter transaction will
use.
--version
Show version information. |} ] ;
@ -294,8 +324,8 @@ let%expect_test _ =
`plain' whenever the TERM env var is `dumb' or undefined.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp the michelson
interpreter transaction will use (e.g. '2000-01-01T10:10:10Z')
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value) the
michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
@ -352,8 +382,8 @@ let%expect_test _ =
`plain' whenever the TERM env var is `dumb' or undefined.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp the michelson
interpreter transaction will use (e.g. '2000-01-01T10:10:10Z')
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value) the
michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported
@ -405,8 +435,8 @@ let%expect_test _ =
`plain' whenever the TERM env var is `dumb' or undefined.
--predecessor-timestamp=PREDECESSOR_TIMESTAMP
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp the michelson
interpreter transaction will use (e.g. '2000-01-01T10:10:10Z')
PREDECESSOR_TIMESTAMP is the pedecessor_timestamp (now value) the
michelson interpreter will use (e.g. '2000-01-01T10:10:10Z')
-s SYNTAX, --syntax=SYNTAX (absent=auto)
SYNTAX is the syntax that will be used. Currently supported

View File

@ -1,11 +1,29 @@
open Ast_simplified
open Trace
module Errors = struct
let bad_string_timestamp ts loc () =
let title = (thunk ("Badly formatted timestamp \""^ts^"\"")) in
let message () = "" in
let data = [
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
] in
error ~data title message ()
end
open Errors
let peephole_expression : expression -> expression result = fun e ->
let return expression = ok { e with expression } in
match e.expression with
| E_ascription (e' , t) as e -> (
match (e'.expression , t.type_expression') with
| (E_literal (Literal_int i) , T_constant (TC_timestamp)) -> return @@ E_literal (Literal_timestamp i)
| (E_literal (Literal_string str) , T_constant (TC_timestamp)) ->
let%bind time =
trace_option (bad_string_timestamp str e'.location)
@@ Memory_proto_alpha.Protocol.Alpha_context.Timestamp.of_notation str in
let itime = Int64.to_int @@ Tezos_utils.Time.Protocol.to_seconds time in
return @@ E_literal (Literal_timestamp itime)
| (E_literal (Literal_string str) , T_constant (TC_address)) -> return @@ E_literal (Literal_address str)
| (E_literal (Literal_string str) , T_constant (TC_bytes)) -> (
let%bind e' = e'_bytes str in
@ -13,4 +31,4 @@ let peephole_expression : expression -> expression result = fun e ->
)
| _ -> return e
)
| e -> return e
| e -> return e

View File

@ -0,0 +1,7 @@
type storage_ is timestamp
function main(const p : unit; const s : storage_) : list(operation) * storage_ is
block {
var toto : timestamp := ("badtimestamp" : timestamp);
}
with ((nil: list(operation)), toto)

View File

@ -0,0 +1,3 @@
type storage_ is timestamp
function main(const p : unit; const s : storage_) : list(operation) * storage_ is ((nil: list(operation)), now)