1
1
mirror of https://github.com/tweag/nickel.git synced 2024-10-05 23:57:09 +03:00

tyw -> uty

Get rid of the last references of the old name of UnifType (previously
TypeWrapper) in function, macro and variable names.
This commit is contained in:
Yann Hamdaoui 2022-11-22 18:49:08 +01:00
parent b529181f62
commit a8bbad464b
No known key found for this signature in database
GPG Key ID: 96305DE11214ABE6
6 changed files with 198 additions and 230 deletions

View File

@ -427,13 +427,13 @@ mod tests {
#[test]
fn test_extract_ident_with_path() {
use nickel_lang::{mk_tyw_record, mk_tyw_row, types::RecordRowsF};
use nickel_lang::{mk_uty_record, mk_uty_row, types::RecordRowsF};
use std::convert::TryInto;
// Representing the type: {a: {b : {c1 : Num, c2: Num}}}
let c_record_type = mk_tyw_record!(("c1", TypeF::Num), ("c2", TypeF::Num));
let b_record_type = mk_tyw_record!(("b", c_record_type));
let a_record_type = mk_tyw_row!(("a", b_record_type));
let c_record_type = mk_uty_record!(("c1", TypeF::Num), ("c2", TypeF::Num));
let b_record_type = mk_uty_record!(("b", c_record_type));
let a_record_type = mk_uty_row!(("a", b_record_type));
let mut path = vec![Ident::from("b"), Ident::from("a")];
// unwrap: the conversion must succeed because we built a type without unification variable

View File

@ -419,31 +419,31 @@ fn type_eq_bounded<E: TermEnvironment>(
| (TypeF::Bool, TypeF::Bool)
| (TypeF::Sym, TypeF::Sym)
| (TypeF::Str, TypeF::Str) => true,
(TypeF::Dict(tyw1), TypeF::Dict(tyw2)) | (TypeF::Array(tyw1), TypeF::Array(tyw2)) => {
type_eq_bounded(state, tyw1, env1, tyw2, env2)
(TypeF::Dict(uty1), TypeF::Dict(uty2)) | (TypeF::Array(uty1), TypeF::Array(uty2)) => {
type_eq_bounded(state, uty1, env1, uty2, env2)
}
(TypeF::Arrow(s1, t1), TypeF::Arrow(s2, t2)) => {
type_eq_bounded(state, s1, env1, s2, env2)
&& type_eq_bounded(state, t1, env1, t2, env2)
}
(TypeF::Enum(tyw1), TypeF::Enum(tyw2)) => {
let rows1 = rows_as_set(tyw1);
let rows2 = rows_as_set(tyw2);
(TypeF::Enum(uty1), TypeF::Enum(uty2)) => {
let rows1 = rows_as_set(uty1);
let rows2 = rows_as_set(uty2);
rows1.is_some() && rows2.is_some() && rows1 == rows2
}
(TypeF::Record(tyw1), TypeF::Record(tyw2)) => {
(TypeF::Record(uty1), TypeF::Record(uty2)) => {
fn type_eq_bounded_wrapper<E: TermEnvironment>(
state: &mut State,
tyw1: &&GenericUnifType<E>,
uty1: &&GenericUnifType<E>,
env1: &E,
tyw2: &&GenericUnifType<E>,
uty2: &&GenericUnifType<E>,
env2: &E,
) -> bool {
type_eq_bounded(state, *tyw1, env1, *tyw2, env2)
type_eq_bounded(state, *uty1, env1, *uty2, env2)
}
let map1 = rows_as_map(tyw1);
let map2 = rows_as_map(tyw2);
let map1 = rows_as_map(uty1);
let map2 = rows_as_map(uty2);
map1.zip(map2)
.map(|(m1, m2)| map_eq(type_eq_bounded_wrapper, state, &m1, env1, &m2, env2))

View File

@ -46,12 +46,12 @@ impl RowUnifError {
RowUnifError::MissingDynTail() => UnifError::MissingDynTail(left, right),
RowUnifError::ExtraRow(id) => UnifError::ExtraRow(id, left, right),
RowUnifError::ExtraDynTail() => UnifError::ExtraDynTail(left, right),
RowUnifError::RowKindMismatch(id, tyw1, tyw2) => {
UnifError::RowKindMismatch(id, tyw1, tyw2)
RowUnifError::RowKindMismatch(id, uty1, uty2) => {
UnifError::RowKindMismatch(id, uty1, uty2)
}
RowUnifError::RowMismatch(id, err) => UnifError::RowMismatch(id, left, right, err),
RowUnifError::UnsatConstr(id, tyw) => UnifError::RowConflict(id, tyw, left, right),
RowUnifError::WithConst(c, tyw) => UnifError::WithConst(c, tyw),
RowUnifError::UnsatConstr(id, uty) => UnifError::RowConflict(id, uty, left, right),
RowUnifError::WithConst(c, uty) => UnifError::WithConst(c, uty),
RowUnifError::ConstMismatch(c1, c2) => UnifError::ConstMismatch(c1, c2),
RowUnifError::UnboundTypeVariable(id) => UnifError::UnboundTypeVariable(id),
}
@ -131,10 +131,10 @@ impl UnifError {
reporting::to_type(state.table, state.names, names, ty2),
pos_opt,
),
UnifError::RowMismatch(ident, tyw1, tyw2, err) => TypecheckError::RowMismatch(
UnifError::RowMismatch(ident, uty1, uty2, err) => TypecheckError::RowMismatch(
ident,
reporting::to_type(state.table, state.names, names, tyw1),
reporting::to_type(state.table, state.names, names, tyw2),
reporting::to_type(state.table, state.names, names, uty1),
reporting::to_type(state.table, state.names, names, uty2),
Box::new((*err).into_typecheck_err_(state, names, TermPos::None)),
pos_opt,
),
@ -160,31 +160,31 @@ impl UnifError {
UnifError::IncomparableFlatTypes(rt1, rt2) => {
TypecheckError::IncomparableFlatTypes(rt1, rt2, pos_opt)
}
UnifError::MissingRow(id, tyw1, tyw2) => TypecheckError::MissingRow(
UnifError::MissingRow(id, uty1, uty2) => TypecheckError::MissingRow(
id,
reporting::to_type(state.table, state.names, names, tyw1),
reporting::to_type(state.table, state.names, names, tyw2),
reporting::to_type(state.table, state.names, names, uty1),
reporting::to_type(state.table, state.names, names, uty2),
pos_opt,
),
UnifError::MissingDynTail(tyw1, tyw2) => TypecheckError::MissingDynTail(
reporting::to_type(state.table, state.names, names, tyw1),
reporting::to_type(state.table, state.names, names, tyw2),
UnifError::MissingDynTail(uty1, uty2) => TypecheckError::MissingDynTail(
reporting::to_type(state.table, state.names, names, uty1),
reporting::to_type(state.table, state.names, names, uty2),
pos_opt,
),
UnifError::ExtraRow(id, tyw1, tyw2) => TypecheckError::ExtraRow(
UnifError::ExtraRow(id, uty1, uty2) => TypecheckError::ExtraRow(
id,
reporting::to_type(state.table, state.names, names, tyw1),
reporting::to_type(state.table, state.names, names, tyw2),
reporting::to_type(state.table, state.names, names, uty1),
reporting::to_type(state.table, state.names, names, uty2),
pos_opt,
),
UnifError::ExtraDynTail(tyw1, tyw2) => TypecheckError::ExtraDynTail(
reporting::to_type(state.table, state.names, names, tyw1),
reporting::to_type(state.table, state.names, names, tyw2),
UnifError::ExtraDynTail(uty1, uty2) => TypecheckError::ExtraDynTail(
reporting::to_type(state.table, state.names, names, uty1),
reporting::to_type(state.table, state.names, names, uty2),
pos_opt,
),
UnifError::RowConflict(id, tyw, left, right) => TypecheckError::RowConflict(
UnifError::RowConflict(id, uty, left, right) => TypecheckError::RowConflict(
id,
tyw.map(|tyw| reporting::to_type(state.table, state.names, names, tyw)),
uty.map(|uty| reporting::to_type(state.table, state.names, names, uty)),
reporting::to_type(state.table, state.names, names, left),
reporting::to_type(state.table, state.names, names, right),
pos_opt,
@ -230,16 +230,16 @@ impl UnifError {
let mut path = ty_path::Path::new();
// The original expected and actual type. They are just updated once, in the first
// iteration of the loop below.
let mut tyws: Option<(UnifType, UnifType)> = None;
let mut utys: Option<(UnifType, UnifType)> = None;
loop {
match curr {
UnifError::DomainMismatch(
tyw1 @ UnifType::Concrete(TypeF::Arrow(_, _)),
tyw2 @ UnifType::Concrete(TypeF::Arrow(_, _)),
uty1 @ UnifType::Concrete(TypeF::Arrow(_, _)),
uty2 @ UnifType::Concrete(TypeF::Arrow(_, _)),
err,
) => {
tyws = tyws.or(Some((tyw1, tyw2)));
utys = utys.or(Some((uty1, uty2)));
path.push(ty_path::Elem::Domain);
curr = *err;
}
@ -247,20 +247,20 @@ impl UnifError {
"typechecking::to_type_path(): domain mismatch error on a non arrow type"
),
UnifError::CodomainMismatch(
tyw1 @ UnifType::Concrete(TypeF::Arrow(_, _)),
tyw2 @ UnifType::Concrete(TypeF::Arrow(_, _)),
uty1 @ UnifType::Concrete(TypeF::Arrow(_, _)),
uty2 @ UnifType::Concrete(TypeF::Arrow(_, _)),
err,
) => {
tyws = tyws.or(Some((tyw1, tyw2)));
utys = utys.or(Some((uty1, uty2)));
path.push(ty_path::Elem::Codomain);
curr = *err;
}
UnifError::CodomainMismatch(_, _, _) => panic!(
"typechecking::to_type_path(): codomain mismatch error on a non arrow type"
),
// tyws equals to `None` iff we did not even enter the case above once, i.e. if
// utys equals to `None` iff we did not even enter the case above once, i.e. if
// `self` was indeed neither a `DomainMismatch` nor a `CodomainMismatch`
_ => break tyws.map(|(expd, actual)| (expd, actual, path, curr)),
_ => break utys.map(|(expd, actual)| (expd, actual, path, curr)),
}
}
}

View File

@ -3,7 +3,7 @@ use super::{TypeF, UnifType};
/// Multi-ary arrow constructor for types implementing `Into<TypeWrapper>`.
#[macro_export]
macro_rules! mk_tyw_arrow {
macro_rules! mk_uty_arrow {
($left:expr, $right:expr) => {
$crate::typecheck::UnifType::Concrete(
$crate::types::TypeF::Arrow(
@ -13,14 +13,14 @@ macro_rules! mk_tyw_arrow {
)
};
( $fst:expr, $snd:expr , $( $types:expr ),+ ) => {
mk_tyw_arrow!($fst, mk_tyw_arrow!($snd, $( $types ),+))
mk_uty_arrow!($fst, mk_uty_arrow!($snd, $( $types ),+))
};
}
/// Multi-ary enum row constructor for types implementing `Into<TypeWrapper>`.
/// `mk_tyw_enum_row!(id1, .., idn; tail)` correspond to `<id1, .., idn | tail>.
/// `mk_uty_enum_row!(id1, .., idn; tail)` correspond to `<id1, .., idn | tail>.
#[macro_export]
macro_rules! mk_tyw_enum_row {
macro_rules! mk_uty_enum_row {
() => {
$crate::typecheck::UnifEnumRows::Concrete(EnumRowsF::Empty)
};
@ -31,17 +31,17 @@ macro_rules! mk_tyw_enum_row {
$crate::typecheck::UnifEnumRows::Concrete(
$crate::types::EnumRowsF::Extend {
row: Ident::from($id),
tail: Box::new(mk_tyw_enum_row!($( $ids ),* $(; $tail)?))
tail: Box::new(mk_uty_enum_row!($( $ids ),* $(; $tail)?))
}
)
};
}
/// Multi-ary record row constructor for types implementing `Into<TypeWrapper>`.
/// `mk_tyw_row!((id1, ty1), .., (idn, tyn); tail)` correspond to `{id1: ty1, .., idn: tyn |
/// `mk_uty_row!((id1, ty1), .., (idn, tyn); tail)` correspond to `{id1: ty1, .., idn: tyn |
/// tail}. The tail can be omitted, in which case the empty row is uses as a tail instead.
#[macro_export]
macro_rules! mk_tyw_row {
macro_rules! mk_uty_row {
() => {
$crate::typecheck::UnifRecordRows::Concrete(RecordRowsF::Empty)
};
@ -55,31 +55,31 @@ macro_rules! mk_tyw_row {
id: Ident::from($id),
types: Box::new($ty.into()),
},
tail: Box::new(mk_tyw_row!($(($ids, $tys)),* $(; $tail)?)),
tail: Box::new(mk_uty_row!($(($ids, $tys)),* $(; $tail)?)),
}
)
};
}
/// Wrapper around `mk_tyw_enum_row!` to build an enum type from an enum row.
/// Wrapper around `mk_uty_enum_row!` to build an enum type from an enum row.
#[macro_export]
macro_rules! mk_tyw_enum {
macro_rules! mk_uty_enum {
($( $ids:expr ),* $(; $tail:expr)?) => {
$crate::typecheck::UnifType::Concrete(
$crate::types::TypeF::Enum(
mk_tyw_enum_row!($( $ids ),* $(; $tail)?)
mk_uty_enum_row!($( $ids ),* $(; $tail)?)
)
)
};
}
/// Wrapper around `mk_tyw_record!` to build a record type from a record row.
/// Wrapper around `mk_uty_record!` to build a record type from a record row.
#[macro_export]
macro_rules! mk_tyw_record {
macro_rules! mk_uty_record {
($(($ids:expr, $tys:expr)),* $(; $tail:expr)?) => {
$crate::typecheck::UnifType::Concrete(
$crate::types::TypeF::Record(
mk_tyw_row!($(($ids, $tys)),* $(; $tail)?)
mk_uty_row!($(($ids, $tys)),* $(; $tail)?)
)
)
};

View File

@ -57,7 +57,7 @@ use crate::{
types::{
EnumRow, EnumRows, EnumRowsF, RecordRowF, RecordRows, RecordRowsF, TypeF, Types, VarKind,
},
{mk_tyw_arrow, mk_tyw_enum, mk_tyw_enum_row, mk_tyw_record, mk_tyw_row},
{mk_uty_arrow, mk_uty_enum, mk_uty_enum_row, mk_uty_record, mk_uty_row},
};
use std::{
@ -72,7 +72,7 @@ pub mod linearization;
pub mod operation;
pub mod reporting;
#[macro_use]
pub mod mk_typewrapper;
pub mod mk_uniftype;
pub mod eq;
use eq::{SimpleTermEnvironment, TermEnvironment};
@ -805,7 +805,7 @@ fn walk<L: Linearizer>(
}
Term::Fun(id, t) => {
// The parameter of an un-annotated function is assigned the type `Dyn`.
ctxt.type_env.insert(*id, mk_typewrapper::dynamic());
ctxt.type_env.insert(*id, mk_uniftype::dynamic());
walk(state, ctxt, lin, linearizer, t)
}
Term::FunPattern(id, pat, t) => {
@ -1044,16 +1044,16 @@ fn type_check_<L: Linearizer>(
match t.as_ref() {
Term::ParseError(_) => Ok(()),
// null is inferred to be of type Dyn
Term::Null => unify(state, &ctxt, ty, mk_typewrapper::dynamic())
Term::Null => unify(state, &ctxt, ty, mk_uniftype::dynamic())
.map_err(|err| err.into_typecheck_err(state, rt.pos)),
Term::Bool(_) => unify(state, &ctxt, ty, mk_typewrapper::bool())
Term::Bool(_) => unify(state, &ctxt, ty, mk_uniftype::bool())
.map_err(|err| err.into_typecheck_err(state, rt.pos)),
Term::Num(_) => unify(state, &ctxt, ty, mk_typewrapper::num())
Term::Num(_) => unify(state, &ctxt, ty, mk_uniftype::num())
.map_err(|err| err.into_typecheck_err(state, rt.pos)),
Term::Str(_) => unify(state, &ctxt, ty, mk_typewrapper::str())
Term::Str(_) => unify(state, &ctxt, ty, mk_uniftype::str())
.map_err(|err| err.into_typecheck_err(state, rt.pos)),
Term::StrChunks(chunks) => {
unify(state, &ctxt, ty, mk_typewrapper::str())
unify(state, &ctxt, ty, mk_uniftype::str())
.map_err(|err| err.into_typecheck_err(state, rt.pos))?;
chunks
@ -1067,7 +1067,7 @@ fn type_check_<L: Linearizer>(
lin,
linearizer.scope(),
t,
mk_typewrapper::str(),
mk_uniftype::str(),
),
}
})
@ -1077,7 +1077,7 @@ fn type_check_<L: Linearizer>(
// TODO what to do here, this makes more sense to me, but it means let x = foo in bar
// behaves quite different to (\x.bar) foo, worth considering if it's ok to type these two differently
let trg = state.table.fresh_type_uvar();
let arr = mk_tyw_arrow!(src.clone(), trg.clone());
let arr = mk_uty_arrow!(src.clone(), trg.clone());
linearizer.retype_ident(lin, x, src.clone());
unify(state, &ctxt, ty, arr).map_err(|err| err.into_typecheck_err(state, rt.pos))?;
@ -1090,7 +1090,7 @@ fn type_check_<L: Linearizer>(
// TODO what to do here, this makes more sense to me, but it means let x = foo in bar
// behaves quite different to (\x.bar) foo, worth considering if it's ok to type these two differently
let trg = state.table.fresh_type_uvar();
let arr = mk_tyw_arrow!(src.clone(), trg.clone());
let arr = mk_uty_arrow!(src.clone(), trg.clone());
if let Some(x) = x {
linearizer.retype_ident(lin, x, src.clone());
ctxt.type_env.insert(*x, src);
@ -1102,7 +1102,7 @@ fn type_check_<L: Linearizer>(
Term::Array(terms, _) => {
let ty_elts = state.table.fresh_type_uvar();
unify(state, &ctxt, ty, mk_typewrapper::array(ty_elts.clone()))
unify(state, &ctxt, ty, mk_uniftype::array(ty_elts.clone()))
.map_err(|err| err.into_typecheck_err(state, rt.pos))?;
terms
@ -1120,7 +1120,7 @@ fn type_check_<L: Linearizer>(
}
Term::Lbl(_) => {
// TODO implement lbl type
unify(state, &ctxt, ty, mk_typewrapper::dynamic())
unify(state, &ctxt, ty, mk_uniftype::dynamic())
.map_err(|err| err.into_typecheck_err(state, rt.pos))
}
Term::Let(x, re, rt, attrs) => {
@ -1171,7 +1171,7 @@ fn type_check_<L: Linearizer>(
}
Term::App(e, t) => {
let src = state.table.fresh_type_uvar();
let arr = mk_tyw_arrow!(src.clone(), ty);
let arr = mk_uty_arrow!(src.clone(), ty);
type_check_(state, ctxt.clone(), lin, linearizer.scope(), e, arr)?;
type_check_(state, ctxt, lin, linearizer, t, src)
@ -1200,13 +1200,13 @@ fn type_check_<L: Linearizer>(
None => cases.iter().try_fold(
EnumRowsF::Empty.into(),
|acc, x| -> Result<UnifEnumRows, TypecheckError> {
Ok(mk_tyw_enum_row!(*x.0; acc))
Ok(mk_uty_enum_row!(*x.0; acc))
},
)?,
};
unify(state, &ctxt, ty, res).map_err(|err| err.into_typecheck_err(state, rt.pos))?;
type_check_(state, ctxt, lin, linearizer, exp, mk_tyw_enum!(; erows))
type_check_(state, ctxt, lin, linearizer, exp, mk_uty_enum!(; erows))
}
Term::Var(x) => {
let x_ty = ctxt
@ -1221,7 +1221,7 @@ fn type_check_<L: Linearizer>(
}
Term::Enum(id) => {
let row = state.table.fresh_erows_uvar();
unify(state, &ctxt, ty, mk_tyw_enum!(*id; row))
unify(state, &ctxt, ty, mk_uty_enum!(*id; row))
.map_err(|err| err.into_typecheck_err(state, rt.pos))
}
// If some fields are defined dynamically, the only potential type that works is `{_ : a}`
@ -1250,7 +1250,7 @@ fn type_check_<L: Linearizer>(
)
})?;
unify(state, &ctxt, ty, mk_typewrapper::dyn_record(ty_dict))
unify(state, &ctxt, ty, mk_uniftype::dyn_record(ty_dict))
.map_err(|err| err.into_typecheck_err(state, rt.pos))
}
Term::Record(record) | Term::RecRecord(record, ..) => {
@ -1284,7 +1284,7 @@ fn type_check_<L: Linearizer>(
})
} else {
let rows = record.fields.iter().try_fold(
mk_tyw_row!(),
mk_uty_row!(),
|acc, (id, field)| -> Result<UnifRecordRows, TypecheckError> {
// In the case of a recursive record, new types (either type variables or
// annotations) have already be determined and put in the typing context,
@ -1304,11 +1304,11 @@ fn type_check_<L: Linearizer>(
ty.clone(),
)?;
Ok(mk_tyw_row!((*id, ty); acc))
Ok(mk_uty_row!((*id, ty); acc))
},
)?;
unify(state, &ctxt, ty, mk_tyw_record!(; rows))
unify(state, &ctxt, ty, mk_uty_record!(; rows))
.map_err(|err| err.into_typecheck_err(state, rt.pos))
}
}
@ -1402,14 +1402,14 @@ fn type_check_<L: Linearizer>(
// TODO: we might have something to with the linearizer to clear the current
// metadata. It looks like it may be unduly attached to the next field definition,
// which is not critical, but still a bug.
_ => unify(state, &ctxt, ty, mk_typewrapper::dynamic())
_ => unify(state, &ctxt, ty, mk_uniftype::dynamic())
.map_err(|err| err.into_typecheck_err(state, rt.pos)),
}
}
Term::SealingKey(_) => unify(state, &ctxt, ty, mk_typewrapper::sym())
Term::SealingKey(_) => unify(state, &ctxt, ty, mk_uniftype::sym())
.map_err(|err| err.into_typecheck_err(state, rt.pos)),
Term::Sealed(_, t, _) => type_check_(state, ctxt, lin, linearizer, t, ty),
Term::Import(_) => unify(state, &ctxt, ty, mk_typewrapper::dynamic())
Term::Import(_) => unify(state, &ctxt, ty, mk_uniftype::dynamic())
.map_err(|err| err.into_typecheck_err(state, rt.pos)),
// We use the apparent type of the import for checking. This function doesn't recursively
// typecheck imports: this is the responsibility of the caller.
@ -1810,12 +1810,12 @@ pub fn unify(
(TypeF::Flat(s), TypeF::Flat(t)) => Err(UnifError::IncomparableFlatTypes(s, t)),
(TypeF::Enum(erows1), TypeF::Enum(erows2)) => {
unify_erows(state, erows1.clone(), erows2.clone()).map_err(|err| {
err.into_unif_err(mk_tyw_enum!(; erows1), mk_tyw_enum!(; erows2))
err.into_unif_err(mk_uty_enum!(; erows1), mk_uty_enum!(; erows2))
})
}
(TypeF::Record(rrows1), TypeF::Record(rrows2)) => {
unify_rrows(state, ctxt, rrows1.clone(), rrows2.clone()).map_err(|err| {
err.into_unif_err(mk_tyw_record!(; rrows1), mk_tyw_record!(; rrows2))
err.into_unif_err(mk_uty_record!(; rrows1), mk_uty_record!(; rrows2))
})
}
(TypeF::Dict(t1), TypeF::Dict(t2)) => unify(state, ctxt, *t1, *t2),

View File

@ -5,7 +5,7 @@ use crate::{
term::{BinaryOp, NAryOp, UnaryOp},
types::TypeF,
};
use crate::{mk_tyw_arrow, mk_tyw_enum, mk_tyw_enum_row, mk_tyw_record, mk_tyw_row};
use crate::{mk_uty_arrow, mk_uty_enum, mk_uty_enum_row, mk_uty_record, mk_uty_row};
/// Type of unary operations.
pub fn get_uop_type(
@ -18,37 +18,36 @@ pub fn get_uop_type(
let branches = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_typewrapper::bool(),
mk_tyw_arrow!(branches.clone(), branches.clone(), branches),
mk_uniftype::bool(),
mk_uty_arrow!(branches.clone(), branches.clone(), branches),
)
}
// Dyn -> [| `Num, `Bool, `Str, `Enum, `Fun, `Array, `Record, `Lbl, `Other |]
UnaryOp::Typeof() => (
mk_typewrapper::dynamic(),
mk_tyw_enum!("Num", "Bool", "Str", "Enum", "Fun", "Array", "Record", "Lbl", "Other"),
mk_uniftype::dynamic(),
mk_uty_enum!("Num", "Bool", "Str", "Enum", "Fun", "Array", "Record", "Lbl", "Other"),
),
// Bool -> Bool -> Bool
UnaryOp::BoolAnd() | UnaryOp::BoolOr() => (
mk_typewrapper::bool(),
mk_tyw_arrow!(TypeF::Bool, TypeF::Bool),
),
UnaryOp::BoolAnd() | UnaryOp::BoolOr() => {
(mk_uniftype::bool(), mk_uty_arrow!(TypeF::Bool, TypeF::Bool))
}
// Bool -> Bool
UnaryOp::BoolNot() => (mk_typewrapper::bool(), mk_typewrapper::bool()),
UnaryOp::BoolNot() => (mk_uniftype::bool(), mk_uniftype::bool()),
// forall a. Dyn -> a
UnaryOp::Blame() => {
let res = UnifType::UnifVar(state.table.fresh_type_var_id());
(mk_typewrapper::dynamic(), res)
(mk_uniftype::dynamic(), res)
}
// Dyn -> Bool
UnaryOp::Pol() => (mk_typewrapper::dynamic(), mk_typewrapper::bool()),
UnaryOp::Pol() => (mk_uniftype::dynamic(), mk_uniftype::bool()),
// forall rows. < | rows> -> <id | rows>
UnaryOp::Embed(id) => {
let row_var_id = state.table.fresh_erows_var_id();
let row = UnifEnumRows::UnifVar(row_var_id);
let domain = mk_tyw_enum!(; row.clone());
let codomain = mk_tyw_enum!(*id; row);
let domain = mk_uty_enum!(; row.clone());
let codomain = mk_uty_enum!(*id; row);
// The codomain is the only type which can impose a constraint on the fresh row
// unification variable, namely that it can't contain `id`.
@ -59,34 +58,34 @@ pub fn get_uop_type(
UnaryOp::Switch(_) => panic!("cannot typecheck Switch()"),
// Dyn -> Dyn
UnaryOp::ChangePolarity() | UnaryOp::GoDom() | UnaryOp::GoCodom() | UnaryOp::GoArray() => {
(mk_typewrapper::dynamic(), mk_typewrapper::dynamic())
(mk_uniftype::dynamic(), mk_uniftype::dynamic())
}
// forall rows a. { id: a | rows} -> a
UnaryOp::StaticAccess(id) => {
let rows = state.table.fresh_rrows_uvar();
let res = state.table.fresh_type_uvar();
(mk_tyw_record!((*id, res.clone()); rows), res)
(mk_uty_record!((*id, res.clone()); rows), res)
}
// forall a b. Array a -> (a -> b) -> Array b
UnaryOp::ArrayMap() => {
let a = UnifType::UnifVar(state.table.fresh_type_var_id());
let b = UnifType::UnifVar(state.table.fresh_type_var_id());
let f_type = mk_tyw_arrow!(a.clone(), b.clone());
let f_type = mk_uty_arrow!(a.clone(), b.clone());
(
mk_typewrapper::array(a),
mk_tyw_arrow!(f_type, mk_typewrapper::array(b)),
mk_uniftype::array(a),
mk_uty_arrow!(f_type, mk_uniftype::array(b)),
)
}
// forall a. Num -> (Num -> a) -> Array a
UnaryOp::ArrayGen() => {
let a = UnifType::UnifVar(state.table.fresh_type_var_id());
let f_type = mk_tyw_arrow!(TypeF::Num, a.clone());
let f_type = mk_uty_arrow!(TypeF::Num, a.clone());
(
mk_typewrapper::num(),
mk_tyw_arrow!(f_type, mk_typewrapper::array(a)),
mk_uniftype::num(),
mk_uty_arrow!(f_type, mk_uniftype::array(a)),
)
}
// forall a b. { _ : a} -> (Str -> a -> b) -> { _ : b }
@ -97,10 +96,10 @@ pub fn get_uop_type(
let a = UnifType::UnifVar(state.table.fresh_type_var_id());
let b = UnifType::UnifVar(state.table.fresh_type_var_id());
let f_type = mk_tyw_arrow!(TypeF::Str, a.clone(), b.clone());
let f_type = mk_uty_arrow!(TypeF::Str, a.clone(), b.clone());
(
mk_typewrapper::dyn_record(a),
mk_tyw_arrow!(f_type, mk_typewrapper::dyn_record(b)),
mk_uniftype::dyn_record(a),
mk_uty_arrow!(f_type, mk_uniftype::dyn_record(b)),
)
}
// forall a b. a -> b -> b
@ -108,93 +107,90 @@ pub fn get_uop_type(
let fst = UnifType::UnifVar(state.table.fresh_type_var_id());
let snd = UnifType::UnifVar(state.table.fresh_type_var_id());
(fst, mk_tyw_arrow!(snd.clone(), snd))
(fst, mk_uty_arrow!(snd.clone(), snd))
}
// forall a. Array a -> a
UnaryOp::ArrayHead() => {
let ty_elt = UnifType::UnifVar(state.table.fresh_type_var_id());
(mk_typewrapper::array(ty_elt.clone()), ty_elt)
(mk_uniftype::array(ty_elt.clone()), ty_elt)
}
// forall a. Array a -> Array a
UnaryOp::ArrayTail() => {
let ty_elt = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_typewrapper::array(ty_elt.clone()),
mk_typewrapper::array(ty_elt),
mk_uniftype::array(ty_elt.clone()),
mk_uniftype::array(ty_elt),
)
}
// forall a. Array a -> Num
UnaryOp::ArrayLength() => {
let ty_elt = UnifType::UnifVar(state.table.fresh_type_var_id());
(mk_typewrapper::array(ty_elt), mk_typewrapper::num())
(mk_uniftype::array(ty_elt), mk_uniftype::num())
}
// This should not happen, as ChunksConcat() is only produced during evaluation.
UnaryOp::ChunksConcat() => panic!("cannot type ChunksConcat()"),
// BEFORE: forall rows. { rows } -> Array
// Dyn -> Array Str
UnaryOp::FieldsOf() => (
mk_typewrapper::dynamic(),
//mk_tyw_record!(; TypeWrapper::Ptr(state.table.fresh_type_var_id())),
mk_typewrapper::array(TypeF::Str),
mk_uniftype::dynamic(),
//mk_uty_record!(; TypeWrapper::Ptr(state.table.fresh_type_var_id())),
mk_uniftype::array(TypeF::Str),
),
// Dyn -> Array Dyn
UnaryOp::ValuesOf() => (mk_typewrapper::dynamic(), mk_typewrapper::array(TypeF::Dyn)),
UnaryOp::ValuesOf() => (mk_uniftype::dynamic(), mk_uniftype::array(TypeF::Dyn)),
// Str -> Str
UnaryOp::StrTrim() => (mk_typewrapper::str(), mk_typewrapper::str()),
UnaryOp::StrTrim() => (mk_uniftype::str(), mk_uniftype::str()),
// Str -> Array Str
UnaryOp::StrChars() => (
mk_typewrapper::str(),
mk_typewrapper::array(mk_typewrapper::str()),
),
UnaryOp::StrChars() => (mk_uniftype::str(), mk_uniftype::array(mk_uniftype::str())),
// Str -> Num
UnaryOp::CharCode() => (mk_typewrapper::str(), mk_typewrapper::num()),
UnaryOp::CharCode() => (mk_uniftype::str(), mk_uniftype::num()),
// Num -> Str
UnaryOp::CharFromCode() => (mk_typewrapper::num(), mk_typewrapper::str()),
UnaryOp::CharFromCode() => (mk_uniftype::num(), mk_uniftype::str()),
// Str -> Str
UnaryOp::StrUppercase() => (mk_typewrapper::str(), mk_typewrapper::str()),
UnaryOp::StrUppercase() => (mk_uniftype::str(), mk_uniftype::str()),
// Str -> Str
UnaryOp::StrLowercase() => (mk_typewrapper::str(), mk_typewrapper::str()),
UnaryOp::StrLowercase() => (mk_uniftype::str(), mk_uniftype::str()),
// Str -> Num
UnaryOp::StrLength() => (mk_typewrapper::str(), mk_typewrapper::num()),
UnaryOp::StrLength() => (mk_uniftype::str(), mk_uniftype::num()),
// Dyn -> Str
UnaryOp::ToStr() => (mk_typewrapper::dynamic(), mk_typewrapper::str()),
UnaryOp::ToStr() => (mk_uniftype::dynamic(), mk_uniftype::str()),
// Str -> Num
UnaryOp::NumFromStr() => (mk_typewrapper::str(), mk_typewrapper::num()),
UnaryOp::NumFromStr() => (mk_uniftype::str(), mk_uniftype::num()),
// Str -> < | a> for a rigid type variable a
UnaryOp::EnumFromStr() => (
mk_typewrapper::str(),
mk_tyw_enum!(; state.table.fresh_erows_const()),
mk_uniftype::str(),
mk_uty_enum!(; state.table.fresh_erows_const()),
),
// Str -> Str -> Bool
UnaryOp::StrIsMatch() => (
mk_typewrapper::str(),
mk_tyw_arrow!(mk_typewrapper::str(), mk_typewrapper::bool()),
mk_uniftype::str(),
mk_uty_arrow!(mk_uniftype::str(), mk_uniftype::bool()),
),
// Str -> Str -> {match: Str, index: Num, groups: Array Str}
UnaryOp::StrMatch() => (
mk_typewrapper::str(),
mk_tyw_arrow!(
mk_typewrapper::str(),
mk_tyw_record!(
mk_uniftype::str(),
mk_uty_arrow!(
mk_uniftype::str(),
mk_uty_record!(
("match", TypeF::Str),
("index", TypeF::Num),
("groups", mk_typewrapper::array(TypeF::Str))
("groups", mk_uniftype::array(TypeF::Str))
)
),
),
// Str -> Bool
UnaryOp::StrIsMatchCompiled(_) => (mk_typewrapper::str(), mk_typewrapper::bool()),
UnaryOp::StrIsMatchCompiled(_) => (mk_uniftype::str(), mk_uniftype::bool()),
// Str -> {match: Str, index: Num, groups: Array Str}
UnaryOp::StrMatchCompiled(_) => (
mk_typewrapper::str(),
mk_tyw_record!(
mk_uniftype::str(),
mk_uty_record!(
("match", TypeF::Str),
("index", TypeF::Num),
("groups", mk_typewrapper::array(TypeF::Str))
("groups", mk_uniftype::array(TypeF::Str))
),
),
// Dyn -> Dyn
UnaryOp::Force(_) => (mk_typewrapper::dynamic(), mk_typewrapper::dynamic()),
UnaryOp::Force(_) => (mk_uniftype::dynamic(), mk_uniftype::dynamic()),
// forall a. a -> a
UnaryOp::PushDefault() => {
let ty = state.table.fresh_type_uvar();
@ -219,70 +215,58 @@ pub fn get_bop_type(
| BinaryOp::Sub()
| BinaryOp::Mult()
| BinaryOp::Div()
| BinaryOp::Modulo() => (
mk_typewrapper::num(),
mk_typewrapper::num(),
mk_typewrapper::num(),
),
| BinaryOp::Modulo() => (mk_uniftype::num(), mk_uniftype::num(), mk_uniftype::num()),
// Sym -> Dyn -> Dyn -> Dyn
BinaryOp::Seal() => (
mk_typewrapper::sym(),
mk_typewrapper::dynamic(),
mk_tyw_arrow!(TypeF::Dyn, TypeF::Dyn),
mk_uniftype::sym(),
mk_uniftype::dynamic(),
mk_uty_arrow!(TypeF::Dyn, TypeF::Dyn),
),
// Str -> Str -> Str
BinaryOp::StrConcat() => (
mk_typewrapper::str(),
mk_typewrapper::str(),
mk_typewrapper::str(),
),
BinaryOp::StrConcat() => (mk_uniftype::str(), mk_uniftype::str(), mk_uniftype::str()),
// Ideally: Contract -> Label -> Dyn -> Dyn
// Currenty: Dyn -> Dyn -> (Dyn -> Dyn)
BinaryOp::Assume() => (
mk_typewrapper::dynamic(),
mk_typewrapper::dynamic(),
mk_tyw_arrow!(mk_typewrapper::dynamic(), mk_typewrapper::dynamic()),
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
mk_uty_arrow!(mk_uniftype::dynamic(), mk_uniftype::dynamic()),
),
// Sym -> Dyn -> Dyn -> Dyn
BinaryOp::Unseal() => (
mk_typewrapper::sym(),
mk_typewrapper::dynamic(),
mk_tyw_arrow!(TypeF::Dyn, TypeF::Dyn),
mk_uniftype::sym(),
mk_uniftype::dynamic(),
mk_uty_arrow!(TypeF::Dyn, TypeF::Dyn),
),
// Str -> Dyn -> Dyn
BinaryOp::Tag() => (
mk_typewrapper::str(),
mk_typewrapper::dynamic(),
mk_typewrapper::dynamic(),
mk_uniftype::str(),
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
),
// forall a b. a -> b -> Bool
BinaryOp::Eq() => (
UnifType::UnifVar(state.table.fresh_type_var_id()),
UnifType::UnifVar(state.table.fresh_type_var_id()),
mk_typewrapper::bool(),
mk_uniftype::bool(),
),
// Num -> Num -> Bool
BinaryOp::LessThan()
| BinaryOp::LessOrEq()
| BinaryOp::GreaterThan()
| BinaryOp::GreaterOrEq() => (
mk_typewrapper::num(),
mk_typewrapper::num(),
mk_typewrapper::bool(),
),
| BinaryOp::GreaterOrEq() => (mk_uniftype::num(), mk_uniftype::num(), mk_uniftype::bool()),
// Str -> Dyn -> Dyn
BinaryOp::GoField() => (
mk_typewrapper::str(),
mk_typewrapper::dynamic(),
mk_typewrapper::dynamic(),
mk_uniftype::str(),
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
),
// forall a. Str -> { _ : a} -> a
BinaryOp::DynAccess() => {
let res = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_typewrapper::str(),
mk_typewrapper::dyn_record(res.clone()),
mk_uniftype::str(),
mk_uniftype::dyn_record(res.clone()),
res,
)
}
@ -290,98 +274,90 @@ pub fn get_bop_type(
BinaryOp::DynExtend() => {
let res = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_typewrapper::str(),
mk_typewrapper::dyn_record(res.clone()),
mk_tyw_arrow!(res.clone(), mk_typewrapper::dyn_record(res)),
mk_uniftype::str(),
mk_uniftype::dyn_record(res.clone()),
mk_uty_arrow!(res.clone(), mk_uniftype::dyn_record(res)),
)
}
// forall a. Str -> { _ : a } -> { _ : a}
BinaryOp::DynRemove() => {
let res = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_typewrapper::str(),
mk_typewrapper::dyn_record(res.clone()),
mk_typewrapper::dyn_record(res),
mk_uniftype::str(),
mk_uniftype::dyn_record(res.clone()),
mk_uniftype::dyn_record(res),
)
}
// forall a. Str -> {_: a} -> Bool
BinaryOp::HasField() => {
let ty_elt = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_typewrapper::str(),
mk_typewrapper::dyn_record(ty_elt),
mk_typewrapper::bool(),
mk_uniftype::str(),
mk_uniftype::dyn_record(ty_elt),
mk_uniftype::bool(),
)
}
// forall a. Array a -> Array a -> Array a
BinaryOp::ArrayConcat() => {
let ty_elt = UnifType::UnifVar(state.table.fresh_type_var_id());
let ty_array = mk_typewrapper::array(ty_elt);
let ty_array = mk_uniftype::array(ty_elt);
(ty_array.clone(), ty_array.clone(), ty_array)
}
// forall a. Array a -> Num -> a
BinaryOp::ArrayElemAt() => {
let ty_elt = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_typewrapper::array(ty_elt.clone()),
mk_typewrapper::num(),
mk_uniftype::array(ty_elt.clone()),
mk_uniftype::num(),
ty_elt,
)
}
// Dyn -> Dyn -> Dyn
BinaryOp::Merge() => (
mk_typewrapper::dynamic(),
mk_typewrapper::dynamic(),
mk_typewrapper::dynamic(),
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
),
// <Md5, Sha1, Sha256, Sha512> -> Str -> Str
BinaryOp::Hash() => (
mk_tyw_enum!("Md5", "Sha1", "Sha256", "Sha512"),
mk_typewrapper::str(),
mk_typewrapper::str(),
mk_uty_enum!("Md5", "Sha1", "Sha256", "Sha512"),
mk_uniftype::str(),
mk_uniftype::str(),
),
// forall a. <Json, Yaml, Toml> -> a -> Str
BinaryOp::Serialize() => {
let ty_input = UnifType::UnifVar(state.table.fresh_type_var_id());
(
mk_tyw_enum!("Json", "Yaml", "Toml"),
mk_uty_enum!("Json", "Yaml", "Toml"),
ty_input,
mk_typewrapper::str(),
mk_uniftype::str(),
)
}
// <Json, Yaml, Toml> -> Str -> Dyn
BinaryOp::Deserialize() => (
mk_tyw_enum!("Json", "Yaml", "Toml"),
mk_typewrapper::str(),
mk_typewrapper::dynamic(),
mk_uty_enum!("Json", "Yaml", "Toml"),
mk_uniftype::str(),
mk_uniftype::dynamic(),
),
// Num -> Num -> Num
BinaryOp::Pow() => (
mk_typewrapper::num(),
mk_typewrapper::num(),
mk_typewrapper::num(),
),
BinaryOp::Pow() => (mk_uniftype::num(), mk_uniftype::num(), mk_uniftype::num()),
// Str -> Str -> Bool
BinaryOp::StrContains() => (
mk_typewrapper::str(),
mk_typewrapper::str(),
mk_typewrapper::bool(),
),
BinaryOp::StrContains() => (mk_uniftype::str(), mk_uniftype::str(), mk_uniftype::bool()),
// Str -> Str -> Array Str
BinaryOp::StrSplit() => (
mk_typewrapper::str(),
mk_typewrapper::str(),
mk_typewrapper::array(TypeF::Str),
mk_uniftype::str(),
mk_uniftype::str(),
mk_uniftype::array(TypeF::Str),
),
// The first argument is a contract, the second is a label.
// forall a. Dyn -> Dyn -> Array a -> Array a
BinaryOp::ArrayLazyAssume() => {
let ty_elt = UnifType::UnifVar(state.table.fresh_type_var_id());
let ty_array = mk_typewrapper::array(ty_elt);
let ty_array = mk_uniftype::array(ty_elt);
(
mk_typewrapper::dynamic(),
mk_typewrapper::dynamic(),
mk_tyw_arrow!(ty_array.clone(), ty_array),
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
mk_uty_arrow!(ty_array.clone(), ty_array),
)
}
})
@ -394,21 +370,13 @@ pub fn get_nop_type(
Ok(match op {
// Str -> Str -> Str -> Str
NAryOp::StrReplace() | NAryOp::StrReplaceRegex() => (
vec![
mk_typewrapper::str(),
mk_typewrapper::str(),
mk_typewrapper::str(),
],
mk_typewrapper::str(),
vec![mk_uniftype::str(), mk_uniftype::str(), mk_uniftype::str()],
mk_uniftype::str(),
),
// Str -> Num -> Num -> Str
NAryOp::StrSubstr() => (
vec![
mk_typewrapper::str(),
mk_typewrapper::num(),
mk_typewrapper::num(),
],
mk_typewrapper::str(),
vec![mk_uniftype::str(), mk_uniftype::num(), mk_uniftype::num()],
mk_uniftype::str(),
),
// This should not happen, as Switch() is only produced during evaluation.
NAryOp::MergeContract() => panic!("cannot typecheck MergeContract()"),