1use galvan_ast::{Ast, Point, RootItem, SegmentedAsts, Span, ToplevelItem};
2use galvan_files::Source;
3use galvan_parse::*;
4
5mod cursor_macro;
6mod items;
7mod modifiers;
8mod result;
9
10use result::CursorUtil;
11pub use result::{AstError, AstResult};
12
13pub trait IntoAst {
14 fn try_into_ast(self, source: Source) -> AstResult;
15}
16
17pub trait SourceIntoAst {
18 fn try_into_ast(self) -> AstResult;
19}
20
21pub trait ReadCursor: Sized {
22 fn read_cursor(cursor: &mut TreeCursor<'_>, source: &str) -> Result<Self, AstError>;
23}
24
25impl SourceIntoAst for Source {
26 fn try_into_ast(self) -> AstResult {
27 let parsed = parse_source(&self)?;
28 parsed.try_into_ast(self)
29 }
30}
31
32impl IntoAst for ParseTree {
33 fn try_into_ast(self, source: Source) -> AstResult {
34 let root = self.root_node();
35 let mut cursor = root.walk();
36
37 let mut ast = Ast {
38 toplevel: vec![],
39 source,
40 };
41
42 if cursor.child() {
43 let item = RootItem::read_cursor(&mut cursor, &ast.source)?;
44
45 ast.toplevel.push(item);
46
47 while cursor.next() {
48 let item = RootItem::read_cursor(&mut cursor, &ast.source)?;
49
50 ast.toplevel.push(item);
51 }
52 }
53
54 Ok(ast)
55 }
56}
57
58pub trait SegmentAst {
59 fn segmented(self) -> Result<SegmentedAsts, AstError>;
60}
61
62impl SegmentAst for Ast {
63 fn segmented(self) -> Result<SegmentedAsts, AstError> {
64 let mut types = Vec::new();
65 let mut functions = Vec::new();
66 let mut tests = Vec::new();
67 let mut main = None;
68
69 for item in self.toplevel {
70 match item {
71 RootItem::Type(item) => types.push(ToplevelItem {
72 item,
73 source: self.source.clone(),
74 }),
75 RootItem::Fn(item) => functions.push(ToplevelItem {
76 item,
77 source: self.source.clone(),
78 }),
79 RootItem::Test(item) => tests.push(ToplevelItem {
80 item,
81 source: self.source.clone(),
82 }),
83 RootItem::Main(item) => {
84 if main.is_some() {
85 return Err(AstError::DuplicateMain);
86 }
87
88 main = Some(ToplevelItem {
89 item,
90 source: self.source.clone(),
91 })
92 }
93 }
94 }
95
96 Ok(SegmentedAsts {
97 types,
98 functions,
99 tests,
100 main,
101 })
102 }
103}
104
105impl SegmentAst for Vec<Ast> {
106 fn segmented(self) -> Result<SegmentedAsts, AstError> {
107 let mut types = Vec::new();
108 let mut functions = Vec::new();
109 let mut tests = Vec::new();
110 let mut main = None;
111 let segmented = self.into_iter().map(SegmentAst::segmented);
112
113 for ast in segmented {
114 let ast = ast?;
115 types.extend(ast.types);
116 functions.extend(ast.functions);
117 tests.extend(ast.tests);
118 if let Some(main_decl) = ast.main {
119 if main.is_some() {
120 return Err(AstError::DuplicateMain);
121 }
122
123 main = Some(main_decl);
124 }
125 }
126
127 Ok(SegmentedAsts {
128 types,
129 functions,
130 tests,
131 main,
132 })
133 }
134}
135
136pub trait SpanExt {
137 fn from_node(node: Node<'_>) -> Span;
138}
139
140impl SpanExt for Span {
141 fn from_node(node: Node<'_>) -> Span {
142 let start_byte = node.start_byte();
143 let end_byte = node.end_byte();
144 let start_point = node.start_position();
145 let end_point = node.end_position();
146
147 let start = Point {
148 row: start_point.row,
149 col: start_point.column,
150 };
151 let end = Point {
152 row: end_point.row,
153 col: end_point.column,
154 };
155
156 Span {
157 range: (start_byte, end_byte),
158 start,
159 end,
160 }
161 }
162}