Coverage Report

Created: 2026-09-04 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dhall-0.13.0/src/lib.rs
Line
Count
Source
1
#![doc(html_root_url = "https://docs.rs/dhall/0.13.0")]
2
#![allow(
3
    clippy::implicit_hasher,
4
    clippy::module_inception,
5
    clippy::needless_lifetimes,
6
    clippy::needless_question_mark,
7
    clippy::new_ret_no_self,
8
    clippy::new_without_default,
9
    clippy::try_err,
10
    clippy::unnecessary_wraps,
11
    clippy::upper_case_acronyms,
12
    clippy::useless_format,
13
    unknown_lints
14
)]
15
16
pub mod builtins;
17
pub mod ctxt;
18
pub mod error;
19
pub mod operations;
20
pub mod semantics;
21
pub mod syntax;
22
pub mod utils;
23
24
use std::path::Path;
25
use url::Url;
26
27
use crate::error::{Error, TypeError};
28
use crate::semantics::parse;
29
use crate::semantics::resolve;
30
use crate::semantics::resolve::ImportLocation;
31
use crate::semantics::{typecheck, typecheck_with, Hir, Nir, Tir, Type};
32
use crate::syntax::Expr;
33
34
pub use ctxt::*;
35
36
#[derive(Debug, Clone)]
37
pub struct Parsed(Expr, ImportLocation);
38
39
/// An expression where all imports have been resolved
40
///
41
/// Invariant: there must be no `Import` nodes or `ImportAlt` operations left.
42
#[derive(Debug, Clone)]
43
pub struct Resolved<'cx>(Hir<'cx>);
44
45
/// A typed expression
46
#[derive(Debug, Clone)]
47
pub struct Typed<'cx> {
48
    pub hir: Hir<'cx>,
49
    pub ty: Type<'cx>,
50
}
51
52
/// A normalized expression.
53
///
54
/// This is actually a lie, because the expression will only get normalized on demand.
55
#[derive(Debug, Clone)]
56
pub struct Normalized<'cx>(Nir<'cx>);
57
58
/// Controls conversion from `Nir` to `Expr`
59
#[derive(Copy, Clone, Default)]
60
pub struct ToExprOptions {
61
    /// Whether to convert all variables to `_`
62
    pub alpha: bool,
63
}
64
65
impl Parsed {
66
    /// Construct from an `Expr`. This `Expr` will have imports disabled.
67
0
    pub fn from_expr_without_imports(e: Expr) -> Self {
68
0
        Parsed(e, ImportLocation::dhall_code_without_imports())
69
0
    }
70
71
0
    pub fn parse_file(f: &Path) -> Result<Parsed, Error> {
72
0
        parse::parse_file(f)
73
0
    }
74
0
    pub fn parse_remote(url: Url) -> Result<Parsed, Error> {
75
0
        parse::parse_remote(url)
76
0
    }
77
0
    pub fn parse_str(s: &str) -> Result<Parsed, Error> {
78
0
        parse::parse_str(s)
79
0
    }
80
0
    pub fn parse_binary_file(f: &Path) -> Result<Parsed, Error> {
81
0
        parse::parse_binary_file(f)
82
0
    }
83
    #[allow(dead_code)]
84
0
    pub fn parse_binary(data: &[u8]) -> Result<Parsed, Error> {
85
0
        parse::parse_binary(data)
86
0
    }
87
88
0
    pub fn resolve<'cx>(self, cx: Ctxt<'cx>) -> Result<Resolved<'cx>, Error> {
89
0
        resolve::resolve(cx, self)
90
0
    }
91
0
    pub fn skip_resolve<'cx>(
92
0
        self,
93
0
        cx: Ctxt<'cx>,
94
0
    ) -> Result<Resolved<'cx>, Error> {
95
0
        resolve::skip_resolve(cx, self)
96
0
    }
97
98
    /// Converts a value back to the corresponding AST expression.
99
0
    pub fn to_expr(&self) -> Expr {
100
0
        self.0.clone()
101
0
    }
102
103
0
    pub fn add_let_binding(self, label: syntax::Label, value: Expr) -> Parsed {
104
0
        let Parsed(expr, import_location) = self;
105
0
        Parsed(expr.add_let_binding(label, value), import_location)
106
0
    }
