///|
/// A record literal is closed.
fn Infer::value_record(
self : Infer,
fields : Map[@ir.Name, @ir.Value],
path : String,
) -> Ty raise Located {
Rec(self.field_types(fields, path), None)
}
///|
/// The type of each field value, by canonical name. Each field is at `path_field`.
fn Infer::field_types(
self : Infer,
fields : Map[@ir.Name, @ir.Value],
path : String,
) -> Map[String, Ty] raise Located {
let out : Map[String, Ty] = Map([])
for name, field in fields {
out[name.to_canonical()] = self.value(
field,
@identities.path_field(path, name),
)
}
out
}
///|
/// `record.name`: the record is `{ ρ | name : α }`, and the result is `α`.
fn Infer::value_field(
self : Infer,
record : @ir.Value,
name : @ir.Name,
path : String,
) -> Ty raise Located {
let rt = self.value(record, @identities.path_record(path))
let field = self.fresh()
self.unify(
path,
Rec(Map([(name.to_canonical(), field)]), Some(self.fresh())),
rt,
)
field
}
///|
/// `.name` is `{ ρ | name : α } -> α`.
fn Infer::value_field_function(self : Infer, name : @ir.Name) -> Ty {
let field = self.fresh()
Fun(Rec(Map([(name.to_canonical(), field)]), Some(self.fresh())), field)
}
///|
/// `{ record | fields }`: the record must have each field with the type of its new value. The result has the
/// type of the record.
fn Infer::value_update(
self : Infer,
record : @ir.Value,
fields : Map[@ir.Name, @ir.Value],
path : String,
) -> Ty raise Located {
let rt = self.value(record, @identities.path_record(path))
let updates = self.field_types(fields, path)
self.unify(path, Rec(updates, Some(self.fresh())), rt)
rt
}