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}