1use std::{ops::Range, str::FromStr};
2
3use lalrpop_util::ParseError;
4
5use crate::lexer::{tokens, ErrorTip, LexicalError};
6
7pub type Location = std::ops::Range<usize>;
8pub mod context;
9
10#[derive(Clone, Copy, Debug, PartialEq)]
11pub enum VarType {
12 I8,
13 I16,
14 I32,
15 I64,
16 U8,
17 U16,
18 U32,
19 U64,
20 Bool,
21 F32,
22 F64,
23 Str,
24 Void,
25 Ptr,
26}
27
28impl std::fmt::Display for VarType {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match self {
31 VarType::I8 => write!(f, "i8"),
32 VarType::I16 => write!(f, "i16"),
33 VarType::I32 => write!(f, "i32"),
34 VarType::I64 => write!(f, "i64"),
35 VarType::U8 => write!(f, "u8"),
36 VarType::U16 => write!(f, "u16"),
37 VarType::U32 => write!(f, "u32"),
38 VarType::U64 => write!(f, "u64"),
39 VarType::Bool => write!(f, "bool"),
40 VarType::F32 => write!(f, "f32"),
41 VarType::F64 => write!(f, "f64"),
42 VarType::Str => write!(f, "str"),
43 VarType::Void => write!(f, "void"),
44 VarType::Ptr => write!(f, "ptr"),
45 }
46 }
47}
48
49impl FromStr for VarType {
50 type Err = String;
51
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 match s {
54 "i8" => Ok(VarType::I8),
55 "i16" => Ok(VarType::I16),
56 "i32" => Ok(VarType::I32),
57 "i64" => Ok(VarType::I64),
58 "u8" => Ok(VarType::U8),
59 "u16" => Ok(VarType::U16),
60 "u32" => Ok(VarType::U32),
61 "u64" => Ok(VarType::U64),
62 "bool" => Ok(VarType::Bool),
63 "f32" => Ok(VarType::F32),
64 "f64" => Ok(VarType::F64),
65 "str" => Ok(VarType::Str),
66 "ptr" => Ok(VarType::Ptr),
67 "void" => Ok(VarType::Void),
68 _ => Err(format!("Invalid type: {}", s)),
69 }
70 }
71}
72
73impl From<String> for VarType {
74 fn from(s: String) -> Self {
75 s.as_str().parse().unwrap()
76 }
77}
78
79impl From<VarType> for String {
80 fn from(value: VarType) -> Self {
81 match value {
82 VarType::I8 => "i8".to_string(),
83 VarType::I16 => "i16".to_string(),
84 VarType::I32 => "i32".to_string(),
85 VarType::I64 => "i64".to_string(),
86 VarType::U8 => "u8".to_string(),
87 VarType::U16 => "u16".to_string(),
88 VarType::U32 => "u32".to_string(),
89 VarType::U64 => "u64".to_string(),
90 VarType::Bool => "bool".to_string(),
91 VarType::F32 => "f32".to_string(),
92 VarType::F64 => "f64".to_string(),
93 VarType::Str => "str".to_string(),
94 VarType::Void => "void".to_string(),
95 VarType::Ptr => "ptr".to_string(),
96 }
97 }
98}
99
100#[derive(Clone, Debug, PartialEq)]
101pub enum Statement {
102 VariableDeclaration(Variable),
103
104 ConditionalJump {
106 condition: Expr,
107 label: String,
108 location: Location,
109 },
110
111 UnconditionalJump {
113 label: String,
114 location: Location,
115 },
116
117 Label {
119 name: String,
120 location: Location,
121 },
122
123 FunctionDefinition(Function),
124
125 Store {
127 at: Operand,
128 from: Operand,
129 location: Location,
130 },
131
132 Call(FunctionCall),
133
134 NoOperation,
135}
136
137#[derive(Clone, Debug, PartialEq)]
138pub struct FunctionCall {
139 pub name: String,
140 pub params: Vec<Operand>,
141 pub return_type: VarType,
142 pub location: Location,
143}
144
145#[derive(Clone, Debug, PartialEq)]
146pub struct Variable {
147 pub var_type: VarType,
148 pub name: String,
149 pub value: Expr,
150 pub location: Location,
151}
152
153#[derive(Clone, Debug, PartialEq)]
154pub struct Function {
155 pub name: String,
156 pub location: Location,
157 pub args: Vec<Argument>,
158 pub body: Vec<Statement>,
159 pub return_type: VarType,
160 pub is_builtin: bool,
161}
162
163#[derive(Clone, Debug, PartialEq)]
166pub enum Expr {
167 BinaryOperation(BinaryOperation),
168 FunctionCall(FunctionCall),
169 Operand(Operand),
170}
171
172#[derive(Clone, Debug, PartialEq)]
175pub struct Return {
176 pub var_type: VarType,
177}
178
179#[derive(Clone, Debug, PartialEq)]
180pub struct Argument {
181 pub name: String,
182 pub var_type: VarType,
183}
184
185#[derive(Clone, Debug, PartialEq)]
186pub enum BinaryOperation {
187 Arithmetic {
188 lhs: Operand,
189 operator: Operator,
190 rhs: Operand,
191 operation_type: VarType,
192 },
193 Conditional {
194 lhs: Operand,
195 condition: Condition,
196 rhs: Operand,
197 operation_type: VarType,
198 },
199}
200
201#[derive(Clone, Debug, PartialEq)]
202pub enum Operand {
203 Identifier(String),
204 Dereference(String),
205 LiteralStr(String),
206 LiteralBool(bool),
207 LiteralI8(i8),
208 LiteralI16(i16),
209 LiteralI32(i32),
210 LiteralI64(i64),
211 LiteralU8(u8),
212 LiteralU16(u16),
213 LiteralU32(u32),
214 LiteralU64(u64),
215 LiteralF32(f32),
216 LiteralF64(f64),
217}
218
219impl Operand {
220 pub fn as_identifier(&self) -> Result<&str, String> {
221 Ok(match self {
222 Operand::Identifier(name) => name,
223 _ => return Err("Expected register, found immediate".to_string()),
224 })
225 }
226
227 pub fn as_immediate(&self) -> Result<i32, String> {
228 Ok(match self {
229 Operand::LiteralI8(val) => *val as i32,
230 Operand::LiteralI16(val) => *val as i32,
231 Operand::LiteralI32(val) => *val as i32,
232 Operand::LiteralI64(val) => *val as i32,
233 Operand::LiteralU8(val) => *val as i32,
234 Operand::LiteralU16(val) => *val as i32,
235 Operand::LiteralU32(val) => *val as i32,
236 Operand::LiteralU64(val) => *val as i32,
237 Operand::LiteralF32(val) => *val as i32,
238 Operand::LiteralF64(val) => *val as i32,
239 Operand::LiteralBool(val) => *val as i32,
240 _ => return Err("Expected immediate, found register".to_string()),
241 })
242 }
243
244 pub fn get_type(
245 &self,
246 context: &context::Context,
247 loc: Range<usize>,
248 ) -> Result<VarType, ParseError<usize, tokens::Token, LexicalError>> {
249 match self {
250 Operand::Identifier(variable_name) => {
251 let var = context
252 .get_variable(variable_name.clone())
253 .ok_or(ParseError::<usize, tokens::Token, LexicalError>::User {
254 error: LexicalError::UnknownVariable {
255 error: vec![ErrorTip {
256 message: format!("unknown variable `{}`", variable_name),
257 location: loc,
258 }],
259 help: None,
260 },
261 })?;
262
263 Ok(var.var_type)
264 }
265 Operand::LiteralStr(_) => Ok(VarType::Str),
266 Operand::LiteralU8(_) => Ok(VarType::U8),
267 Operand::LiteralU16(_) => Ok(VarType::U16),
268 Operand::LiteralU32(_) => Ok(VarType::U32),
269 Operand::LiteralU64(_) => Ok(VarType::U64),
270 Operand::LiteralI8(_) => Ok(VarType::I8),
271 Operand::LiteralI16(_) => Ok(VarType::I16),
272 Operand::LiteralI32(_) => Ok(VarType::I32),
273 Operand::LiteralI64(_) => Ok(VarType::I64),
274 Operand::LiteralBool(_) => Ok(VarType::Bool),
275 Operand::LiteralF32(_) => Ok(VarType::F32),
276 Operand::LiteralF64(_) => Ok(VarType::F64),
277 Operand::Dereference(_) => Ok(VarType::Ptr),
278 }
279 }
280}
281
282impl TryFrom<Operand> for VarType {
283 type Error = String;
284
285 fn try_from(operand: Operand) -> Result<Self, Self::Error> {
286 match operand {
287 Operand::Identifier(_) => Err("Cannot convert identifier to type".to_string()),
288 Operand::LiteralStr(_) => Ok(VarType::Str),
289 Operand::LiteralU8(_) => Ok(VarType::U8),
290 Operand::LiteralU16(_) => Ok(VarType::U16),
291 Operand::LiteralU32(_) => Ok(VarType::U32),
292 Operand::LiteralU64(_) => Ok(VarType::U64),
293 Operand::LiteralI8(_) => Ok(VarType::I8),
294 Operand::LiteralI16(_) => Ok(VarType::I16),
295 Operand::LiteralI32(_) => Ok(VarType::I32),
296 Operand::LiteralI64(_) => Ok(VarType::I64),
297 Operand::LiteralBool(_) => Ok(VarType::Bool),
298 Operand::LiteralF32(_) => Ok(VarType::F32),
299 Operand::LiteralF64(_) => Ok(VarType::F64),
300 Operand::Dereference(_) => Ok(VarType::Ptr),
301 }
302 }
303}
304
305impl std::fmt::Display for Operand {
306 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
307 match self {
308 Operand::Identifier(name) => write!(f, "{}", name),
309 Operand::LiteralStr(value) => write!(f, "{}", value),
310 Operand::LiteralBool(value) => write!(f, "{}", value),
311 Operand::LiteralI8(value) => write!(f, "{}", value),
312 Operand::LiteralI16(value) => write!(f, "{}", value),
313 Operand::LiteralI32(value) => write!(f, "{}", value),
314 Operand::LiteralI64(value) => write!(f, "{}", value),
315 Operand::LiteralU8(value) => write!(f, "{}", value),
316 Operand::LiteralU16(value) => write!(f, "{}", value),
317 Operand::LiteralU32(value) => write!(f, "{}", value),
318 Operand::LiteralU64(value) => write!(f, "{}", value),
319 Operand::LiteralF32(value) => write!(f, "{}", value),
320 Operand::LiteralF64(value) => write!(f, "{}", value),
321 Operand::Dereference(value) => write!(f, "*{}", value),
322 }
323 }
324}
325
326#[derive(Clone, Debug, PartialEq)]
327pub enum Operator {
328 Add,
329 Sub,
330 Mul,
331 Div,
332}
333
334impl std::fmt::Display for Operator {
335 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
336 match self {
337 Operator::Add => write!(f, "+"),
338 Operator::Sub => write!(f, "-"),
339 Operator::Mul => write!(f, "*"),
340 Operator::Div => write!(f, "/"),
341 }
342 }
343}
344
345#[derive(Clone, Debug, PartialEq)]
346pub enum Condition {
347 LessThan,
348 GreaterThan,
349 LessThanOrEqual,
350 GreaterThanOrEqual,
351 Equal,
352 NotEqual,
353 And,
354 Or,
355}