Type record projections and collection operators
This commit is contained in:
2 files changed
+79
-4
No files matched your search
+27
-3
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user