1use crate::parser::ast::{self, Spanned};
7use crate::parser::ast_schema as schema;
8use crate::policy::Expression as CoreExpression;
9
10impl From<&ast::FileMetadata> for schema::FileMetadata {
15 fn from(m: &ast::FileMetadata) -> Self {
16 schema::FileMetadata {
17 namespace: m.namespace.clone(),
18 version: m.version.clone(),
19 owner: m.owner.clone(),
20 profile: m.profile.clone(),
21 imports: m.imports.iter().map(|i| i.into()).collect(),
22 }
23 }
24}
25
26impl From<&ast::ImportDecl> for schema::ImportDecl {
27 fn from(i: &ast::ImportDecl) -> Self {
28 schema::ImportDecl {
29 specifier: (&i.specifier).into(),
30 from_module: i.from_module.clone(),
31 }
32 }
33}
34
35impl From<&ast::ImportSpecifier> for schema::ImportSpecifier {
36 fn from(s: &ast::ImportSpecifier) -> Self {
37 match s {
38 ast::ImportSpecifier::Named(items) => schema::ImportSpecifier::Named {
39 items: items.iter().map(|i| i.into()).collect(),
40 },
41 ast::ImportSpecifier::Wildcard(alias) => schema::ImportSpecifier::Wildcard {
42 alias: alias.clone(),
43 },
44 }
45 }
46}
47
48impl From<&ast::ImportItem> for schema::ImportItem {
49 fn from(i: &ast::ImportItem) -> Self {
50 schema::ImportItem {
51 name: i.name.clone(),
52 alias: i.alias.clone(),
53 }
54 }
55}
56
57impl From<&ast::PolicyMetadata> for schema::PolicyMetadata {
62 fn from(m: &ast::PolicyMetadata) -> Self {
63 schema::PolicyMetadata {
64 kind: m.kind.as_ref().map(|k| k.into()),
65 modality: m.modality.as_ref().map(|m| m.into()),
66 priority: m.priority,
67 rationale: m.rationale.clone(),
68 tags: m.tags.clone(),
69 }
70 }
71}
72
73impl From<&ast::PolicyKind> for schema::PolicyKind {
74 fn from(k: &ast::PolicyKind) -> Self {
75 match k {
76 ast::PolicyKind::Constraint => schema::PolicyKind::Constraint,
77 ast::PolicyKind::Derivation => schema::PolicyKind::Derivation,
78 ast::PolicyKind::Obligation => schema::PolicyKind::Obligation,
79 }
80 }
81}
82
83impl From<&ast::PolicyModality> for schema::PolicyModality {
84 fn from(m: &ast::PolicyModality) -> Self {
85 match m {
86 ast::PolicyModality::Obligation => schema::PolicyModality::Obligation,
87 ast::PolicyModality::Prohibition => schema::PolicyModality::Prohibition,
88 ast::PolicyModality::Permission => schema::PolicyModality::Permission,
89 }
90 }
91}
92
93impl From<&ast::MetricMetadata> for schema::MetricMetadata {
98 fn from(m: &ast::MetricMetadata) -> Self {
99 schema::MetricMetadata {
100 refresh_interval: m
101 .refresh_interval
102 .map(|d| format!("PT{}S", d.num_seconds())),
103 unit: m.unit.clone(),
104 threshold: m.threshold.map(|d| d.to_string()),
105 severity: m.severity.as_ref().map(|s| s.into()),
106 target: m.target.map(|d| d.to_string()),
107 window: m.window.map(|d| format!("PT{}S", d.num_seconds())),
108 }
109 }
110}
111
112impl From<&crate::primitives::Severity> for schema::Severity {
113 fn from(s: &crate::primitives::Severity) -> Self {
114 match s {
115 crate::primitives::Severity::Info => schema::Severity::Info,
116 crate::primitives::Severity::Warning => schema::Severity::Warning,
117 crate::primitives::Severity::Error => schema::Severity::Error,
118 _ => schema::Severity::Error,
120 }
121 }
122}
123
124impl From<&ast::TargetFormat> for schema::TargetFormat {
129 fn from(t: &ast::TargetFormat) -> Self {
130 match t {
131 ast::TargetFormat::Calm => schema::TargetFormat::Calm,
132 ast::TargetFormat::Kg => schema::TargetFormat::Kg,
133 ast::TargetFormat::Sbvr => schema::TargetFormat::Sbvr,
134 ast::TargetFormat::Protobuf => schema::TargetFormat::Protobuf,
135 }
136 }
137}
138
139impl From<&ast::MappingRule> for schema::MappingRule {
140 fn from(r: &ast::MappingRule) -> Self {
141 schema::MappingRule {
142 primitive_type: r.primitive_type.clone(),
143 primitive_name: r.primitive_name.clone(),
144 target_type: r.target_type.clone(),
145 fields: r.fields.clone(),
146 }
147 }
148}
149
150impl From<&ast::ProjectionOverride> for schema::ProjectionOverride {
151 fn from(o: &ast::ProjectionOverride) -> Self {
152 schema::ProjectionOverride {
153 primitive_type: o.primitive_type.clone(),
154 primitive_name: o.primitive_name.clone(),
155 fields: o.fields.clone(),
156 }
157 }
158}
159
160impl From<&CoreExpression> for schema::Expression {
165 fn from(e: &CoreExpression) -> Self {
166 match e {
167 CoreExpression::Literal(v) => schema::Expression::Literal { value: v.clone() },
168 CoreExpression::QuantityLiteral { value, unit } => {
169 schema::Expression::QuantityLiteral {
170 value: value.to_string(),
171 unit: unit.clone(),
172 }
173 }
174 CoreExpression::TimeLiteral(ts) => schema::Expression::TimeLiteral {
175 timestamp: ts.clone(),
176 },
177 CoreExpression::IntervalLiteral { start, end } => schema::Expression::IntervalLiteral {
178 start: start.clone(),
179 end: end.clone(),
180 },
181 CoreExpression::Variable(name) => schema::Expression::Variable { name: name.clone() },
182 CoreExpression::GroupBy {
183 variable,
184 collection,
185 filter,
186 key,
187 condition,
188 } => schema::Expression::GroupBy {
189 variable: variable.clone(),
190 collection: Box::new(collection.as_ref().into()),
191 filter: filter.as_ref().map(|f| Box::new(f.as_ref().into())),
192 key: Box::new(key.as_ref().into()),
193 condition: Box::new(condition.as_ref().into()),
194 },
195 CoreExpression::Binary { op, left, right } => schema::Expression::Binary {
196 op: op.into(),
197 left: Box::new(left.as_ref().into()),
198 right: Box::new(right.as_ref().into()),
199 },
200 CoreExpression::Unary { op, operand } => schema::Expression::Unary {
201 op: op.into(),
202 operand: Box::new(operand.as_ref().into()),
203 },
204 CoreExpression::Cast {
205 operand,
206 target_type,
207 } => schema::Expression::Cast {
208 operand: Box::new(operand.as_ref().into()),
209 target_type: target_type.clone(),
210 },
211 CoreExpression::Quantifier {
212 quantifier,
213 variable,
214 collection,
215 condition,
216 } => schema::Expression::Quantifier {
217 quantifier: quantifier.into(),
218 variable: variable.clone(),
219 collection: Box::new(collection.as_ref().into()),
220 condition: Box::new(condition.as_ref().into()),
221 },
222 CoreExpression::MemberAccess { object, member } => schema::Expression::MemberAccess {
223 object: object.clone(),
224 member: member.clone(),
225 },
226 CoreExpression::Aggregation {
227 function,
228 collection,
229 field,
230 filter,
231 } => schema::Expression::Aggregation {
232 function: function.into(),
233 collection: Box::new(collection.as_ref().into()),
234 field: field.clone(),
235 filter: filter.as_ref().map(|f| Box::new(f.as_ref().into())),
236 },
237 CoreExpression::AggregationComprehension {
238 function,
239 variable,
240 collection,
241 window,
242 predicate,
243 projection,
244 target_unit,
245 } => schema::Expression::AggregationComprehension {
246 function: function.into(),
247 variable: variable.clone(),
248 collection: Box::new(collection.as_ref().into()),
249 window: window.as_ref().map(|w| w.into()),
250 predicate: Box::new(predicate.as_ref().into()),
251 projection: Box::new(projection.as_ref().into()),
252 target_unit: target_unit.clone(),
253 },
254 }
255 }
256}
257
258impl From<&crate::policy::BinaryOp> for schema::BinaryOp {
259 fn from(op: &crate::policy::BinaryOp) -> Self {
260 match op {
261 crate::policy::BinaryOp::And => schema::BinaryOp::And,
262 crate::policy::BinaryOp::Or => schema::BinaryOp::Or,
263 crate::policy::BinaryOp::Equal => schema::BinaryOp::Equal,
264 crate::policy::BinaryOp::NotEqual => schema::BinaryOp::NotEqual,
265 crate::policy::BinaryOp::GreaterThan => schema::BinaryOp::GreaterThan,
266 crate::policy::BinaryOp::LessThan => schema::BinaryOp::LessThan,
267 crate::policy::BinaryOp::GreaterThanOrEqual => schema::BinaryOp::GreaterThanOrEqual,
268 crate::policy::BinaryOp::LessThanOrEqual => schema::BinaryOp::LessThanOrEqual,
269 crate::policy::BinaryOp::Plus => schema::BinaryOp::Plus,
270 crate::policy::BinaryOp::Minus => schema::BinaryOp::Minus,
271 crate::policy::BinaryOp::Multiply => schema::BinaryOp::Multiply,
272 crate::policy::BinaryOp::Divide => schema::BinaryOp::Divide,
273 crate::policy::BinaryOp::Contains => schema::BinaryOp::Contains,
274 crate::policy::BinaryOp::StartsWith => schema::BinaryOp::StartsWith,
275 crate::policy::BinaryOp::EndsWith => schema::BinaryOp::EndsWith,
276 crate::policy::BinaryOp::Matches => schema::BinaryOp::Matches,
277 crate::policy::BinaryOp::HasRole => schema::BinaryOp::HasRole,
278 crate::policy::BinaryOp::Before => schema::BinaryOp::Before,
279 crate::policy::BinaryOp::After => schema::BinaryOp::After,
280 crate::policy::BinaryOp::During => schema::BinaryOp::During,
281 }
282 }
283}
284
285impl From<&crate::policy::UnaryOp> for schema::UnaryOp {
286 fn from(op: &crate::policy::UnaryOp) -> Self {
287 match op {
288 crate::policy::UnaryOp::Not => schema::UnaryOp::Not,
289 crate::policy::UnaryOp::Negate => schema::UnaryOp::Negate,
290 }
291 }
292}
293
294impl From<&crate::policy::Quantifier> for schema::Quantifier {
295 fn from(q: &crate::policy::Quantifier) -> Self {
296 match q {
297 crate::policy::Quantifier::ForAll => schema::Quantifier::ForAll,
298 crate::policy::Quantifier::Exists => schema::Quantifier::Exists,
299 crate::policy::Quantifier::ExistsUnique => schema::Quantifier::ExistsUnique,
300 }
301 }
302}
303
304impl From<&crate::policy::AggregateFunction> for schema::AggregateFunction {
305 fn from(f: &crate::policy::AggregateFunction) -> Self {
306 match f {
307 crate::policy::AggregateFunction::Count => schema::AggregateFunction::Count,
308 crate::policy::AggregateFunction::Sum => schema::AggregateFunction::Sum,
309 crate::policy::AggregateFunction::Min => schema::AggregateFunction::Min,
310 crate::policy::AggregateFunction::Max => schema::AggregateFunction::Max,
311 crate::policy::AggregateFunction::Avg => schema::AggregateFunction::Avg,
312 }
313 }
314}
315
316impl From<&crate::policy::WindowSpec> for schema::WindowSpec {
317 fn from(w: &crate::policy::WindowSpec) -> Self {
318 schema::WindowSpec {
319 duration: w.duration,
320 unit: "seconds".to_string(),
321 }
322 }
323}
324
325impl From<&Spanned<ast::AstNode>> for schema::SpannedAstNode {
330 fn from(s: &Spanned<ast::AstNode>) -> Self {
331 schema::SpannedAstNode {
332 node: (&s.node).into(),
333 line: s.line,
334 column: s.column,
335 }
336 }
337}
338
339impl From<&ast::AstNode> for schema::AstNode {
340 fn from(n: &ast::AstNode) -> Self {
341 match n {
342 ast::AstNode::Export(inner) => schema::AstNode::Export {
343 declaration: Box::new(inner.as_ref().into()),
344 },
345 ast::AstNode::Entity {
346 name,
347 version,
348 annotations,
349 domain,
350 } => schema::AstNode::Entity {
351 name: name.clone(),
352 version: version.clone(),
353 annotations: annotations.clone(),
354 domain: domain.clone(),
355 },
356 ast::AstNode::Resource {
357 name,
358 annotations,
359 unit_name,
360 domain,
361 } => schema::AstNode::Resource {
362 name: name.clone(),
363 annotations: annotations.clone(),
364 unit_name: unit_name.clone(),
365 domain: domain.clone(),
366 },
367 ast::AstNode::Flow {
368 resource_name,
369 annotations,
370 from_entity,
371 to_entity,
372 quantity,
373 } => schema::AstNode::Flow {
374 resource_name: resource_name.clone(),
375 annotations: annotations.clone(),
376 from_entity: from_entity.clone(),
377 to_entity: to_entity.clone(),
378 quantity: *quantity,
379 },
380 ast::AstNode::Pattern { name, regex } => schema::AstNode::Pattern {
381 name: name.clone(),
382 regex: regex.clone(),
383 },
384 ast::AstNode::Role { name, domain } => schema::AstNode::Role {
385 name: name.clone(),
386 domain: domain.clone(),
387 },
388 ast::AstNode::Relation {
389 name,
390 subject_role,
391 predicate,
392 object_role,
393 via_flow,
394 } => schema::AstNode::Relation {
395 name: name.clone(),
396 subject_role: subject_role.clone(),
397 predicate: predicate.clone(),
398 object_role: object_role.clone(),
399 via_flow: via_flow.clone(),
400 },
401 ast::AstNode::Dimension { name } => schema::AstNode::Dimension { name: name.clone() },
402 ast::AstNode::UnitDeclaration {
403 symbol,
404 dimension,
405 factor,
406 base_unit,
407 } => schema::AstNode::UnitDeclaration {
408 symbol: symbol.clone(),
409 dimension: dimension.clone(),
410 factor: factor.to_string(),
411 base_unit: base_unit.clone(),
412 },
413 ast::AstNode::Policy {
414 name,
415 version,
416 metadata,
417 expression,
418 } => schema::AstNode::Policy {
419 name: name.clone(),
420 version: version.clone(),
421 metadata: metadata.into(),
422 expression: expression.into(),
423 },
424 ast::AstNode::Instance {
425 name,
426 entity_type,
427 fields,
428 } => schema::AstNode::Instance {
429 name: name.clone(),
430 entity_type: entity_type.clone(),
431 fields: fields.iter().map(|(k, v)| (k.clone(), v.into())).collect(),
432 },
433 ast::AstNode::ConceptChange {
434 name,
435 from_version,
436 to_version,
437 migration_policy,
438 breaking_change,
439 } => schema::AstNode::ConceptChange {
440 name: name.clone(),
441 from_version: from_version.clone(),
442 to_version: to_version.clone(),
443 migration_policy: migration_policy.clone(),
444 breaking_change: *breaking_change,
445 },
446 ast::AstNode::Metric {
447 name,
448 expression,
449 metadata,
450 } => schema::AstNode::Metric {
451 name: name.clone(),
452 expression: expression.into(),
453 metadata: metadata.into(),
454 },
455 ast::AstNode::MappingDecl {
456 name,
457 target,
458 rules,
459 } => schema::AstNode::MappingDecl {
460 name: name.clone(),
461 target: target.into(),
462 rules: rules.iter().map(|r| r.into()).collect(),
463 },
464 ast::AstNode::ProjectionDecl {
465 name,
466 target,
467 overrides,
468 } => schema::AstNode::ProjectionDecl {
469 name: name.clone(),
470 target: target.into(),
471 overrides: overrides.iter().map(|o| o.into()).collect(),
472 },
473 }
474 }
475}
476
477impl From<&ast::Ast> for schema::Ast {
482 fn from(a: &ast::Ast) -> Self {
483 schema::Ast {
484 metadata: (&a.metadata).into(),
485 declarations: a.declarations.iter().map(|d| d.into()).collect(),
486 }
487 }
488}
489
490impl From<ast::Ast> for schema::Ast {
491 fn from(a: ast::Ast) -> Self {
492 (&a).into()
493 }
494}