1use std::fmt;
8
9use crate::loc::Loc;
10
11pub struct Program<'a> {
12 pub items: Vec<TopLevelItem<'a>>,
13}
14
15impl<'a> Program<'a> {
16 pub fn imports(&self) -> impl Iterator<Item = &Loc<Import<'a>>> {
17 self.items.iter().filter_map(|item| match item {
18 TopLevelItem::Import(import) => Some(import),
19 _ => None,
20 })
21 }
22
23 pub fn functions(&self) -> impl Iterator<Item = &Loc<Function<'a>>> {
24 self.items.iter().filter_map(|item| match item {
25 TopLevelItem::Function(function) => Some(function),
26 _ => None,
27 })
28 }
29}
30
31pub enum TopLevelItem<'a> {
32 Import(Loc<Import<'a>>),
33 Function(Loc<Function<'a>>),
34 Comment(Loc<&'a str>),
35 Newline(Loc<()>),
36}
37
38pub struct ImportedFunctionAlias<'a> {
39 pub as_token: Loc<()>,
40 pub name: Loc<&'a str>,
41}
42
43pub struct ImportedFunction<'a> {
44 pub name: Loc<&'a str>,
45 pub alias: Option<Loc<ImportedFunctionAlias<'a>>>,
46}
47
48pub struct Import<'a> {
49 pub from_token: Loc<()>,
50 pub path: Loc<&'a str>,
51 pub import_token: Loc<()>,
52 pub imported_functions: Vec<Loc<ImportedFunction<'a>>>,
53}
54
55pub struct Function<'a> {
56 pub name: Loc<&'a str>,
57 pub parameters: Vec<(Loc<&'a str>, Loc<TypeAnnotation>)>,
58 pub return_type: Option<Loc<TypeAnnotation>>,
59 pub body: Vec<Loc<FunctionCode<'a>>>,
60}
61
62pub enum FunctionCode<'a> {
63 Label {
64 label: Loc<Label<'a>>,
65 colon_token: Loc<()>,
66 comment: Option<Loc<&'a str>>,
67 },
68 Instruction {
69 inner: Loc<Instruction<'a>>,
70 comment: Option<Loc<&'a str>>,
71 },
72 Comment(Loc<&'a str>),
73 EmptyLine(Loc<()>),
74}
75
76pub struct Label<'a> {
77 pub name: Loc<&'a str>,
78}
79
80#[derive(Debug, Clone)]
81pub enum Type {
82 Int,
83 Bool,
84 Float,
85 Char,
86 Ptr(Box<Loc<Type>>),
87}
88
89impl Type {
90 pub fn is_same_type_as(&self, other: &Self) -> bool {
91 match (self, other) {
92 (Type::Int, Type::Int)
93 | (Type::Bool, Type::Bool)
94 | (Type::Float, Type::Float)
95 | (Type::Char, Type::Char) => true,
96 (Type::Ptr(inner), Type::Ptr(inner2)) => inner.is_same_type_as(inner2),
97 _ => false,
98 }
99 }
100}
101
102impl fmt::Display for Type {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 match self {
105 Type::Int => "int".fmt(f),
106 Type::Bool => "bool".fmt(f),
107 Type::Float => "float".fmt(f),
108 Type::Char => "char".fmt(f),
109 Type::Ptr(inner) => write!(f, "ptr<{}>", inner),
110 }
111 }
112}
113
114pub struct TypeAnnotation {
115 pub colon_token: Loc<()>,
116 pub ty: Loc<Type>,
117}
118
119pub enum Instruction<'a> {
120 Constant(Loc<Constant<'a>>),
121 ValueOperation(Loc<ValueOperation<'a>>),
122 EffectOperation(Loc<EffectOperation<'a>>),
123}
124
125pub enum ConstantValue {
126 IntegerLiteral(Loc<i64>),
127 BooleanLiteral(Loc<bool>),
128 FloatLiteral(Loc<f64>),
129 CharacterLiteral(Loc<char>),
130}
131
132pub struct Constant<'a> {
133 pub name: Loc<&'a str>,
134 pub type_annotation: Option<Loc<TypeAnnotation>>,
135 pub equals_token: Loc<()>,
136 pub const_token: Loc<()>,
137 pub value: Loc<ConstantValue>,
138 pub semi_token: Loc<()>,
139}
140
141pub enum ValueOperationOp<'a> {
142 Add(Loc<&'a str>, Loc<&'a str>),
143 Mul(Loc<&'a str>, Loc<&'a str>),
144 Sub(Loc<&'a str>, Loc<&'a str>),
145 Div(Loc<&'a str>, Loc<&'a str>),
146
147 Eq(Loc<&'a str>, Loc<&'a str>),
148 Lt(Loc<&'a str>, Loc<&'a str>),
149 Gt(Loc<&'a str>, Loc<&'a str>),
150 Le(Loc<&'a str>, Loc<&'a str>),
151 Ge(Loc<&'a str>, Loc<&'a str>),
152
153 Not(Loc<&'a str>),
154 And(Loc<&'a str>, Loc<&'a str>),
155 Or(Loc<&'a str>, Loc<&'a str>),
156
157 Call(Loc<&'a str>, Vec<Loc<&'a str>>),
159 Id(Loc<&'a str>),
160
161 Fadd(Loc<&'a str>, Loc<&'a str>),
162 Fmul(Loc<&'a str>, Loc<&'a str>),
163 Fsub(Loc<&'a str>, Loc<&'a str>),
164 Fdiv(Loc<&'a str>, Loc<&'a str>),
165 Feq(Loc<&'a str>, Loc<&'a str>),
166 Flt(Loc<&'a str>, Loc<&'a str>),
167 Fle(Loc<&'a str>, Loc<&'a str>),
168 Fgt(Loc<&'a str>, Loc<&'a str>),
169 Fge(Loc<&'a str>, Loc<&'a str>),
170
171 Alloc(Loc<&'a str>),
172 Load(Loc<&'a str>),
173 PtrAdd(Loc<&'a str>, Loc<&'a str>),
174
175 Ceq(Loc<&'a str>, Loc<&'a str>),
176 Clt(Loc<&'a str>, Loc<&'a str>),
177 Cgt(Loc<&'a str>, Loc<&'a str>),
178 Cle(Loc<&'a str>, Loc<&'a str>),
179 Cge(Loc<&'a str>, Loc<&'a str>),
180 Char2Int(Loc<&'a str>),
181 Int2Char(Loc<&'a str>),
182}
183
184pub struct ValueOperation<'a> {
185 pub name: Loc<&'a str>,
186 pub type_annotation: Option<Loc<TypeAnnotation>>,
187 pub equals_token: Loc<()>,
188 pub op: Loc<ValueOperationOp<'a>>,
189 pub semi_token: Loc<()>,
190}
191
192pub enum EffectOperationOp<'a> {
193 Jmp(Loc<Label<'a>>),
194 Br(Loc<&'a str>, Loc<Label<'a>>, Loc<Label<'a>>),
195 Call(Loc<&'a str>, Vec<Loc<&'a str>>),
197 Ret(Option<Loc<&'a str>>),
198
199 Print(Vec<Loc<&'a str>>),
200 Nop,
201
202 Store(Loc<&'a str>, Loc<&'a str>),
203 Free(Loc<&'a str>),
204}
205
206pub struct EffectOperation<'a> {
207 pub op: Loc<EffectOperationOp<'a>>,
208 pub semi_token: Loc<()>,
209}