1use crate::{prelude::CompileTimeEnv, span::Spanned, types::Type};
4
5#[derive(Debug, PartialEq)]
6pub enum Expr {
7 Bool(Box<ExprBool>),
8 Identifier(Box<ExprIdentifier>),
9 Call(Box<ExprCall>),
10 String(Box<ExprString>),
11 Number(Box<ExprNumber>),
12 Error,
13}
14
15impl Expr {
16 pub fn identifier(identifier: &str) -> Self {
17 Self::Identifier(Box::new(ExprIdentifier::new(identifier)))
18 }
19
20 pub fn identifier_with_type(identifier: &str, ty: Type) -> Self {
21 Self::Identifier(Box::new(ExprIdentifier(
22 identifier.to_string(),
23 ExprIdentifier::get_identifier_kind(identifier),
24 Some(ty),
25 )))
26 }
27
28 pub fn string(string: &str) -> Self {
29 Self::String(ExprString::new(string).into())
30 }
31
32 pub fn number(value: f64) -> Self {
33 Self::Number(ExprNumber::new(value).into())
34 }
35
36 pub fn call(callee: ExprS, args: Vec<ExprS>) -> Self {
37 Self::Call(Box::new(ExprCall {
38 callee: callee.into(),
39 args,
40 }))
41 }
42
43 pub fn bool(value: bool) -> Self {
44 Self::Bool(Box::new(ExprBool::new(value)))
45 }
46
47 pub fn get_type(&self) -> Type {
48 match self {
49 Expr::Bool(_) => Type::Bool,
50 Expr::Identifier(identifier) => identifier
51 .get_type()
52 .as_ref()
53 .unwrap_or(&Type::Unknown)
54 .clone(),
55 Expr::Call(_) => Type::Unknown,
56 Expr::String(_) => Type::String,
57 Expr::Number(_) => Type::Number,
58 Expr::Error => Type::Unknown,
59 }
60 }
61}
62
63#[derive(Debug, PartialEq)]
64pub struct ExprIdentifier(pub String, pub IdentifierKind, pub Option<Type>);
65
66impl ExprIdentifier {
67 pub fn new(identifier: &str) -> Self {
68 Self(
69 identifier.to_string(),
70 Self::get_identifier_kind(identifier),
71 None,
72 )
73 }
74
75 pub fn get_identifier_kind(identifier: &str) -> IdentifierKind {
76 let identifier_prefix = &identifier[..1];
77
78 match identifier_prefix {
79 "?" => IdentifierKind::Prompt,
80 "!" => IdentifierKind::Secret,
81 ":" => IdentifierKind::Var,
82 "@" => IdentifierKind::Client,
83 _ => {
84 let prefix_char: char = identifier_prefix.chars().nth(0).unwrap();
85
86 if prefix_char.is_uppercase() {
87 IdentifierKind::Type
88 } else {
89 IdentifierKind::Builtin
90 }
91 }
92 }
93 }
94
95 pub fn full_name(&self) -> &str {
100 &self.0
101 }
102
103 pub fn lookup_name(&self) -> &str {
117 match self.identifier_kind() {
118 IdentifierKind::Builtin => &self.0,
119 IdentifierKind::Var => &self.0[1..],
120 IdentifierKind::Prompt => &self.0[1..],
121 IdentifierKind::Secret => &self.0[1..],
122 IdentifierKind::Client => &self.0[1..],
123 IdentifierKind::Type => &self.0,
124 }
125 }
126
127 pub fn identifier_kind(&self) -> &IdentifierKind {
128 &self.1
129 }
130
131 pub fn get_type(&self) -> &Option<Type> {
132 &self.2
133 }
134}
135
136#[derive(Debug, PartialEq)]
137pub enum IdentifierKind {
138 Builtin,
139 Var,
140 Prompt,
141 Secret,
142 Client,
143 Type,
144}
145
146#[derive(Debug, PartialEq)]
147pub struct ExprString(pub String);
148
149impl ExprString {
150 pub fn new(string: &str) -> Self {
151 Self(string.to_string())
152 }
153}
154
155#[derive(Debug, PartialEq)]
156pub struct ExprNumber(pub f64);
157
158impl ExprNumber {
159 pub fn new(value: f64) -> Self {
160 Self(value)
161 }
162}
163
164#[derive(Debug, PartialEq)]
165pub struct ExprCall {
166 pub callee: Box<ExprS>,
167 pub args: Vec<ExprS>,
168}
169
170#[derive(Debug, PartialEq)]
171pub struct ExprBool(pub bool);
172
173impl ExprBool {
174 pub fn new(value: bool) -> Self {
175 Self(value)
176 }
177}
178
179pub type ExprS = Spanned<Expr>;
180
181pub fn add_type_to_expr_parse(expr: &mut Expr) {
182 match expr {
183 Expr::Identifier(expr_identifier) => match expr_identifier.identifier_kind() {
184 IdentifierKind::Builtin => {}
185 IdentifierKind::Var => {
186 expr_identifier.2 = Some(Type::String);
187 }
188 IdentifierKind::Prompt => {
189 expr_identifier.2 = Some(Type::String);
190 }
191 IdentifierKind::Secret => {
192 expr_identifier.2 = Some(Type::String);
193 }
194 IdentifierKind::Client => {
195 expr_identifier.2 = Some(Type::Value);
196 }
197 IdentifierKind::Type => {
198 }
200 },
201 Expr::Call(expr_call) => {
202 for arg in &mut expr_call.args {
203 add_type_to_expr_parse(&mut arg.0);
204 }
205 }
206 _ => {}
207 }
208}
209
210pub fn add_type_to_expr(expr: &mut Expr, env: &CompileTimeEnv) {
211 match expr {
212 Expr::Identifier(expr_identifier) => match expr_identifier.identifier_kind() {
213 IdentifierKind::Builtin => {
214 if let Some((_, index)) = env.get_builtin_index(expr_identifier.lookup_name()) {
215 if let Some(v) = env.get_builtin(index as usize) {
216 let v_type: Type = v.clone().into();
217
218 expr_identifier.2 = Some(v_type);
219 }
220 } else if let Some((_, index)) =
221 env.get_user_builtin_index(expr_identifier.lookup_name())
222 {
223 if let Some(v) = env.get_builtin(index as usize) {
224 let v_type: Type = v.clone().into();
225
226 expr_identifier.2 = Some(v_type);
227 }
228 }
229 }
230 IdentifierKind::Var => {
231 let index = env.get_var_index(expr_identifier.lookup_name());
232
233 if index.is_some() {
234 expr_identifier.2 = Some(Type::String);
235 }
236 }
237 IdentifierKind::Prompt => {
238 let index = env.get_prompt_index(expr_identifier.lookup_name());
239
240 if index.is_some() {
241 expr_identifier.2 = Some(Type::String);
242 }
243 }
244 IdentifierKind::Secret => {
245 let index = env.get_secret_index(expr_identifier.lookup_name());
246
247 if index.is_some() {
248 expr_identifier.2 = Some(Type::String);
249 }
250 }
251 IdentifierKind::Client => {
252 let index = env.get_client_context_index(expr_identifier.lookup_name());
253
254 if index.is_some() {
255 expr_identifier.2 = Some(Type::String);
256 }
257 }
258 IdentifierKind::Type => {
259 }
261 },
262 Expr::Call(expr_call) => {
263 for arg in &mut expr_call.args {
264 add_type_to_expr(&mut arg.0, env);
265 }
266 }
267 _ => {}
268 }
269}