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

TyRoXx / NonlocalityOS / 14775573298

01 May 2025 12:44PM UTC coverage: 76.482% (-1.2%) from 77.667%
14775573298

Pull #221

github

web-flow
Merge 0afee8720 into e15d5670f
Pull Request #221: Hello world

281 of 359 new or added lines in 9 files covered. (78.27%)

18 existing lines in 4 files now uncovered.

3948 of 5162 relevant lines covered (76.48%)

1826.01 hits per line

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

60.58
/lambda_compiler/src/parsing.rs
1
use crate::{
2
    compilation::{CompilerError, CompilerOutput, SourceLocation},
3
    tokenization::{Token, TokenContent},
4
};
5
use astraea::tree::{HashedValue, Value};
6
use lambda::expressions::{DeepExpression, Expression};
7
use lambda::types::{Name, NamespaceId};
8
use std::sync::Arc;
9

10
#[derive(Debug)]
11
pub struct ParserError {
12
    pub message: String,
13
}
14

15
impl ParserError {
16
    pub fn new(message: String) -> Self {
1✔
17
        Self { message }
18
    }
19
}
20

21
impl std::fmt::Display for ParserError {
22
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1✔
23
        write!(f, "{}", &self.message)
1✔
24
    }
25
}
26

27
pub type ParserResult<T> = std::result::Result<T, ParserError>;
28

29
pub fn pop_next_non_whitespace_token<'t>(
45✔
30
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
31
) -> Option<&'t Token> {
32
    let token = peek_next_non_whitespace_token(tokens);
45✔
33
    if token.is_some() {
85✔
34
        tokens.next();
40✔
35
    }
36

37
    return token;
45✔
38
}
39

40
pub fn peek_next_non_whitespace_token<'t>(
61✔
41
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
42
) -> Option<&'t Token> {
43
    loop {
×
44
        let next = tokens.peek();
75✔
45
        match next {
75✔
46
            Some(token) => match token.content {
60✔
47
                TokenContent::Whitespace => {
×
48
                    tokens.next();
14✔
49
                    continue;
14✔
50
                }
51
                TokenContent::Identifier(_)
×
52
                | TokenContent::Assign
×
53
                | TokenContent::LeftParenthesis
×
54
                | TokenContent::RightParenthesis
×
55
                | TokenContent::Dot
×
56
                | TokenContent::Quotes(_)
×
57
                | TokenContent::FatArrow => return Some(token),
46✔
58
            },
59
            None => return None,
15✔
60
        }
61
    }
62
}
63

64
fn expect_right_parenthesis(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) {
10✔
65
    match pop_next_non_whitespace_token(tokens) {
10✔
66
        Some(non_whitespace) => match &non_whitespace.content {
10✔
67
            TokenContent::Whitespace => todo!(),
68
            TokenContent::Identifier(_) => todo!(),
69
            TokenContent::Assign => todo!(),
70
            TokenContent::LeftParenthesis => todo!(),
71
            TokenContent::RightParenthesis => {}
10✔
72
            TokenContent::Dot => todo!(),
73
            TokenContent::Quotes(_) => todo!(),
74
            TokenContent::FatArrow => todo!(),
75
        },
76
        None => todo!(),
77
    }
78
}
79

80
fn expect_fat_arrow(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) {
7✔
81
    match pop_next_non_whitespace_token(tokens) {
7✔
82
        Some(non_whitespace) => match &non_whitespace.content {
7✔
83
            TokenContent::Whitespace => todo!(),
84
            TokenContent::Identifier(_) => todo!(),
85
            TokenContent::Assign => todo!(),
86
            TokenContent::LeftParenthesis => todo!(),
87
            TokenContent::RightParenthesis => todo!(),
88
            TokenContent::Dot => todo!(),
89
            TokenContent::Quotes(_) => todo!(),
90
            TokenContent::FatArrow => {}
7✔
91
        },
92
        None => todo!(),
93
    }
94
}
95

96
async fn parse_expression_start<'t>(
17✔
97
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
98
    local_namespace: &NamespaceId,
99
) -> ParserResult<DeepExpression> {
100
    match pop_next_non_whitespace_token(tokens) {
17✔
101
        Some(non_whitespace) => match &non_whitespace.content {
16✔
102
            TokenContent::Whitespace => todo!(),
103
            TokenContent::Identifier(identifier) => Ok(DeepExpression(Expression::ReadVariable(
8✔
104
                Name::new(*local_namespace, identifier.clone()),
8✔
105
            ))),
106
            TokenContent::Assign => todo!(),
107
            TokenContent::LeftParenthesis => Box::pin(parse_lambda(tokens, local_namespace)).await,
7✔
108
            TokenContent::RightParenthesis => todo!(),
109
            TokenContent::Dot => todo!(),
110
            TokenContent::Quotes(content) => Ok(DeepExpression(Expression::Literal(
1✔
111
                HashedValue::from(Arc::new(
1✔
112
                    Value::from_string(&content).expect("It's too long. That's what she said."),
1✔
113
                ))
114
                .digest()
1✔
115
                .clone(),
1✔
116
            ))),
117
            TokenContent::FatArrow => todo!(),
118
        },
119
        None => Err(ParserError::new(
1✔
120
            "Expected expression, got EOF.".to_string(),
1✔
121
        )),
122
    }
123
}
124