107
}
108
109
impl<'cx> Resolved<'cx> {
110
0
    pub fn typecheck(&self, cx: Ctxt<'cx>) -> Result<Typed<'cx>, TypeError> {
111
0
        Ok(Typed::from_tir(typecheck(cx, &self.0)?))
112
0
    }
113
0
    pub fn typecheck_with(
114
0
        self,
115
0
        cx: Ctxt<'cx>,
116
0
        ty: &Hir<'cx>,
117
0
    ) -> Result<Typed<'cx>, TypeError> {
118
0
        Ok(Typed::from_tir(typecheck_with(cx, &self.0, ty)?))
119
0
    }
120
    /// Converts a value back to the corresponding AST expression.
121
0
    pub fn to_expr(&self, cx: Ctxt<'cx>) -> Expr {
122
0
        self.0.to_expr_noopts(cx)
123
0
    }
124
}
125
126
impl<'cx> Typed<'cx> {
127
0
    fn from_tir(tir: Tir<'cx, '_>) -> Self {
128
0
        Typed {
129
0
            hir: tir.as_hir().clone(),
130
0
            ty: tir.ty().clone(),
131
0
        }
132
0
    }
133
    /// Reduce an expression to its normal form, performing beta reduction
134
0
    pub fn normalize(&self, cx: Ctxt<'cx>) -> Normalized<'cx> {
135
0
        Normalized(self.hir.eval_closed_expr(cx))
136
0
    }
137
138
    /// Converts a value back to the corresponding AST expression.
139
0
    fn to_expr(&self, cx: Ctxt<'cx>) -> Expr {
140
0
        self.hir.to_expr(cx, ToExprOptions { alpha: false })
141
0
    }
142
143
0
    pub fn as_hir(&self) -> &Hir<'cx> {
144
0
        &self.hir
145
0
    }
146
0
    pub fn ty(&self) -> &Type<'cx> {
147
0
        &self.ty
148
0
    }
149
0
    pub fn get_type(&self) -> Result<Normalized<'cx>, TypeError> {
150
0
        Ok(Normalized(self.ty.clone().into_nir()))
151
0
    }
152
}
153
154
impl<'cx> Normalized<'cx> {
155
    /// Converts a value back to the corresponding AST expression.
156
0
    pub fn to_expr(&self, cx: Ctxt<'cx>) -> Expr {
157
0
        self.0.to_expr(cx, ToExprOptions::default())
158
0
    }
159
    /// Converts a value back to the corresponding Hir expression.
160
0
    pub fn to_hir(&self) -> Hir<'cx> {
161
0
        self.0.to_hir_noenv()
162
0
    }
163
0
    pub fn as_nir(&self) -> &Nir<'cx> {
164
0
        &self.0
165
0
    }
166
    /// Converts a value back to the corresponding AST expression, alpha-normalizing in the process.
167
0
    pub fn to_expr_alpha(&self, cx: Ctxt<'cx>) -> Expr {
168
0
        self.0.to_expr(cx, ToExprOptions { alpha: true })
169
0
    }
170
}
171
172
macro_rules! derive_traits_for_wrapper_struct {
173
    ($ty:ident) => {
174
        impl std::cmp::PartialEq for $ty {
175
0
            fn eq(&self, other: &Self) -> bool {
176
0
                self.0 == other.0
177
0
            }
178
        }
179
180
        impl std::cmp::Eq for $ty {}
181
182
        impl std::fmt::Display for $ty {
183
0
            fn fmt(
184
0
                &self,
185
0
                f: &mut std::fmt::Formatter,
186
0
            ) -> Result<(), std::fmt::Error> {
187
0
                self.0.fmt(f)
188
0
            }
189
        }
190
    };
191
}
192
193
derive_traits_for_wrapper_struct!(Parsed);
194
195
impl From<Parsed> for Expr {
196
0
    fn from(other: Parsed) -> Self {
197
0
        other.to_expr()
198
0
    }
199
}
200
201
impl<'cx> Eq for Normalized<'cx> {}
202
impl<'cx> PartialEq for Normalized<'cx> {
203
0
    fn eq(&self, other: &Self) -> bool {
204
0
        self.0 == other.0
205
0
    }
206
}