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

TyRoXx / NonlocalityOS / 13852727264

14 Mar 2025 08:30AM UTC coverage: 79.181% (-0.6%) from 79.739%
13852727264

Pull #202

github

web-flow
Merge 2ad6a92a0 into 49862011f
Pull Request #202: Compiler update

4024 of 5082 relevant lines covered (79.18%)

1854.76 hits per line

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

63.73
/lambda_compiler/src/parsing.rs
1
use crate::{
2
    compilation::{CompilerError, CompilerOutput, SourceLocation},
3
    tokenization::{Token, TokenContent},
4
};
5
use astraea::tree::{BlobDigest, HashedValue, Value};
6
use lambda::builtins::{BUILTINS_NAMESPACE, LAMBDA_APPLY_METHOD_NAME, UTF8_STRING_TYPE_NAME};
7
use lambda::expressions::{Application, Expression, LambdaExpression};
8
use lambda::types::{Name, NamespaceId, Type};
9
use std::sync::Arc;
10

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

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

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

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

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

38
    return token;
45✔
39
}
40

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

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

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

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

129
pub async fn parse_expression<'t>(
17✔
130
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
131
    local_namespace: &NamespaceId,
132
) -> ParserResult<Expression> {
133
    let start = parse_expression_start(tokens, local_namespace).await?;
34✔
134
    match peek_next_non_whitespace_token(tokens) {
×
135
        Some(more) => match &more.content {
6✔
136
            TokenContent::Whitespace => unreachable!(),
137
            TokenContent::Identifier(_) => Ok(start),
×
138
            TokenContent::Assign => Ok(start),
×
139
            TokenContent::LeftParenthesis => {
×
140
                tokens.next();
3✔
141
                let argument = Box::pin(parse_expression(tokens, local_namespace)).await?;
6✔
142
                expect_right_parenthesis(tokens);
×
143
                Ok(Expression::Apply(Box::new(Application::new(
×
144
                    start,
×
145
                    BlobDigest::hash(b"todo"),
×
146
                    Name::new(BUILTINS_NAMESPACE, LAMBDA_APPLY_METHOD_NAME.to_string()),
×
147
                    argument,
×
148
                ))))
149
            }
150
            TokenContent::RightParenthesis => Ok(start),
3✔
151
            TokenContent::Dot => todo!(),
152
            TokenContent::Quotes(_) => todo!(),
153
            TokenContent::FatArrow => todo!(),
154
        },
155
        None => Ok(start),
10✔
156
    }
157
}
158

159
async fn parse_lambda<'t>(
7✔
160
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
161
    local_namespace: &NamespaceId,
162
) -> ParserResult<Expression> {
163
    let parameter_name = Name::new(
164
        *local_namespace,
7✔
165
        match pop_next_non_whitespace_token(tokens) {
7✔
166
            Some(non_whitespace) => match &non_whitespace.content {
7✔
167
                TokenContent::Whitespace => todo!(),
×
168
                TokenContent::Identifier(identifier) => identifier.clone(),
7✔
169
                TokenContent::Assign => todo!(),
×
170
                TokenContent::LeftParenthesis => todo!(),
×
171
                TokenContent::RightParenthesis => todo!(),
×
172
                TokenContent::Dot => todo!(),
×
173
                TokenContent::Quotes(_) => todo!(),
×
174
                TokenContent::FatArrow => todo!(),
×
175
            },
176
            None => todo!(),
×
177
        },
178
    );
179
    expect_right_parenthesis(tokens);
7✔
180
    expect_fat_arrow(tokens);
7✔
181
    let body = parse_expression(tokens, local_namespace).await?;
14✔
182
    Ok(Expression::Lambda(Box::new(LambdaExpression::new(
×
183
        Type::Unit, // todo: do propper typechecking
184
        parameter_name,
×
185
        body,
×
186
    ))))
187
}
188

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