Skip to content

Commit 1ba9f06

Browse files
author
Fabrice Le Fessant
committed
commit Solidity_primitives.UTILS
1 parent c1eafd0 commit 1ba9f06

File tree

6 files changed

+78
-22
lines changed

6 files changed

+78
-22
lines changed

src/solidity-typechecker/solidity_checker_TYPES.ml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ and variable_desc = {
102102
mutable variable_getter : function_desc option; (* when the variable has a getter*)
103103
variable_is_primitive : bool;
104104
variable_def : Solidity_ast.state_variable_definition option; (* module/contract*)
105-
mutable variable_assigns : function_desc list ;
105+
mutable variable_ops : ( function_desc * variable_operation ) list ;
106106
}
107107

108108
and function_desc = {
@@ -117,9 +117,21 @@ and function_desc = {
117117
function_is_method : bool;
118118
function_is_primitive : bool;
119119
function_def : Solidity_ast.function_definition option; (* Primitives have no definition *)
120-
mutable function_assigns : variable_desc list ;
120+
mutable function_ops : ( variable_desc * variable_operation ) list ;
121+
mutable function_purity : function_purity ;
121122
}
122123

124+
and function_purity = (* whether it modifies its contract *)
125+
| PurityUnknown
126+
| PurityPure
127+
| PurityView
128+
| PurityMute
129+
130+
and variable_operation =
131+
| OpAssign
132+
| OpAccess
133+
| OpCall of function_desc
134+
123135
and modifier_desc = {
124136
modifier_abs_name : absolute LongIdent.t;
125137
mutable modifier_params : (type_ * Ident.t option) list;

src/solidity-typechecker/solidity_primitives.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ let register id p f_desc =
2424
Solidity_tenv.add_primitive_desc id f_desc
2525

2626
let primitive_fun_named ?(returns_lvalue=false)
27+
?(purity=PurityPure)
2728
arg_types ret_types function_mutability =
2829
Function { function_abs_name = LongIdent.empty;
2930
function_params = arg_types;
@@ -36,7 +37,8 @@ let primitive_fun_named ?(returns_lvalue=false)
3637
function_is_method = false; (* can be true *)
3738
function_is_primitive = true;
3839
function_def = None;
39-
function_assigns = [];
40+
function_ops = [];
41+
function_purity = purity;
4042
}
4143

4244
let make_fun = Solidity_type_builder.primitive_fun

src/solidity-typechecker/solidity_primitives.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module UTILS : sig
2323
unit
2424
val primitive_fun_named :
2525
?returns_lvalue:bool ->
26+
?purity:Solidity_checker_TYPES.function_purity ->
2627
(Solidity_checker_TYPES.type_ *
2728
Solidity_common.IdentSet.elt option)
2829
list ->
@@ -33,6 +34,7 @@ module UTILS : sig
3334
Solidity_checker_TYPES.type_ -> Solidity_checker_TYPES.ident_desc
3435
val make_fun :
3536
?returns_lvalue:bool ->
37+
?purity:Solidity_checker_TYPES.function_purity ->
3638
Solidity_checker_TYPES.type_ list ->
3739
Solidity_checker_TYPES.type_ list ->
3840
Solidity_ast.fun_mutability -> Solidity_checker_TYPES.ident_desc

src/solidity-typechecker/solidity_tenv.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ let find_constructor pos { contract_abs_name; contract_env; _ } =
195195
function_is_method = true;
196196
function_is_primitive = false;
197197
function_def = None;
198-
function_assigns = [];
198+
function_ops = [];
199+
function_purity = PurityUnknown;
199200
}
200201

201202
let has_abstract_function cd =

src/solidity-typechecker/solidity_type_builder.ml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ and function_type_to_desc pos env ft =
258258
function_is_method = false;
259259
function_is_primitive = false;
260260
function_def = None;
261-
function_assigns = [];
261+
function_ops = [];
262+
function_purity = PurityUnknown;
262263
}
263264

