• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TyRoXx / NonlocalityOS / 15094543999

18 May 2025 09:28AM UTC coverage: 71.894% (-0.2%) from 72.054%
15094543999

Pull #245

github

web-flow
Merge b2ba4ee99 into 4e7b17925
Pull Request #245: GH-244: multiple parameters actually work

149 of 186 new or added lines in 7 files covered. (80.11%)

6 existing lines in 2 files now uncovered.

3177 of 4419 relevant lines covered (71.89%)

2245.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.92
/lambda_compiler/src/type_checking.rs
1
use crate::{
2
    ast,
3
    compilation::{CompilerOutput, SourceLocation},
4
};
5
use astraea::{
6
    storage::{StoreError, StoreTree},
7
    tree::{HashedTree, Tree},
8
};
9
use lambda::{
10
    expressions::{DeepExpression, Expression},
11
    name::Name,
12
};
13
use std::{collections::BTreeMap, sync::Arc};
14

15
async fn check_tree_construction_or_argument_list<'t: 'u, 'u: 't>(
9✔
16
    arguments: &[ast::Expression],
17
    environment_builder: &'u EnvironmentBuilder<'t>,
18
    storage: &dyn StoreTree,
19
) -> Result<CompilerOutput, StoreError> {
20
    Box::pin(async move {
18✔
21
        let mut errors = Vec::new();
9✔
22
        let mut checked_arguments = Vec::new();
9✔
23
        for argument in arguments {
25✔
24
            let output = check_types(argument, environment_builder, storage).await?;
16✔
NEW
25
            errors.extend(output.errors);
×
26
            if let Some(checked) = output.entry_point {
8✔
NEW
27
                checked_arguments.push(Arc::new(checked));
×
28
            } else {
NEW
29
                return Ok(CompilerOutput::new(None, errors));
×
30
            }
31
        }
32
        Ok(CompilerOutput {
9✔
33
            entry_point: Some(lambda::expressions::DeepExpression(
9✔
34
                lambda::expressions::Expression::ConstructTree(checked_arguments),
9✔
35
            )),
36
            errors,
9✔
37
        })
38
    })
39
    .await
9✔
40
}
41

42
pub struct LocalVariable {}
43

44
pub struct EnvironmentBuilder<'a> {
45
    parent: Option<&'a EnvironmentBuilder<'a>>,
46
    names: BTreeMap<Name, LocalVariable>,
47
}
48

49
impl<'a> EnvironmentBuilder<'a> {
50
    pub fn new(parent: Option<&'a EnvironmentBuilder<'a>>, argument_names: &[Name]) -> Self {
33✔
51
        let mut names = BTreeMap::new();
33✔
52
        for name in argument_names {
51✔
53
            let pre_existed = names.insert(name.clone(), LocalVariable {});
9✔
54
            if pre_existed.is_some() {
9✔
55
                todo!("Duplicate argument name: {}", name);
56
            }
57
        }
58
        Self { parent, names }
59
    }
60

61
    pub fn read(&self, name: &Name, location: &SourceLocation) -> CompilerOutput {
11✔
62
        self.names.get(name).map_or_else(
11✔
63
            || match &self.parent {
2✔
NEW
64
                Some(parent) => parent.read(name, location),
×
65
                None => CompilerOutput::new(
2✔
66
                    None,
2✔
67
                    vec![crate::compilation::CompilerError::new(
2✔
68
                        format!("Identifier {} not found", name),
2✔
69
                        *location,
2✔
70
                    )],
71
                ),
72
            },
73
            |_| {
9✔
74
                CompilerOutput::new(
9✔
75
                    Some(DeepExpression(
9✔
76
                        Expression::make_argument(), /*TODO: access nth child*/
9✔
77
                    )),
78
                    Vec::new(),
9✔
79
                )
80
            },
81
        )
82
    }
83
}
84

