1use std::collections::HashMap;
2
3pub type Id = usize;
4
5#[cfg_attr(feature = "withserde", derive(serde::Serialize, serde::Deserialize))]
6#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
7pub struct Effect {
8 pub input: Type,
9 pub output: Type,
10}
11
12#[cfg_attr(feature = "withserde", derive(serde::Serialize, serde::Deserialize))]
13#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
14pub enum Type {
15 Number,
16 String,
17 Product(Vec<Self>),
18 Sum(Vec<Self>),
19 Function {
20 parameters: Vec<Self>,
21 body: Box<Self>,
22 },
23 Array(Box<Self>),
24 Set(Box<Self>),
25 Variable(Id),
26 ForAll {
27 variable: Id,
28 body: Box<Self>,
29 },
30 Effectful {
31 ty: Box<Self>,
32 effects: EffectExpr,
33 },
34 Brand {
35 brand: String,
36 item: Box<Self>,
37 },
38 Label {
39 label: String,
40 item: Box<Self>,
41 },
42}
43
44#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
45#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
46pub enum EffectExpr {
47 Effects(Vec<Effect>),
48 Add(Vec<EffectExpr>),
49 Sub {
50 minuend: Box<EffectExpr>,
51 subtrahend: Box<EffectExpr>,
52 },
53 Apply {
54 function: Box<Type>,
55 arguments: Vec<Type>,
56 },
57}
58
59impl Type {
60 pub fn unit() -> Self {
61 Type::Product(vec![])
62 }
63 pub fn label(label: impl Into<String>, item: Self) -> Self {
64 Type::Label {
65 label: label.into(),
66 item: Box::new(item),
67 }
68 }
69 pub fn product(mut types: Vec<Self>) -> Self {
70 types.sort();
71 Type::Product(types)
72 }
73 pub fn sum(mut types: Vec<Self>) -> Self {
74 types.sort();
75 types.dedup();
76 if types.len() == 1 {
77 types.pop().unwrap()
78 } else {
79 Type::Sum(types)
80 }
81 }
82 pub fn function(mut parameters: Vec<Self>, body: Self) -> Self {
83 parameters.sort();
84 Type::Function {
85 parameters,
86 body: Box::new(body),
87 }
88 }
89}
90
91#[derive(Clone, Debug, PartialEq, Eq, Default)]
92pub struct Types {
93 pub types: HashMap<Id, Type>,
94}
95
96impl Types {
97 pub fn get(&self, id: &Id) -> Option<&Type> {
98 self.types.get(id)
99 }
100}
101
102#[derive(Clone, Debug, PartialEq, Default)]
103pub struct IdGen {
104 pub next_id: Id,
105}
106
107impl IdGen {
108 pub fn next_id(&mut self) -> Id {
109 let id = self.next_id;
110 self.next_id += 1;
111 id
112 }
113}