125
pub async fn parse_expression<'t>(
17✔
126
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
127
    local_namespace: &NamespaceId,
128
) -> ParserResult<DeepExpression> {
129
    let start = parse_expression_start(tokens, local_namespace).await?;
34✔
130
    match peek_next_non_whitespace_token(tokens) {
×
131
        Some(more) => match &more.content {
6✔
132
            TokenContent::Whitespace => unreachable!(),
133
            TokenContent::Identifier(_) => Ok(start),
×
134
            TokenContent::Assign => Ok(start),
×
135
            TokenContent::LeftParenthesis => {
×
136
                tokens.next();
3✔
137
                let argument = Box::pin(parse_expression(tokens, local_namespace)).await?;
6✔
138
                expect_right_parenthesis(tokens);
×
NEW
139
                Ok(DeepExpression(Expression::make_apply(
×
NEW
140
                    Arc::new(start),
×
NEW
141
                    Arc::new(argument),
×
142
                )))
143
            }
144
            TokenContent::RightParenthesis => Ok(start),
3✔
145
            TokenContent::Dot => todo!(),
146
            TokenContent::Quotes(_) => todo!(),
147
            TokenContent::FatArrow => todo!(),
148
        },
149
        None => Ok(start),
10✔
150
    }
151
}
152

153
async fn parse_lambda<'t>(
7✔
154
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
155
    local_namespace: &NamespaceId,
156
) -> ParserResult<DeepExpression> {
157
    let parameter_name: Name = Name::new(
158
        *local_namespace,
7✔
159
        match pop_next_non_whitespace_token(tokens) {
7✔
160
            Some(non_whitespace) => match &non_whitespace.content {
7✔
161
                TokenContent::Whitespace => todo!(),
×
162
                TokenContent::Identifier(identifier) => identifier.clone(),
7✔
163
                TokenContent::Assign => todo!(),
×
164
                TokenContent::LeftParenthesis => todo!(),
×
165
                TokenContent::RightParenthesis => todo!(),
×
166
                TokenContent::Dot => todo!(),
×
167
                TokenContent::Quotes(_) => todo!(),
×
168
                TokenContent::FatArrow => todo!(),
×
169
            },
170
            None => todo!(),
×
171
        },
172
    );
173
    expect_right_parenthesis(tokens);
7✔
174
    expect_fat_arrow(tokens);
7✔
175
    let body = parse_expression(tokens, local_namespace).await?;
14✔
NEW
176
    Ok(DeepExpression(Expression::make_lambda(
×
UNCOV
177
        parameter_name,
×
NEW
178
        Arc::new(body),
×
179
    )))
180
}
181

182
pub async fn parse_entry_point_lambda<'t>(
4✔
183
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
184
    local_namespace: &NamespaceId,
185
) -> CompilerOutput {
186
    let mut errors = Vec::new();
4✔
187
    let entry_point_result = parse_expression(tokens, local_namespace).await;
8✔
188
    match entry_point_result {
4✔
189
        Ok(entry_point) => match &entry_point.0 {
3✔
190
            Expression::Unit
×
NEW
191
            | Expression::Literal(_)
×
NEW
192
            | Expression::Apply {
×
NEW
193
                callee: _,
×
NEW
194
                argument: _,
×
195
            }
196
            | Expression::ReadVariable(_) => {
×
197
                errors.push(CompilerError::new(
×
198
                    "The entry point is expected to be a lambda expression.".to_string(),
×
199
                    SourceLocation::new(0, 0),
×
200
                ));
NEW
201
                CompilerOutput::new(DeepExpression(Expression::Unit), errors)
×
202
            }
NEW
203
            Expression::Lambda {
×
NEW
204
                parameter_name: _,
×
NEW
205
                body: _,
×
206
            } => CompilerOutput::new(entry_point, errors),
3✔
NEW
207
            Expression::Construct(_arguments) => {
×
208
                todo!()
209
            }
210
        },
211
        Err(error) => {
1✔
212
            errors.push(CompilerError::new(
1✔
213
                format!("Parser error: {}", &error),
1✔
214
                SourceLocation::new(0, 0),
1✔
215
            ));
216
            CompilerOutput::new(DeepExpression(Expression::Unit), errors)
1✔
217
        }
218
    }
219
}
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