1use crate::{parse::*, parser::*, syntax::*};
5use microcad_syntax::ast;
6
7impl Assignment {
9 fn from_ast_local(
10 node: &ast::LocalAssignment,
11 context: &ParseContext,
12 ) -> Result<Self, ParseError> {
13 Ok(Assignment {
14 doc: None,
15 visibility: Visibility::Private,
16 id: Identifier::from_ast(&node.name, context)?,
17 qualifier: Qualifier::Value,
18 specified_type: node
19 .ty
20 .as_ref()
21 .map(|ty| TypeAnnotation::from_ast(ty, context))
22 .transpose()?,
23 expression: Expression::from_ast(&node.value, context)?,
24 src_ref: context.src_ref(&node.span),
25 })
26 }
27
28 fn from_ast_prop(
29 node: &ast::PropertyAssignment,
30 context: &ParseContext,
31 ) -> Result<Self, ParseError> {
32 Ok(Assignment {
33 doc: node
34 .doc
35 .as_ref()
36 .map(|doc| DocBlock::from_ast(doc, context))
37 .transpose()?,
38 visibility: Visibility::Private,
39 id: Identifier::from_ast(&node.name, context)?,
40 qualifier: Qualifier::Prop,
41 specified_type: node
42 .ty
43 .as_ref()
44 .map(|ty| TypeAnnotation::from_ast(ty, context))
45 .transpose()?,
46 expression: Expression::from_ast(&node.value, context)?,
47 src_ref: context.src_ref(&node.span),
48 })
49 }
50
51 fn from_ast_const(
52 node: &ast::ConstAssignment,
53 context: &ParseContext,
54 ) -> Result<Self, ParseError> {
55 Ok(Assignment {
56 doc: node
57 .doc
58 .as_ref()
59 .map(|doc| DocBlock::from_ast(doc, context))
60 .transpose()?,
61 visibility: node
62 .visibility
63 .as_ref()
64 .map(|v| Visibility::from_ast(v, context))
65 .transpose()?
66 .unwrap_or_default(),
67 id: Identifier::from_ast(&node.name, context)?,
68 qualifier: Qualifier::Const,
69 specified_type: node
70 .ty
71 .as_ref()
72 .map(|ty| TypeAnnotation::from_ast(ty, context))
73 .transpose()?,
74 expression: Expression::from_ast(&node.value, context)?,
75 src_ref: context.src_ref(&node.span),
76 })
77 }
78}
79
80impl AssignmentStatement {
82 fn from_ast_local(
83 node: &ast::LocalAssignment,
84 context: &ParseContext,
85 ) -> Result<Self, ParseError> {
86 Ok(AssignmentStatement {
87 attribute_list: AttributeList::from_ast(&node.attributes, context)?,
88 assignment: std::rc::Rc::new(Assignment::from_ast_local(node, context)?),
89 src_ref: context.src_ref(&node.span),
90 })
91 }
92
93 fn from_ast_prop(
94 node: &ast::PropertyAssignment,
95 context: &ParseContext,
96 ) -> Result<Self, ParseError> {
97 Ok(AssignmentStatement {
98 attribute_list: AttributeList::from_ast(&node.attributes, context)?,
99 assignment: std::rc::Rc::new(Assignment::from_ast_prop(node, context)?),
100 src_ref: context.src_ref(&node.span),
101 })
102 }
103
104 fn from_ast_const(
105 node: &ast::ConstAssignment,
106 context: &ParseContext,
107 ) -> Result<Self, ParseError> {
108 Ok(AssignmentStatement {
109 attribute_list: AttributeList::from_ast(&node.attributes, context)?,
110 assignment: std::rc::Rc::new(Assignment::from_ast_const(node, context)?),
111 src_ref: context.src_ref(&node.span),
112 })
113 }
114}
115
116impl FromAst for IfStatement {
117 type AstNode = ast::If;
118
119 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
120 Ok(IfStatement {
121 if_ref: context.src_ref(&node.if_span),
122 cond: Expression::from_ast(&node.condition, context)?,
123 body: Body::from_ast(&node.body, context)?,
124 next_if_ref: node
125 .next_if_span
126 .as_ref()
127 .map(|span| context.src_ref(span)),
128 next_if: node
129 .next_if
130 .as_ref()
131 .map(|next| IfStatement::from_ast(next, context))
132 .transpose()?
133 .map(Box::new),
134 else_ref: node.else_span.as_ref().map(|span| context.src_ref(span)),
135 body_else: node
136 .else_body
137 .as_ref()
138 .map(|body| Body::from_ast(body, context))
139 .transpose()?,
140 src_ref: context.src_ref(&node.span),
141 })
142 }
143}
144
145impl FromAst for ExpressionStatement {
146 type AstNode = ast::ExpressionStatement;
147
148 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
149 Ok(ExpressionStatement {
150 src_ref: context.src_ref(&node.span),
151 attribute_list: AttributeList::from_ast(&node.attributes, context)?,
152 expression: Expression::from_ast(&node.expression, context)?,
153 })
154 }
155}
156
157impl FromAst for Statement {
158 type AstNode = ast::Statement;
159
160 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
161 Ok(match node {
162 ast::Statement::Module(module) => Statement::Module(std::rc::Rc::new(
163 ModuleDefinition::from_ast(module, context)?,
164 )),
165 ast::Statement::Use(statement) => {
166 Statement::Use(UseStatement::from_ast(statement, context)?)
167 }
168 ast::Statement::Expression(ast::ExpressionStatement {
169 expression: ast::Expression::If(if_statement),
170 ..
171 }) => Statement::If(IfStatement::from_ast(if_statement, context)?),
172 ast::Statement::Expression(statement) => {
173 Statement::Expression(ExpressionStatement::from_ast(statement, context)?)
174 }
175 ast::Statement::Workbench(w) => {
176 Statement::Workbench(<std::rc::Rc<WorkbenchDefinition>>::from_ast(w, context)?)
177 }
178 ast::Statement::Function(f) => {
179 Statement::Function(std::rc::Rc::new(FunctionDefinition::from_ast(f, context)?))
180 }
181 ast::Statement::Init(i) => {
182 Statement::Init(std::rc::Rc::new(InitDefinition::from_ast(i, context)?))
183 }
184 ast::Statement::Return(r) => Statement::Return(ReturnStatement::from_ast(r, context)?),
185 ast::Statement::InnerAttribute(a) => {
186 Statement::InnerAttribute(Attribute::from_ast(a, context)?)
187 }
188 ast::Statement::InnerDocComment(i) => {
189 Statement::InnerDocComment(InnerDocComment::from_ast(i, context)?)
190 }
191 ast::Statement::LocalAssignment(a) => {
192 Statement::Assignment(AssignmentStatement::from_ast_local(a, context)?)
193 }
194 ast::Statement::Property(a) => {
195 Statement::Assignment(AssignmentStatement::from_ast_prop(a, context)?)
196 }
197 ast::Statement::Const(a) => {
198 Statement::Assignment(AssignmentStatement::from_ast_const(a, context)?)
199 }
200 ast::Statement::Comment(_) => unreachable!("comments are filtered out"),
201 ast::Statement::Error(span) => {
202 return Err(ParseError::InvalidStatement {
203 src_ref: context.src_ref(span),
204 });
205 }
206 })
207 }
208}
209
210impl FromAst for ReturnStatement {
211 type AstNode = ast::Return;
212
213 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
214 Ok(ReturnStatement {
215 keyword_ref: context.src_ref(&node.keyword_span),
216 result: node
217 .value
218 .as_ref()
219 .map(|res| Expression::from_ast(res, context))
220 .transpose()?,
221 src_ref: context.src_ref(&node.span),
222 })
223 }
224}
225
226impl FromAst for StatementList {
227 type AstNode = ast::StatementList;
228
229 fn from_ast(node: &Self::AstNode, context: &ParseContext) -> Result<Self, ParseError> {
230 Ok(StatementList(
231 node.statements
232 .iter()
233 .chain(node.tail.iter().map(|tail| tail.as_ref()))
234 .filter(|statement| !matches!(statement, ast::Statement::Comment(_)))
235 .map(|statement| Statement::from_ast(statement, context))
236 .collect::<Result<Vec<_>, _>>()?,
237 ))
238 }
239}
240
241impl FromAst for Qualifier {
242 type AstNode = ast::AssignmentQualifier;
243
244 fn from_ast(node: &Self::AstNode, _context: &ParseContext) -> Result<Self, ParseError> {
245 Ok(match node {
246 ast::AssignmentQualifier::Const => Qualifier::Const,
247 ast::AssignmentQualifier::Prop => Qualifier::Prop,
248 })
249 }
250}