Type record projections and collection operators

This commit is contained in:
milner committed 2017-02-09 09:54:00 +00:00
1 parent 9d0221933c
commit b44640692c
2 files changed
+79 -4

No files matched your search

+52 -1
View File
@@ -59,7 +59,7 @@ let cases =
infer_program "input rows : collection int\nlet f n = n + 1\nquery q = rows |> map (fun r -> f \"a\")\n") );
( "projection on a non record is rejected",
fun () ->
check_message "projection" "type mismatch: expected order but got int"
check_message "projection" "cannot project field `total` from a value of type int"
(fun () ->
infer_program
"type order = { total : int }\ninput rows : collection int\nquery q = rows |> map (fun r -> r.total)\n") );
@@ -157,4 +157,55 @@ let cases =
Ident.reset ();
let second = Typed.program_to_string (infer_program (read_fixture "expensive_order.delta")) in
check_equal_string "identical dumps" first second );
( "nested record projections are typed",
fun () ->
let program =
infer_program
"type inner = { amount : int }\ntype outer = { inner : inner; label : string }\ninput rows : collection outer\nquery q = rows |> map (fun r -> (r.inner.amount, r.label))\n"
in
check_equal_string "query type" "collection (int, string)"
(Types.pp program.Typed.tp_query_body.Typed.ty) );
( "projecting a field of another record is rejected",
fun () ->
check_message "wrong record" "cannot project field `amount` from a value of type outer"
(fun () ->
infer_program
"type inner = { amount : int }\ntype outer = { inner : inner }\ninput rows : collection outer\nquery q = rows |> map (fun r -> r.amount)\n") );
( "projecting from a scalar is rejected",
fun () ->
check_message "scalar projection" "cannot project field `amount` from a value of type int"
(fun () ->
infer_program
"type inner = { amount : int }\ninput rows : collection int\nquery q = rows |> map (fun r -> r.amount)\n") );
( "a filter predicate must return bool",
fun () ->
check_message "predicate type" "type mismatch: expected int but got bool"
(fun () ->
infer_program
"type order = { total : int }\ninput rows : collection order\nquery q = rows |> filter (fun r -> r.total)\n") );
( "a map projection may not return a function",
fun () ->
check_message "function element" "collections of functions are not supported: mapped element"
(fun () ->
infer_program
"input rows : collection int\nquery q = rows |> map (fun r -> fun x -> r + x)\n") );
( "collections may not appear inside tuples",
fun () ->
check_message "collection in tuple"
"collections may not appear inside tuples, but this component has type collection int"
(fun () -> infer_program "input rows : collection int\nquery q = (rows, 1)\n") );
( "a collection cannot be stored in a record field",
fun () ->
check_message "collection in record" "type mismatch: expected collection int but got int"
(fun () ->
infer_program
"type box = { items : int }\ninput rows : collection int\nquery q = rows |> map (fun r -> { items = rows })\n") );
( "filter and map over a helper name are typed",
fun () ->
let program =
infer_program
"type order = { total : int }\ninput rows : collection order\nlet big o = o.total > 1000\nlet value o = o.total\nquery q = rows |> filter big |> map value\n"
in
check_equal_string "query type" "collection int"
(Types.pp program.Typed.tp_query_body.Typed.ty) );
]