1use id_arena::Id;
2use num_bigint::BigInt;
3use smol_str::SmolStr;
4
5use crate::db::MirDb;
6
7use super::{
8 constant::ConstantId,
9 function::BodyDataStore,
10 inst::InstId,
11 types::{TypeId, TypeKind},
12 SourceInfo,
13};
14
15pub type ValueId = Id<Value>;
16
17#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18pub enum Value {
19 Temporary { inst: InstId, ty: TypeId },
21
22 Local(Local),
24
25 Immediate { imm: BigInt, ty: TypeId },
27
28 Constant { constant: ConstantId, ty: TypeId },
30
31 Unit { ty: TypeId },
33}
34
35impl Value {
36 pub fn ty(&self) -> TypeId {
37 match self {
38 Self::Local(val) => val.ty,
39 Self::Immediate { ty, .. }
40 | Self::Temporary { ty, .. }
41 | Self::Unit { ty }
42 | Self::Constant { ty, .. } => *ty,
43 }
44 }
45
46 pub fn is_imm(&self) -> bool {
47 matches!(self, Self::Immediate { .. })
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash)]
52pub enum AssignableValue {
53 Value(ValueId),
54 Aggregate {
55 lhs: Box<AssignableValue>,
56 idx: ValueId,
57 },
58 Map {
59 lhs: Box<AssignableValue>,
60 key: ValueId,
61 },
62}
63
64impl From<ValueId> for AssignableValue {
65 fn from(value: ValueId) -> Self {
66 Self::Value(value)
67 }
68}
69
70impl AssignableValue {
71 pub fn ty(&self, db: &dyn MirDb, store: &BodyDataStore) -> TypeId {
72 match self {
73 Self::Value(value) => store.value_ty(*value),
74 Self::Aggregate { lhs, idx } => {
75 let lhs_ty = lhs.ty(db, store);
76 lhs_ty.projection_ty(db, store.value_data(*idx))
77 }
78 Self::Map { lhs, .. } => {
79 let lhs_ty = lhs.ty(db, store).deref(db);
80 match lhs_ty.data(db).kind {
81 TypeKind::Map(def) => def.value_ty.make_sptr(db),
82 _ => unreachable!(),
83 }
84 }
85 }
86 }
87
88 pub fn value_id(&self) -> Option<ValueId> {
89 match self {
90 Self::Value(value) => Some(*value),
91 _ => None,
92 }
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Hash)]
97pub struct Local {
98 pub name: SmolStr,
100
101 pub ty: TypeId,
102
103 pub is_arg: bool,
105
106 pub is_tmp: bool,
108
109 pub source: SourceInfo,
110}
111
112impl Local {
113 pub fn user_local(name: SmolStr, ty: TypeId, source: SourceInfo) -> Local {
114 Self {
115 name,
116 ty,
117 is_arg: false,
118 is_tmp: false,
119 source,
120 }
121 }
122
123 pub fn arg_local(name: SmolStr, ty: TypeId, source: SourceInfo) -> Local {
124 Self {
125 name,
126 ty,
127 is_arg: true,
128 is_tmp: false,
129 source,
130 }
131 }
132
133 pub fn tmp_local(name: SmolStr, ty: TypeId) -> Local {
134 Self {
135 name,
136 ty,
137 is_arg: false,
138 is_tmp: true,
139 source: SourceInfo::dummy(),
140 }
141 }
142}