fusabi_frontend/
typed_ast.rs1use crate::ast::{Expr, Pattern};
12use crate::types::Type;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct Span {
17 pub start: usize,
19 pub end: usize,
21 pub line: usize,
23 pub column: usize,
25}
26
27impl Span {
28 pub fn new(start: usize, end: usize, line: usize, column: usize) -> Self {
30 Span {
31 start,
32 end,
33 line,
34 column,
35 }
36 }
37
38 pub fn from_offsets(start: usize, end: usize) -> Self {
40 Span {
41 start,
42 end,
43 line: 1,
44 column: 1,
45 }
46 }
47
48 pub fn combine(&self, other: &Span) -> Span {
50 Span {
51 start: self.start.min(other.start),
52 end: self.end.max(other.end),
53 line: self.line.min(other.line),
54 column: self.column.min(other.column),
55 }
56 }
57}
58
59#[derive(Debug, Clone)]
63pub struct TypedExpr {
64 pub expr: Expr,
66 pub ty: Type,
68 pub span: Option<Span>,
70}
71
72impl TypedExpr {
73 pub fn new(expr: Expr, ty: Type) -> Self {
75 TypedExpr {
76 expr,
77 ty,
78 span: None,
79 }
80 }
81
82 pub fn with_span(expr: Expr, ty: Type, span: Span) -> Self {
84 TypedExpr {
85 expr,
86 ty,
87 span: Some(span),
88 }
89 }
90
91 pub fn get_type(&self) -> &Type {
93 &self.ty
94 }
95
96 pub fn get_expr(&self) -> &Expr {
98 &self.expr
99 }
100
101 pub fn get_span(&self) -> Option<&Span> {
103 self.span.as_ref()
104 }
105
106 pub fn into_expr(self) -> Expr {
108 self.expr
109 }
110}
111
112#[derive(Debug, Clone)]
116pub struct TypedPattern {
117 pub pattern: Pattern,
119 pub ty: Type,
121}
122
123impl TypedPattern {
124 pub fn new(pattern: Pattern, ty: Type) -> Self {
126 TypedPattern { pattern, ty }
127 }
128
129 pub fn get_type(&self) -> &Type {
131 &self.ty
132 }
133
134 pub fn get_pattern(&self) -> &Pattern {
136 &self.pattern
137 }
138
139 pub fn into_pattern(self) -> Pattern {
141 self.pattern
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use crate::ast::Literal;
149
150 #[test]
151 fn test_span_new() {
152 let span = Span::new(0, 10, 1, 1);
153 assert_eq!(span.start, 0);
154 assert_eq!(span.end, 10);
155 assert_eq!(span.line, 1);
156 assert_eq!(span.column, 1);
157 }
158
159 #[test]
160 fn test_span_from_offsets() {
161 let span = Span::from_offsets(5, 15);
162 assert_eq!(span.start, 5);
163 assert_eq!(span.end, 15);
164 }
165
166 #[test]
167 fn test_span_combine() {
168 let span1 = Span::new(0, 5, 1, 1);
169 let span2 = Span::new(10, 15, 1, 11);
170 let combined = span1.combine(&span2);
171 assert_eq!(combined.start, 0);
172 assert_eq!(combined.end, 15);
173 }
174
175 #[test]
176 fn test_typed_expr_new() {
177 let expr = Expr::Lit(Literal::Int(42));
178 let ty = Type::Int;
179 let typed = TypedExpr::new(expr.clone(), ty.clone());
180 assert_eq!(typed.get_type(), &ty);
181 assert_eq!(typed.get_expr(), &expr);
182 assert!(typed.get_span().is_none());
183 }
184
185 #[test]
186 fn test_typed_expr_with_span() {
187 let expr = Expr::Lit(Literal::Bool(true));
188 let ty = Type::Bool;
189 let span = Span::new(0, 4, 1, 1);
190 let typed = TypedExpr::with_span(expr, ty.clone(), span);
191 assert_eq!(typed.get_type(), &ty);
192 assert!(typed.get_span().is_some());
193 }
194
195 #[test]
196 fn test_typed_expr_into_expr() {
197 let expr = Expr::Lit(Literal::Int(42));
198 let ty = Type::Int;
199 let typed = TypedExpr::new(expr.clone(), ty);
200 let untyped = typed.into_expr();
201 assert_eq!(untyped, expr);
202 }
203
204 #[test]
205 fn test_typed_pattern_new() {
206 let pattern = Pattern::Wildcard;
207 let ty = Type::Int;
208 let typed = TypedPattern::new(pattern.clone(), ty.clone());
209 assert_eq!(typed.get_type(), &ty);
210 assert_eq!(typed.get_pattern(), &pattern);
211 }
212
213 #[test]
214 fn test_typed_pattern_into_pattern() {
215 let pattern = Pattern::Var("x".to_string());
216 let ty = Type::String;
217 let typed = TypedPattern::new(pattern.clone(), ty);
218 let untyped = typed.into_pattern();
219 assert_eq!(untyped, pattern);
220 }
221}