1use region::RegionId;
2use serde::{Deserialize, Serialize};
3
4mod region;
5
6#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
7pub struct ConcEffect {
8 pub input: ConcType,
9 pub output: ConcType,
10}
11
12#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
16pub enum ConcType {
17 Number,
18 String,
19 Tuple(Vec<Self>),
20 Enum(Vec<Self>),
21 Function {
22 parameters: Vec<Self>,
23 body: Box<Self>,
24 },
25 Array(Box<Self>),
26 Set(Box<Self>),
27 Variable(String),
28 ForAll {
29 variable: String,
30 body: Box<Self>,
31 },
32 Effectful {
33 ty: Box<Self>,
34 effects: ConcEffectExpr,
35 },
36 Ref {
37 region: RegionId,
38 item: Box<Self>,
39 },
40 RefMut {
41 region: RegionId,
42 item: Box<Self>,
43 },
44 Label {
45 label: String,
47 item: Box<Self>,
48 },
49}
50
51impl ConcType {
52 pub fn needs_cast_to(&self, other: &Self) -> bool {
53 match (self, other) {
54 (x, y) if x == y => false,
55 (
56 ConcType::Effectful { ty, effects: _ },
57 ConcType::Effectful {
58 ty: ty2,
59 effects: _effects2,
60 },
61 ) if !ty.needs_cast_to(ty2) => false,
62 (ConcType::Label { label: _, item }, x) if !item.needs_cast_to(x) => false,
63 (x, ConcType::Label { label: _, item }) if !item.needs_cast_to(x) => false,
64 (ConcType::Enum(types), ConcType::Enum(types2)) => types
65 .iter()
66 .zip(types2.iter())
67 .any(|(x, y)| x.needs_cast_to(y)),
68 (ConcType::Tuple(types), ConcType::Tuple(types2)) => types
69 .iter()
70 .zip(types2.iter())
71 .any(|(x, y)| x.needs_cast_to(y)),
72 (x, ConcType::Effectful { ty, effects: _ }) if !x.needs_cast_to(ty) => false,
73 _ => true,
74 }
75 }
76}
77
78#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
79pub enum ConcEffectExpr {
80 Effects(Vec<ConcEffect>),
81 Add(Vec<ConcEffectExpr>),
82 Sub {
83 minuend: Box<ConcEffectExpr>,
84 subtrahend: Box<ConcEffectExpr>,
85 },
86 Apply {
87 function: Box<ConcType>,
88 arguments: Vec<ConcType>,
89 },
90}