Michelson: change semantics of CONCAT

This commit is contained in:
Benjamin Canou 2018-06-18 13:24:16 +02:00 committed by Grégoire Henry
parent bd709a44ba
commit c691068209
11 changed files with 36 additions and 28 deletions

View File

@ -1,8 +1,7 @@
parameter string; parameter string;
storage string; storage string;
code {DUP; # We're going to need both the storage and parameter code { DUP;
CAR; # Get the parameter DIP { CDR ; NIL string ; SWAP ; CONS } ;
DIP{CDR}; # Get the storage value CAR ; CONS ;
SWAP; # Get the order we want (this is optional) CONCAT;
CONCAT; # Concatenate the strings NIL operation; PAIR}
NIL operation; PAIR} # Match the calling convention

View File

@ -1,4 +1,7 @@
parameter (list string); parameter (list string);
storage (list string); storage (list string);
code{ CAR; code{ CAR;
MAP { PUSH @hello string "Hello "; CONCAT }; NIL operation; PAIR}; MAP { NIL string ; SWAP ; CONS ;
PUSH @hello string "Hello "; CONS ;
CONCAT };
NIL operation; PAIR};

View File

@ -1,5 +1,5 @@
parameter (list string); parameter (list string);
storage string; storage string;
code {CAR; PUSH string ""; SWAP; code {CAR; PUSH string ""; SWAP;
ITER {SWAP; CONCAT}; ITER {SWAP; DIP{NIL string; SWAP; CONS}; CONS; CONCAT};
NIL operation; PAIR}; NIL operation; PAIR};

View File

@ -1,5 +1,7 @@
parameter string; parameter string;
storage string; storage string;
code {CAR; code {CAR;
LAMBDA string string {PUSH string "_abc"; SWAP; CONCAT}; LAMBDA string string
{PUSH string "_abc"; NIL string ;
SWAP ; CONS ; SWAP ; CONS ; CONCAT};
SWAP; EXEC; NIL operation; PAIR}; SWAP; EXEC; NIL operation; PAIR};

View File

@ -1,5 +1,3 @@
parameter (list string); parameter (list string);
storage string; storage string;
code { CAR; PUSH string ""; SWAP; code { UNPAIR ; SWAP ; CONS ; CONCAT; NIL operation; PAIR}
ITER { CONCAT };
NIL operation; PAIR}

View File

@ -114,8 +114,8 @@ assert_storage $contract_dir/list_map_block.tz '{0}' '{ 1 ; 2 ; 3 ; 0 }' '{ 1 ;
assert_storage $contract_dir/list_iter.tz 0 '{ 10 ; 2 ; 1 }' 20 assert_storage $contract_dir/list_iter.tz 0 '{ 10 ; 2 ; 1 }' 20
assert_storage $contract_dir/list_iter.tz 0 '{ 3 ; 6 ; 9 }' 162 assert_storage $contract_dir/list_iter.tz 0 '{ 3 ; 6 ; 9 }' 162
assert_storage $contract_dir/list_iter2.tz '"?"' '{ "a" ; "b" ; "c" }' '"cba"' assert_storage $contract_dir/list_iter2.tz '"abc"' '{ "d" ; "e" ; "f" }' '"abcdef"'
assert_storage $contract_dir/list_iter2.tz '"?"' '{}' '""' assert_storage $contract_dir/list_iter2.tz '"abc"' '{}' '"abc"'
# Identity on sets # Identity on sets

View File

@ -53,8 +53,13 @@ module Cost_of = struct
let zint z = let zint z =
alloc_bits_cost (Z.numbits z) alloc_bits_cost (Z.numbits z)
let concat s1 s2 = let concat cost length ss =
string (String.length s1 + String.length s2) let rec cum acc = function
| [] -> acc
| s :: ss -> cum (cost (length s) +@ acc) ss in
cum free ss
let concat_string ss = concat string String.length ss
(* Cost per cycle of a loop, fold, etc *) (* Cost per cycle of a loop, fold, etc *)
let loop_cycle = step_cost 2 let loop_cycle = step_cost 2

View File

@ -38,7 +38,7 @@ module Cost_of : sig
val cons : Gas.cost val cons : Gas.cost
val variant_no_data : Gas.cost val variant_no_data : Gas.cost
val branch : Gas.cost val branch : Gas.cost
val concat : string -> string -> Gas.cost val concat_string : string list -> Gas.cost
val map_mem : val map_mem :
'a -> ('b, 'c) Script_typed_ir.map -> Gas.cost 'a -> ('b, 'c) Script_typed_ir.map -> Gas.cost
val map_to_list : val map_to_list :

View File

@ -415,8 +415,10 @@ let rec interp
consume_gas_binop descr (Script_timestamp.diff, t1, t2) consume_gas_binop descr (Script_timestamp.diff, t1, t2)
Interp_costs.diff_timestamps rest ctxt Interp_costs.diff_timestamps rest ctxt
(* string operations *) (* string operations *)
| Concat, Item (x, Item (y, rest)) -> | Concat, Item (ss, rest) ->
consume_gas_binop descr ((^), x, y) Interp_costs.concat rest ctxt Lwt.return (Gas.consume ctxt (Interp_costs.concat_string ss)) >>=? fun ctxt ->
let s = String.concat "" ss in
logged_return (Item (s, rest), ctxt)
(* currency operations *) (* currency operations *)
| Add_tez, Item (x, Item (y, rest)) -> | Add_tez, Item (x, Item (y, rest)) ->
Lwt.return (Gas.consume ctxt Interp_costs.int64_op) >>=? fun ctxt -> Lwt.return (Gas.consume ctxt Interp_costs.int64_op) >>=? fun ctxt ->