85
pub async fn check_lambda<'t, 'u>(
16✔
86
    parameter_names: &[Name],
87
    body: &ast::Expression,
88
    environment_builder: &'u EnvironmentBuilder<'t>,
89
    storage: &dyn StoreTree,
90
) -> Result<CompilerOutput, StoreError> {
91
    Box::pin(async move {
32✔
92
        let lambda_environment_builder =
16✔
93
            EnvironmentBuilder::new(Some(environment_builder), parameter_names);
16✔
94
        let body_output = check_types(body, &lambda_environment_builder, storage).await?;
32✔
NEW
95
        match body_output.entry_point {
×
96
            Some(body_checked) => Ok(CompilerOutput {
16✔
NEW
97
                entry_point: Some(lambda::expressions::DeepExpression(
×
NEW
98
                    lambda::expressions::Expression::Lambda {
×
99
                        // TODO: capture variables
100
                        environment: Arc::new(DeepExpression(Expression::make_literal(
16✔
101
                            storage
16✔
102
                                .store_tree(&HashedTree::from(Arc::new(Tree::empty())))
16✔
103
                                .await?,
16✔
104
                        ))),
NEW
105
                        body: Arc::new(body_checked),
×
106
                    },
107
                )),
NEW
108
                errors: body_output.errors,
×
109
            }),
NEW
110
            None => Ok(CompilerOutput::new(None, body_output.errors)),
×
111
        }
112
    })
113
    .await
16✔
114
}
115

116
pub async fn check_types<'t: 'u, 'u: 't>(
50✔
117
    syntax_tree: &ast::Expression,
118
    environment_builder: &'u EnvironmentBuilder<'t>,
119
    storage: &dyn StoreTree,
120
) -> Result<CompilerOutput, StoreError> {
121
    match syntax_tree {
50✔
122
        ast::Expression::Identifier(name, location) => Ok(environment_builder.read(name, location)),
11✔
123
        ast::Expression::StringLiteral(value) => Ok(CompilerOutput::new(
16✔
UNCOV
124
            Some(lambda::expressions::DeepExpression(
×
UNCOV
125
                lambda::expressions::Expression::Literal(
×
126
                    storage
8✔
127
                        .store_tree(&HashedTree::from(Arc::new(
8✔
128
                            Tree::from_string(value).unwrap(/*TODO*/),
8✔
129
                        )))
130
                        .await?,
8✔
131
                ),
132
            )),
UNCOV
133
            Vec::new(),
×
134
        )),
135
        ast::Expression::Apply { callee, arguments } => {
4✔
136
            Box::pin(async move {
8✔
137
                let callee_output = check_types(callee, environment_builder, storage).await?;
8✔
138

139
                let argument_output = if arguments.len() == 1 {
4✔
140
                    // For N=1 we don't need an indirection.
141
                    check_types(&arguments[0], environment_builder, storage).await?
4✔
142
                } else {
NEW
143
                    check_tree_construction_or_argument_list(
×
NEW
144
                        &arguments[..],
×
NEW
145
                        environment_builder,
×
NEW
146
                        storage,
×
147
                    )
NEW
148
                    .await?
×
149
                };
NEW
150
                let errors = callee_output
×
NEW
151
                    .errors
×
NEW
152
                    .into_iter()
×
NEW
153
                    .chain(argument_output.errors)
×
NEW
154
                    .collect();
×
NEW
155
                match (callee_output.entry_point, argument_output.entry_point) {
×
156
                    (Some(callee_checked), Some(argument_checked)) => Ok(CompilerOutput {
3✔
157
                        entry_point: Some(lambda::expressions::DeepExpression(
3✔
158
                            lambda::expressions::Expression::Apply {
3✔
159
                                callee: Arc::new(callee_checked),
3✔
160
                                argument: Arc::new(argument_checked),
3✔
161
                            },
162
                        )),
163
                        errors,
3✔
164
                    }),
165
                    (None, _) | (_, None) => Ok(CompilerOutput::new(None, errors)),
1✔
166
                }
167
            })
168
            .await
4✔
169
        }
UNCOV
170
        ast::Expression::Lambda {
×
171
            parameter_names,
16✔
172
            body,
16✔
173
        } => check_lambda(&parameter_names[..], body, environment_builder, storage).await,
16✔
174
        ast::Expression::ConstructTree(arguments) => {
9✔
175
            check_tree_construction_or_argument_list(&arguments[..], environment_builder, storage)
9✔
176
                .await
9✔
177
        }
178
        ast::Expression::Braces(expression) => {
2✔
179
            let output = Box::pin(check_types(expression, environment_builder, storage)).await?;
4✔
UNCOV
180
            Ok(output)
×
181
        }
182
    }
183
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc