feat: implements ord for Ty (#667)

* feat: implements partial ord for `Ty`

* feat: implements ord for `Ty`

* test: update snapshot
This commit is contained in:
Myriad-Dreamin 2024-10-13 14:37:03 +08:00 committed by GitHub
parent 0e41ea33b2
commit cc29728fc9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 83 additions and 17 deletions

View file

@ -207,6 +207,24 @@ impl<T: Internable> PartialEq for Interned<T> {
impl<T: Internable> Eq for Interned<T> {}
impl<T: Internable + PartialOrd> PartialOrd for Interned<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.as_ref().partial_cmp(other.as_ref())
}
}
impl<T: Internable + Ord> Ord for Interned<T> {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
if self == other {
std::cmp::Ordering::Equal
} else {
self.as_ref().cmp(other.as_ref())
}
}
}
impl PartialOrd for Interned<str> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))

View file

@ -3,4 +3,4 @@ source: crates/tinymist-query/src/analysis.rs
expression: CallSnapshot(result.as_deref())
input_file: crates/tinymist-query/src/fixtures/call_info/builtin.typ
---
1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "angle", docs: "The angle whose sine to calculate.", base_type: (Type(integer) | Type(float) | Type(angle)), type_repr: Some("int | float | angle"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } }
1 -> CallParamInfo { kind: Positional, is_content_block: false, param: ParamSpec { name: "angle", docs: "The angle whose sine to calculate.", base_type: (Type(angle) | Type(float) | Type(integer)), type_repr: Some("int | float | angle"), expr: None, default: None, positional: true, named: false, variadic: false, settable: false } }

View file

@ -3,11 +3,10 @@ source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/infer.typ
---
---
1..6 -> Func(image)
1..18 -> Element(image)
21..25 -> Func(read)
21..37 -> (Type(string) | Type(bytes))
21..37 -> (Type(bytes) | Type(string))
40..44 -> Func(json)
40..57 -> Any
60..64 -> Func(yaml)

View file

@ -7,7 +7,7 @@ input_file: crates/tinymist-query/src/fixtures/type_check/sig_template_set.typ
"class" = ( ⪰ "article" | "article" | "letter" | "article" | "letter")
"content" = Any
"font" = None
"tmpl" = (Any, "authors": ( ⪯ (Type(string) | Type(array))), "class": Any, "font": ( ⪯ (TextFont | Array<TextFont>))) => Any
"tmpl" = (Any, "authors": ( ⪯ (Type(array) | Type(string))), "class": Any, "font": ( ⪯ (TextFont | Array<TextFont>))) => Any
---
5..9 -> @tmpl
10..17 -> @content

View file

@ -16,5 +16,5 @@ input_file: crates/tinymist-query/src/fixtures/type_check/with.typ
24..30 -> (@x) => @x
24..33 -> ((@x) => @x).with(..(1) => any)
40..41 -> @x
44..45 -> (@g | Any)
44..45 -> (Any | @g)
44..47 -> 1

View file

@ -11,7 +11,7 @@ use typst::{
use crate::{adt::interner::Interned, ty::*};
#[derive(Debug, Clone, Hash, PartialEq, Eq, EnumIter)]
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, EnumIter)]
pub enum PathPreference {
Source,
Csv,
@ -156,7 +156,7 @@ impl<'a> Iterator for UnionIter<'a> {
}
}
#[derive(Clone, Hash, PartialEq, Eq)]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum BuiltinTy {
Clause,
Undef,

View file

@ -29,7 +29,7 @@ pub(super) type TyRef = Interned<Ty>;
pub(super) type StrRef = Interned<str>;
/// All possible types in tinymist
#[derive(Hash, Clone, PartialEq, Eq)]
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Ty {
// Simple Types
/// A top type, whose negation is bottom type.
@ -147,7 +147,9 @@ impl Ty {
/// Create a union type from an iterator of types
pub fn iter_union(e: impl IntoIterator<Item = Ty>) -> Self {
Ty::Union(Interned::new(e.into_iter().collect()))
let mut v: Vec<Ty> = e.into_iter().collect();
v.sort();
Ty::Union(Interned::new(v))
}
/// Create an undefined type (which will emit an error)
@ -213,7 +215,7 @@ impl TypeSource {
}
/// An ordered list of names
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct NameBone {
/// The names in the bone
pub names: Box<[StrRef]>,
@ -273,7 +275,7 @@ impl NameBone {
/// A frozen type variable (bounds of some type in program)
/// `t :> t1 | ... | tn <: f1 & ... & fn`
/// ` lbs------------- ubs-------------`
#[derive(Hash, Clone, PartialEq, Eq, Default)]
#[derive(Hash, Clone, PartialEq, Eq, Default, PartialOrd, Ord)]
pub struct TypeBounds {
/// The lower bounds
pub lbs: EcoVec<Ty>,
@ -348,6 +350,20 @@ pub struct InsTy {
/// For example, a float instance which is NaN.
impl Eq for InsTy {}
impl PartialOrd for InsTy {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for InsTy {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.val
.partial_cmp(&other.val)
.unwrap_or(std::cmp::Ordering::Equal)
}
}
impl InsTy {
/// Create a instance
pub fn new(val: Value) -> Interned<Self> {
@ -381,7 +397,7 @@ impl InsTy {
}
/// A field type
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FieldTy {
/// The name of the field
pub name: StrRef,
@ -446,7 +462,7 @@ impl TypeVar {
}
/// A record type
#[derive(Hash, Clone, PartialEq, Eq)]
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct RecordTy {
/// The names of the fields
pub names: Interned<NameBone>,
@ -503,7 +519,7 @@ impl fmt::Debug for RecordTy {
}
/// A typst function type
#[derive(Hash, Clone, PartialEq, Eq)]
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SigTy {
/// The input types of the function
pub inputs: Interned<Vec<Ty>>,
@ -725,7 +741,7 @@ impl fmt::Debug for SigTy {
pub type ArgsTy = SigTy;
/// A type with partially applied arguments
#[derive(Hash, Clone, PartialEq, Eq)]
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SigWithTy {
/// The signature of the function
pub sig: TyRef,
@ -747,7 +763,7 @@ impl fmt::Debug for SigWithTy {
}
/// A field selection type
#[derive(Hash, Clone, PartialEq, Eq)]
#[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SelectTy {
/// The type to select from
pub ty: TyRef,
@ -803,6 +819,22 @@ pub struct TypeUnary {
pub op: UnaryOp,
}
impl PartialOrd for TypeUnary {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TypeUnary {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let op_as_int = self.op as u8;
let other_op_as_int = other.op as u8;
op_as_int
.cmp(&other_op_as_int)
.then_with(|| self.lhs.cmp(&other.lhs))
}
}
impl TypeUnary {
/// Create a unary operation type
pub fn new(op: UnaryOp, lhs: TyRef) -> Interned<Self> {
@ -827,6 +859,22 @@ pub struct TypeBinary {
pub op: BinaryOp,
}
impl PartialOrd for TypeBinary {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TypeBinary {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let op_as_int = self.op as u8;
let other_op_as_int = other.op as u8;
op_as_int
.cmp(&other_op_as_int)
.then_with(|| self.operands.cmp(&other.operands))
}
}
impl TypeBinary {
/// Create a binary operation type
pub fn new(op: BinaryOp, lhs: TyRef, rhs: TyRef) -> Interned<Self> {
@ -844,7 +892,7 @@ impl TypeBinary {
/// A conditional type
/// `if t1 then t2 else t3`
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct IfTy {
/// The condition
pub cond: TyRef,

View file

@ -0,0 +1 @@