1use crate::{Cst, LineCol, Rule, Span};
4use anyhow::{anyhow, Result};
5use itertools::Itertools;
6
7trait FromCst: Sized {
8 fn from_cst(cst: &Cst) -> Result<Self>;
9}
10
11#[derive(Debug)]
13pub struct ProgramText {
14 pub structure: Result<Program>,
15 pub cst: Cst,
16 pub lines: Vec<usize>,
17 pub text: String,
18}
19
20impl ProgramText {
21 pub fn parse(text: &str) -> std::result::Result<Self, (LineCol, Vec<&'static str>)> {
22 match crate::grammar::program(text) {
23 Ok(cst) => {
24 let mut lines = vec![0usize];
25 lines.extend(text.match_indices('\n').map(|(p, _)| p + 1));
26 let structure = Program::from_cst(&cst);
27 Ok(ProgramText {
28 text: text.to_owned(),
29 cst,
30 lines,
31 structure,
32 })
33 }
34 Err(e) => {
35 let peg::str::LineCol { line, column, .. } = e.location;
36 let lc = LineCol {
37 line: line - 1,
38 column: column - 1,
39 }; let expected: Vec<_> = e.expected.tokens().collect();
41 Err((lc, expected))
42 }
43 }
44 }
45
46 pub fn get_text_from_span(&self, span: Span) -> &str {
48 let text = self.text.as_str();
49 let Span { start, end } = span;
50 &text[start..end]
51 }
52
53 pub fn get_text(&self, cst: &Cst) -> &str {
55 let text = self.text.as_str();
56 let Span { start, end } = cst.span;
57 &text[start..end]
58 }
59
60 pub fn get_line_col(&self, pos: usize) -> Option<LineCol> {
62 if pos > self.text.len() {
63 return None;
64 }
65 let line = match self.lines.binary_search(&pos) {
66 Ok(i) => i,
67 Err(i) => i - 1,
68 };
69 let column = pos - self.lines[line];
70 Some(LineCol { line, column })
71 }
72
73 pub fn from_line_col(&self, line: usize, column: usize) -> Option<usize> {
75 let idxline = self.lines.get(line)?;
76 let max_idx = match self.lines.get(line + 1) {
77 Some(idx) => *idx,
78 None => self.text.len(),
79 };
80 if (*idxline + column) < max_idx {
81 Some(*idxline + column)
82 } else {
83 None
84 }
85 }
86
87 pub fn pritty_cst(&self, cst: &Cst) -> String {
89 let mut s = String::new();
90 s.push_str(&format!("[{:?}]", cst.rule));
91
92 let Span { start, end } = cst.span;
94 let slice = &self.text[start..end];
95 if !slice.contains('\n') && slice.len() < 80 {
96 s.push_str(&format!(": \"{}\"", slice));
97 } else {
98 let LineCol {
99 line: start_line,
100 column: start_column,
101 } = self.get_line_col(start).unwrap();
102 let LineCol {
103 line: end_line,
104 column: end_column,
105 } = self.get_line_col(end).unwrap();
106 s.push_str(&format!(
107 " (L{}-C{} .. L{}-C{})",
108 start_line + 1,
109 start_column + 1,
110 end_line + 1,
111 end_column + 1
112 ));
113 }
114 s
115 }
116
117 pub fn is_comment(&self, pos: usize) -> bool {
119 let dig = self.cst.dig(pos);
120 let cst = dig.get(0);
121 if cst.is_none() {
122 return false;
123 }
124 let cst = cst.unwrap();
125 let span = cst
128 .get_terminal_spans()
129 .into_iter()
130 .find(|span| span.includes(pos));
131 if span.is_none() {
132 return false;
134 }
135 let span = span.unwrap();
136
137 let text = self.get_text_from_span(span);
139 let char_indices = text.char_indices().map(|(idx, _)| idx).collect_vec();
140 let pos_char = char_indices
141 .binary_search(&(pos - span.start))
142 .unwrap_or_else(|x| x);
143 for c in text.chars().take(pos_char).collect_vec().into_iter().rev() {
144 match c {
145 '\n' => return false,
147 '%' => return true,
149 _ => continue,
150 }
151 }
152 false
154 }
155}
156
157#[derive(Debug, PartialEq, Eq)]
158pub enum Program {
159 Saty {
160 header_stage: Option<Cst>,
161 header: Vec<Header>,
162 preamble: Vec<Statement>,
163 expr: Cst,
164 },
165 Satyh {
166 header_stage: Option<Cst>,
167 header: Vec<Header>,
168 preamble: Vec<Statement>,
169 },
170}
171
172impl FromCst for Program {
173 fn from_cst(cst: &Cst) -> Result<Self> {
174 let mut inner = cst.inner.iter().peekable();
175 let header_stage = if inner
176 .peek()
177 .ok_or(anyhow!("expected stage or headers."))?
178 .rule
179 == Rule::stage
180 {
181 let stage = inner.next().unwrap();
182 Some(stage.clone())
183 } else {
184 None
185 };
186 let header = {
187 let headers = inner.next().unwrap();
188 let v: Result<Vec<_>> = headers
189 .inner
190 .iter()
191 .map(|cst| Header::from_cst(cst))
192 .collect();
193 v?
194 };
195
196 match cst.rule {
197 Rule::program_saty => {
198 let preamble = if inner
199 .peek()
200 .ok_or(anyhow!("expected preamble or expr"))?
201 .rule
202 == Rule::preamble
203 {
204 let preamble = inner.next().unwrap();
205 let v: Result<Vec<_>> = preamble
206 .inner
207 .iter()
208 .map(|cst| Statement::from_cst(cst))
209 .collect();
210 v?
211 } else {
212 vec![]
213 };
214 let expr = inner.next().ok_or(anyhow!("expected expr"))?.clone();
215 Ok(Program::Saty {
216 header_stage,
217 header,
218 preamble,
219 expr,
220 })
221 }
222 Rule::program_satyh => {
223 let preamble = {
224 let preamble = inner.next().ok_or(anyhow!("expected preamble"))?;
225 let v: Result<Vec<_>> = preamble
226 .inner
227 .iter()
228 .map(|cst| Statement::from_cst(cst))
229 .collect();
230 v?
231 };
232 Ok(Program::Satyh {
233 header_stage,
234 header,
235 preamble,
236 })
237 }
238 _ => unreachable!(),
239 }
240 }
241}
242
243#[derive(Debug, PartialEq, Eq)]
244pub struct Header {
245 pub name: Cst,
246 pub kind: HeaderKind,
247}
248
249impl FromCst for Header {
250 fn from_cst(cst: &Cst) -> Result<Self> {
251 let name = cst.inner.get(0).ok_or(anyhow!("expected pkgname"))?.clone();
252 let kind = match cst.rule {
253 Rule::header_require => HeaderKind::Require,
254 Rule::header_import => HeaderKind::Import,
255 _ => unreachable!(),
256 };
257 Ok(Header { name, kind })
258 }
259}
260
261#[derive(Debug, PartialEq, Eq)]
262pub enum HeaderKind {
263 Require,
264 Import,
265}
266
267#[derive(Debug, PartialEq, Eq)]
268pub enum Statement {
269 Let {
270 pat: Cst,
271 type_annot: Option<Cst>,
272 args: Vec<Cst>,
273 expr: Cst,
274 },
275 LetRec(Vec<LetRecInner>),
276 LetInline {
277 var_context: Option<Cst>,
278 cmd: Cst,
279 args: Vec<Cst>,
280 expr: Cst,
281 },
282 LetBlock {
283 var_context: Option<Cst>,
284 cmd: Cst,
285 args: Vec<Cst>,
286 expr: Cst,
287 },
288 LetMath {
289 cmd: Cst,
290 args: Vec<Cst>,
291 expr: Cst,
292 },
293 LetMutable {
294 var: Cst,
295 expr: Cst,
296 },
297 Type(Vec<TypeInner>),
298 Module {
299 name: Cst,
300 signature: Vec<Signature>,
301 statements: Vec<Statement>,
302 },
303 Open(Cst),
304}
305
306impl FromCst for Statement {
307 fn from_cst(cst: &Cst) -> Result<Self> {
308 let stmt = match cst.rule {
309 Rule::let_stmt => {
310 let mut inner = cst.inner.iter().peekable();
311 let pat = inner.next().ok_or(anyhow!("expected pattern"))?.clone();
312 let type_annot = if inner
313 .peek()
314 .ok_or(anyhow!("expected type_expr or arg"))?
315 .rule
316 == Rule::type_expr
317 {
318 Some(inner.next().unwrap().clone())
319 } else {
320 None
321 };
322 let mut args = vec![];
323 while inner.peek().ok_or(anyhow!("expected expr"))?.rule == Rule::arg {
324 let arg = inner.next().unwrap().clone();
325 args.push(arg);
326 }
327 let expr = inner.next().unwrap().clone();
328 Statement::Let {
329 pat,
330 type_annot,
331 args,
332 expr,
333 }
334 }
335
336 Rule::let_rec_stmt => {
337 let let_rec_inner: Result<Vec<_>> = cst
338 .inner
339 .iter()
340 .map(|rec_inner| LetRecInner::from_cst(rec_inner))
341 .collect();
342 Statement::LetRec(let_rec_inner?)
343 }
344
345 Rule::let_inline_stmt_ctx => {
346 let mut inner = cst.inner.iter().peekable();
347 let var_context = Some(inner.next().ok_or(anyhow!("expected context"))?.clone());
348 let cmd = inner
349 .next()
350 .ok_or(anyhow!("expected command name"))?
351 .clone();
352 let mut args = vec![];
353 while inner.peek().ok_or(anyhow!("expected expr"))?.rule == Rule::pattern {
354 let arg = inner.next().unwrap().clone();
355 args.push(arg);
356 }
357 let expr = inner.next().unwrap().clone();
358 Statement::LetInline {
359 var_context,
360 cmd,
361 args,
362 expr,
363 }
364 }
365 Rule::let_inline_stmt_noctx => {
366 let mut inner = cst.inner.iter().peekable();
367 let var_context = None;
368 let cmd = inner
369 .next()
370 .ok_or(anyhow!("expected command name"))?
371 .clone();
372 let mut args = vec![];
373 while inner.peek().ok_or(anyhow!("expected expr"))?.rule == Rule::arg {
374 let arg = inner.next().unwrap().clone();
375 args.push(arg);
376 }
377 let expr = inner.next().unwrap().clone();
378 Statement::LetInline {
379 var_context,
380 cmd,
381 args,
382 expr,
383 }
384 }
385
386 Rule::let_block_stmt_ctx => {
387 let mut inner = cst.inner.iter().peekable();
388 let var_context = Some(inner.next().ok_or(anyhow!("expected context"))?.clone());
389 let cmd = inner
390 .next()
391 .ok_or(anyhow!("expected command name"))?
392 .clone();
393 let mut args = vec![];
394 while inner.peek().ok_or(anyhow!("expected expr"))?.rule == Rule::pattern {
395 let arg = inner.next().unwrap().clone();
396 args.push(arg);
397 }
398 let expr = inner.next().unwrap().clone();
399 Statement::LetBlock {
400 var_context,
401 cmd,
402 args,
403 expr,
404 }
405 }
406 Rule::let_block_stmt_noctx => {
407 let mut inner = cst.inner.iter().peekable();
408 let var_context = None;
409 let cmd = inner
410 .next()
411 .ok_or(anyhow!("expected command name"))?
412 .clone();
413 let mut args = vec![];
414 while inner.peek().ok_or(anyhow!("expected expr"))?.rule == Rule::arg {
415 let arg = inner.next().unwrap().clone();
416 args.push(arg);
417 }
418 let expr = inner.next().unwrap().clone();
419 Statement::LetBlock {
420 var_context,
421 cmd,
422 args,
423 expr,
424 }
425 }
426
427 Rule::let_math_stmt => {
428 let mut inner = cst.inner.iter().peekable();
429 let cmd = inner
430 .next()
431 .ok_or(anyhow!("expected command name"))?
432 .clone();
433 let mut args = vec![];
434 while inner.peek().ok_or(anyhow!("expected expr"))?.rule == Rule::arg {
435 let arg = inner.next().unwrap().clone();
436 args.push(arg);
437 }
438 let expr = inner.next().unwrap().clone();
439 Statement::LetMath { cmd, args, expr }
440 }
441
442 Rule::let_mutable_stmt => {
443 let var = cst
444 .inner
445 .get(0)
446 .ok_or(anyhow!("expected var name"))?
447 .clone();
448 let expr = cst.inner.get(1).ok_or(anyhow!("expected expr"))?.clone();
449 Statement::LetMutable { var, expr }
450 }
451
452 Rule::type_stmt => {
453 let type_inners: Result<Vec<_>> = cst
454 .inner
455 .iter()
456 .map(|type_inner| TypeInner::from_cst(type_inner))
457 .collect();
458 Statement::Type(type_inners?)
459 }
460
461 Rule::module_stmt => {
462 let name = cst.inner.get(0).ok_or(anyhow!("expected name"))?.clone();
463 let sig_stmt = cst.inner.get(1).ok_or(anyhow!("expected sig_stmt"))?;
464 let struct_stmt = cst.inner.get(2).ok_or(anyhow!("expected struct_stmt"))?;
465 let signature: Result<Vec<_>> = sig_stmt
466 .inner
467 .iter()
468 .map(|sig_inner| Signature::from_cst(sig_inner))
469 .collect();
470 let signature = signature?;
471 let statements: Result<Vec<_>> = struct_stmt
472 .inner
473 .iter()
474 .map(|stmt| Statement::from_cst(stmt))
475 .collect();
476 let statements = statements?;
477 Statement::Module {
478 name,
479 signature,
480 statements,
481 }
482 }
483
484 Rule::open_stmt => Statement::Open(
485 cst.inner
486 .get(0)
487 .ok_or(anyhow!("expected module name"))?
488 .clone(),
489 ),
490
491 Rule::dummy_stmt => return Err(anyhow!("dummy statement")),
492 _ => unreachable!(),
493 };
494 Ok(stmt)
495 }
496}
497
498#[derive(Debug, PartialEq, Eq)]
499pub enum Signature {
500 Type {
501 param: Vec<Cst>,
502 name: Cst,
503 constraint: Vec<Cst>,
504 },
505 Val {
506 var: Cst,
507 signature: Cst,
508 constraint: Vec<Cst>,
509 },
510 Direct {
511 var: Cst,
512 signature: Cst,
513 constraint: Vec<Cst>,
514 },
515}
516
517impl FromCst for Signature {
518 fn from_cst(cst: &Cst) -> Result<Self> {
519 match cst.rule {
520 Rule::sig_type_stmt => {
521 let mut inner = cst.inner.iter().peekable();
522 let mut param = vec![];
523 while inner.peek().ok_or(anyhow!("expect type name"))?.rule == Rule::type_param {
524 let p = inner.next().unwrap().clone();
525 param.push(p);
526 }
527 let name = inner.next().unwrap().clone();
528 let constraint = inner.map(|cst| cst.clone()).collect();
529 Ok(Signature::Type {
530 param,
531 name,
532 constraint,
533 })
534 }
535
536 Rule::sig_val_stmt => {
537 let mut inner = cst.inner.iter();
538 let var = inner.next().ok_or(anyhow!("expect var"))?.clone();
539 let signature = inner.next().ok_or(anyhow!("expect signature"))?.clone();
540 let constraint = inner.map(|cst| cst.clone()).collect();
541 Ok(Signature::Val {
542 var,
543 signature,
544 constraint,
545 })
546 }
547
548 Rule::sig_direct_stmt => {
549 let mut inner = cst.inner.iter();
550 let var = inner.next().ok_or(anyhow!("expect var"))?.clone();
551 let signature = inner.next().ok_or(anyhow!("expect signature"))?.clone();
552 let constraint = inner.cloned().collect();
553 Ok(Signature::Direct {
554 var,
555 signature,
556 constraint,
557 })
558 }
559
560 Rule::dummy_sig_stmt => Err(anyhow!("dummy signature statement")),
561 _ => unreachable!(),
562 }
563 }
564}
565
566#[derive(Debug, PartialEq, Eq)]
567pub struct LetRecInner {
568 pub pattern: Cst,
569 pub type_expr: Option<Cst>,
570 pub variant: Vec<LetRecVariant>,
571}
572
573#[derive(Debug, PartialEq, Eq)]
574pub struct LetRecVariant {
575 pub args: Vec<Cst>,
576 pub expr: Cst,
577}
578
579impl FromCst for LetRecInner {
580 fn from_cst(cst: &Cst) -> Result<Self> {
581 let mut inner = cst.inner.iter().peekable();
582 let pattern = inner.next().ok_or(anyhow!("expected pattern"))?.clone();
583 let type_expr = if inner
584 .peek()
585 .ok_or(anyhow!("expected variant or expr"))?
586 .rule
587 == Rule::type_expr
588 {
589 Some(inner.next().unwrap().clone())
590 } else {
591 None
592 };
593 let mut variant = vec![];
594 while inner.peek().is_some() {
595 let mut args = vec![];
596 while inner.peek().ok_or(anyhow!("expected expr"))?.rule == Rule::arg {
597 args.push(inner.next().unwrap().clone())
598 }
599 let expr = inner.next().unwrap().clone();
600 variant.push(LetRecVariant { args, expr });
601 }
602 Ok(LetRecInner {
603 pattern,
604 type_expr,
605 variant,
606 })
607 }
608}
609
610#[derive(Debug, PartialEq, Eq)]
611pub struct TypeInner {
612 pub param: Vec<Cst>,
613 pub name: Cst,
614 pub constraint: Vec<Cst>,
615 pub body: TypeBody,
616}
617
618impl FromCst for TypeInner {
619 fn from_cst(cst: &Cst) -> Result<Self> {
620 let mut inner = cst.inner.iter().peekable();
621 let mut param = vec![];
622 while inner.peek().ok_or(anyhow!("expected type name"))?.rule == Rule::type_param {
623 let p = inner.next().unwrap().clone();
624 param.push(p);
625 }
626 let name = inner.next().unwrap().clone();
627
628 let body = if inner
629 .peek()
630 .ok_or(anyhow!("expected type expr or type variant"))?
631 .rule
632 == Rule::type_expr
633 {
634 TypeBody::Expr(inner.next().unwrap().clone())
635 } else {
636 let mut variants = vec![];
637 while inner.peek().is_some() && inner.peek().unwrap().rule == Rule::type_variant {
638 let v = inner.next().unwrap().clone();
639 variants.push(v);
640 }
641 TypeBody::Variants(variants)
642 };
643 let constraint = inner.cloned().collect();
644 Ok(TypeInner {
645 param,
646 name,
647 constraint,
648 body,
649 })
650 }
651}
652
653#[derive(Debug, PartialEq, Eq)]
654pub enum TypeBody {
655 Variants(Vec<Cst>),
656 Expr(Cst),
657}