1use cl_ast::Expr;
4use cl_lexer::Lexer;
5use cl_parser::Parser;
6use cl_structures::intern::interned::Symbol;
7use repline::{Response, error::Error as RlError};
8
9fn main() -> Result<(), RlError> {
10 repline::read_and("\x1b[33m", "y> ", " > ", |line| {
11 let mut parser = Parser::new(Lexer::new(Symbol::default(), line));
12 let code = parser.parse::<Expr>(0)?;
13
14 Yamler::new().yaml(&code);
15 println!();
16 Ok(Response::Accept)
17 })
18}
19
20pub use yamler::Yamler;
21pub mod yamler {
22 use crate::yamlify::Yamlify;
23 use std::{
24 io::Write,
25 ops::{Deref, DerefMut},
26 };
27 #[derive(Debug, Default)]
28 pub struct Yamler {
29 depth: usize,
30 needs_indent: bool,
31 }
32
33 impl Yamler {
34 pub fn new() -> Self {
35 Self::default()
36 }
37
38 pub fn indent(&mut self) -> Section<'_> {
39 Section::new(self)
40 }
41
42 #[inline]
44 pub fn yaml<T: Yamlify>(&mut self, yaml: &T) -> &mut Self {
45 yaml.yaml(self);
46 self
47 }
48
49 fn newline(&mut self) -> &mut Self {
50 if !self.needs_indent {
51 println!();
52 }
53 self.needs_indent = true;
54 self
55 }
56
57 fn increase(&mut self) {
58 self.depth += 1;
59 }
60
61 fn decrease(&mut self) {
62 self.depth -= 1;
63 }
64
65 fn print_indentation(&mut self, writer: &mut impl Write) {
66 if !self.needs_indent {
67 return;
68 }
69 for _ in 0..self.depth {
70 let _ = write!(writer, " ");
71 }
72 self.needs_indent = false
73 }
74
75 pub fn key(&mut self, name: impl Yamlify) -> Section<'_> {
77 self.print_indentation(&mut std::io::stdout().lock());
78 name.yaml(self);
79 println!(":");
80 self.needs_indent = true;
81 self.newline().indent()
82 }
83
84 pub fn pair<D: Yamlify, T: Yamlify>(&mut self, name: D, value: T) -> &mut Self {
86 self.print_indentation(&mut std::io::stdout().lock());
87 self.key(name).value(value);
88 self
89 }
90
91 pub fn value<D: Yamlify>(&mut self, value: D) -> &mut Self {
93 self.print_indentation(&mut std::io::stdout().lock());
94 value.yaml(self);
95 self.newline()
96 }
97
98 pub fn list<D: Yamlify>(&mut self, list: &[D]) -> &mut Self {
99 for value in list {
100 self.print_indentation(&mut std::io::stdout().lock());
101 print!("- ");
102 self.yaml(value).newline();
103 }
104 self
105 }
106 }
107
108 pub struct Section<'y> {
110 yamler: &'y mut Yamler,
111 }
112
113 impl<'y> Section<'y> {
114 pub fn new(yamler: &'y mut Yamler) -> Self {
115 yamler.increase();
116 Self { yamler }
117 }
118 }
119
120 impl Deref for Section<'_> {
121 type Target = Yamler;
122 fn deref(&self) -> &Self::Target {
123 self.yamler
124 }
125 }
126 impl DerefMut for Section<'_> {
127 fn deref_mut(&mut self) -> &mut Self::Target {
128 self.yamler
129 }
130 }
131
132 impl Drop for Section<'_> {
133 fn drop(&mut self) {
134 let Self { yamler } = self;
135 yamler.decrease();
136 }
137 }
138}
139
140pub mod yamlify {
141 use super::yamler::Yamler;
142 use cl_ast::{
143 AstTypes,
144 types::{Literal, Path, Symbol},
145 *,
146 };
147 use cl_structures::span::Span;
148
149 pub trait Yamlify {
150 fn yaml(&self, y: &mut Yamler);
151 }
152
153 impl Yamlify for Expr {
154 fn yaml(&self, y: &mut Yamler) {
155 match self {
156 Self::Omitted => y.yaml(&"Omitted"),
157 Self::Id(path) => y.yaml(path),
158 Self::MetId(id) => y.yaml(id),
159 Self::Lit(lit) => y.yaml(lit),
160 Self::Use(item) => y.yaml(item),
161 Self::Bind(bind) => y.yaml(bind),
162 Self::Make(make) => y.yaml(make),
163 Self::Match(mtch) => y.yaml(mtch),
164 Self::Op(op, annos) => y.pair(op, annos),
165 };
166 }
167 }
168
169 impl Yamlify for Pat {
170 fn yaml(&self, y: &mut Yamler) {
171 match self {
172 Self::Ignore => y.yaml(&"_"),
173 Self::Never => y.yaml(&"!"),
174 Self::MetId(id) => y.pair("meta", id),
175 Self::Name(name) => y.pair("named", name),
176 Self::Value(body) => y.pair("constant", body),
177 Self::Op(op, pats) => y.pair(op, pats),
178 };
179 }
180 }
181
182 impl Yamlify for Bind {
183 fn yaml(&self, y: &mut Yamler) {
184 let Self(op, gens, pat, exprs) = self;
185 y.key(op)
186 .pair("generics", gens)
187 .pair("pattern", pat)
188 .pair("body", exprs);
189 }
190 }
191
192 impl Yamlify for Make {
193 fn yaml(&self, y: &mut Yamler) {
194 let Self(ty, arms) = self;
195 y.pair(ty, arms);
196 }
197 }
198
199 impl Yamlify for MakeArm {
200 fn yaml(&self, y: &mut Yamler) {
201 let Self(name, expr) = self;
202 y.pair(name, expr);
203 }
204 }
205
206 impl Yamlify for Match {
207 fn yaml(&self, y: &mut Yamler) {
208 let Self(scrutinee, arms) = self;
209 y.pair("scrutinee", scrutinee).pair("arms", arms);
210 }
211 }
212
213 impl Yamlify for MatchArm {
214 fn yaml(&self, y: &mut Yamler) {
215 let Self(pat, expr) = self;
216 y.pair("pat", pat).pair("expr", expr);
217 }
218 }
219
220 impl Yamlify for Use {
221 fn yaml(&self, y: &mut Yamler) {
222 match self {
223 Self::Glob => y.yaml(&"*"),
224 Self::Name(name) => y.yaml(name),
225 Self::Alias(from, to) => y.pair(from, to),
226 Self::Path(name, rest) => y.pair(name, rest),
227 Self::Tree(items) => y.yaml(items),
228 };
229 }
230 }
231
232 impl<T: Yamlify + AstNode, A: AstTypes> Yamlify for At<T, A>
233 where A::Annotation: Yamlify
234 {
235 fn yaml(&self, y: &mut Yamler) {
236 let Self(t, _) = self;
237 y.yaml(t);
238 }
239 }
240
241 impl<T: Yamlify> Yamlify for Option<T> {
242 fn yaml(&self, y: &mut Yamler) {
243 if let Some(v) = self {
244 y.yaml(v);
245 } else {
246 y.yaml(&"");
247 }
248 }
249 }
250 impl<T: Yamlify> Yamlify for Box<T> {
251 fn yaml(&self, y: &mut Yamler) {
252 y.yaml(&**self);
253 }
254 }
255 impl<T: Yamlify> Yamlify for Vec<T> {
256 fn yaml(&self, y: &mut Yamler) {
257 y.list(self);
258 }
259 }
260 impl Yamlify for () {
261 fn yaml(&self, _y: &mut Yamler) {}
262 }
263
264 impl<T: Yamlify> Yamlify for &T {
265 fn yaml(&self, y: &mut Yamler) {
266 (*self).yaml(y)
267 }
268 }
269
270 macro_rules! scalar {
271 ($($t:ty),*$(,)?) => {
272 $(impl Yamlify for $t {
273 fn yaml(&self, _y: &mut Yamler) {
274 print!("{self}");
275 }
276 })*
277 };
278 }
279
280 macro_rules! debug_scalar {
281 ($($t:ty),*$(,)?) => {
282 $(impl Yamlify for $t {
283 fn yaml(&self, _y: &mut Yamler) {
284 print!("{self:?}");
285 }
286 })*
287 };
288 }
289
290 scalar! {
291 bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, str, &str, String,
292 Symbol, Path, Literal
293 }
294
295 debug_scalar!(Op, BindOp, PatOp, Span);
296}