264265
and process_fun_params pos env ~ext params =
@@ -324,7 +325,8 @@ let variable_desc_to_function_desc pos vid variable_abs_name vt :
324325
function_is_method = true;
325326
function_is_primitive = false;
326327
function_def = None;
327-
function_assigns = [];
328+
function_ops = [];
329+
function_purity = PurityUnknown;
328330
}
329331

330332
(* Build the function corresponding to an event *)
@@ -340,7 +342,8 @@ let event_desc_to_function_desc (ed : event_desc) : function_desc =
340342
function_is_method = false;
341343
function_is_primitive = false;
342344
function_def = None;
343-
function_assigns = [];
345+
function_ops = [];
346+
function_purity = PurityUnknown;
344347
}
345348

346349
(* Make a ident description for a local variable *)
@@ -354,7 +357,7 @@ let local_variable_desc variable_type : variable_desc =
354357
variable_getter = None;
355358
variable_is_primitive = false;
356359
variable_def = None;
357-
variable_assigns = [] ;
360+
variable_ops = [] ;
358361
}
359362

360363

@@ -404,7 +407,7 @@ let make_variable_desc vlid vd =
404407
variable_getter = None;
405408
variable_is_primitive = false;
406409
variable_def = Some (vd);
407-
variable_assigns = [] ;
410+
variable_ops = [] ;
408411
}
409412

410413
let update_variable_desc pos env vd kind_opt =
@@ -439,7 +442,8 @@ let make_function_desc flid fd method_ =
439442
function_is_method = method_;
440443
function_is_primitive = false;
441444
function_def = Some (fd);
442-
function_assigns = [];
445+
function_ops = [];
446+
function_purity = PurityUnknown;
443447
}
444448

445449
let update_function_desc pos env fd kind_opt =
@@ -480,6 +484,7 @@ let update_struct_fields sd fields =
480484
(* Functions to build primitive types/desc *)
481485

482486
let primitive_fun_desc ?(returns_lvalue=false)
487+
?(purity=PurityPure)
483488
arg_types ret_types function_mutability =
484489
{ function_abs_name = LongIdent.empty;
485490
function_params = List.map (fun t -> (t, None)) arg_types;
@@ -492,7 +497,8 @@ let primitive_fun_desc ?(returns_lvalue=false)
492497
function_is_method = false; (* can be true *)
493498
function_is_primitive = true;
494499
function_def = None;
495-
function_assigns = [];
500+
function_ops = [];
501+
function_purity = purity;
496502
}
497503

498504
let primitive_fun_type ?(kind=KOther) ?(returns_lvalue=false)
@@ -501,9 +507,9 @@ let primitive_fun_type ?(kind=KOther) ?(returns_lvalue=false)
501507
arg_types ret_types function_mutability in
502508
TFunction (fd, { new_fun_options with kind })
503509

504-
let primitive_fun ?(returns_lvalue=false)
510+
let primitive_fun ?(returns_lvalue=false) ?purity
505511
arg_types ret_types function_mutability =
506-
let fd = primitive_fun_desc ~returns_lvalue
512+
let fd = primitive_fun_desc ~returns_lvalue ?purity
507513
arg_types ret_types function_mutability in
508514
Function (fd)
509515

@@ -517,7 +523,7 @@ let primitive_var_desc (*?(is_lvalue=false)*) variable_type =
517523
variable_getter = None;
518524
variable_is_primitive = true;
519525
variable_def = None;
520-
variable_assigns = [] ;
526+
variable_ops = [] ;
521527
}
522528

523529
let primitive_var (*?(is_lvalue=false)*) variable_type =

src/solidity-typechecker/solidity_typechecker.ml

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ let lv_of_bool = function
4141
| true -> LeftValue []
4242
| false -> RightValue
4343

44+
(* Currently, FieldExpression does not fill the variable_desc correctly
45+
in the LeftValue list *)
46+
4447
let check_lv pos opt lv =
4548
match lv with
4649
| RightValue ->
@@ -51,8 +54,8 @@ let check_lv pos opt lv =
5154
| Some fd ->
5255
List.iter (function
5356
| AVariable (vd, _) ->
54-
vd.variable_assigns <- fd :: vd.variable_assigns;
55-
fd.function_assigns <- vd :: fd.function_assigns;
57+
vd.variable_ops <- ( fd, OpAssign ) :: vd.variable_ops;
58+
fd.function_ops <- ( vd, OpAssign ) :: fd.function_ops;
5659
| _ -> ()
5760
) list
5861

