open_vaf/ast_lowering/mod.rs
1/*
2 * ******************************************************************************************
3 * Copyright (c) 2019 Pascal Kuthe. This file is part of the OpenVAF project.
4 * It is subject to the license terms in the LICENSE file found in the top-level directory
5 * of this distribution and at https://gitlab.com/DSPOM/OpenVAF/blob/master/LICENSE.
6 * No part of OpenVAF, including this file, may be copied, modified, propagated, or
7 * distributed except according to the terms contained in the LICENSE file.
8 * *****************************************************************************************
9 */
10
11//! This module is responsible for lowering an [`Ast`](crate::ast::Ast) to an [`Hir`](crate::hir::Hir)
12//!
13//! The main transformations in this module are
14//!
15//! * [**Name resolution**](name_resolution) -
16//! Names (such as variable references) are resolved to declarations.
17//! It is enforced that the resolved declarations are the right type of Hir node
18//! (no type checking that happens during [hir_lowering](crate::hir_lowering).
19//! Ids of the resolved declarations are then stored in the HIR inplace of identifiers in the AST
20//!
21//! * [**Branch resolution**](BranchResolver) -
22//! Unnamed branches ( accessed using for example using `<nature>(<net1>,<net2>)` ) are created as needed
23//! and tracked so that the same unnamed branch isn't created multiple times.
24//! Furthermore it is enforced that disciplines of the nets defining a branch are comparable
25//! and that branches are only accessed using the flow/potential Nature of those disciplines
26//!
27//! * **Context based information** -
28//! Some expressions and statements are not allowed in some places (for example in an analog/digital context).
29//! During the fold these (states)[ast_to_hir_fold::VerilogContext) are tracked and errors are generated when an illegal expressions/statements is used
30//!
31//!
32//! The lowering process happens in a series of folds implemented in the [`ast_to_hir_fold`] module
33//!
34//!
35pub use ast_to_hir_fold::Fold;
36#[doc(inline)]
37pub use branch_resolution::BranchResolver;
38
39use crate::ast::Ast;
40use crate::ast_lowering::ast_to_hir_fold::{DeclarationHandler, Global};
41use crate::ast_lowering::error::Error;
42use crate::ir::hir::Hir;
43use crate::SourceMap;
44
45#[cfg(test)]
46mod test;
47#[macro_use]
48pub mod name_resolution;
49pub mod ast_to_hir_fold;
50mod branch_resolution;
51pub mod error;
52
53//TODO input/output enforcement
54
55impl Ast {
56 /// Lowers an AST to an HIR by resolving references, ambiguities and enforcing nature/discipline comparability
57 pub fn lower(mut self) -> Result<Hir, (Vec<Error>, Self)> {
58 self.try_fold_to_hir().map_err(|err| (err, self))
59 }
60
61 /// Lowers an AST to an HIR by resolving references, ambiguities and enforcing nature/discipline comparability
62 pub fn lower_with_decl_handler(
63 mut self,
64 declaration_handler: &mut impl DeclarationHandler,
65 ) -> Result<Hir, (Vec<Error>, Self)> {
66 self.try_fold_to_hir_with_decl_handler(declaration_handler)
67 .map_err(|err| (err, self))
68 }
69
70 /// Lowers an AST to an HIR by resolving references, ambiguities and enforcing nature/discipline comparability and printing any errors or warnings that might occur
71 pub fn lower_and_print_errors(
72 self,
73 source_map: &SourceMap,
74 translate_lines: bool,
75 ) -> Option<Hir> {
76 self.lower()
77 .map_err(|(errors, ast)| {
78 errors
79 .into_iter()
80 .for_each(|err| err.print(source_map, &ast, translate_lines))
81 })
82 .ok()
83 }
84
85 /// Lowers an AST to an HIR by resolving references, ambiguities and enforcing nature/discipline comparability and printing any errors or warnings that might occur
86 pub fn lower_and_print_errors_with_var_decl_handle(
87 self,
88 source_map: &SourceMap,
89 translate_lines: bool,
90 declaration_handler: &mut impl DeclarationHandler,
91 ) -> Option<Hir> {
92 self.lower_with_decl_handler(declaration_handler)
93 .map_err(|(errors, ast)| {
94 errors
95 .into_iter()
96 .for_each(|err| err.print(source_map, &ast, translate_lines))
97 })
98 .ok()
99 }
100
101 /// A Helper method to avoid code duplication until try blocks are stable
102 fn try_fold_to_hir(&mut self) -> Result<Hir, Vec<Error>> {
103 Ok(Global::new(self, &mut ()).fold()?.fold()?.fold()?)
104 }
105 fn try_fold_to_hir_with_decl_handler(
106 &mut self,
107 declaration_handler: &mut impl DeclarationHandler,
108 ) -> Result<Hir, Vec<Error>> {
109 Ok(Global::new(self, declaration_handler)
110 .fold()?
111 .fold()?
112 .fold()?)
113 }
114}