Merge branch '8-reporting-of-error-messages' of gitlab.com:ligolang/ligo into 8-reporting-of-error-messages
This commit is contained in:
commit
1ccaef23fb
@ -346,7 +346,7 @@ and conditional = {
|
|||||||
|
|
||||||
let sprintf = Printf.sprintf
|
let sprintf = Printf.sprintf
|
||||||
|
|
||||||
let region_of_type_expr = function
|
let type_expr_to_region = function
|
||||||
TProd {region; _}
|
TProd {region; _}
|
||||||
| TSum {region; _}
|
| TSum {region; _}
|
||||||
| TRecord {region; _}
|
| TRecord {region; _}
|
||||||
@ -355,12 +355,11 @@ let region_of_type_expr = function
|
|||||||
| TPar {region; _}
|
| TPar {region; _}
|
||||||
| TAlias {region; _} -> region
|
| TAlias {region; _} -> region
|
||||||
|
|
||||||
|
let list_pattern_to_region = function
|
||||||
let region_of_list_pattern = function
|
|
||||||
Sugar {region; _} | PCons {region; _} -> region
|
Sugar {region; _} | PCons {region; _} -> region
|
||||||
|
|
||||||
let region_of_pattern = function
|
let pattern_to_region = function
|
||||||
PList p -> region_of_list_pattern p
|
PList p -> list_pattern_to_region p
|
||||||
| PTuple {region;_} | PVar {region;_}
|
| PTuple {region;_} | PVar {region;_}
|
||||||
| PUnit {region;_} | PInt {region;_}
|
| PUnit {region;_} | PInt {region;_}
|
||||||
| PTrue region | PFalse region
|
| PTrue region | PFalse region
|
||||||
@ -368,38 +367,38 @@ let region_of_pattern = function
|
|||||||
| PConstr {region; _} | PPar {region;_}
|
| PConstr {region; _} | PPar {region;_}
|
||||||
| PRecord {region; _} | PTyped {region; _} -> region
|
| PRecord {region; _} | PTyped {region; _} -> region
|
||||||
|
|
||||||
let region_of_bool_expr = function
|
let bool_expr_to_region = function
|
||||||
Or {region;_} | And {region;_}
|
Or {region;_} | And {region;_}
|
||||||
| True region | False region
|
| True region | False region
|
||||||
| Not {region;_} -> region
|
| Not {region;_} -> region
|
||||||
|
|
||||||
let region_of_comp_expr = function
|
let comp_expr_to_region = function
|
||||||
Lt {region;_} | Leq {region;_}
|
Lt {region;_} | Leq {region;_}
|
||||||
| Gt {region;_} | Geq {region;_}
|
| Gt {region;_} | Geq {region;_}
|
||||||
| Neq {region;_} | Equal {region;_} -> region
|
| Neq {region;_} | Equal {region;_} -> region
|
||||||
|
|
||||||
let region_of_logic_expr = function
|
let logic_expr_to_region = function
|
||||||
BoolExpr e -> region_of_bool_expr e
|
BoolExpr e -> bool_expr_to_region e
|
||||||
| CompExpr e -> region_of_comp_expr e
|
| CompExpr e -> comp_expr_to_region e
|
||||||
|
|
||||||
let region_of_arith_expr = function
|
let arith_expr_to_region = function
|
||||||
Add {region;_} | Sub {region;_} | Mult {region;_}
|
Add {region;_} | Sub {region;_} | Mult {region;_}
|
||||||
| Div {region;_} | Mod {region;_} | Neg {region;_}
|
| Div {region;_} | Mod {region;_} | Neg {region;_}
|
||||||
| Int {region;_} | Mtz {region; _}
|
| Int {region;_} | Mtz {region; _}
|
||||||
| Nat {region; _} -> region
|
| Nat {region; _} -> region
|
||||||
|
|
||||||
let region_of_string_expr = function
|
let string_expr_to_region = function
|
||||||
String {region;_} | Cat {region;_} -> region
|
String {region;_} | Cat {region;_} -> region
|
||||||
|
|
||||||
let region_of_list_expr = function
|
let list_expr_to_region = function
|
||||||
Cons {region; _} | List {region; _}
|
Cons {region; _} | List {region; _}
|
||||||
(* | Append {region; _}*) -> region
|
(* | Append {region; _}*) -> region
|
||||||
|
|
||||||
let region_of_expr = function
|
let expr_to_region = function
|
||||||
ELogic e -> region_of_logic_expr e
|
ELogic e -> logic_expr_to_region e
|
||||||
| EArith e -> region_of_arith_expr e
|
| EArith e -> arith_expr_to_region e
|
||||||
| EString e -> region_of_string_expr e
|
| EString e -> string_expr_to_region e
|
||||||
| EList e -> region_of_list_expr e
|
| EList e -> list_expr_to_region e
|
||||||
| EAnnot {region;_ } | ELetIn {region;_} | EFun {region;_}
|
| EAnnot {region;_ } | ELetIn {region;_} | EFun {region;_}
|
||||||
| ECond {region;_} | ETuple {region;_} | ECase {region;_}
|
| ECond {region;_} | ETuple {region;_} | ECase {region;_}
|
||||||
| ECall {region;_} | EVar {region; _} | EProj {region; _}
|
| ECall {region;_} | EVar {region; _} | EProj {region; _}
|
||||||
|
@ -470,9 +470,9 @@ val print_tokens : (*?undo:bool ->*) ast -> unit
|
|||||||
(* Projecting regions from sundry nodes of the AST. See the first
|
(* Projecting regions from sundry nodes of the AST. See the first
|
||||||
comment at the beginning of this file. *)
|
comment at the beginning of this file. *)
|
||||||
|
|
||||||
val region_of_pattern : pattern -> Region.t
|
val pattern_to_region : pattern -> Region.t
|
||||||
val region_of_expr : expr -> Region.t
|
val expr_to_region : expr -> Region.t
|
||||||
val region_of_type_expr : type_expr -> Region.t
|
val type_expr_to_region : type_expr -> Region.t
|
||||||
|
|
||||||
(* Simplifications *)
|
(* Simplifications *)
|
||||||
|
|
||||||
|
@ -315,7 +315,8 @@ and statement =
|
|||||||
| Data of data_decl
|
| Data of data_decl
|
||||||
|
|
||||||
and local_decl =
|
and local_decl =
|
||||||
LocalLam of lambda_decl
|
LocalFun of fun_decl reg
|
||||||
|
| LocalProc of proc_decl reg
|
||||||
| LocalData of data_decl
|
| LocalData of data_decl
|
||||||
|
|
||||||
and data_decl =
|
and data_decl =
|
||||||
@ -785,9 +786,8 @@ let pattern_to_region = function
|
|||||||
| PTuple {region; _} -> region
|
| PTuple {region; _} -> region
|
||||||
|
|
||||||
let local_decl_to_region = function
|
let local_decl_to_region = function
|
||||||
LocalLam FunDecl {region; _}
|
LocalFun {region; _}
|
||||||
| LocalLam ProcDecl {region; _}
|
| LocalProc {region; _}
|
||||||
| LocalLam EntryDecl {region; _}
|
|
||||||
| LocalData LocalConst {region; _}
|
| LocalData LocalConst {region; _}
|
||||||
| LocalData LocalVar {region; _} -> region
|
| LocalData LocalVar {region; _} -> region
|
||||||
|
|
||||||
|
@ -299,7 +299,8 @@ and statement =
|
|||||||
| Data of data_decl
|
| Data of data_decl
|
||||||
|
|
||||||
and local_decl =
|
and local_decl =
|
||||||
LocalLam of lambda_decl
|
LocalFun of fun_decl reg
|
||||||
|
| LocalProc of proc_decl reg
|
||||||
| LocalData of data_decl
|
| LocalData of data_decl
|
||||||
|
|
||||||
and data_decl =
|
and data_decl =
|
||||||
|
@ -426,7 +426,8 @@ open_var_decl:
|
|||||||
in {region; value}}
|
in {region; value}}
|
||||||
|
|
||||||
local_decl:
|
local_decl:
|
||||||
lambda_decl { LocalLam $1 }
|
fun_decl { LocalFun $1 }
|
||||||
|
| proc_decl { LocalProc $1 }
|
||||||
| data_decl { LocalData $1 }
|
| data_decl { LocalData $1 }
|
||||||
|
|
||||||
data_decl:
|
data_decl:
|
||||||
|
@ -251,7 +251,8 @@ and print_local_decls sequence =
|
|||||||
List.iter print_local_decl sequence
|
List.iter print_local_decl sequence
|
||||||
|
|
||||||
and print_local_decl = function
|
and print_local_decl = function
|
||||||
LocalLam decl -> print_lambda_decl decl
|
LocalFun decl -> print_fun_decl decl
|
||||||
|
| LocalProc decl -> print_proc_decl decl
|
||||||
| LocalData decl -> print_data_decl decl
|
| LocalData decl -> print_data_decl decl
|
||||||
|
|
||||||
and print_data_decl = function
|
and print_data_decl = function
|
||||||
|
@ -23,7 +23,7 @@ module Errors = struct
|
|||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("expected", fun () -> expected_name);
|
("expected", fun () -> expected_name);
|
||||||
("actual_loc" , fun () -> Format.asprintf "%a" Location.pp_lift @@ Raw.region_of_pattern actual)
|
("actual_loc" , fun () -> Format.asprintf "%a" Location.pp_lift @@ Raw.pattern_to_region actual)
|
||||||
] in
|
] in
|
||||||
error ~data title message
|
error ~data title message
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ module Errors = struct
|
|||||||
let message () =
|
let message () =
|
||||||
Format.asprintf "multiple patterns in \"%s\" are not supported yet" construct in
|
Format.asprintf "multiple patterns in \"%s\" are not supported yet" construct in
|
||||||
let patterns_loc =
|
let patterns_loc =
|
||||||
List.fold_left (fun a p -> Region.cover a (Raw.region_of_pattern p))
|
List.fold_left (fun a p -> Region.cover a (Raw.pattern_to_region p))
|
||||||
Region.min patterns in
|
Region.min patterns in
|
||||||
let data = [
|
let data = [
|
||||||
("patterns_loc", fun () -> Format.asprintf "%a" Location.pp_lift @@ patterns_loc)
|
("patterns_loc", fun () -> Format.asprintf "%a" Location.pp_lift @@ patterns_loc)
|
||||||
@ -53,7 +53,7 @@ module Errors = struct
|
|||||||
let title () = "arithmetic expressions" in
|
let title () = "arithmetic expressions" in
|
||||||
let message () =
|
let message () =
|
||||||
Format.asprintf "this arithmetic operator is not supported yet" in
|
Format.asprintf "this arithmetic operator is not supported yet" in
|
||||||
let expr_loc = Raw.region_of_expr expr in
|
let expr_loc = Raw.expr_to_region expr in
|
||||||
let data = [
|
let data = [
|
||||||
("expr_loc",
|
("expr_loc",
|
||||||
fun () -> Format.asprintf "%a" Location.pp_lift @@ expr_loc)
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ expr_loc)
|
||||||
@ -64,7 +64,7 @@ module Errors = struct
|
|||||||
let title () = "string expressions" in
|
let title () = "string expressions" in
|
||||||
let message () =
|
let message () =
|
||||||
Format.asprintf "string concatenation is not supported yet" in
|
Format.asprintf "string concatenation is not supported yet" in
|
||||||
let expr_loc = Raw.region_of_expr expr in
|
let expr_loc = Raw.expr_to_region expr in
|
||||||
let data = [
|
let data = [
|
||||||
("expr_loc",
|
("expr_loc",
|
||||||
fun () -> Format.asprintf "%a" Location.pp_lift @@ expr_loc)
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ expr_loc)
|
||||||
@ -86,7 +86,7 @@ module Errors = struct
|
|||||||
let title () = "tuple pattern" in
|
let title () = "tuple pattern" in
|
||||||
let message () =
|
let message () =
|
||||||
Format.asprintf "tuple patterns are not supported yet" in
|
Format.asprintf "tuple patterns are not supported yet" in
|
||||||
let pattern_loc = Raw.region_of_pattern p in
|
let pattern_loc = Raw.pattern_to_region p in
|
||||||
let data = [
|
let data = [
|
||||||
("pattern_loc",
|
("pattern_loc",
|
||||||
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
||||||
@ -97,13 +97,67 @@ module Errors = struct
|
|||||||
let title () = "constant constructor" in
|
let title () = "constant constructor" in
|
||||||
let message () =
|
let message () =
|
||||||
Format.asprintf "constant constructors are not supported yet" in
|
Format.asprintf "constant constructors are not supported yet" in
|
||||||
let pattern_loc = Raw.region_of_pattern p in
|
let pattern_loc = Raw.pattern_to_region p in
|
||||||
let data = [
|
let data = [
|
||||||
("pattern_loc",
|
("pattern_loc",
|
||||||
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message
|
error ~data title message
|
||||||
|
|
||||||
|
let unsupported_non_var_pattern p =
|
||||||
|
let title () = "pattern is not a variable" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "non-variable patterns in constructors \
|
||||||
|
are not supported yet" in
|
||||||
|
let pattern_loc = Raw.pattern_to_region p in
|
||||||
|
let data = [
|
||||||
|
("pattern_loc",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let simplifying_expr t =
|
||||||
|
let title () = "simplifying expression" in
|
||||||
|
let message () = "" in
|
||||||
|
let data = [
|
||||||
|
("expression" ,
|
||||||
|
thunk @@ Format.asprintf "%a" (PP_helpers.printer Raw.print_expr) t)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let only_constructors p =
|
||||||
|
let title () = "constructors in patterns" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "currently, only constructors are supported in patterns" in
|
||||||
|
let pattern_loc = Raw.pattern_to_region p in
|
||||||
|
let data = [
|
||||||
|
("pattern_loc",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let unsupported_sugared_lists region =
|
||||||
|
let title () = "lists in patterns" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "currently, only empty lists and constructors (::) \
|
||||||
|
are supported in patterns" in
|
||||||
|
let data = [
|
||||||
|
("pattern_loc",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ region)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
open Errors
|
open Errors
|
||||||
@ -174,10 +228,12 @@ let rec simpl_type_expression : Raw.type_expr -> type_expression result = fun te
|
|||||||
)
|
)
|
||||||
| TRecord r ->
|
| TRecord r ->
|
||||||
let aux = fun (x, y) -> let%bind y = simpl_type_expression y in ok (x, y) in
|
let aux = fun (x, y) -> let%bind y = simpl_type_expression y in ok (x, y) in
|
||||||
|
let apply (x:Raw.field_decl Raw.reg) =
|
||||||
|
(x.value.field_name.value, x.value.field_type) in
|
||||||
let%bind lst =
|
let%bind lst =
|
||||||
bind_list
|
bind_list
|
||||||
@@ List.map aux
|
@@ List.map aux
|
||||||
@@ List.map (fun (x:Raw.field_decl Raw.reg) -> (x.value.field_name.value, x.value.field_type))
|
@@ List.map apply
|
||||||
@@ pseq_to_list r.value.elements in
|
@@ pseq_to_list r.value.elements in
|
||||||
let m = List.fold_left (fun m (x, y) -> SMap.add x y m) SMap.empty lst in
|
let m = List.fold_left (fun m (x, y) -> SMap.add x y m) SMap.empty lst in
|
||||||
ok @@ T_record m
|
ok @@ T_record m
|
||||||
@ -227,14 +283,7 @@ let rec simpl_expression :
|
|||||||
return @@ e_accessor ~loc var path'
|
return @@ e_accessor ~loc var path'
|
||||||
in
|
in
|
||||||
|
|
||||||
trace (
|
trace (simplifying_expr t) @@
|
||||||
let title () = "simplifying expression" in
|
|
||||||
let message () = "" in
|
|
||||||
let data = [
|
|
||||||
("expression" , thunk @@ Format.asprintf "%a" (PP_helpers.printer Raw.print_expr) t)
|
|
||||||
] in
|
|
||||||
error ~data title message
|
|
||||||
) @@
|
|
||||||
match t with
|
match t with
|
||||||
| Raw.ELetIn e -> (
|
| Raw.ELetIn e -> (
|
||||||
let Raw.{binding ; body ; _} = e.value in
|
let Raw.{binding ; body ; _} = e.value in
|
||||||
@ -522,14 +571,14 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap result =
|
|||||||
let {name;type_expr} : Raw.type_decl = x.value in
|
let {name;type_expr} : Raw.type_decl = x.value in
|
||||||
let%bind type_expression = simpl_type_expression type_expr in
|
let%bind type_expression = simpl_type_expression type_expr in
|
||||||
ok @@ loc x @@ Declaration_type (name.value , type_expression)
|
ok @@ loc x @@ Declaration_type (name.value , type_expression)
|
||||||
| LetEntry x (* -> simple_fail "no entry point yet" *)
|
| LetEntry x
|
||||||
| Let x -> (
|
| Let x -> (
|
||||||
let _ , binding = x.value in
|
let _ , binding = x.value in
|
||||||
let {bindings ; lhs_type ; let_rhs} = binding in
|
let {bindings ; lhs_type ; let_rhs} = binding in
|
||||||
let%bind (var , args) =
|
let%bind (var , args) =
|
||||||
let%bind (hd , tl) =
|
let%bind (hd , tl) =
|
||||||
match bindings with
|
match bindings with
|
||||||
| [] -> simple_fail "let without bindings"
|
| [] -> fail @@ corner_case ~loc:__LOC__ "let without bindings"
|
||||||
| hd :: tl -> ok (hd , tl)
|
| hd :: tl -> ok (hd , tl)
|
||||||
in
|
in
|
||||||
let%bind var = pattern_to_var hd in
|
let%bind var = pattern_to_var hd in
|
||||||
@ -556,19 +605,17 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap result =
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
and simpl_cases : type a . (Raw.pattern * a) list -> a matching result = fun t ->
|
and simpl_cases : type a . (Raw.pattern * a) list -> a matching result =
|
||||||
|
fun t ->
|
||||||
let open Raw in
|
let open Raw in
|
||||||
let get_var (t:Raw.pattern) = match t with
|
let rec get_var (t:Raw.pattern) =
|
||||||
|
match t with
|
||||||
| PVar v -> ok v.value
|
| PVar v -> ok v.value
|
||||||
| _ ->
|
| PPar p -> get_var p.value.inside
|
||||||
let error =
|
| _ -> fail @@ unsupported_non_var_pattern t
|
||||||
let title () = "not a var" in
|
|
||||||
let content () = Format.asprintf "%a" (PP_helpers.printer Raw.print_pattern) t in
|
|
||||||
error title content
|
|
||||||
in
|
in
|
||||||
fail error
|
let rec get_tuple (t:Raw.pattern) =
|
||||||
in
|
match t with
|
||||||
let rec get_tuple (t:Raw.pattern) = match t with
|
|
||||||
| PTuple v -> npseq_to_list v.value
|
| PTuple v -> npseq_to_list v.value
|
||||||
| PPar p -> get_tuple p.value.inside
|
| PPar p -> get_tuple p.value.inside
|
||||||
| x -> [ x ]
|
| x -> [ x ]
|
||||||
@ -578,8 +625,11 @@ and simpl_cases : type a . (Raw.pattern * a) list -> a matching result = fun t -
|
|||||||
let%bind () =
|
let%bind () =
|
||||||
trace_strong (unsupported_tuple_pattern t) @@
|
trace_strong (unsupported_tuple_pattern t) @@
|
||||||
Assert.assert_list_size t' 1 in
|
Assert.assert_list_size t' 1 in
|
||||||
ok (List.hd t') in
|
ok (List.hd t')
|
||||||
let get_constr (t:Raw.pattern) = match t with
|
in
|
||||||
|
let rec get_constr (t:Raw.pattern) =
|
||||||
|
match t with
|
||||||
|
| PPar p -> get_constr p.value.inside
|
||||||
| PConstr v -> (
|
| PConstr v -> (
|
||||||
let (const , pat_opt) = v.value in
|
let (const , pat_opt) = v.value in
|
||||||
let%bind pat =
|
let%bind pat =
|
||||||
@ -589,23 +639,24 @@ and simpl_cases : type a . (Raw.pattern * a) list -> a matching result = fun t -
|
|||||||
let%bind var = get_var single_pat in
|
let%bind var = get_var single_pat in
|
||||||
ok (const.value , var)
|
ok (const.value , var)
|
||||||
)
|
)
|
||||||
| _ -> simple_fail "not a constr"
|
| _ -> fail @@ only_constructors t
|
||||||
in
|
in
|
||||||
let%bind patterns =
|
let%bind patterns =
|
||||||
let aux (x , y) =
|
let aux (x , y) =
|
||||||
let xs = get_tuple x in
|
let xs = get_tuple x in
|
||||||
trace_strong (simple_error "no tuple in patterns yet") @@
|
trace_strong (unsupported_tuple_pattern x) @@
|
||||||
Assert.assert_list_size xs 1 >>? fun () ->
|
Assert.assert_list_size xs 1 >>? fun () ->
|
||||||
ok (List.hd xs , y)
|
ok (List.hd xs , y)
|
||||||
in
|
in
|
||||||
bind_map_list aux t in
|
bind_map_list aux t in
|
||||||
match patterns with
|
match patterns with
|
||||||
| [(PFalse _ , f) ; (PTrue _ , t)]
|
| [(PFalse _ , f) ; (PTrue _ , t)]
|
||||||
| [(PTrue _ , t) ; (PFalse _ , f)] -> ok @@ Match_bool {match_true = t ; match_false = f}
|
| [(PTrue _ , t) ; (PFalse _ , f)] ->
|
||||||
|
ok @@ Match_bool {match_true = t ; match_false = f}
|
||||||
| [(PList (PCons c) , cons) ; (PList (Sugar sugar_nil) , nil)]
|
| [(PList (PCons c) , cons) ; (PList (Sugar sugar_nil) , nil)]
|
||||||
| [(PList (Sugar sugar_nil) , nil) ; (PList (PCons c), cons)] -> (
|
| [(PList (Sugar sugar_nil) , nil) ; (PList (PCons c), cons)] -> (
|
||||||
let%bind () =
|
let%bind () =
|
||||||
trace_strong (simple_error "Only empty list patterns and cons are allowed yet")
|
trace_strong (unsupported_sugared_lists sugar_nil.region)
|
||||||
@@ Assert.assert_list_empty
|
@@ Assert.assert_list_empty
|
||||||
@@ pseq_to_list
|
@@ pseq_to_list
|
||||||
@@ sugar_nil.value.elements in
|
@@ sugar_nil.value.elements in
|
||||||
@ -618,7 +669,8 @@ and simpl_cases : type a . (Raw.pattern * a) list -> a matching result = fun t -
|
|||||||
ok @@ Match_list {match_cons = (a, b, cons) ; match_nil = nil}
|
ok @@ Match_list {match_cons = (a, b, cons) ; match_nil = nil}
|
||||||
)
|
)
|
||||||
| lst -> (
|
| lst -> (
|
||||||
trace (simple_info "weird patterns not supported yet") @@
|
trace (simple_info "currently, only booleans, lists and constructors \
|
||||||
|
are supported in patterns") @@
|
||||||
let%bind constrs =
|
let%bind constrs =
|
||||||
let aux (x , y) =
|
let aux (x , y) =
|
||||||
let error =
|
let error =
|
||||||
|
@ -14,6 +14,94 @@ let pseq_to_list = function
|
|||||||
| Some lst -> npseq_to_list lst
|
| Some lst -> npseq_to_list lst
|
||||||
let get_value : 'a Raw.reg -> 'a = fun x -> x.value
|
let get_value : 'a Raw.reg -> 'a = fun x -> x.value
|
||||||
|
|
||||||
|
module Errors = struct
|
||||||
|
let unsupported_entry_decl decl =
|
||||||
|
let title () = "entry point declarations" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "entry points within the contract are not supported yet" in
|
||||||
|
let data = [
|
||||||
|
("declaration",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ decl.Region.region)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let unsupported_proc_decl decl =
|
||||||
|
let title () = "procedure declarations" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "procedures are not supported yet" in
|
||||||
|
let data = [
|
||||||
|
("declaration",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ decl.Region.region)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let unsupported_local_proc region =
|
||||||
|
let title () = "local procedure declarations" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "local procedures are not supported yet" in
|
||||||
|
let data = [
|
||||||
|
("declaration",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ region)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
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 unknown_predefined_type name =
|
||||||
|
let title () = "type constants" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "unknown predefined type \"%s\"" name.Region.value in
|
||||||
|
let data = [
|
||||||
|
("typename_loc",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ name.Region.region)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let unsupported_arith_op expr =
|
||||||
|
let title () = "arithmetic expressions" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "this arithmetic operator is not supported yet" in
|
||||||
|
let expr_loc = Raw.expr_to_region expr in
|
||||||
|
let data = [
|
||||||
|
("expr_loc",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ expr_loc)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let unsupported_string_catenation expr =
|
||||||
|
let title () = "string expressions" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "string concatenation is not supported yet" in
|
||||||
|
let expr_loc = Raw.expr_to_region expr in
|
||||||
|
let data = [
|
||||||
|
("expr_loc",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ expr_loc)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
|
||||||
|
let unsupported_set_expr expr =
|
||||||
|
let title () = "set expressions" in
|
||||||
|
let message () =
|
||||||
|
Format.asprintf "set type is not supported yet" in
|
||||||
|
let expr_loc = Raw.expr_to_region expr in
|
||||||
|
let data = [
|
||||||
|
("expr_loc",
|
||||||
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ expr_loc)
|
||||||
|
] in
|
||||||
|
error ~data title message
|
||||||
|
end
|
||||||
|
|
||||||
|
open Errors
|
||||||
open Operators.Simplify.Pascaligo
|
open Operators.Simplify.Pascaligo
|
||||||
|
|
||||||
let r_split = Location.r_split
|
let r_split = Location.r_split
|
||||||
@ -26,7 +114,7 @@ let return expr = ok @@ fun expr'_opt ->
|
|||||||
|
|
||||||
let return_let_in ?loc binder rhs = ok @@ fun expr'_opt ->
|
let return_let_in ?loc binder rhs = ok @@ fun expr'_opt ->
|
||||||
match expr'_opt with
|
match expr'_opt with
|
||||||
| None -> simple_fail "missing return" (* Hard to explain. Shouldn't happen in prod. *)
|
| None -> fail @@ corner_case ~loc:__LOC__ "missing return"
|
||||||
| Some expr' -> ok @@ e_let_in ?loc binder rhs expr'
|
| Some expr' -> ok @@ e_let_in ?loc binder rhs expr'
|
||||||
|
|
||||||
let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
||||||
@ -48,7 +136,7 @@ let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
|||||||
let lst = npseq_to_list tuple.value.inside in
|
let lst = npseq_to_list tuple.value.inside in
|
||||||
let%bind lst' = bind_list @@ List.map simpl_type_expression lst in
|
let%bind lst' = bind_list @@ List.map simpl_type_expression lst in
|
||||||
let%bind cst =
|
let%bind cst =
|
||||||
trace_option (simple_error "unrecognized type constants") @@
|
trace_option (unknown_predefined_type name) @@
|
||||||
List.assoc_opt name.value type_constants in
|
List.assoc_opt name.value type_constants in
|
||||||
ok @@ T_constant (cst , lst')
|
ok @@ T_constant (cst , lst')
|
||||||
| TProd p ->
|
| TProd p ->
|
||||||
@ -57,9 +145,11 @@ let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
|||||||
ok tpl
|
ok tpl
|
||||||
| TRecord r ->
|
| TRecord r ->
|
||||||
let aux = fun (x, y) -> let%bind y = simpl_type_expression y in ok (x, y) in
|
let aux = fun (x, y) -> let%bind y = simpl_type_expression y in ok (x, y) in
|
||||||
|
let apply =
|
||||||
|
fun (x:Raw.field_decl Raw.reg) -> (x.value.field_name.value, x.value.field_type) in
|
||||||
let%bind lst = bind_list
|
let%bind lst = bind_list
|
||||||
@@ List.map aux
|
@@ List.map aux
|
||||||
@@ List.map (fun (x:Raw.field_decl Raw.reg) -> (x.value.field_name.value, x.value.field_type))
|
@@ List.map apply
|
||||||
@@ pseq_to_list r.value.elements in
|
@@ pseq_to_list r.value.elements in
|
||||||
let m = List.fold_left (fun m (x, y) -> SMap.add x y m) SMap.empty lst in
|
let m = List.fold_left (fun m (x, y) -> SMap.add x y m) SMap.empty lst in
|
||||||
ok @@ T_record m
|
ok @@ T_record m
|
||||||
@ -194,18 +284,20 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
|||||||
let n = Z.to_int @@ snd @@ n in
|
let n = Z.to_int @@ snd @@ n in
|
||||||
return @@ e_literal ~loc (Literal_tez n)
|
return @@ e_literal ~loc (Literal_tez n)
|
||||||
)
|
)
|
||||||
| EArith _ -> simple_fail "arith: not supported yet"
|
| EArith _ as e ->
|
||||||
|
fail @@ unsupported_arith_op e
|
||||||
| EString (String s) ->
|
| EString (String s) ->
|
||||||
let (s , loc) = r_split s in
|
let (s , loc) = r_split s in
|
||||||
let s' =
|
let s' =
|
||||||
(* S contains quotes *)
|
(* S contains quotes *)
|
||||||
String.(sub s 1 ((length s) - 2))
|
String.(sub s 1 (length s - 2))
|
||||||
in
|
in
|
||||||
return @@ e_literal ~loc (Literal_string s')
|
return @@ e_literal ~loc (Literal_string s')
|
||||||
| EString _ -> simple_fail "string: not supported yet"
|
| EString (Cat _) as e ->
|
||||||
|
fail @@ unsupported_string_catenation e
|
||||||
| ELogic l -> simpl_logic_expression l
|
| ELogic l -> simpl_logic_expression l
|
||||||
| EList l -> simpl_list_expression l
|
| EList l -> simpl_list_expression l
|
||||||
| ESet _ -> simple_fail "set: not supported yet"
|
| ESet _ -> fail @@ unsupported_set_expr t
|
||||||
| ECase c -> (
|
| ECase c -> (
|
||||||
let (c , loc) = r_split c in
|
let (c , loc) = r_split c in
|
||||||
let%bind e = simpl_expression c.expr in
|
let%bind e = simpl_expression c.expr in
|
||||||
@ -224,7 +316,8 @@ let rec simpl_expression (t:Raw.expr) : expr result =
|
|||||||
let (mi , loc) = r_split mi in
|
let (mi , loc) = r_split mi in
|
||||||
let%bind lst =
|
let%bind lst =
|
||||||
let lst = List.map get_value @@ pseq_to_list mi.elements in
|
let lst = List.map get_value @@ pseq_to_list mi.elements in
|
||||||
let aux : Raw.binding -> (expression * expression) result = fun b ->
|
let aux : Raw.binding -> (expression * expression) result =
|
||||||
|
fun b ->
|
||||||
let%bind src = simpl_expression b.source in
|
let%bind src = simpl_expression b.source in
|
||||||
let%bind dst = simpl_expression b.image in
|
let%bind dst = simpl_expression b.image in
|
||||||
ok (src, dst) in
|
ok (src, dst) in
|
||||||
@ -309,26 +402,20 @@ and simpl_tuple_expression ?loc (lst:Raw.expr list) : expression result =
|
|||||||
match lst with
|
match lst with
|
||||||
| [] -> return @@ e_literal Literal_unit
|
| [] -> return @@ e_literal Literal_unit
|
||||||
| [hd] -> simpl_expression hd
|
| [hd] -> simpl_expression hd
|
||||||
| lst -> (
|
| lst ->
|
||||||
let%bind lst = bind_list @@ List.map simpl_expression lst in
|
let%bind lst = bind_list @@ List.map simpl_expression lst in
|
||||||
return @@ e_tuple ?loc lst
|
return @@ e_tuple ?loc lst
|
||||||
)
|
|
||||||
|
|
||||||
and simpl_local_declaration : Raw.local_decl -> _ result = fun t ->
|
and simpl_local_declaration : Raw.local_decl -> _ result = fun t ->
|
||||||
match t with
|
match t with
|
||||||
| LocalData d -> simpl_data_declaration d
|
| LocalData d ->
|
||||||
| LocalLam l -> simpl_lambda_declaration l
|
simpl_data_declaration d
|
||||||
|
| LocalFun f ->
|
||||||
and simpl_lambda_declaration : Raw.lambda_decl -> _ result = fun l ->
|
|
||||||
match l with
|
|
||||||
| FunDecl f -> (
|
|
||||||
let (f , loc) = r_split f in
|
let (f , loc) = r_split f in
|
||||||
let%bind (name , e) = simpl_fun_declaration ~loc f in
|
let%bind (name , e) = simpl_fun_declaration ~loc f in
|
||||||
return_let_in ~loc name e
|
return_let_in ~loc name e
|
||||||
)
|
| LocalProc d ->
|
||||||
| ProcDecl _ -> simple_fail "no local procedure yet"
|
fail @@ unsupported_local_proc d.Region.region
|
||||||
| EntryDecl _ -> simple_fail "no local entry-point yet"
|
|
||||||
|
|
||||||
and simpl_data_declaration : Raw.data_decl -> _ result = fun t ->
|
and simpl_data_declaration : Raw.data_decl -> _ result = fun t ->
|
||||||
match t with
|
match t with
|
||||||
| LocalVar x ->
|
| LocalVar x ->
|
||||||
@ -344,7 +431,8 @@ and simpl_data_declaration : Raw.data_decl -> _ result = fun t ->
|
|||||||
let%bind expression = simpl_expression x.init in
|
let%bind expression = simpl_expression x.init in
|
||||||
return_let_in ~loc (name , Some t) expression
|
return_let_in ~loc (name , Some t) expression
|
||||||
|
|
||||||
and simpl_param : Raw.param_decl -> (type_name * type_expression) result = fun t ->
|
and simpl_param : Raw.param_decl -> (type_name * type_expression) result =
|
||||||
|
fun t ->
|
||||||
match t with
|
match t with
|
||||||
| ParamConst c ->
|
| ParamConst c ->
|
||||||
let c = c.value in
|
let c = c.value in
|
||||||
@ -357,11 +445,15 @@ and simpl_param : Raw.param_decl -> (type_name * type_expression) result = fun t
|
|||||||
let%bind type_expression = simpl_type_expression c.param_type in
|
let%bind type_expression = simpl_type_expression c.param_type in
|
||||||
ok (type_name , type_expression)
|
ok (type_name , type_expression)
|
||||||
|
|
||||||
and simpl_fun_declaration : loc:_ -> Raw.fun_decl -> ((name * type_expression option) * expression) result = fun ~loc x ->
|
and simpl_fun_declaration :
|
||||||
|
loc:_ -> Raw.fun_decl -> ((name * type_expression option) * expression) result =
|
||||||
|
fun ~loc x ->
|
||||||
let open! Raw in
|
let open! Raw in
|
||||||
let {name;param;ret_type;local_decls;block;return} : fun_decl = x in
|
let {name;param;ret_type;local_decls;block;return} : fun_decl = x in
|
||||||
(match npseq_to_list param.value.inside with
|
(match npseq_to_list param.value.inside with
|
||||||
| [] -> simple_fail "function without parameters are not allowed"
|
| [] ->
|
||||||
|
fail @@
|
||||||
|
corner_case ~loc:__LOC__ "parameter-less function should not exist"
|
||||||
| [a] -> (
|
| [a] -> (
|
||||||
let%bind input = simpl_param a in
|
let%bind input = simpl_param a in
|
||||||
let name = name.value in
|
let name = name.value in
|
||||||
@ -390,7 +482,7 @@ and simpl_fun_declaration : loc:_ -> Raw.fun_decl -> ((name * type_expression op
|
|||||||
(arguments_name , type_expression) in
|
(arguments_name , type_expression) in
|
||||||
let%bind tpl_declarations =
|
let%bind tpl_declarations =
|
||||||
let aux = fun i x ->
|
let aux = fun i x ->
|
||||||
let expr = e_accessor (e_variable arguments_name) [ Access_tuple i ] in
|
let expr = e_accessor (e_variable arguments_name) [Access_tuple i] in
|
||||||
let type_ = Some (snd x) in
|
let type_ = Some (snd x) in
|
||||||
let ass = return_let_in (fst x , type_) expr in
|
let ass = return_let_in (fst x , type_) expr in
|
||||||
ass
|
ass
|
||||||
@ -407,12 +499,14 @@ and simpl_fun_declaration : loc:_ -> Raw.fun_decl -> ((name * type_expression op
|
|||||||
let%bind result =
|
let%bind result =
|
||||||
let aux prec cur = cur (Some prec) in
|
let aux prec cur = cur (Some prec) in
|
||||||
bind_fold_right_list aux result body in
|
bind_fold_right_list aux result body in
|
||||||
let expression = e_lambda ~loc binder (Some input_type) (Some output_type) result in
|
let expression =
|
||||||
|
e_lambda ~loc binder (Some input_type) (Some output_type) result in
|
||||||
let type_annotation = Some (T_function (input_type, output_type)) in
|
let type_annotation = Some (T_function (input_type, output_type)) in
|
||||||
ok ((name.value , type_annotation) , expression)
|
ok ((name.value , type_annotation) , expression)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
and simpl_declaration : Raw.declaration -> declaration Location.wrap result = fun t ->
|
and simpl_declaration : Raw.declaration -> declaration Location.wrap result =
|
||||||
|
fun t ->
|
||||||
let open! Raw in
|
let open! Raw in
|
||||||
match t with
|
match t with
|
||||||
| TypeDecl x -> (
|
| TypeDecl x -> (
|
||||||
@ -434,15 +528,19 @@ and simpl_declaration : Raw.declaration -> declaration Location.wrap result = fu
|
|||||||
let%bind ((name , ty_opt) , expr) = simpl_fun_declaration ~loc x in
|
let%bind ((name , ty_opt) , expr) = simpl_fun_declaration ~loc x in
|
||||||
ok @@ Location.wrap ~loc (Declaration_constant (name , ty_opt , expr))
|
ok @@ Location.wrap ~loc (Declaration_constant (name , ty_opt , expr))
|
||||||
)
|
)
|
||||||
| LambdaDecl (ProcDecl _) -> simple_fail "no proc declaration yet"
|
| LambdaDecl (ProcDecl decl) ->
|
||||||
| LambdaDecl (EntryDecl _)-> simple_fail "no entry point yet"
|
fail @@ unsupported_proc_decl decl
|
||||||
|
| LambdaDecl (EntryDecl decl) ->
|
||||||
|
fail @@ unsupported_entry_decl decl
|
||||||
|
|
||||||
and simpl_statement : Raw.statement -> (_ -> expression result) result = fun s ->
|
and simpl_statement : Raw.statement -> (_ -> expression result) result =
|
||||||
|
fun s ->
|
||||||
match s with
|
match s with
|
||||||
| Instr i -> simpl_instruction i
|
| Instr i -> simpl_instruction i
|
||||||
| Data d -> simpl_data_declaration d
|
| Data d -> simpl_data_declaration d
|
||||||
|
|
||||||
and simpl_single_instruction : Raw.single_instr -> (_ -> expression result) result = fun t ->
|
and simpl_single_instruction : Raw.single_instr -> (_ -> expression result) result =
|
||||||
|
fun t ->
|
||||||
match t with
|
match t with
|
||||||
| ProcCall _ -> simple_fail "no proc call"
|
| ProcCall _ -> simple_fail "no proc call"
|
||||||
| Fail e -> (
|
| Fail e -> (
|
||||||
|
@ -16,106 +16,123 @@ module Errors = struct
|
|||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("variable" , fun () -> Format.asprintf "%s" n) ;
|
("variable" , fun () -> Format.asprintf "%s" n) ;
|
||||||
|
(* TODO: types don't have srclocs for now. *)
|
||||||
|
(* ("location" , fun () -> Format.asprintf "%a" Location.pp (n.location)) ; *)
|
||||||
("in" , fun () -> Format.asprintf "%a" Environment.PP.full_environment e)
|
("in" , fun () -> Format.asprintf "%a" Environment.PP.full_environment e)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let unbound_variable (e:environment) (n:string) () =
|
let unbound_variable (e:environment) (n:string) (loc:Location.t) () =
|
||||||
let title = (thunk "unbound variable") in
|
let title = (thunk "unbound variable") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("variable" , fun () -> Format.asprintf "%s" n) ;
|
("variable" , fun () -> Format.asprintf "%s" n) ;
|
||||||
("environment" , fun () -> Format.asprintf "%a" Environment.PP.full_environment e)
|
("environment" , fun () -> Format.asprintf "%a" Environment.PP.full_environment e) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let match_empty_variant : type a . a I.matching -> unit -> _ =
|
let match_empty_variant : type a . a I.matching -> Location.t -> unit -> _ =
|
||||||
fun matching () ->
|
fun matching loc () ->
|
||||||
let title = (thunk "match with no cases") in
|
let title = (thunk "match with no cases") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("variant" , fun () -> Format.asprintf "%a" I.PP.matching_type matching)
|
("variant" , fun () -> Format.asprintf "%a" I.PP.matching_type matching) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let match_missing_case : type a . a I.matching -> unit -> _ =
|
let match_missing_case : type a . a I.matching -> Location.t -> unit -> _ =
|
||||||
fun matching () ->
|
fun matching loc () ->
|
||||||
let title = (thunk "missing case in match") in
|
let title = (thunk "missing case in match") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("variant" , fun () -> Format.asprintf "%a" I.PP.matching_type matching)
|
("variant" , fun () -> Format.asprintf "%a" I.PP.matching_type matching) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let match_redundant_case : type a . a I.matching -> unit -> _ =
|
let match_redundant_case : type a . a I.matching -> Location.t -> unit -> _ =
|
||||||
fun matching () ->
|
fun matching loc () ->
|
||||||
let title = (thunk "missing case in match") in
|
let title = (thunk "missing case in match") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("variant" , fun () -> Format.asprintf "%a" I.PP.matching_type matching)
|
("variant" , fun () -> Format.asprintf "%a" I.PP.matching_type matching) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let unbound_constructor (e:environment) (n:string) () =
|
let unbound_constructor (e:environment) (n:string) (loc:Location.t) () =
|
||||||
let title = (thunk "unbound constructor") in
|
let title = (thunk "unbound constructor") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("constructor" , fun () -> Format.asprintf "%s" n) ;
|
("constructor" , fun () -> Format.asprintf "%s" n) ;
|
||||||
("environment" , fun () -> Format.asprintf "%a" Environment.PP.full_environment e)
|
("environment" , fun () -> Format.asprintf "%a" Environment.PP.full_environment e) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let unrecognized_constant (n:string) () =
|
let unrecognized_constant (n:string) (loc:Location.t) () =
|
||||||
let title = (thunk "unrecognized constant") in
|
let title = (thunk "unrecognized constant") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("constant" , fun () -> Format.asprintf "%s" n) ;
|
("constant" , fun () -> Format.asprintf "%s" n) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let wrong_arity (n:string) (expected:int) (actual:int) () =
|
let wrong_arity (n:string) (expected:int) (actual:int) (loc : Location.t) () =
|
||||||
let title () = "wrong arity" in
|
let title () = "wrong arity" in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("function" , fun () -> Format.asprintf "%s" n) ;
|
("function" , fun () -> Format.asprintf "%s" n) ;
|
||||||
("expected" , fun () -> Format.asprintf "%d" expected) ;
|
("expected" , fun () -> Format.asprintf "%d" expected) ;
|
||||||
("actual" , fun () -> Format.asprintf "%d" actual)
|
("actual" , fun () -> Format.asprintf "%d" actual) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let match_tuple_wrong_arity (expected:'a list) (actual:'b list) () =
|
let match_tuple_wrong_arity (expected:'a list) (actual:'b list) (loc:Location.t) () =
|
||||||
let title () = "matching tuple of different size" in
|
let title () = "matching tuple of different size" in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("expected" , fun () -> Format.asprintf "%d" (List.length expected)) ;
|
("expected" , fun () -> Format.asprintf "%d" (List.length expected)) ;
|
||||||
("actual" , fun () -> Format.asprintf "%d" (List.length actual))
|
("actual" , fun () -> Format.asprintf "%d" (List.length actual)) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
|
(* TODO: this should be a trace_info? *)
|
||||||
let program_error (p:I.program) () =
|
let program_error (p:I.program) () =
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let title = (thunk "typing program") in
|
let title = (thunk "typing program") in
|
||||||
let data = [
|
let data = [
|
||||||
"program" , fun () -> Format.asprintf "%a" I.PP.program p
|
("program" , fun () -> Format.asprintf "%a" I.PP.program p)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let constant_declaration_error (name:string) (ae:I.expr) () =
|
let constant_declaration_error (name:string) (ae:I.expr) (expected: O.type_value option) () =
|
||||||
let title = (thunk "typing constant declaration") in
|
let title = (thunk "typing constant declaration") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("constant" , fun () -> Format.asprintf "%s" name) ;
|
("constant" , fun () -> Format.asprintf "%s" name) ;
|
||||||
("expression" , fun () -> Format.asprintf "%a" I.PP.expression ae)
|
("expression" , fun () -> Format.asprintf "%a" I.PP.expression ae) ;
|
||||||
|
("expected" , fun () ->
|
||||||
|
match expected with
|
||||||
|
None -> "(no annotation for the expected type)"
|
||||||
|
| Some expected -> Format.asprintf "%a" O.PP.type_value expected) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp ae.location)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let match_error : type a . ?msg:string -> expected: a I.matching -> actual: O.type_value -> unit -> _ =
|
let match_error : type a . ?msg:string -> expected: a I.matching -> actual: O.type_value -> Location.t -> unit -> _ =
|
||||||
fun ?(msg = "") ~expected ~actual () ->
|
fun ?(msg = "") ~expected ~actual loc () ->
|
||||||
let title = (thunk "typing match") in
|
let title = (thunk "typing match") in
|
||||||
let message () = msg in
|
let message () = msg in
|
||||||
let data = [
|
let data = [
|
||||||
("expected" , fun () -> Format.asprintf "%a" I.PP.matching_type expected);
|
("expected" , fun () -> Format.asprintf "%a" I.PP.matching_type expected);
|
||||||
("actual" , fun () -> Format.asprintf "%a" O.PP.type_value actual)
|
("actual" , fun () -> Format.asprintf "%a" O.PP.type_value actual) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
@ -123,47 +140,52 @@ module Errors = struct
|
|||||||
let title = (thunk "this expression must be annotated with its type") in
|
let title = (thunk "this expression must be annotated with its type") in
|
||||||
let message () = Format.asprintf "%s needs an annotation" case in
|
let message () = Format.asprintf "%s needs an annotation" case in
|
||||||
let data = [
|
let data = [
|
||||||
("expression" , fun () -> Format.asprintf "%a" I.PP.expression e)
|
("expression" , fun () -> Format.asprintf "%a" I.PP.expression e) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp e.location)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let type_error_approximate ?(msg="") ~(expected: string) ~(actual: O.type_value) ~(expression : O.value) () =
|
let type_error_approximate ?(msg="") ~(expected: string) ~(actual: O.type_value) ~(expression : O.value) (loc:Location.t) () =
|
||||||
let title = (thunk "type error") in
|
let title = (thunk "type error") in
|
||||||
let message () = msg in
|
let message () = msg in
|
||||||
let data = [
|
let data = [
|
||||||
("expected" , fun () -> Format.asprintf "%s" expected);
|
("expected" , fun () -> Format.asprintf "%s" expected);
|
||||||
("actual" , fun () -> Format.asprintf "%a" O.PP.type_value actual);
|
("actual" , fun () -> Format.asprintf "%a" O.PP.type_value actual);
|
||||||
("expression" , fun () -> Format.asprintf "%a" O.PP.value expression)
|
("expression" , fun () -> Format.asprintf "%a" O.PP.value expression) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let type_error ?(msg="") ~(expected: O.type_value) ~(actual: O.type_value) ~(expression : O.value) () =
|
let type_error ?(msg="") ~(expected: O.type_value) ~(actual: O.type_value) ~(expression : O.value) (loc:Location.t) () =
|
||||||
let title = (thunk "type error") in
|
let title = (thunk "type error") in
|
||||||
let message () = msg in
|
let message () = msg in
|
||||||
let data = [
|
let data = [
|
||||||
("expected" , fun () -> Format.asprintf "%a" O.PP.type_value expected);
|
("expected" , fun () -> Format.asprintf "%a" O.PP.type_value expected);
|
||||||
("actual" , fun () -> Format.asprintf "%a" O.PP.type_value actual);
|
("actual" , fun () -> Format.asprintf "%a" O.PP.type_value actual);
|
||||||
("expression" , fun () -> Format.asprintf "%a" O.PP.value expression)
|
("expression" , fun () -> Format.asprintf "%a" O.PP.value expression) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let bad_tuple_index (index : int) (ae : I.expression) (t : O.type_value) () =
|
let bad_tuple_index (index : int) (ae : I.expression) (t : O.type_value) (loc:Location.t) () =
|
||||||
let title = (thunk "invalid tuple index") in
|
let title = (thunk "invalid tuple index") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("index" , fun () -> Format.asprintf "%d" index) ;
|
("index" , fun () -> Format.asprintf "%d" index) ;
|
||||||
("tuple_value" , fun () -> Format.asprintf "%a" I.PP.expression ae) ;
|
("tuple_value" , fun () -> Format.asprintf "%a" I.PP.expression ae) ;
|
||||||
("tuple_type" , fun () -> Format.asprintf "%a" O.PP.type_value t)
|
("tuple_type" , fun () -> Format.asprintf "%a" O.PP.type_value t) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
let bad_record_access (field : string) (ae : I.expression) (t : O.type_value) () =
|
let bad_record_access (field : string) (ae : I.expression) (t : O.type_value) (loc:Location.t) () =
|
||||||
let title = (thunk "invalid record field") in
|
let title = (thunk "invalid record field") in
|
||||||
let message () = "" in
|
let message () = "" in
|
||||||
let data = [
|
let data = [
|
||||||
("field" , fun () -> Format.asprintf "%s" field) ;
|
("field" , fun () -> Format.asprintf "%s" field) ;
|
||||||
("record_value" , fun () -> Format.asprintf "%a" I.PP.expression ae) ;
|
("record_value" , fun () -> Format.asprintf "%a" I.PP.expression ae) ;
|
||||||
("tuple_type" , fun () -> Format.asprintf "%a" O.PP.type_value t)
|
("tuple_type" , fun () -> Format.asprintf "%a" O.PP.type_value t) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp loc)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
@ -171,7 +193,8 @@ module Errors = struct
|
|||||||
let title = (thunk "not suported yet") in
|
let title = (thunk "not suported yet") in
|
||||||
let message () = message in
|
let message () = message in
|
||||||
let data = [
|
let data = [
|
||||||
("expression" , fun () -> Format.asprintf "%a" I.PP.expression ae)
|
("expression" , fun () -> Format.asprintf "%a" I.PP.expression ae) ;
|
||||||
|
("location" , fun () -> Format.asprintf "%a" Location.pp ae.location)
|
||||||
] in
|
] in
|
||||||
error ~data title message ()
|
error ~data title message ()
|
||||||
|
|
||||||
@ -208,24 +231,24 @@ and type_declaration env : I.declaration -> (environment * O.declaration option)
|
|||||||
| Declaration_constant (name , tv_opt , expression) -> (
|
| Declaration_constant (name , tv_opt , expression) -> (
|
||||||
let%bind tv'_opt = bind_map_option (evaluate_type env) tv_opt in
|
let%bind tv'_opt = bind_map_option (evaluate_type env) tv_opt in
|
||||||
let%bind ae' =
|
let%bind ae' =
|
||||||
trace (constant_declaration_error name expression) @@
|
trace (constant_declaration_error name expression tv'_opt) @@
|
||||||
type_expression ?tv_opt:tv'_opt env expression in
|
type_expression ?tv_opt:tv'_opt env expression in
|
||||||
let env' = Environment.add_ez_ae name ae' env in
|
let env' = Environment.add_ez_ae name ae' env in
|
||||||
ok (env', Some (O.Declaration_constant ((make_n_e name ae') , (env , env'))))
|
ok (env', Some (O.Declaration_constant ((make_n_e name ae') , (env , env'))))
|
||||||
)
|
)
|
||||||
|
|
||||||
and type_match : type i o . (environment -> i -> o result) -> environment -> O.type_value -> i I.matching -> o O.matching result =
|
and type_match : type i o . (environment -> i -> o result) -> environment -> O.type_value -> i I.matching -> Location.t -> o O.matching result =
|
||||||
fun f e t i -> match i with
|
fun f e t i loc -> match i with
|
||||||
| Match_bool {match_true ; match_false} ->
|
| Match_bool {match_true ; match_false} ->
|
||||||
let%bind _ =
|
let%bind _ =
|
||||||
trace_strong (match_error ~expected:i ~actual:t)
|
trace_strong (match_error ~expected:i ~actual:t loc)
|
||||||
@@ get_t_bool t in
|
@@ get_t_bool t in
|
||||||
let%bind match_true = f e match_true in
|
let%bind match_true = f e match_true in
|
||||||
let%bind match_false = f e match_false in
|
let%bind match_false = f e match_false in
|
||||||
ok (O.Match_bool {match_true ; match_false})
|
ok (O.Match_bool {match_true ; match_false})
|
||||||
| Match_option {match_none ; match_some} ->
|
| Match_option {match_none ; match_some} ->
|
||||||
let%bind t_opt =
|
let%bind t_opt =
|
||||||
trace_strong (match_error ~expected:i ~actual:t)
|
trace_strong (match_error ~expected:i ~actual:t loc)
|
||||||
@@ get_t_option t in
|
@@ get_t_option t in
|
||||||
let%bind match_none = f e match_none in
|
let%bind match_none = f e match_none in
|
||||||
let (n, b) = match_some in
|
let (n, b) = match_some in
|
||||||
@ -235,7 +258,7 @@ and type_match : type i o . (environment -> i -> o result) -> environment -> O.t
|
|||||||
ok (O.Match_option {match_none ; match_some = (n', b')})
|
ok (O.Match_option {match_none ; match_some = (n', b')})
|
||||||
| Match_list {match_nil ; match_cons} ->
|
| Match_list {match_nil ; match_cons} ->
|
||||||
let%bind t_list =
|
let%bind t_list =
|
||||||
trace_strong (match_error ~expected:i ~actual:t)
|
trace_strong (match_error ~expected:i ~actual:t loc)
|
||||||
@@ get_t_list t in
|
@@ get_t_list t in
|
||||||
let%bind match_nil = f e match_nil in
|
let%bind match_nil = f e match_nil in
|
||||||
let (hd, tl, b) = match_cons in
|
let (hd, tl, b) = match_cons in
|
||||||
@ -245,10 +268,10 @@ and type_match : type i o . (environment -> i -> o result) -> environment -> O.t
|
|||||||
ok (O.Match_list {match_nil ; match_cons = (hd, tl, b')})
|
ok (O.Match_list {match_nil ; match_cons = (hd, tl, b')})
|
||||||
| Match_tuple (lst, b) ->
|
| Match_tuple (lst, b) ->
|
||||||
let%bind t_tuple =
|
let%bind t_tuple =
|
||||||
trace_strong (match_error ~expected:i ~actual:t)
|
trace_strong (match_error ~expected:i ~actual:t loc)
|
||||||
@@ get_t_tuple t in
|
@@ get_t_tuple t in
|
||||||
let%bind lst' =
|
let%bind lst' =
|
||||||
generic_try (match_tuple_wrong_arity t_tuple lst)
|
generic_try (match_tuple_wrong_arity t_tuple lst loc)
|
||||||
@@ (fun () -> List.combine lst t_tuple) in
|
@@ (fun () -> List.combine lst t_tuple) in
|
||||||
let aux prev (name, tv) = Environment.add_ez_binder name tv prev in
|
let aux prev (name, tv) = Environment.add_ez_binder name tv prev in
|
||||||
let e' = List.fold_left aux e lst' in
|
let e' = List.fold_left aux e lst' in
|
||||||
@ -258,7 +281,7 @@ and type_match : type i o . (environment -> i -> o result) -> environment -> O.t
|
|||||||
let%bind variant_opt =
|
let%bind variant_opt =
|
||||||
let aux acc ((constructor_name , _) , _) =
|
let aux acc ((constructor_name , _) , _) =
|
||||||
let%bind (_ , variant) =
|
let%bind (_ , variant) =
|
||||||
trace_option (unbound_constructor e constructor_name) @@
|
trace_option (unbound_constructor e constructor_name loc) @@
|
||||||
Environment.get_constructor constructor_name e in
|
Environment.get_constructor constructor_name e in
|
||||||
let%bind acc = match acc with
|
let%bind acc = match acc with
|
||||||
| None -> ok (Some variant)
|
| None -> ok (Some variant)
|
||||||
@ -270,11 +293,11 @@ and type_match : type i o . (environment -> i -> o result) -> environment -> O.t
|
|||||||
trace (simple_info "in match variant") @@
|
trace (simple_info "in match variant") @@
|
||||||
bind_fold_list aux None lst in
|
bind_fold_list aux None lst in
|
||||||
let%bind variant =
|
let%bind variant =
|
||||||
trace_option (match_empty_variant i) @@
|
trace_option (match_empty_variant i loc) @@
|
||||||
variant_opt in
|
variant_opt in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
let%bind variant_cases' =
|
let%bind variant_cases' =
|
||||||
trace (match_error ~expected:i ~actual:t)
|
trace (match_error ~expected:i ~actual:t loc)
|
||||||
@@ Ast_typed.Combinators.get_t_sum variant in
|
@@ Ast_typed.Combinators.get_t_sum variant in
|
||||||
let variant_cases = List.map fst @@ Map.String.to_kv_list variant_cases' in
|
let variant_cases = List.map fst @@ Map.String.to_kv_list variant_cases' in
|
||||||
let match_cases = List.map (Function.compose fst fst) lst in
|
let match_cases = List.map (Function.compose fst fst) lst in
|
||||||
@ -282,17 +305,17 @@ and type_match : type i o . (environment -> i -> o result) -> environment -> O.t
|
|||||||
Assert.assert_true (List.mem c match_cases)
|
Assert.assert_true (List.mem c match_cases)
|
||||||
in
|
in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
trace_strong (match_missing_case i) @@
|
trace_strong (match_missing_case i loc) @@
|
||||||
bind_iter_list test_case variant_cases in
|
bind_iter_list test_case variant_cases in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
trace_strong (match_redundant_case i) @@
|
trace_strong (match_redundant_case i loc) @@
|
||||||
Assert.assert_true List.(length variant_cases = length match_cases) in
|
Assert.assert_true List.(length variant_cases = length match_cases) in
|
||||||
ok ()
|
ok ()
|
||||||
in
|
in
|
||||||
let%bind lst' =
|
let%bind lst' =
|
||||||
let aux ((constructor_name , name) , b) =
|
let aux ((constructor_name , name) , b) =
|
||||||
let%bind (constructor , _) =
|
let%bind (constructor , _) =
|
||||||
trace_option (unbound_constructor e constructor_name) @@
|
trace_option (unbound_constructor e constructor_name loc) @@
|
||||||
Environment.get_constructor constructor_name e in
|
Environment.get_constructor constructor_name e in
|
||||||
let e' = Environment.add_ez_binder name constructor e in
|
let e' = Environment.add_ez_binder name constructor e in
|
||||||
let%bind b' = f e' b in
|
let%bind b' = f e' b in
|
||||||
@ -361,7 +384,7 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
| E_failwith _ -> fail @@ needs_annotation ae "the failwith keyword"
|
| E_failwith _ -> fail @@ needs_annotation ae "the failwith keyword"
|
||||||
| E_variable name ->
|
| E_variable name ->
|
||||||
let%bind tv' =
|
let%bind tv' =
|
||||||
trace_option (unbound_variable e name)
|
trace_option (unbound_variable e name ae.location)
|
||||||
@@ Environment.get_opt name e in
|
@@ Environment.get_opt name e in
|
||||||
return (E_variable name) tv'.type_value
|
return (E_variable name) tv'.type_value
|
||||||
| E_literal (Literal_bool b) ->
|
| E_literal (Literal_bool b) ->
|
||||||
@ -391,30 +414,30 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
let%bind lst' = bind_list @@ List.map (type_expression e) lst in
|
let%bind lst' = bind_list @@ List.map (type_expression e) lst in
|
||||||
let tv_lst = List.map get_type_annotation lst' in
|
let tv_lst = List.map get_type_annotation lst' in
|
||||||
return (E_tuple lst') (t_tuple tv_lst ())
|
return (E_tuple lst') (t_tuple tv_lst ())
|
||||||
| E_accessor (ae, path) ->
|
| E_accessor (ae', path) ->
|
||||||
let%bind e' = type_expression e ae in
|
let%bind e' = type_expression e ae' in
|
||||||
let aux (prev:O.annotated_expression) (a:I.access) : O.annotated_expression result =
|
let aux (prev:O.annotated_expression) (a:I.access) : O.annotated_expression result =
|
||||||
match a with
|
match a with
|
||||||
| Access_tuple index -> (
|
| Access_tuple index -> (
|
||||||
let%bind tpl_tv = get_t_tuple prev.type_annotation in
|
let%bind tpl_tv = get_t_tuple prev.type_annotation in
|
||||||
let%bind tv =
|
let%bind tv =
|
||||||
generic_try (bad_tuple_index index ae prev.type_annotation)
|
generic_try (bad_tuple_index index ae' prev.type_annotation ae.location)
|
||||||
@@ (fun () -> List.nth tpl_tv index) in
|
@@ (fun () -> List.nth tpl_tv index) in
|
||||||
return (E_tuple_accessor (prev , index)) tv
|
return (E_tuple_accessor (prev , index)) tv
|
||||||
)
|
)
|
||||||
| Access_record property -> (
|
| Access_record property -> (
|
||||||
let%bind r_tv = get_t_record prev.type_annotation in
|
let%bind r_tv = get_t_record prev.type_annotation in
|
||||||
let%bind tv =
|
let%bind tv =
|
||||||
generic_try (bad_record_access property ae prev.type_annotation)
|
generic_try (bad_record_access property ae' prev.type_annotation ae.location)
|
||||||
@@ (fun () -> SMap.find property r_tv) in
|
@@ (fun () -> SMap.find property r_tv) in
|
||||||
return (E_record_accessor (prev , property)) tv
|
return (E_record_accessor (prev , property)) tv
|
||||||
)
|
)
|
||||||
| Access_map ae -> (
|
| Access_map ae' -> (
|
||||||
let%bind ae' = type_expression e ae in
|
let%bind ae'' = type_expression e ae' in
|
||||||
let%bind (k , v) = get_t_map prev.type_annotation in
|
let%bind (k , v) = get_t_map prev.type_annotation in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
Ast_typed.assert_type_value_eq (k , get_type_annotation ae') in
|
Ast_typed.assert_type_value_eq (k , get_type_annotation ae'') in
|
||||||
return (E_look_up (prev , ae')) v
|
return (E_look_up (prev , ae'')) v
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
trace (simple_info "accessing") @@
|
trace (simple_info "accessing") @@
|
||||||
@ -533,7 +556,7 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
| E_constant (name, lst) ->
|
| E_constant (name, lst) ->
|
||||||
let%bind lst' = bind_list @@ List.map (type_expression e) lst in
|
let%bind lst' = bind_list @@ List.map (type_expression e) lst in
|
||||||
let tv_lst = List.map get_type_annotation lst' in
|
let tv_lst = List.map get_type_annotation lst' in
|
||||||
let%bind (name', tv) = type_constant name tv_lst tv_opt in
|
let%bind (name', tv) = type_constant name tv_lst tv_opt ae.location in
|
||||||
return (E_constant (name' , lst')) tv
|
return (E_constant (name' , lst')) tv
|
||||||
| E_application (f, arg) ->
|
| E_application (f, arg) ->
|
||||||
let%bind f = type_expression e f in
|
let%bind f = type_expression e f in
|
||||||
@ -547,6 +570,7 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
~expected:"should be a function type"
|
~expected:"should be a function type"
|
||||||
~expression:f
|
~expression:f
|
||||||
~actual:f.type_annotation
|
~actual:f.type_annotation
|
||||||
|
f.location
|
||||||
in
|
in
|
||||||
return (E_application (f , arg)) tv
|
return (E_application (f , arg)) tv
|
||||||
| E_look_up dsi ->
|
| E_look_up dsi ->
|
||||||
@ -565,10 +589,14 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
let%bind mf' = type_expression e match_false in
|
let%bind mf' = type_expression e match_false in
|
||||||
let t = get_type_annotation ex' in
|
let t = get_type_annotation ex' in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
trace_strong (match_error ~expected:m ~actual:t)
|
trace_strong (match_error ~expected:m ~actual:t ae.location)
|
||||||
@@ assert_t_bool t in
|
@@ assert_t_bool t in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
trace_strong (match_error ~msg:"matching not-unit on an assert" ~expected:m ~actual:t)
|
trace_strong (match_error
|
||||||
|
~msg:"matching not-unit on an assert"
|
||||||
|
~expected:m
|
||||||
|
~actual:t
|
||||||
|
ae.location)
|
||||||
@@ assert_t_unit (get_type_annotation mf') in
|
@@ assert_t_unit (get_type_annotation mf') in
|
||||||
let mt' = make_a_e
|
let mt' = make_a_e
|
||||||
(E_constant ("ASSERT" , [ex' ; fw']))
|
(E_constant ("ASSERT" , [ex' ; fw']))
|
||||||
@ -579,7 +607,7 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
return (O.E_matching (ex' , m')) (t_unit ())
|
return (O.E_matching (ex' , m')) (t_unit ())
|
||||||
)
|
)
|
||||||
| _ -> (
|
| _ -> (
|
||||||
let%bind m' = type_match (type_expression ?tv_opt:None) e ex'.type_annotation m in
|
let%bind m' = type_match (type_expression ?tv_opt:None) e ex'.type_annotation m ae.location in
|
||||||
let tvs =
|
let tvs =
|
||||||
let aux (cur:O.value O.matching) =
|
let aux (cur:O.value O.matching) =
|
||||||
match cur with
|
match cur with
|
||||||
@ -597,7 +625,7 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
ok (Some cur) in
|
ok (Some cur) in
|
||||||
let%bind tv_opt = bind_fold_list aux None tvs in
|
let%bind tv_opt = bind_fold_list aux None tvs in
|
||||||
let%bind tv =
|
let%bind tv =
|
||||||
trace_option (match_empty_variant m) @@
|
trace_option (match_empty_variant m ae.location) @@
|
||||||
tv_opt in
|
tv_opt in
|
||||||
return (O.E_matching (ex', m')) tv
|
return (O.E_matching (ex', m')) tv
|
||||||
)
|
)
|
||||||
@ -611,7 +639,8 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
~msg:"first part of the sequence should be of unit type"
|
~msg:"first part of the sequence should be of unit type"
|
||||||
~expected:(O.t_unit ())
|
~expected:(O.t_unit ())
|
||||||
~actual:a'_type_annot
|
~actual:a'_type_annot
|
||||||
~expression:a') @@
|
~expression:a'
|
||||||
|
a'.location) @@
|
||||||
Ast_typed.assert_type_value_eq (t_unit () , a'_type_annot) in
|
Ast_typed.assert_type_value_eq (t_unit () , a'_type_annot) in
|
||||||
return (O.E_sequence (a' , b')) (get_type_annotation b')
|
return (O.E_sequence (a' , b')) (get_type_annotation b')
|
||||||
| E_loop (expr , body) ->
|
| E_loop (expr , body) ->
|
||||||
@ -623,7 +652,8 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
~msg:"while condition isn't of type bool"
|
~msg:"while condition isn't of type bool"
|
||||||
~expected:(O.t_bool ())
|
~expected:(O.t_bool ())
|
||||||
~actual:t_expr'
|
~actual:t_expr'
|
||||||
~expression:expr') @@
|
~expression:expr'
|
||||||
|
expr'.location) @@
|
||||||
Ast_typed.assert_type_value_eq (t_bool () , t_expr') in
|
Ast_typed.assert_type_value_eq (t_bool () , t_expr') in
|
||||||
let t_body' = get_type_annotation body' in
|
let t_body' = get_type_annotation body' in
|
||||||
let%bind () =
|
let%bind () =
|
||||||
@ -631,7 +661,8 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
~msg:"while body isn't of unit type"
|
~msg:"while body isn't of unit type"
|
||||||
~expected:(O.t_unit ())
|
~expected:(O.t_unit ())
|
||||||
~actual:t_body'
|
~actual:t_body'
|
||||||
~expression:body') @@
|
~expression:body'
|
||||||
|
body'.location) @@
|
||||||
Ast_typed.assert_type_value_eq (t_unit () , t_body') in
|
Ast_typed.assert_type_value_eq (t_unit () , t_body') in
|
||||||
return (O.E_loop (expr' , body')) (t_unit ())
|
return (O.E_loop (expr' , body')) (t_unit ())
|
||||||
| E_assign (name , path , expr) ->
|
| E_assign (name , path , expr) ->
|
||||||
@ -644,14 +675,14 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
| Access_tuple index -> (
|
| Access_tuple index -> (
|
||||||
let%bind tpl = get_t_tuple prec_tv in
|
let%bind tpl = get_t_tuple prec_tv in
|
||||||
let%bind tv' =
|
let%bind tv' =
|
||||||
trace_option (bad_tuple_index index ae prec_tv) @@
|
trace_option (bad_tuple_index index ae prec_tv ae.location) @@
|
||||||
List.nth_opt tpl index in
|
List.nth_opt tpl index in
|
||||||
ok (tv' , prec_path @ [O.Access_tuple index])
|
ok (tv' , prec_path @ [O.Access_tuple index])
|
||||||
)
|
)
|
||||||
| Access_record property -> (
|
| Access_record property -> (
|
||||||
let%bind m = get_t_record prec_tv in
|
let%bind m = get_t_record prec_tv in
|
||||||
let%bind tv' =
|
let%bind tv' =
|
||||||
trace_option (bad_record_access property ae prec_tv) @@
|
trace_option (bad_record_access property ae prec_tv ae.location) @@
|
||||||
Map.String.find_opt property m in
|
Map.String.find_opt property m in
|
||||||
ok (tv' , prec_path @ [O.Access_record property])
|
ok (tv' , prec_path @ [O.Access_record property])
|
||||||
)
|
)
|
||||||
@ -666,7 +697,8 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
~msg:"type of the expression to assign doesn't match left-hand-side"
|
~msg:"type of the expression to assign doesn't match left-hand-side"
|
||||||
~expected:assign_tv
|
~expected:assign_tv
|
||||||
~actual:t_expr'
|
~actual:t_expr'
|
||||||
~expression:expr') @@
|
~expression:expr'
|
||||||
|
expr'.location) @@
|
||||||
Ast_typed.assert_type_value_eq (assign_tv , t_expr') in
|
Ast_typed.assert_type_value_eq (assign_tv , t_expr') in
|
||||||
return (O.E_assign (typed_name , path' , expr')) (t_unit ())
|
return (O.E_assign (typed_name , path' , expr')) (t_unit ())
|
||||||
| E_let_in {binder ; rhs ; result} ->
|
| E_let_in {binder ; rhs ; result} ->
|
||||||
@ -682,11 +714,11 @@ and type_expression : environment -> ?tv_opt:O.type_value -> I.expression -> O.a
|
|||||||
ok {expr' with type_annotation}
|
ok {expr' with type_annotation}
|
||||||
|
|
||||||
|
|
||||||
and type_constant (name:string) (lst:O.type_value list) (tv_opt:O.type_value option) : (string * O.type_value) result =
|
and type_constant (name:string) (lst:O.type_value list) (tv_opt:O.type_value option) (loc : Location.t) : (string * O.type_value) result =
|
||||||
(* Constant poorman's polymorphism *)
|
(* Constant poorman's polymorphism *)
|
||||||
let ct = Operators.Typer.constant_typers in
|
let ct = Operators.Typer.constant_typers in
|
||||||
let%bind typer =
|
let%bind typer =
|
||||||
trace_option (unrecognized_constant name) @@
|
trace_option (unrecognized_constant name loc) @@
|
||||||
Map.String.find_opt name ct in
|
Map.String.find_opt name ct in
|
||||||
typer lst tv_opt
|
typer lst tv_opt
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user