Skip to content

Commit

Permalink
add for-range and repeat freeton type-checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabrice Le Fessant committed Aug 16, 2021
1 parent a3d31ba commit 06bb243
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 13 deletions.
4 changes: 3 additions & 1 deletion src/solidity-common/solidity_ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ and raw_statement =
| Break
| PlaceholderStatement
| RepeatStatement of expression * statement (* freeton *)
| ForRangeStatement of variable_definition * statement (* freeton *)
| ForRangeStatement of
(type_ * storage_location option * ident) option list *
expression * statement (* freeton *)

and expression = raw_expression node

Expand Down
4 changes: 3 additions & 1 deletion src/solidity-common/solidity_ast.mli
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ and raw_statement =
(** Placeholder for modifiers *)

| RepeatStatement of expression * statement (* freeton *)
| ForRangeStatement of variable_definition * statement (* freeton *)
| ForRangeStatement of
(type_ * storage_location option * ident) option list *
expression * statement (* freeton *)

and expression = raw_expression node

Expand Down
19 changes: 16 additions & 3 deletions src/solidity-common/solidity_printer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -496,10 +496,23 @@ and statement b indent s =
| RepeatStatement (e, body) ->
bprint b indent (Format.sprintf "repeat (%s)" (string_of_expression e));
statement b (indent + 2) body
| ForRangeStatement (vd, s2) ->
| ForRangeStatement (var_decl_list, e , s2) ->
bprint b indent
( Printf.sprintf "for ( %s )"
(string_of_variable_definition vd)) ;
( Printf.sprintf "for ( %s : %s )"
(
match var_decl_list with
| [Some variable_declaration] ->
string_of_variable_declaration variable_declaration
| _ ->
Format.sprintf "(%s)"
(String.concat ", "
(List.map (function
| None -> ""
| Some var_decl ->
string_of_variable_declaration var_decl
) var_decl_list))
)
(string_of_expression e)) ;
statement b (indent + 2) s2

and string_of_expression_option = function
Expand Down
10 changes: 8 additions & 2 deletions src/solidity-common/solidity_visitor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,14 @@ and visitStatement (v : #ast_visitor) (s : statement) : unit =
| RepeatStatement (e, s) ->
visitExpression v e;
visitStatement v s
| ForRangeStatement (vd, s2) ->
visitVariableDef v vd ;
| ForRangeStatement (var_decl_list, e, s2) ->
visitList
(visitOpt
(visitXYZ
visitType
(visitOpt visitStorageLocation)
(visitNode visitIdent))) v var_decl_list;
visitExpression v e;
visitStatement v s2
in
handleAction v#visitStatement continueVisit s
Expand Down
2 changes: 1 addition & 1 deletion src/solidity-parser/solidity_raw_parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ for_statement:
{ ForStatement ($3, $5, $7, $9) }
| FOR LPAREN variable_declaration_opt_list COLON expression RPAREN
statement
{ ForRangeStatement ( VarType ($3, Some $5), $7) }
{ ForRangeStatement ( $3, $5, $7) }
;;

while_statement:
Expand Down
61 changes: 56 additions & 5 deletions src/solidity-typechecker/solidity_typechecker.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1120,8 +1120,59 @@ let rec type_statement opt env s =
expect_expression_type opt env e TBool;
type_statement { opt with in_loop = true } env s

| RepeatStatement (_e, _s) -> assert false (* freeton TODO *)
| ForRangeStatement _ -> assert false (* freeton TODO *)
| RepeatStatement (e, s) ->
expect_expression_type opt env e TBool;
type_statement opt env s

| ForRangeStatement ( var_decl_list, e, s) ->
let env' = Solidity_tenv_builder.new_env ~upper_env:env () in

begin
let var_decl_list =
List.map (fun var_decl_opt ->
Option.map (fun (t, loc_opt, var_name) ->
Solidity_type_builder.var_type_to_type
pos env ~arg:false ~ext:false loc_opt t,
var_name
) var_decl_opt
) var_decl_list
in
let tl =
match type_expression opt env e with
| TArray (t, _, _) -> [t]
| TMapping (tk, tv, _) -> [tk ; tv]
| _ ->
error pos "Type is not iterable"
in
if not (ExtList.same_lengths tl var_decl_list) then
error pos "Left hand side and right hand side \
must have the same number of elements"
else
List.iter2 (fun var_decl_opt t ->
Option.iter (fun (t', _var_name) ->
if not (Solidity_type_conv.implicitly_convertible
~from:t ~to_:t' ()) then
error pos
"Incompatible types in assignment: %S expected, got %S"
( Solidity_type_printer.string_of_type t')
( Solidity_type_printer.string_of_type t )
) var_decl_opt
) var_decl_list tl;
let annot =
match var_decl_list with
| [Some (t, _id)] -> t
| tidol -> TTuple (List.map (Option.map fst) tidol)
in
set_annot s (AType annot);
List.iter (function
| None -> ()
| Some (t, var_name) ->
Solidity_tenv_builder.add_local_variable pos env
(strip var_name) (Solidity_type_builder.local_variable_desc t)
) var_decl_list

end;
type_statement { opt with in_loop = true } env' s

| DoWhileStatement (s, e) ->
let env' = Solidity_tenv_builder.new_env ~upper_env:env () in
Expand Down Expand Up @@ -1169,8 +1220,8 @@ let rec type_statement opt env s =
List.iter2 (fun (rt, _id_opt1) (t, _id_opt2) ->
if not (Solidity_type.same_type rt t) then
error pos "Invalid type, expected %s but got %s"
(Solidity_type_printer.string_of_type rt)
(Solidity_type_printer.string_of_type t)
(Solidity_type_printer.string_of_type rt)
(Solidity_type_printer.string_of_type t)
) returns fd.function_returns;
returns
in
Expand All @@ -1193,7 +1244,7 @@ let rec type_statement opt env s =
List.iter (fun (t, loc_opt, name_opt) ->
Option.iter (fun name ->
let t = Solidity_type_builder.var_type_to_type
pos env ~arg:true ~ext:false loc_opt t in
pos env ~arg:true ~ext:false loc_opt t in
Solidity_tenv_builder.add_local_variable pos env'
(strip name) (Solidity_type_builder.local_variable_desc t)
) name_opt
Expand Down

0 comments on commit 06bb243

Please sign in to comment.