View File

@ -2111,9 +2111,8 @@ and parse_instr
(Item_t (Int_t tname, rest, annot)) (Item_t (Int_t tname, rest, annot))
(* string operations *) (* string operations *)
| Prim (loc, I_CONCAT, [], annot), | Prim (loc, I_CONCAT, [], annot),
Item_t (String_t tn1, Item_t (String_t tn2, rest, _), _) -> Item_t (List_t (String_t tname, _), rest, list_annot) ->
parse_var_annot loc annot >>=? fun annot -> parse_var_annot ~default:list_annot loc annot >>=? fun annot ->
Lwt.return @@ merge_type_annot tn1 tn2 >>=? fun tname ->
typed ctxt loc Concat typed ctxt loc Concat
(Item_t (String_t tname, rest, annot)) (Item_t (String_t tname, rest, annot))
(* currency operations *) (* currency operations *)
@ -2611,10 +2610,10 @@ and parse_instr
get_toplevel_type tc_context get_toplevel_type tc_context
(* Primitive parsing errors *) (* Primitive parsing errors *)
| Prim (loc, (I_DROP | I_DUP | I_SWAP | I_SOME | I_UNIT | Prim (loc, (I_DROP | I_DUP | I_SWAP | I_SOME | I_UNIT
| I_PAIR | I_CAR | I_CDR | I_CONS | I_PAIR | I_CAR | I_CDR | I_CONS | I_CONCAT
| I_MEM | I_UPDATE | I_MAP | I_MEM | I_UPDATE | I_MAP
| I_GET | I_EXEC | I_FAILWITH | I_SIZE | I_GET | I_EXEC | I_FAILWITH | I_SIZE
| I_CONCAT | I_ADD | I_SUB | I_ADD | I_SUB
| I_MUL | I_EDIV | I_OR | I_AND | I_XOR | I_MUL | I_EDIV | I_OR | I_AND | I_XOR
| I_NOT | I_NOT
| I_ABS | I_NEG | I_LSL | I_LSR | I_ABS | I_NEG | I_LSL | I_LSR
@ -2643,12 +2642,12 @@ and parse_instr
(* Stack errors *) (* Stack errors *)
| Prim (loc, (I_ADD | I_SUB | I_MUL | I_EDIV | Prim (loc, (I_ADD | I_SUB | I_MUL | I_EDIV
| I_AND | I_OR | I_XOR | I_LSL | I_LSR | I_AND | I_OR | I_XOR | I_LSL | I_LSR
| I_CONCAT | I_COMPARE as name), [], _), | I_COMPARE as name), [], _),
Item_t (ta, Item_t (tb, _, _), _) -> Item_t (ta, Item_t (tb, _, _), _) ->
Lwt.return @@ serialize_ty_for_error ctxt ta >>=? fun (ta, ctxt) -> Lwt.return @@ serialize_ty_for_error ctxt ta >>=? fun (ta, ctxt) ->
Lwt.return @@ serialize_ty_for_error ctxt tb >>=? fun (tb, _ctxt) -> Lwt.return @@ serialize_ty_for_error ctxt tb >>=? fun (tb, _ctxt) ->
fail (Undefined_binop (loc, name, ta, tb)) fail (Undefined_binop (loc, name, ta, tb))
| Prim (loc, (I_NEG | I_ABS | I_NOT | Prim (loc, (I_NEG | I_ABS | I_NOT | I_CONCAT
| I_EQ | I_NEQ | I_LT | I_GT | I_LE | I_GE as name), | I_EQ | I_NEQ | I_LT | I_GT | I_LE | I_GE as name),
[], _), [], _),
Item_t (t, _, _) -> Item_t (t, _, _) ->
@ -2683,7 +2682,7 @@ and parse_instr
| I_GET | I_MEM | I_EXEC | I_GET | I_MEM | I_EXEC
| I_CHECK_SIGNATURE | I_ADD | I_SUB | I_MUL | I_CHECK_SIGNATURE | I_ADD | I_SUB | I_MUL
| I_EDIV | I_AND | I_OR | I_XOR | I_EDIV | I_AND | I_OR | I_XOR
| I_LSL | I_LSR | I_CONCAT as name), _, _), | I_LSL | I_LSR as name), _, _),
stack -> stack ->
serialize_stack_for_error ctxt stack >>=? fun (stack, _ctxt) -> serialize_stack_for_error ctxt stack >>=? fun (stack, _ctxt) ->
fail (Bad_stack (loc, name, 2, stack)) fail (Bad_stack (loc, name, 2, stack))

View File

@ -203,7 +203,7 @@ and ('bef, 'aft) instr =
('key * ('value option * (('key, 'value) big_map * 'rest)), ('key, 'value) big_map * 'rest) instr ('key * ('value option * (('key, 'value) big_map * 'rest)), ('key, 'value) big_map * 'rest) instr
(* string operations *) (* string operations *)
| Concat : | Concat :
(string * (string * 'rest), string * 'rest) instr (string list * 'rest, string * 'rest) instr
(* timestamp operations *) (* timestamp operations *)
| Add_seconds_to_timestamp : | Add_seconds_to_timestamp :
(z num * (Script_timestamp.t * 'rest), (z num * (Script_timestamp.t * 'rest),