c_ast/
syntax.rs

1use crate::*;
2
3pub trait IntoVec<T> {
4    fn into_vec(self) -> Vec<T>;
5}
6
7// ==== Expression Functions ====
8
9pub 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
113// ==== Type Expression Functions ====
114
115pub 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
142// ==== Statement Functions ====
143
144pub 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}