Type record projections and collection operators

This commit is contained in:
sneeker committed 2017-02-09 09:54:00 +00:00
1 parent 999b9e3262
commit 3091746467
2 files changed
+79 -4

No files matched your search

+27 -3
View File
@@ -227,6 +227,13 @@ let rec infer env syntax =
Typed.make (Typed.TBinop (Syntax.Sub, Typed.make (Typed.TInt 0) Types.TInt span, operand)) Types.TInt span
| Resolve.RTuple items ->
let items = List.map (infer env) items in
List.iter
(fun item ->
if contains_collection item.Typed.ty then
Diagnostic.error item.Typed.tspan
"collections may not appear inside tuples, but this component has type %s"
(Types.pp item.Typed.ty))
items;
Typed.make (Typed.TTuple items) (Types.TTuple (List.map (fun item -> item.Typed.ty) items)) span
| Resolve.RRecord fields -> infer_record env span fields
| Resolve.RField (record, label) ->
@@ -234,15 +241,32 @@ let rec infer env syntax =
(match Util.assoc_opt label env.ctx.Types.labels with
| None -> Diagnostic.error span "no record type declares a field named `%s`" label
| Some (name, field_ty) ->
Types.unify span record.Typed.ty (Types.TRecord name);
(match Types.repr record.Typed.ty with
| Types.TRecord actual when actual = name -> ()
| Types.TVar _ -> Types.unify span record.Typed.ty (Types.TRecord name)
| other ->
Diagnostic.error span "cannot project field `%s` from a value of type %s" label
(Types.pp other));
Typed.make (Typed.TField (record, label)) field_ty span)
and infer_function env element argument =
match argument.Resolve.r with
| Resolve.RLambda (ident, body) ->
let body = infer (bind env ident (scheme_of element)) body in
Typed.make (Typed.TLambda (ident, body)) (Types.TArrow (element, body.Typed.ty))
argument.Resolve.rspan
| _ ->
let fn = infer env argument in
let result = Types.fresh_var () in
Types.unify argument.Resolve.rspan fn.Typed.ty (Types.TArrow (element, result));
fn
and infer_filter env span predicate collection =
let collection = infer env collection in
let element = Types.fresh_var () in
Types.unify collection.Typed.tspan collection.Typed.ty (Types.TCollection element);
check_element collection.Typed.tspan "filter element" element;
let predicate = infer env predicate in
let predicate = infer_function env element predicate in
Types.unify predicate.Typed.tspan predicate.Typed.ty (Types.TArrow (element, Types.TBool));
Typed.make (Typed.TFilter (collection, predicate)) collection.Typed.ty span
@@ -251,7 +275,7 @@ and infer_map env span projection collection =
let element = Types.fresh_var () in
Types.unify collection.Typed.tspan collection.Typed.ty (Types.TCollection element);
check_element collection.Typed.tspan "map element" element;
let projection = infer env projection in
let projection = infer_function env element projection in
let result = Types.fresh_var () in
Types.unify projection.Typed.tspan projection.Typed.ty (Types.TArrow (element, result));
check_element projection.Typed.tspan "mapped element" result;