1
use crate::errors::{FatalParseError, RecoverableParseError};
2
use crate::expression::parse_expression;
3
use crate::field;
4
use crate::parser::ParseContext;
5
use crate::parser::domain::parse_domain;
6
use crate::util::{TypecheckingContext, named_children};
7
use conjure_cp_core::ast::{AbstractLiteral, DomainPtr, Expression};
8
use conjure_cp_core::{domain_int, range};
9
use tree_sitter::Node;
10

            
11
1767445
pub fn parse_abstract(
12
1767445
    ctx: &mut ParseContext,
13
1767445
    node: &Node,
14
1767445
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
15
1767445
    if typecheck_abstract_literal(ctx, node) {
16
24
        return Ok(None);
17
1767421
    }
18

            
19
1767421
    match node.kind() {
20
15480
        "record" => parse_record(ctx, node),
21
14040
        "variant" => parse_variant(ctx, node),
22
205372
        "tuple" => parse_tuple(ctx, node),
23
1014735
        "matrix" => parse_matrix(ctx, node),
24
313912
        "set_literal" => parse_set_literal(ctx, node),
25
25584
        "mset_literal" => parse_mset_literal(ctx, node),
26
162192
        "sequence_literal" => parse_sequence_literal(ctx, node),
27
216
        "function_literal" => parse_function_literal(ctx, node),
28
1752
        "relation_literal" => parse_relation_literal(ctx, node),
29
648
        "partition_literal" => parse_partition_literal(ctx, node),
30
13490
        "permutation_literal" => parse_permutation_literal(ctx, node),
31
        _ => {
32
            ctx.record_error(RecoverableParseError::new(
33
                format!("Expected abstract literal, got: {}", node.kind()),
34
                Some(node.range()),
35
            ));
36
            Ok(None)
37
        }
38
    }
39
1767445
}
40

            
41
1767445
fn typecheck_abstract_literal(ctx: &mut ParseContext, node: &Node) -> bool {
42
1767445
    let expected = match ctx.typechecking_context {
43
        TypecheckingContext::Boolean => "bool",
44
        TypecheckingContext::Arithmetic => "int",
45
2000
        TypecheckingContext::Set => "set",
46
344220
        TypecheckingContext::SetOrMatrix => "set or matrix",
47
        TypecheckingContext::MSet => "mset",
48
47232
        TypecheckingContext::Matrix => "matrix",
49
7008
        TypecheckingContext::Tuple => "tuple",
50
3504
        TypecheckingContext::Record => "record",
51
216
        TypecheckingContext::Partition => "partition",
52
        TypecheckingContext::Permutation => "permutation",
53
7800
        TypecheckingContext::Sequence => "sequence",
54
        TypecheckingContext::Function => "function",
55
        TypecheckingContext::Relation => "relation",
56
1355465
        TypecheckingContext::Unknown => "unknown",
57
    };
58

            
59
1767445
    let got = match node.kind() {
60
313912
        "set_literal" => "set",
61
25584
        "mset_literal" => "mset",
62
162192
        "sequence_literal" => "sequence",
63
216
        "function_literal" => "function",
64
1752
        "relation_literal" => "relation",
65
648
        "partition_literal" => "partition",
66
13490
        "permutation_literal" => "permutation",
67
1014735
        "matrix" => "matrix",
68
205396
        "tuple" => "tuple",
69
15480
        "record" => "record",
70
14040
        "variant" => "variant",
71
        _ => {
72
            ctx.record_error(RecoverableParseError::new(
73
                format!("Expected abstract literal, got: {}", node.kind()),
74
                Some(node.range()),
75
            ));
76
            return true;
77
        }
78
    };
79

            
80
1767445
    if expected != "unknown"
81
411980
        && !(ctx.typechecking_context == TypecheckingContext::SetOrMatrix
82
344220
            && matches!(got, "set" | "matrix"))
83
67784
        && expected != got
84
    {
85
24
        ctx.record_error(RecoverableParseError::new(
86
24
            format!(
87
24
                "Type error: {}\n\tExpected: {}\n\tGot: {}",
88
24
                ctx.source_code[node.start_byte()..node.end_byte()].trim(),
89
24
                expected,
90
24
                got
91
24
            ),
92
24
            Some(node.range()),
93
24
        ));
94
24
        return true;
95
1767421
    }
96

            
97
1767421
    false
98
1767445
}
99

            
100
14040
fn parse_variant(
101
14040
    ctx: &mut ParseContext,
102
14040
    node: &Node,
103
14040
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
104
14040
    let Some(pair) = node.child_by_field_name("name_value_pair") else {
105
        return Ok(None);
106
    };
107
14040
    let Some(name_node) = field!(recover, ctx, pair, "name") else {
108
        return Ok(None);
109
    };
110
14040
    let name = conjure_cp_core::ast::Name::user(
111
14040
        &ctx.source_code[name_node.start_byte()..name_node.end_byte()],
112
14040
    );
113
14040
    let Some(value_node) = field!(recover, ctx, pair, "value") else {
114
        return Ok(None);
115
    };
116
14040
    let saved_context = ctx.typechecking_context;
117
14040
    let saved_inner_context = ctx.inner_typechecking_context;
118
14040
    ctx.typechecking_context = ctx.inner_typechecking_context;
119
14040
    ctx.inner_typechecking_context = TypecheckingContext::Unknown;
120
14040
    let value = parse_expression(ctx, value_node)?;
121
14040
    ctx.typechecking_context = saved_context;
122
14040
    ctx.inner_typechecking_context = saved_inner_context;
123
14040
    let Some(value) = value else {
124
        return Ok(None);
125
    };
126
14040
    Ok(Some(AbstractLiteral::Variant(
127
14040
        conjure_cp_core::ast::Moo::new(conjure_cp_core::ast::records::Field { name, value }),
128
14040
    )))
129
14040
}
130

            
131
15480
fn parse_record(
132
15480
    ctx: &mut ParseContext,
133
15480
    node: &Node,
134
15480
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
135
15480
    let saved_ctx = ctx.typechecking_context;
136
15480
    let saved_inner_ctx = ctx.inner_typechecking_context;
137
15480
    let mut values = Vec::new();
138
15480
    let mut had_error = false;
139
15480
    for child in node.children_by_field_name("name_value_pair", &mut node.walk()) {
140
30960
        let Some(name_node) = field!(recover, ctx, child, "name") else {
141
            return Ok(None);
142
        };
143
30960
        let name_str = &ctx.source_code[name_node.start_byte()..name_node.end_byte()];
144
30960
        let name = conjure_cp_core::ast::Name::user(name_str);
145

            
146
30960
        let Some(value_node) = field!(recover, ctx, child, "value") else {
147
            return Ok(None);
148
        };
149

            
150
        // Record fields are heterogeneous, just like tuple positions.
151
30960
        ctx.typechecking_context = TypecheckingContext::Unknown;
152
30960
        ctx.inner_typechecking_context = TypecheckingContext::Unknown;
153
30960
        let Some(value) = parse_expression(ctx, value_node)? else {
154
            had_error = true;
155
            continue;
156
        };
157

            
158
30960
        values.push(conjure_cp_core::ast::records::Field { name, value });
159
    }
160

            
161
15480
    ctx.typechecking_context = saved_ctx;
162
15480
    ctx.inner_typechecking_context = saved_inner_ctx;
163
15480
    if had_error {
164
        Ok(None)
165
    } else {
166
15480
        Ok(Some(AbstractLiteral::Record(values)))
167
    }
168
15480
}
169

            
170
205372
fn parse_tuple(
171
205372
    ctx: &mut ParseContext,
172
205372
    node: &Node,
173
205372
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
174
    // Save the typechecking context
175
205372
    let saved_ctx = ctx.typechecking_context;
176
205372
    let saved_inner_ctx = ctx.inner_typechecking_context;
177

            
178
205372
    let mut elements = Vec::new();
179
205372
    let mut had_error = false;
180
205372
    for child in named_children(node) {
181
        // A tuple is heterogeneous: each position has its own type, so the surrounding scalar
182
        // context says nothing about any given element. `(y, z)` of type `(int, bool)` must not
183
        // have `z` checked against the tuple's own context.
184
410892
        ctx.typechecking_context = TypecheckingContext::Unknown;
185
410892
        ctx.inner_typechecking_context = TypecheckingContext::Unknown;
186

            
187
410892
        let Some(expr) = parse_expression(ctx, child)? else {
188
            had_error = true;
189
            continue;
190
        };
191
410892
        elements.push(expr);
192
    }
193

            
194
205372
    ctx.typechecking_context = saved_ctx;
195
205372
    ctx.inner_typechecking_context = saved_inner_ctx;
196
205372
    if had_error {
197
        Ok(None)
198
    } else {
199
205372
        Ok(Some(AbstractLiteral::Tuple(elements)))
200
    }
201
205372
}
202

            
203
1014735
fn parse_matrix(
204
1014735
    ctx: &mut ParseContext,
205
1014735
    node: &Node,
206
1014735
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
207
    // Save the typechecking contexts
208
1014735
    let saved_ctx = ctx.typechecking_context;
209
1014735
    let saved_inner_ctx = ctx.inner_typechecking_context;
210

            
211
1014735
    let mut elements = vec![];
212
1014735
    let mut domain: Option<DomainPtr> = None;
213
1014735
    let mut had_error = false;
214
1014735
    for child in named_children(node) {
215
2750143
        if matches!(child.kind(), "single_line_comment" | "language_declaration") {
216
            continue;
217
2750143
        }
218
2750143
        if child.kind() == "arithmetic_expr"
219
1925167
            || child.kind() == "bool_expr"
220
1921271
            || child.kind() == "comparison_expr"
221
1909091
            || child.kind() == "atom"
222
        {
223
            // Parse elements with inner typechecking context
224
2650567
            ctx.typechecking_context = saved_inner_ctx;
225
2650567
            ctx.inner_typechecking_context = TypecheckingContext::Unknown;
226

            
227
2650567
            let Some(expr) = parse_expression(ctx, child)? else {
228
216
                had_error = true;
229
216
                continue;
230
            };
231
2650351
            elements.push(expr);
232
        } else {
233
            // Parse domains with unknown typechecking context
234
99576
            ctx.typechecking_context = TypecheckingContext::Unknown;
235

            
236
99576
            let Some(parsed_domain) = parse_domain(ctx, child)? else {
237
24
                had_error = true;
238
24
                continue;
239
            };
240
99552
            domain = Some(parsed_domain);
241
        }
242
    }
243
1014735
    if domain.is_none() {
244
915183
        let count = elements.len() as i32;
245
915183
        domain = Some(domain_int!(1..count));
246
99552
    }
247

            
248
1014735
    ctx.typechecking_context = saved_ctx;
249
1014735
    ctx.inner_typechecking_context = saved_inner_ctx;
250
1014735
    if had_error {
251
168
        Ok(None)
252
    } else {
253
1014567
        Ok(Some(AbstractLiteral::Matrix(elements, domain.unwrap())))
254
    }
255
1014735
}
256

            
257
314632
fn parse_set_literal(
258
314632
    ctx: &mut ParseContext,
259
314632
    node: &Node,
260
314632
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
261
    // Save the typechecking contexts
262
314632
    let saved_ctx = ctx.typechecking_context;
263
314632
    let saved_inner_ctx = ctx.inner_typechecking_context;
264

            
265
314632
    let mut elements = Vec::new();
266
314632
    let mut had_error = false;
267
314632
    for child in named_children(node) {
268
        // Parse elements with inner typechecking context
269
651368
        ctx.typechecking_context = saved_inner_ctx;
270
651368
        ctx.inner_typechecking_context = TypecheckingContext::Unknown;
271

            
272
651368
        let Some(expr) = parse_expression(ctx, child)? else {
273
72
            had_error = true;
274
72
            continue;
275
        };
276
651296
        elements.push(expr);
277
    }
278

            
279
314632
    ctx.typechecking_context = saved_ctx;
280
314632
    ctx.inner_typechecking_context = saved_inner_ctx;
281
314632
    if had_error {
282
72
        Ok(None)
283
    } else {
284
314560
        Ok(Some(AbstractLiteral::Set(elements)))
285
    }
286
314632
}
287

            
288
25584
fn parse_mset_literal(
289
25584
    ctx: &mut ParseContext,
290
25584
    node: &Node,
291
25584
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
292
25584
    let saved_ctx = ctx.typechecking_context;
293
25584
    let saved_inner_ctx = ctx.inner_typechecking_context;
294
25584
    let mut elements = Vec::new();
295
25584
    let mut had_error = false;
296
25584
    for child in named_children(node) {
297
34056
        ctx.typechecking_context = saved_inner_ctx;
298
34056
        ctx.inner_typechecking_context = TypecheckingContext::Unknown;
299
34056
        let Some(expression) = parse_expression(ctx, child)? else {
300
            had_error = true;
301
            continue;
302
        };
303
34056
        elements.push(expression);
304
    }
305
25584
    ctx.typechecking_context = saved_ctx;
306
25584
    ctx.inner_typechecking_context = saved_inner_ctx;
307
25584
    if had_error {
308
        Ok(None)
309
    } else {
310
25584
        Ok(Some(AbstractLiteral::MSet(elements)))
311
    }
312
25584
}
313

            
314
162192
fn parse_sequence_literal(
315
162192
    ctx: &mut ParseContext,
316
162192
    node: &Node,
317
162192
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
318
162192
    let saved_ctx = ctx.typechecking_context;
319
162192
    let saved_inner_ctx = ctx.inner_typechecking_context;
320
162192
    let mut elements = Vec::new();
321
162192
    let mut had_error = false;
322
162192
    for child in named_children(node) {
323
312864
        ctx.typechecking_context = saved_inner_ctx;
324
312864
        ctx.inner_typechecking_context = TypecheckingContext::Unknown;
325
312864
        let Some(expression) = parse_expression(ctx, child)? else {
326
            had_error = true;
327
            continue;
328
        };
329
312864
        elements.push(expression);
330
    }
331
162192
    ctx.typechecking_context = saved_ctx;
332
162192
    ctx.inner_typechecking_context = saved_inner_ctx;
333
162192
    if had_error {
334
        Ok(None)
335
    } else {
336
162192
        Ok(Some(AbstractLiteral::Sequence(elements)))
337
    }
338
162192
}
339

            
340
216
fn parse_function_literal(
341
216
    ctx: &mut ParseContext,
342
216
    node: &Node,
343
216
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
344
216
    let saved_ctx = ctx.typechecking_context;
345
216
    let saved_inner_ctx = ctx.inner_typechecking_context;
346
216
    let mut pairs = Vec::new();
347
216
    let mut had_error = false;
348
216
    for pair in named_children(node) {
349
        // key/value can be of any type (matching the domain/codomain of the function), so
350
        // typecheck context is relaxed here, mirroring the other abstract literal parsers.
351
360
        ctx.typechecking_context = TypecheckingContext::Unknown;
352
360
        ctx.inner_typechecking_context = TypecheckingContext::Unknown;
353

            
354
360
        let Some(key_node) = field!(recover, ctx, pair, "key") else {
355
            had_error = true;
356
            continue;
357
        };
358
360
        let Some(key) = parse_expression(ctx, key_node)? else {
359
            had_error = true;
360
            continue;
361
        };
362

            
363
360
        let Some(value_node) = field!(recover, ctx, pair, "value") else {
364
            had_error = true;
365
            continue;
366
        };
367
360
        let Some(value) = parse_expression(ctx, value_node)? else {
368
            had_error = true;
369
            continue;
370
        };
371

            
372
360
        pairs.push((key, value));
373
    }
374
216
    ctx.typechecking_context = saved_ctx;
375
216
    ctx.inner_typechecking_context = saved_inner_ctx;
376
216
    if had_error {
377
        Ok(None)
378
    } else {
379
216
        Ok(Some(AbstractLiteral::Function(pairs)))
380
    }
381
216
}
382

            
383
1752
fn parse_relation_literal(
384
1752
    ctx: &mut ParseContext,
385
1752
    node: &Node,
386
1752
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
387
1752
    let saved_ctx = ctx.typechecking_context;
388
1752
    let saved_inner_ctx = ctx.inner_typechecking_context;
389
1752
    let mut tuples = Vec::new();
390
1752
    let mut had_error = false;
391
1752
    for tuple_node in named_children(node) {
392
5256
        let mut fields = Vec::new();
393
5256
        for field_node in named_children(&tuple_node) {
394
            // Each column can be of any type (matching the relation's own column domains), so
395
            // typecheck context is relaxed here, mirroring the other abstract literal parsers.
396
10512
            ctx.typechecking_context = TypecheckingContext::Unknown;
397
10512
            ctx.inner_typechecking_context = TypecheckingContext::Unknown;
398

            
399
10512
            let Some(expr) = parse_expression(ctx, field_node)? else {
400
                had_error = true;
401
                continue;
402
            };
403
10512
            fields.push(expr);
404
        }
405
5256
        tuples.push(fields);
406
    }
407
1752
    ctx.typechecking_context = saved_ctx;
408
1752
    ctx.inner_typechecking_context = saved_inner_ctx;
409
1752
    if had_error {
410
        Ok(None)
411
    } else {
412
1752
        Ok(Some(AbstractLiteral::Relation(tuples)))
413
    }
414
1752
}
415

            
416
648
fn parse_partition_literal(
417
648
    ctx: &mut ParseContext,
418
648
    node: &Node,
419
648
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
420
648
    let saved_ctx = ctx.typechecking_context;
421
648
    let saved_inner_ctx = ctx.inner_typechecking_context;
422
648
    let mut parts = Vec::new();
423
648
    let mut had_error = false;
424
648
    for part_node in named_children(node) {
425
        // Each part is itself a set literal; its elements can be of any type (matching the
426
        // partition's own inner domain), so typecheck context is relaxed here, mirroring the
427
        // other abstract literal parsers.
428
720
        ctx.typechecking_context = TypecheckingContext::Unknown;
429
720
        ctx.inner_typechecking_context = TypecheckingContext::Unknown;
430

            
431
720
        let Some(AbstractLiteral::Set(elements)) = parse_set_literal(ctx, &part_node)? else {
432
            had_error = true;
433
            continue;
434
        };
435
720
        parts.push(elements);
436
    }
437
648
    ctx.typechecking_context = saved_ctx;
438
648
    ctx.inner_typechecking_context = saved_inner_ctx;
439
648
    if had_error {
440
        Ok(None)
441
    } else {
442
648
        Ok(Some(AbstractLiteral::Partition(parts)))
443
    }
444
648
}
445

            
446
13490
fn parse_permutation_literal(
447
13490
    ctx: &mut ParseContext,
448
13490
    node: &Node,
449
13490
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
450
13490
    let saved_ctx = ctx.typechecking_context;
451
13490
    let saved_inner_ctx = ctx.inner_typechecking_context;
452
13490
    let mut cycles = Vec::new();
453
13490
    let mut had_error = false;
454
13490
    for cycle_node in named_children(node) {
455
13850
        let mut elements = Vec::new();
456
13850
        for element_node in named_children(&cycle_node) {
457
            // Each element can be of any type (matching the permutation's own inner domain), so
458
            // typecheck context is relaxed here, mirroring the other abstract literal parsers.
459
40685
            ctx.typechecking_context = TypecheckingContext::Unknown;
460
40685
            ctx.inner_typechecking_context = TypecheckingContext::Unknown;
461

            
462
40685
            let Some(expr) = parse_expression(ctx, element_node)? else {
463
                had_error = true;
464
                continue;
465
            };
466
40685
            elements.push(expr);
467
        }
468
13850
        cycles.push(elements);
469
    }
470
13490
    ctx.typechecking_context = saved_ctx;
471
13490
    ctx.inner_typechecking_context = saved_inner_ctx;
472
13490
    if had_error {
473
        Ok(None)
474
    } else {
475
13490
        Ok(Some(AbstractLiteral::Permutation(cycles)))
476
    }
477
13490
}