1#[macro_use]
2extern crate core;
3
4use std::{cell::RefCell, ops::Deref};
5
6use galvan_files::Source;
7use itertools::Itertools;
8
9mod item;
10
11pub use item::*;
12
13#[derive(Debug, PartialEq, Eq)]
14pub struct Ast {
15 pub toplevel: Vec<RootItem>,
16 pub source: Source,
17}
18
19impl Ast {
20 pub fn with_source(self, source: Source) -> Ast {
21 if self.source != Source::Missing {
22 panic!("Attempting to set a source to an AST that already had a source!");
23 }
24
25 Ast {
26 toplevel: self.toplevel,
27 source,
28 }
29 }
30}
31
32#[derive(Debug, PartialEq, Eq)]
33pub struct ToplevelItem<R: RootItemMarker> {
34 pub item: R,
35 pub source: Source,
36 }
38
39impl<R> Deref for ToplevelItem<R>
40where
41 R: RootItemMarker,
42{
43 type Target = R;
44
45 fn deref(&self) -> &Self::Target {
46 &self.item
47 }
48}
49
50#[derive(Debug, PartialEq, Eq)]
51pub struct SegmentedAsts {
52 pub types: Vec<ToplevelItem<TypeDecl>>,
53 pub functions: Vec<ToplevelItem<FnDecl>>,
54 pub tests: Vec<ToplevelItem<TestDecl>>,
55 pub main: Option<ToplevelItem<MainDecl>>,
56 }
58
59pub trait PrintAst {
60 fn print_ast(&self, indent: usize) -> String;
61}
62
63pub trait AstNode {
64 fn span(&self) -> Span;
65 fn print(&self, indent: usize) -> String;
66}
67
68impl PrintAst for bool {
69 fn print_ast(&self, indent: usize) -> String {
70 let indent_str = " ".repeat(indent);
71 format!("{indent_str}{self}\n")
72 }
73}
74
75impl<T> PrintAst for RefCell<T>
76where
77 T: PrintAst,
78{
79 fn print_ast(&self, indent: usize) -> String {
80 self.borrow().print_ast(indent)
81 }
82}
83
84impl PrintAst for Box<Expression> {
85 fn print_ast(&self, indent: usize) -> String {
86 self.deref().print_ast(indent)
87 }
88}
89
90impl<T> PrintAst for Vec<T>
91where
92 T: PrintAst,
93{
94 fn print_ast(&self, indent: usize) -> String {
95 self.iter().map(|i| i.print_ast(indent)).join("\n")
96 }
97}
98
99impl<T> PrintAst for Option<T>
100where
101 T: PrintAst,
102{
103 fn print_ast(&self, indent: usize) -> String {
104 self.iter().map(|i| i.print_ast(indent)).join("\n")
105 }
106}
107
108impl<T> PrintAst for T
109where
110 T: AstNode,
111{
112 fn print_ast(&self, indent: usize) -> String {
113 AstNode::print(self, indent)
114 }
115}
116
117#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
118pub struct Span {
119 pub range: (usize, usize),
120 pub start: Point,
122 pub end: Point,
124}
125
126#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
127pub struct Point {
128 pub row: usize,
129 pub col: usize,
130}