@@ -302,7 +305,7 @@ let get_variable_getter pos vd =
302305
| Some (fd) -> fd
303306
| None -> error pos "Variable is missing a getter !"
304307

305-
let type_and_annot_of_id_desc pos base_t_opt idd is_uf =
308+
let type_and_annot_of_id_desc pos opt base_t_opt idd is_uf =
306309
match idd with
307310
| Type (td) ->
308311
(* Note: user types have their storage location
@@ -331,6 +334,12 @@ let type_and_annot_of_id_desc pos base_t_opt idd is_uf =
331334
LeftValue [annot]
332335
else RightValue
333336
in
337+
(match opt.in_function with
338+
| None -> ()
339+
| Some in_fd ->
340+
in_fd.function_ops <- (vd, OpAccess) :: in_fd.function_ops ;
341+
vd.variable_ops <- (in_fd, OpAccess) :: vd.variable_ops
342+
);
334343
vd.variable_type, lv, annot
335344
| Function (fd) when is_uf ->
336345
assert (using_for_allowed base_t_opt);
@@ -599,7 +608,7 @@ let type_ident opt env base_t_opt id_node =
599608
let idd, is_uf = resolve_overloads pos opt base_t_opt id iddl uf_iddl in
600609

601610
(* Finally, retrieve the type and annotation for this ident *)
602-
let t, lv, a = type_and_annot_of_id_desc id_node.pos base_t_opt idd is_uf in
611+
let t, lv, a = type_and_annot_of_id_desc id_node.pos opt base_t_opt idd is_uf in
603612
set_annot id_node a;
604613
t, lv
605614

@@ -868,19 +877,42 @@ and type_expression_lv opt env exp
868877
type_ident opt env None id_node
869878

870879
| FieldExpression (e, id_node) ->
871-
let t = type_expression opt env e in
872-
type_ident opt env (Some t) id_node
880+
let t, lv1 = type_expression_lv opt env e in
881+
let t, lv2 = type_ident opt env (Some t) id_node in
882+
let lv = match lv1, lv2 with
883+
| LeftValue x, LeftValue y -> LeftValue ( x @ y )
884+
| _, _ -> lv2
885+
in
886+
t, lv
873887

874888
| FunctionCallExpression (e, args) ->
875889
let args = type_function_args opt env args in
876-
let t = type_expression { opt with call_args = Some (args) } env e in
890+
let t, lv = type_expression_lv
891+
{ opt with call_args = Some (args) } env e in
877892
begin
878893
match t, args with
879894

880895
(* Function call *)
881896
| TFunction (fd, _fo), args ->
882897
check_function_application pos "function call"
883898
fd.function_params args;
899+
900+
begin
901+
match lv with
902+
| RightValue -> ()
903+
| LeftValue list ->
904+
List.iter (function
905+
| AVariable ( vd, _ ) ->
906+
begin
907+
match opt.in_function with
908+
| None -> ()
909+
| Some in_fd ->
910+
in_fd.function_ops <-
911+
( vd, OpCall fd ) :: in_fd.function_ops
912+
end
913+
| _ -> ()) list
914+
end;
915+
884916
begin
885917
match fd.function_returns with
886918
| [t, _id_opt] ->
@@ -1949,7 +1981,8 @@ let preprocess_free_function_definition menv (mlid : absolute LongIdent.t) fd =
19491981
function_is_method = false;
19501982
function_is_primitive = false;
19511983
function_def = Some (fd);
1952-
function_assigns = [] ;
1984+
function_ops = [] ;
1985+
function_purity = PurityUnknown;
19531986
}
19541987
in
19551988
Solidity_tenv_builder.add_module_ident menv id (Function (fd'));

0 commit comments

Comments
 (0)