1use crate::*;
2
3pub trait IntoVec<T> {
4 fn into_vec(self) -> Vec<T>;
5}
6
7pub fn var(name: impl Into<String>) -> Expr {
10 Expr::Var(name.into())
11}
12
13pub trait ExprExt: Into<Expr> {
14 fn call(self, parameters: impl Into<Vec<Expr>>) -> Expr {
15 Expr::Call(Box::new(self.into()), parameters.into())
16 }
17
18 fn index(self, index: impl Into<Expr>) -> Expr {
19 Expr::Index(Box::new(self.into()), Box::new(index.into()))
20 }
21
22 fn cast(self, type_expr: impl IntoPTypeExpr) -> Expr {
23 Expr::Cast(type_expr.into_p_type_expr(), Box::new(self.into()))
24 }
25
26 fn dot(self, field: impl Into<String>) -> Expr {
27 Expr::Dot(Box::new(self.into()), field.into())
28 }
29
30 fn arrow(self, field: impl Into<String>) -> Expr {
31 Expr::Arrow(Box::new(self.into()), field.into())
32 }
33
34 fn inc(self) -> Expr {
35 Expr::Inc(Box::new(self.into()))
36 }
37
38 fn dec(self) -> Expr {
39 Expr::Dec(Box::new(self.into()))
40 }
41}
42
43impl<T: Into<Expr>> ExprExt for T {}
44
45pub fn int(value: impl Into<i32>) -> Expr {
46 Expr::Int(value.into())
47}
48
49pub fn str(value: impl Into<String>) -> Expr {
50 Expr::Str(value.into())
51}
52
53pub fn char(value: impl Into<char>) -> Expr {
54 Expr::Char(value.into())
55}
56
57pub fn unary(op: UnaryOp, expr: impl Into<Expr>) -> Expr {
58 Expr::Unary(op, expr.into().into())
59}
60
61pub fn binary(op: BinaryOp, left: impl Into<Expr>, right: impl Into<Expr>) -> Expr {
62 Expr::Binary(op, left.into().into(), right.into().into())
63}
64
65pub fn cast(type_expr: impl Into<PTypeExpr>, expr: impl Into<Expr>) -> Expr {
66 Expr::Cast(type_expr.into(), expr.into().into())
67}
68
69pub fn sizeof(type_expr: impl Into<PTypeExpr>) -> Expr {
70 Expr::SizeOf(type_expr.into())
71}
72
73pub trait Literal {
74 fn literal(self) -> Expr;
75}
76
77impl Literal for i32 {
78 fn literal(self) -> Expr {
79 Expr::Int(self)
80 }
81}
82
83impl Literal for String {
84 fn literal(self) -> Expr {
85 Expr::Str(self)
86 }
87}
88
89impl Literal for char {
90 fn literal(self) -> Expr {
91 Expr::Char(self)
92 }
93}
94
95impl Literal for &str {
96 fn literal(self) -> Expr {
97 Expr::Str(self.into())
98 }
99}
100
101impl From<String> for Expr {
102 fn from(name: String) -> Self {
103 Expr::Var(name)
104 }
105}
106
107impl From<&str> for Expr {
108 fn from(name: &str) -> Self {
109 Expr::Var(name.into())
110 }
111}
112
113pub fn tvar(name: impl Into<String>) -> PTypeExpr {
116 TypeExpr::Var(name.into()).into_p_type_expr()
117}
118
119impl From<String> for TypeExpr {
120 fn from(name: String) -> Self {
121 TypeExpr::Var(name)
122 }
123}
124
125impl From<&str> for TypeExpr {
126 fn from(name: &str) -> Self {
127 TypeExpr::Var(name.into())
128 }
129}
130
131pub trait TypeExprExt: Into<PTypeExpr> {
132 fn ptr(self) -> PTypeExpr {
133 TypeExpr::Ptr(self.into()).into_p_type_expr()
134 }
135 fn array(self) -> PTypeExpr {
136 TypeExpr::Array(self.into()).into_p_type_expr()
137 }
138}
139
140impl<T: Into<PTypeExpr>> TypeExprExt for T {}
141
142pub trait IntoPTypeExpr {
145 fn into_p_type_expr(self) -> PTypeExpr;
146}
147
148impl IntoPTypeExpr for PTypeExpr {
149 fn into_p_type_expr(self) -> PTypeExpr {
150 self
151 }
152}
153
154impl<T: Into<TypeExpr>> IntoPTypeExpr for T {
155 fn into_p_type_expr(self) -> PTypeExpr {
156 PTypeExpr::new(self.into())
157 }
158}
159
160pub fn declare(
161 type_expr: impl IntoPTypeExpr,
162 name: impl Into<String>,
163 value: impl Into<Expr>,
164) -> Statement {
165 Statement::Declaration {
166 type_expression: type_expr.into_p_type_expr(),
167 name: name.into(),
168 initializer: Some(value.into()),
169 }
170}
171
172pub fn return_(value: impl Into<Expr>) -> Statement {
173 Statement::Return(value.into())
174}
175
176#[macro_export]
177macro_rules! typ {
178 ( < { $expr:expr } > ) => {
179 $crate::Include::Arrow($expr.into())
180 };
181 ( "" { $expr:expr } "" ) => {
182 $crate::Include::Arrow($expr.into())
183 };
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[test]
191 fn test_call() {
192 "printf".call(["Hello, world!".into()]);
193 }
194
195 #[test]
196 fn test_stuff() {
197 let func = Function {
198 return_type: tvar("int"),
199 name: "main".into(),
200 parameters: vec![
201 (tvar("int"), "argc".into()),
202 (tvar("char").ptr().array(), "argv".into()),
203 ],
204 body: Some(vec![declare("int", "i", 0.literal())]),
205 };
206
207 assert_eq!(
208 func.to_string(),
209 "int main(int argc, char* argv[]) {\n int i = 0;\n}\n"
210 );
211 }
212}