galvan_ast/
lib.rs

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    // pub span: Span,
37}
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    // pub other: Vec<ToplevelItem<CustomTaskDecl>>
57}
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    /// Start as Row, Column position
121    pub start: Point,
122    /// End as Row, Column position
123    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}