1use std::rc::Rc;
2
3use petr_utils::{Identifier, Path, SpannedItem};
4
5use crate::comments::Commented;
6
7pub struct Ast {
9 pub modules: Vec<Module>,
10}
11
12impl std::fmt::Debug for Ast {
13 fn fmt(
14 &self,
15 f: &mut std::fmt::Formatter<'_>,
16 ) -> std::fmt::Result {
17 writeln!(f, "AST")?;
18 for module in self.modules.iter() {
19 let path = module.name.iter().map(|x| format!("{}", x.id)).collect::<Vec<_>>().join(".");
20 writeln!(f, "Module: {path}")?;
21 for node in module.nodes.iter() {
22 match node.item() {
23 AstNode::FunctionDeclaration(fun) => writeln!(f, " Function: {}", fun.item().name.id)?,
24 AstNode::TypeDeclaration(ty) => writeln!(f, " Type: {}", ty.item().name.id)?,
25 AstNode::ImportStatement(i) => writeln!(
26 f,
27 " Import: {}",
28 i.item().path.iter().map(|x| format!("{}", x.id)).collect::<Vec<_>>().join(".")
29 )?,
30 }
31 }
32 }
33 Ok(())
34 }
35}
36
37pub struct Module {
38 pub name: Path,
39 pub nodes: Vec<SpannedItem<AstNode>>,
40}
41impl Module {
42 fn span_pointing_to_beginning_of_module(&self) -> petr_utils::Span {
43 let first = self.nodes.first().expect("Module was empty");
44 let span = first.span();
45 span.zero_length()
47 }
48}
49
50impl Ast {
51 pub fn new(nodes: Vec<Module>) -> Ast {
52 Self { modules: nodes }
53 }
54
55 pub fn span_pointing_to_beginning_of_ast(&self) -> petr_utils::Span {
57 let first = self.modules.first().expect("AST was empty");
58 first.span_pointing_to_beginning_of_module()
59 }
60}
61
62pub enum AstNode {
63 FunctionDeclaration(Commented<FunctionDeclaration>),
64 TypeDeclaration(Commented<TypeDeclaration>),
65 ImportStatement(Commented<ImportStatement>),
66}
67
68pub struct ImportStatement {
69 pub path: Path,
70 pub alias: Option<Identifier>,
71 pub visibility: Visibility,
72}
73impl ImportStatement {
74 pub fn is_exported(&self) -> bool {
75 self.visibility == Visibility::Exported
76 }
77}
78
79#[derive(Clone)]
80pub struct TypeDeclaration {
81 pub name: Identifier,
82 pub variants: Box<[SpannedItem<TypeVariant>]>,
83 pub visibility: Visibility,
84}
85
86impl TypeDeclaration {
87 pub fn is_exported(&self) -> bool {
88 self.visibility == Visibility::Exported
89 }
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub enum Visibility {
94 Local,
95 Exported,
96}
97
98#[derive(Clone)]
99pub struct TypeVariant {
100 pub name: Identifier,
101 pub fields: Box<[SpannedItem<TypeField>]>,
102}
103
104#[derive(Clone)]
105pub struct TypeField {
106 pub name: Identifier,
107 pub ty: Ty,
108}
109
110#[derive(Clone)]
111pub struct FunctionDeclaration {
112 pub name: Identifier,
113 pub parameters: Box<[FunctionParameter]>,
114 pub return_type: Ty,
115 pub body: SpannedItem<Expression>,
116 pub visibility: Visibility,
117}
118impl FunctionDeclaration {
119 pub fn is_exported(&self) -> bool {
120 self.visibility == Visibility::Exported
121 }
122}
123
124#[derive(Clone)]
125pub enum Expression {
126 Literal(Literal),
127 List(List),
128 Operator(Box<OperatorExpression>),
129 FunctionCall(FunctionCall),
130 Variable(Identifier),
131 IntrinsicCall(IntrinsicCall),
132 Binding(ExpressionWithBindings),
133 TypeConstructor(petr_utils::TypeId, Box<[SpannedItem<Expression>]>),
134}
135
136#[derive(Clone)]
137pub struct ExpressionWithBindings {
138 pub bindings: Vec<Binding>,
139 pub expression: Box<SpannedItem<Expression>>,
140 pub expr_id: ExprId,
141}
142
143#[derive(Clone, Debug, PartialOrd, Ord, Eq, PartialEq, Copy)]
144pub struct ExprId(pub usize);
145
146#[derive(Clone)]
147pub struct Binding {
148 pub name: Identifier,
149 pub val: SpannedItem<Expression>,
150}
151
152#[derive(Clone)]
153pub struct IntrinsicCall {
154 pub intrinsic: Intrinsic,
155 pub args: Box<[SpannedItem<Expression>]>,
156}
157
158impl std::fmt::Display for Intrinsic {
159 fn fmt(
160 &self,
161 f: &mut std::fmt::Formatter<'_>,
162 ) -> std::fmt::Result {
163 match self {
164 Intrinsic::Puts => write!(f, "puts"),
165 Intrinsic::Add => write!(f, "add"),
166 Intrinsic::Subtract => write!(f, "subtract"),
167 Intrinsic::Multiply => write!(f, "multiply"),
168 Intrinsic::Divide => write!(f, "divide"),
169 Intrinsic::Malloc => write!(f, "malloc"),
170 }
171 }
172}
173
174#[derive(Clone, Debug)]
175pub enum Intrinsic {
176 Puts,
178 Add,
179 Subtract,
180 Multiply,
181 Divide,
182 Malloc,
183}
184
185#[derive(Clone)]
186pub struct FunctionCall {
187 pub func_name: Path,
188 pub args: Box<[SpannedItem<Expression>]>,
189 pub args_were_parenthesized: bool,
191}
192
193#[derive(Clone)]
194pub struct VariableExpression {
195 pub name: Identifier,
196}
197#[derive(Clone)]
198pub struct List {
199 pub elements: Box<[Commented<SpannedItem<Expression>>]>,
200}
201
202#[derive(Clone, Debug)]
203pub enum Literal {
204 Integer(i64),
205 Boolean(bool),
206 String(Rc<str>),
207}
208
209impl std::fmt::Display for Literal {
210 fn fmt(
211 &self,
212 f: &mut std::fmt::Formatter<'_>,
213 ) -> std::fmt::Result {
214 match self {
215 Literal::Integer(i) => write!(f, "{}", i),
216 Literal::Boolean(b) => write!(f, "{}", b),
217 Literal::String(s) => write!(f, "\"{}\"", s),
218 }
219 }
220}
221
222#[derive(Clone)]
223pub struct OperatorExpression {
224 pub lhs: SpannedItem<Expression>,
225 pub rhs: SpannedItem<Expression>,
226 pub op: SpannedItem<Operator>,
227}
228
229#[derive(Clone, Debug, Copy)]
230pub struct FunctionParameter {
231 pub name: Identifier,
232 pub ty: Ty,
233}
234
235#[derive(Clone, Copy, Debug)]
236pub enum Ty {
237 Int,
238 Bool,
239 Named(Identifier),
240 String,
241 Unit,
242}
243
244#[derive(Clone)]
245pub enum Operator {
246 Plus,
247 Minus,
248 Star,
249 Slash,
250}
251
252impl Operator {
253 pub fn as_str(&self) -> &'static str {
254 match self {
255 Operator::Plus => "+",
256 Operator::Minus => "-",
257 Operator::Star => "*",
258 Operator::Slash => "/",
259 }
260 }
261}
262
263#[derive(Clone)]
264pub struct Comment {
265 pub content: Rc<str>,
266}
267
268impl Comment {
269 pub fn new(item: impl AsRef<str>) -> Self {
270 Self {
271 content: Rc::from(item.as_ref()),
272 }
273 }
274}