Skip to main content

scheme_rs/
ast.rs

1//! Data structures for expanding and representing Scheme code.
2
3// TODO: All of these functions need to be improved to reduce the amount of
4// cloning that occurs. I was going to add that as part of the set-of-scopes
5// change, but it proved too unwieldy
6
7use crate::{
8    Either,
9    cps::{Compile, PrimOp},
10    env::{Binding, Environment, Local, Scope, Var},
11    exceptions::Exception,
12    expand::{SyntaxRule, Template},
13    gc::Trace,
14    proc::{ContBarrier, Procedure},
15    runtime::Runtime,
16    symbols::Symbol,
17    syntax::{Identifier, Span, Syntax},
18    value::{Expect1, Value},
19};
20
21use scheme_rs_macros::{maybe_async, maybe_await};
22use std::{fmt, str::FromStr, sync::Arc};
23
24use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
25
26#[cfg(feature = "async")]
27use futures::future::BoxFuture;
28
29/// Collection of errors that can occur while parsing, grouped in functions to
30/// ensure consistency in their error messages.
31mod error {
32    use crate::exceptions::{Message, SyntaxViolation};
33
34    use super::*;
35
36    pub(super) fn syntax_error(
37        form: &Syntax,
38        subform: Option<&Syntax>,
39        error: impl fmt::Display,
40    ) -> Exception {
41        Exception::from((
42            SyntaxViolation::new(form.clone(), subform.cloned()),
43            Message::new(error),
44        ))
45    }
46
47    pub(super) fn bad_form(form: &Syntax, subform: Option<&Syntax>) -> Exception {
48        syntax_error(form, subform, "bad form")
49    }
50
51    pub(super) fn undefined_variable(form: &Syntax, subform: Option<&Syntax>) -> Exception {
52        syntax_error(form, subform, "undefined variable")
53    }
54
55    pub(super) fn immutable_variable(form: &Syntax, subform: &Syntax) -> Exception {
56        syntax_error(form, Some(subform), "cannot set immutable variable")
57    }
58
59    pub(super) fn name_previously_bound(form: &Syntax, subform: &Syntax) -> Exception {
60        syntax_error(form, Some(subform), "name previously bound")
61    }
62
63    pub(super) fn expected_list(form: &Syntax) -> Exception {
64        syntax_error(form, None, "expected list")
65    }
66
67    pub(super) fn expected_more_arguments(form: &Syntax) -> Exception {
68        syntax_error(form, None, "expected more arguments")
69    }
70
71    pub(super) fn expected_identifier(form: &Syntax, subform: Option<&Syntax>) -> Exception {
72        syntax_error(form, subform, "expected identifier")
73    }
74
75    pub(super) fn expected_body(form: &Syntax) -> Exception {
76        syntax_error(form, None, "expected body")
77    }
78
79    pub(super) fn expected_import_spec(form: &Syntax) -> Exception {
80        syntax_error(form, None, "expected import spec")
81    }
82
83    pub(super) fn expected_export_spec(form: &Syntax) -> Exception {
84        syntax_error(form, None, "expected export spec")
85    }
86
87    pub(super) fn expected_number(form: &Syntax, subform: &Syntax) -> Exception {
88        syntax_error(form, Some(subform), "expected number")
89    }
90
91    pub(super) fn expected_keyword(form: &Syntax, subform: &Syntax, keyword: &str) -> Exception {
92        syntax_error(form, Some(subform), format!("expected `{keyword}` keyword"))
93    }
94
95    pub(super) fn unexpected_argument(form: &Syntax, subform: &Syntax) -> Exception {
96        syntax_error(form, Some(subform), "unexpected argument")
97    }
98
99    pub(super) fn unexpected_define(form: &Syntax) -> Exception {
100        syntax_error(form, None, "unexpected define")
101    }
102
103    pub(super) fn unexpected_define_syntax(form: &Syntax) -> Exception {
104        syntax_error(form, None, "unexpected define-syntax")
105    }
106
107    pub(super) fn unexpected_import(form: &Syntax) -> Exception {
108        syntax_error(form, None, "illegal import")
109    }
110
111    pub(super) fn import_not_permitted(form: &Syntax, lib_name: &[Symbol]) -> Exception {
112        let lib_name = lib_name
113            .iter()
114            .map(|s| s.to_str().to_string())
115            .collect::<Vec<_>>()
116            .join(" ");
117        syntax_error(
118            form,
119            None,
120            format!("import of ({lib_name}) is not permitted"),
121        )
122    }
123
124    pub(super) fn unexpected_empty_list(form: &Syntax, subform: Option<&Syntax>) -> Exception {
125        syntax_error(form, subform, "unexpected empty list")
126    }
127}
128
129/// Primitives that the compiler needs to be aware of in order to create a
130/// proper AST as specified by R6RS base.
131#[derive(Copy, Clone, Trace, Debug, PartialEq, Eq)]
132pub enum Primitive {
133    Undefined,
134    Begin,
135    Lambda,
136    Let,
137    LetSyntax,
138    LetRecSyntax,
139    If,
140    And,
141    Or,
142    Quote,
143    Syntax,
144    SyntaxCase,
145    Set,
146    Define,
147    DefineSyntax,
148    Import,
149}
150
151#[derive(Debug)]
152pub struct LibrarySpec {
153    pub(crate) name: LibraryName,
154    pub(crate) exports: ExportSpec,
155    pub(crate) imports: ImportSpec,
156    pub(crate) body: Syntax,
157}
158
159impl LibrarySpec {
160    pub fn parse(form: &Syntax) -> Result<Self, Exception> {
161        match form.as_list() {
162            Some(
163                [
164                    library_keyword @ Syntax::Identifier {
165                        ident: library_decl,
166                        ..
167                    },
168                    library_name,
169                    body @ ..,
170                    end,
171                ],
172            ) if end.is_null() => {
173                if library_decl != "library" {
174                    return Err(error::expected_keyword(form, library_keyword, "library"));
175                }
176                let mut exports = ExportSpec::default();
177                let mut imports = ImportSpec::default();
178                let mut body = body;
179                while let Some(spec) = body.first() {
180                    if spec.has_car("export") {
181                        exports.join(ExportSpec::parse(spec)?);
182                    } else if spec.has_car("import") {
183                        imports.join(ImportSpec::parse(spec)?);
184                    } else {
185                        break;
186                    }
187                    body = &body[1..];
188                }
189                let mut body = body.to_vec();
190                let end = end.clone();
191                let body = if body.is_empty() {
192                    end
193                } else {
194                    body.push(end);
195                    Syntax::List {
196                        span: body[0].span().clone(),
197                        list: body,
198                    }
199                };
200
201                Ok(Self {
202                    name: LibraryName::parse(library_name)?,
203                    exports,
204                    imports,
205                    body,
206                })
207            }
208            _ => Err(error::bad_form(form, None)),
209        }
210    }
211}
212
213#[derive(Clone, Default, PartialEq, Eq, Hash, Trace, Debug)]
214pub struct LibraryName {
215    pub name: Vec<Symbol>,
216    pub version: Version,
217}
218
219impl LibraryName {
220    pub fn parse(form: &Syntax) -> Result<Self, Exception> {
221        match form.as_list() {
222            Some([name @ .., Syntax::List { list: version, .. }, end]) if end.is_null() => {
223                Ok(Self {
224                    name: list_to_name(name, form)?,
225                    version: Version::parse(version, form)?,
226                })
227            }
228            Some([name @ .., end]) if end.is_null() => Ok(Self {
229                name: list_to_name(name, form)?,
230                version: Version::default(),
231            }),
232            _ => Err(error::bad_form(form, None)),
233        }
234    }
235
236    pub fn from_str(s: &str, file_name: Option<&str>) -> Result<Self, Exception> {
237        let form = Syntax::from_str(s, file_name)?;
238        match form.as_list() {
239            Some([item, end]) if end.is_null() => Self::parse(item),
240            _ => Err(Exception::error(format!(
241                "expected a single library form, got: {s}"
242            ))),
243        }
244    }
245
246    pub fn name(&self) -> String {
247        let lib_name = self
248            .name
249            .iter()
250            .map(|x| x.to_string())
251            .collect::<Vec<String>>();
252        format!("({})", lib_name.join(" "))
253    }
254}
255
256fn list_to_name(name: &[Syntax], form: &Syntax) -> Result<Vec<Symbol>, Exception> {
257    name.iter()
258        .map(|name| {
259            if let Syntax::Identifier { ident, .. } = name {
260                Ok(ident.sym)
261            } else {
262                Err(error::expected_identifier(form, Some(name)))
263            }
264        })
265        .collect()
266}
267
268/*
269#[derive(Debug)]
270pub enum ParseLibraryNameError {
271    ParseSyntaxError(ParseSyntaxError),
272    ParseAstError(ParseAstError),
273}
274
275impl From<ParseSyntaxError> for ParseLibraryNameError {
276    fn from(pse: ParseSyntaxError) -> Self {
277        Self::ParseSyntaxError(pse)
278    }
279}
280
281impl From<ParseAstError> for ParseLibraryNameError {
282    fn from(pae: ParseAstError) -> Self {
283        Self::ParseAstError(pae)
284    }
285}
286*/
287
288#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default, Trace, Debug)]
289pub struct Version {
290    version: Vec<usize>,
291}
292
293impl Version {
294    fn parse(version: &[Syntax], form: &Syntax) -> Result<Self, Exception> {
295        match version {
296            [version @ .., end] if end.is_null() => {
297                let version: Result<Vec<usize>, _> = version
298                    .iter()
299                    .map(|subvers| {
300                        if let Syntax::Wrapped { value, .. } = subvers {
301                            Ok(value.try_into()?)
302                        } else {
303                            Err(error::expected_number(form, subvers))
304                        }
305                    })
306                    .collect();
307                Ok(Self { version: version? })
308            }
309            _ => Err(error::bad_form(form, None)),
310        }
311    }
312}
313
314impl fmt::Display for Version {
315    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316        write!(f, "(")?;
317        for (i, sv) in self.version.iter().enumerate() {
318            if i > 0 {
319                write!(f, " ")?;
320            }
321            write!(f, "{sv}")?;
322        }
323        write!(f, ")")
324    }
325}
326
327impl<const N: usize> From<[usize; N]> for Version {
328    fn from(value: [usize; N]) -> Self {
329        Self {
330            version: Vec::from(value),
331        }
332    }
333}
334
335#[derive(Debug)]
336pub enum VersionReference {
337    SubVersions(Vec<SubVersionReference>),
338    And(Vec<VersionReference>),
339    Or(Vec<VersionReference>),
340    Not(Box<VersionReference>),
341}
342
343impl VersionReference {
344    pub fn matches(&self, version: &Version) -> bool {
345        match self {
346            Self::SubVersions(subversions) if version.version.len() >= subversions.len() => {
347                subversions
348                    .iter()
349                    .zip(version.version.iter())
350                    .all(|(svr, ver)| svr.matches(*ver))
351            }
352            Self::SubVersions(_) => false,
353            Self::And(vrs) => vrs.iter().all(|vr| vr.matches(version)),
354            Self::Or(vrs) => vrs.iter().any(|vr| vr.matches(version)),
355            Self::Not(vr) => !vr.matches(version),
356        }
357    }
358
359    fn parse(form: &Syntax) -> Result<Self, Exception> {
360        match form.as_list() {
361            Some([Syntax::Identifier { ident: kw, .. }, version_refs @ .., end])
362                if kw == "and" && end.is_null() =>
363            {
364                let version_refs = version_refs
365                    .iter()
366                    .map(VersionReference::parse)
367                    .collect::<Result<Vec<_>, _>>()?;
368                Ok(Self::And(version_refs))
369            }
370            Some([Syntax::Identifier { ident: kw, .. }, version_refs @ .., end])
371                if kw == "or" && end.is_null() =>
372            {
373                let version_refs = version_refs
374                    .iter()
375                    .map(VersionReference::parse)
376                    .collect::<Result<Vec<_>, _>>()?;
377                Ok(Self::Or(version_refs))
378            }
379            Some([Syntax::Identifier { ident: kw, .. }, version_ref, end])
380                if kw == "not" && end.is_null() =>
381            {
382                let version_ref = VersionReference::parse(version_ref)?;
383                Ok(Self::Not(Box::new(version_ref)))
384            }
385            Some([subversion_refs @ .., end]) if end.is_null() => {
386                let subversion_refs = subversion_refs
387                    .iter()
388                    .map(SubVersionReference::parse)
389                    .collect::<Result<Vec<_>, _>>()?;
390                Ok(Self::SubVersions(subversion_refs))
391            }
392            None => Err(error::expected_list(form)),
393            _ => Err(error::bad_form(form, None)),
394        }
395    }
396}
397
398impl fmt::Display for VersionReference {
399    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400        match self {
401            Self::SubVersions(svs) => {
402                write!(f, "(")?;
403                for (i, sv) in svs.iter().enumerate() {
404                    if i > 0 {
405                        write!(f, " ")?;
406                    }
407                    write!(f, "{sv}")?;
408                }
409                write!(f, ")")
410            }
411            Self::And(svs) => {
412                write!(f, "(and ")?;
413                for (i, sv) in svs.iter().enumerate() {
414                    if i > 0 {
415                        write!(f, " ")?;
416                    }
417                    write!(f, "{sv}")?;
418                }
419                write!(f, ")")
420            }
421            Self::Or(svs) => {
422                write!(f, "(and ")?;
423                for (i, sv) in svs.iter().enumerate() {
424                    if i > 0 {
425                        write!(f, " ")?;
426                    }
427                    write!(f, "{sv}")?;
428                }
429                write!(f, ")")
430            }
431            Self::Not(sv) => {
432                write!(f, "(not {sv})")
433            }
434        }
435    }
436}
437
438#[derive(Debug)]
439pub enum SubVersionReference {
440    SubVersion(usize),
441    Gte(usize),
442    Lte(usize),
443    And(Vec<SubVersionReference>),
444    Or(Vec<SubVersionReference>),
445    Not(Box<SubVersionReference>),
446}
447
448impl SubVersionReference {
449    fn matches(&self, lhs: usize) -> bool {
450        match self {
451            Self::SubVersion(rhs) => lhs == *rhs,
452            Self::Gte(rhs) => lhs >= *rhs,
453            Self::Lte(rhs) => lhs <= *rhs,
454            Self::And(refs) => refs.iter().all(|r| r.matches(lhs)),
455            Self::Or(refs) => refs.iter().any(|r| r.matches(lhs)),
456            Self::Not(svr) => !svr.matches(lhs),
457        }
458    }
459
460    fn parse(form: &Syntax) -> Result<Self, Exception> {
461        match form {
462            Syntax::Wrapped { value, .. } => Ok(Self::SubVersion(value.try_into()?)),
463            _ => match form.as_list() {
464                Some(
465                    [
466                        Syntax::Identifier { ident: kw, .. },
467                        Syntax::Wrapped { value, .. },
468                        end,
469                    ],
470                ) if kw == ">=" && end.is_null() => Ok(Self::Gte(value.try_into()?)),
471                Some(
472                    [
473                        Syntax::Identifier { ident: kw, .. },
474                        Syntax::Wrapped { value, .. },
475                        end,
476                    ],
477                ) if kw == "<=" && end.is_null() => Ok(Self::Lte(value.try_into()?)),
478                Some(
479                    [
480                        Syntax::Identifier { ident: kw, .. },
481                        subversion_refs @ ..,
482                        end,
483                    ],
484                ) if kw == "and" && end.is_null() => {
485                    let subversion_refs = subversion_refs
486                        .iter()
487                        .map(SubVersionReference::parse)
488                        .collect::<Result<Vec<_>, _>>()?;
489                    Ok(Self::And(subversion_refs))
490                }
491                Some(
492                    [
493                        Syntax::Identifier { ident: kw, .. },
494                        subversion_refs @ ..,
495                        end,
496                    ],
497                ) if kw == "or" && end.is_null() => {
498                    let subversion_refs = subversion_refs
499                        .iter()
500                        .map(SubVersionReference::parse)
501                        .collect::<Result<Vec<_>, _>>()?;
502                    Ok(Self::Or(subversion_refs))
503                }
504                Some([Syntax::Identifier { ident: kw, .. }, subversion_ref, end])
505                    if kw == "not" && end.is_null() =>
506                {
507                    let subversion_ref = SubVersionReference::parse(subversion_ref)?;
508                    Ok(Self::Not(Box::new(subversion_ref)))
509                }
510                None => Err(error::expected_list(form)),
511                _ => Err(error::bad_form(form, None)),
512            },
513        }
514    }
515}
516
517impl fmt::Display for SubVersionReference {
518    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519        match self {
520            Self::SubVersion(sv) => write!(f, "{sv}"),
521            Self::Gte(sv) => write!(f, "(>= {sv})"),
522            Self::Lte(sv) => write!(f, "(<= {sv})"),
523            Self::And(svs) => {
524                write!(f, "(and ")?;
525                for (i, sv) in svs.iter().enumerate() {
526                    if i > 0 {
527                        write!(f, " ")?;
528                    }
529                    write!(f, "{sv}")?;
530                }
531                write!(f, ")")
532            }
533            Self::Or(svs) => {
534                write!(f, "(and ")?;
535                for (i, sv) in svs.iter().enumerate() {
536                    if i > 0 {
537                        write!(f, " ")?;
538                    }
539                    write!(f, "{sv}")?;
540                }
541                write!(f, ")")
542            }
543            Self::Not(sv) => {
544                write!(f, "(not {sv})")
545            }
546        }
547    }
548}
549
550#[derive(Debug)]
551pub enum ExportSet {
552    Internal {
553        rename: Option<Symbol>,
554        name: Symbol,
555    },
556    External(ImportSpec),
557}
558
559impl ExportSet {
560    pub fn parse_rename(form: &Syntax) -> Result<Self, Exception> {
561        match form.as_list() {
562            Some(
563                [
564                    Syntax::Identifier { ident: from, .. },
565                    Syntax::Identifier { ident: to, .. },
566                    end,
567                ],
568            ) if end.is_null() => Ok(Self::Internal {
569                rename: Some(to.sym),
570                name: from.sym,
571            }),
572            _ => Err(error::bad_form(form, None)),
573        }
574    }
575
576    pub fn parse(form: &Syntax) -> Result<Vec<Self>, Exception> {
577        match form {
578            Syntax::Identifier { ident, .. } => Ok(vec![Self::Internal {
579                rename: None,
580                name: ident.sym,
581            }]),
582            Syntax::List { list, .. } => match list.as_slice() {
583                [Syntax::Identifier { ident, .. }, renames @ .., end]
584                    if ident == "rename" && end.is_null() =>
585                {
586                    Ok(renames
587                        .iter()
588                        .map(Self::parse_rename)
589                        .collect::<Result<Vec<_>, _>>()?)
590                }
591                [Syntax::Identifier { ident, .. }, .., end]
592                    if ident == "import" && end.is_null() =>
593                {
594                    Ok(vec![Self::External(ImportSpec::parse(form)?)])
595                }
596                _ => Err(error::bad_form(form, None)),
597            },
598            _ => Err(error::bad_form(form, None)),
599        }
600    }
601}
602
603#[derive(Default, Debug)]
604pub struct ExportSpec {
605    pub(crate) export_sets: Vec<ExportSet>,
606}
607
608impl ExportSpec {
609    pub fn parse(form: &Syntax) -> Result<Self, Exception> {
610        match form.as_list() {
611            Some(
612                [
613                    Syntax::Identifier {
614                        ident: export_decl, ..
615                    },
616                    exports @ ..,
617                    end,
618                ],
619            ) if export_decl == "export" && end.is_null() => Ok(ExportSpec {
620                export_sets: exports
621                    .iter()
622                    .map(ExportSet::parse)
623                    .collect::<Result<Vec<_>, _>>()?
624                    .into_iter()
625                    .flatten()
626                    .collect(),
627            }),
628            _ => Err(error::expected_export_spec(form)),
629        }
630    }
631
632    pub fn join(&mut self, rhs: ExportSpec) {
633        self.export_sets.extend(rhs.export_sets);
634    }
635}
636
637#[derive(Default, Debug)]
638pub struct ImportSpec {
639    pub(crate) import_sets: Vec<ImportSet>,
640}
641
642impl ImportSpec {
643    pub fn parse(form: &Syntax) -> Result<Self, Exception> {
644        match form.as_list() {
645            Some(
646                [
647                    Syntax::Identifier {
648                        ident: import_decl, ..
649                    },
650                    imports @ ..,
651                    end,
652                ],
653            ) if import_decl == "import" && end.is_null() => Ok(ImportSpec {
654                import_sets: imports
655                    .iter()
656                    .map(|import| ImportSet::parse(discard_for(import)))
657                    .collect::<Result<Vec<_>, _>>()?,
658            }),
659            _ => Err(error::expected_import_spec(form)),
660        }
661    }
662
663    pub fn join(&mut self, rhs: ImportSpec) {
664        self.import_sets.extend(rhs.import_sets);
665    }
666}
667
668pub(crate) fn discard_for(syn: &Syntax) -> &Syntax {
669    match syn.as_list() {
670        Some(
671            [
672                Syntax::Identifier { ident: for_kw, .. },
673                import_set,
674                _import_level @ ..,
675                end,
676            ],
677        ) if for_kw == "for" && end.is_null() => {
678            // We should eventually check that the import levels are well
679            // formed, even if we ignore them.
680            import_set
681        }
682        _ => syn,
683    }
684}
685
686#[derive(Debug)]
687pub enum ImportSet {
688    Library(LibraryReference),
689    Only {
690        set: Box<ImportSet>,
691        allowed: HashSet<Symbol>,
692    },
693    Except {
694        set: Box<ImportSet>,
695        disallowed: HashSet<Symbol>,
696    },
697    Prefix {
698        set: Box<ImportSet>,
699        prefix: Symbol,
700    },
701    Rename {
702        set: Box<ImportSet>,
703        /// Imported identifiers to rename (from, to).
704        renames: HashMap<Symbol, Symbol>,
705    },
706}
707
708impl ImportSet {
709    pub fn parse(form: &Syntax) -> Result<Self, Exception> {
710        match form.as_list() {
711            Some(
712                [
713                    Syntax::Identifier {
714                        ident: import_type, ..
715                    },
716                    lib_ref,
717                    end,
718                ],
719            ) if import_type == "library" && end.is_null() => {
720                Ok(Self::Library(LibraryReference::parse(lib_ref)?))
721            }
722            Some(
723                [
724                    Syntax::Identifier {
725                        ident: import_type, ..
726                    },
727                    import_set,
728                    imports @ ..,
729                    end,
730                ],
731            ) if import_type == "only" && end.is_null() => {
732                let import_set = ImportSet::parse(import_set)?;
733                let allowed = imports
734                    .iter()
735                    .map(|allowed| match allowed {
736                        Syntax::Identifier { ident, .. } => Ok(ident.sym),
737                        _ => Err(error::expected_identifier(form, Some(allowed))),
738                    })
739                    .collect::<Result<HashSet<_>, _>>()?;
740                Ok(Self::Only {
741                    set: Box::new(import_set),
742                    allowed,
743                })
744            }
745            Some(
746                [
747                    Syntax::Identifier {
748                        ident: import_type, ..
749                    },
750                    import_set,
751                    exceptions @ ..,
752                    end,
753                ],
754            ) if import_type == "except" && end.is_null() => {
755                let import_set = ImportSet::parse(import_set)?;
756                let disallowed = exceptions
757                    .iter()
758                    .map(|disallowed| match disallowed {
759                        Syntax::Identifier { ident, .. } => Ok(ident.sym),
760                        _ => Err(error::expected_identifier(form, Some(disallowed))),
761                    })
762                    .collect::<Result<HashSet<_>, _>>()?;
763                Ok(Self::Except {
764                    set: Box::new(import_set),
765                    disallowed,
766                })
767            }
768            Some(
769                [
770                    Syntax::Identifier {
771                        ident: import_type, ..
772                    },
773                    import_set,
774                    Syntax::Identifier { ident: prefix, .. },
775                    end,
776                ],
777            ) if import_type == "prefix" && end.is_null() => {
778                let import_set = ImportSet::parse(import_set)?;
779                Ok(Self::Prefix {
780                    set: Box::new(import_set),
781                    prefix: prefix.sym,
782                })
783            }
784            Some(
785                [
786                    Syntax::Identifier {
787                        ident: import_type, ..
788                    },
789                    import_set,
790                    renames @ ..,
791                    end,
792                ],
793            ) if import_type == "rename" && end.is_null() => {
794                let import_set = ImportSet::parse(import_set)?;
795                let renames = renames
796                    .iter()
797                    .map(|rename| match rename.as_list() {
798                        Some(
799                            [
800                                Syntax::Identifier { ident: from, .. },
801                                Syntax::Identifier { ident: to, .. },
802                                end,
803                            ],
804                        ) if end.is_null() => Ok((from.sym, to.sym)),
805                        _ => Err(error::bad_form(form, Some(rename))),
806                    })
807                    .collect::<Result<HashMap<_, _>, _>>()?;
808                Ok(Self::Rename {
809                    set: Box::new(import_set),
810                    renames,
811                })
812            }
813            Some(_) => Ok(Self::Library(LibraryReference::parse(form)?)),
814            _ => Err(error::expected_list(form)),
815        }
816    }
817
818    /// Returns the base library name for this import set, recursively unwrapping
819    /// any Only/Except/Prefix/Rename wrappers.
820    pub fn library_name(&self) -> &[Symbol] {
821        match self {
822            ImportSet::Library(lib_ref) => &lib_ref.name,
823            ImportSet::Only { set, .. }
824            | ImportSet::Except { set, .. }
825            | ImportSet::Prefix { set, .. }
826            | ImportSet::Rename { set, .. } => set.library_name(),
827        }
828    }
829}
830
831impl FromStr for ImportSet {
832    type Err = Exception;
833
834    fn from_str(s: &str) -> Result<Self, Self::Err> {
835        let form = Syntax::from_str(s, None)?;
836        match form.as_list() {
837            Some([item, end]) if end.is_null() => Self::parse(item),
838            _ => Err(Exception::error(format!(
839                "expected a single import set, got: {s}"
840            ))),
841        }
842    }
843}
844
845#[derive(Debug)]
846pub struct LibraryReference {
847    pub(crate) name: Vec<Symbol>,
848    pub(crate) version_ref: VersionReference,
849}
850
851impl LibraryReference {
852    fn parse(form: &Syntax) -> Result<Self, Exception> {
853        match form.as_list() {
854            Some([syms @ .., version_ref @ Syntax::List { .. }, end]) if end.is_null() => {
855                let name = syms
856                    .iter()
857                    .map(|atom| match atom {
858                        Syntax::Identifier { ident, .. } => Ok(ident.sym),
859                        _ => Err(error::expected_identifier(form, Some(atom))),
860                    })
861                    .collect::<Result<Vec<_>, _>>()?;
862                let version_ref = VersionReference::parse(version_ref)?;
863                Ok(LibraryReference { name, version_ref })
864            }
865            Some([syms @ .., end]) if end.is_null() => {
866                let name = syms
867                    .iter()
868                    .map(|atom| match atom {
869                        Syntax::Identifier { ident, .. } => Ok(ident.sym),
870                        _ => Err(error::expected_identifier(form, Some(atom))),
871                    })
872                    .collect::<Result<Vec<_>, _>>()?;
873                Ok(LibraryReference {
874                    name,
875                    version_ref: VersionReference::SubVersions(Vec::new()),
876                })
877            }
878            None => Err(error::expected_list(form)),
879            _ => Err(error::bad_form(form, None)),
880        }
881    }
882}
883
884/// A set of library names that are permitted to be imported.
885#[derive(Clone, Debug, Default)]
886pub struct AllowList(HashSet<Vec<Symbol>>);
887
888impl AllowList {
889    /// Create an allowlist from string library names.
890    ///
891    /// Each entry is a slice of strings representing the library name
892    /// components, e.g., `&["rnrs", "base"]` for `(rnrs base)`.
893    pub fn from_slice(libs: &[&[&str]]) -> Self {
894        let set = libs
895            .iter()
896            .map(|lib| lib.iter().map(|s| Symbol::intern(s)).collect())
897            .collect();
898        AllowList(set)
899    }
900
901    /// Add a library to the allowlist.
902    pub fn add_lib(&mut self, lib: Vec<Symbol>) {
903        self.0.insert(lib);
904    }
905
906    /// Returns `true` if the given library name is in the allowlist.
907    pub fn contains(&self, lib_name: &[Symbol]) -> bool {
908        self.0.contains(lib_name)
909    }
910}
911
912impl FromStr for AllowList {
913    type Err = Exception;
914
915    /// Parse an allowlist from a string of s-expressions.
916    ///
917    /// The string should be a list of library names, e.g.,
918    /// `"((rnrs base) (rnrs io simple))"`.
919    fn from_str(s: &str) -> Result<Self, Self::Err> {
920        let form = Syntax::from_str(s, None)?;
921        // Syntax::from_str wraps in an outer program-level list; unwrap it
922        let Some([inner, end]) = form.as_list() else {
923            return Err(Exception::error(format!("expected list in '{s}'")));
924        };
925        if !end.is_null() {
926            return Err(Exception::error(format!("expected single list in '{s}'")));
927        }
928        let Some([libs @ .., end]) = inner.as_list() else {
929            return Err(Exception::error(format!("expected list in '{s}'")));
930        };
931        if !end.is_null() {
932            return Err(Exception::error(format!("improper list in '{s}'")));
933        }
934        let mut set = HashSet::default();
935        for lib in libs {
936            let Some([syms @ .., end]) = lib.as_list() else {
937                return Err(Exception::error(format!(
938                    "expected library name list in '{s}'"
939                )));
940            };
941            if !end.is_null() {
942                return Err(Exception::error(format!(
943                    "improper library name list in '{s}'"
944                )));
945            }
946            let name = syms
947                .iter()
948                .map(|atom| match atom {
949                    Syntax::Identifier { ident, .. } => Ok(ident.sym),
950                    _ => Err(error::expected_identifier(inner, Some(atom))),
951                })
952                .collect::<Result<Vec<_>, _>>()?;
953            set.insert(name);
954        }
955        Ok(AllowList(set))
956    }
957}
958
959/// Controls which libraries may be imported during evaluation.
960#[derive(Clone, Debug)]
961pub enum ImportPolicy {
962    /// All imports are allowed.
963    Allow,
964    /// Only the listed libraries may be imported. An empty set means no imports
965    /// are allowed.
966    AllowList(AllowList),
967}
968
969impl ImportPolicy {
970    /// Returns `true` if the given import set is permitted under this policy.
971    pub fn is_allowed(&self, import_set: &ImportSet) -> bool {
972        match self {
973            ImportPolicy::Allow => true,
974            ImportPolicy::AllowList(allowed) => allowed.contains(import_set.library_name()),
975        }
976    }
977
978    /// Create an import policy from an allowlist.
979    pub fn allow_only(allow_list: AllowList) -> Self {
980        ImportPolicy::AllowList(allow_list)
981    }
982
983    /// Create an allowlist with no entries.
984    pub fn deny_all() -> Self {
985        ImportPolicy::AllowList(AllowList::default())
986    }
987}
988
989impl From<bool> for ImportPolicy {
990    fn from(allow: bool) -> Self {
991        if allow {
992            ImportPolicy::Allow
993        } else {
994            ImportPolicy::deny_all()
995        }
996    }
997}
998
999pub struct ParseContext {
1000    runtime: Runtime,
1001    import_policy: ImportPolicy,
1002}
1003
1004impl ParseContext {
1005    pub fn new(runtime: &Runtime, import_policy: impl Into<ImportPolicy>) -> Self {
1006        Self {
1007            runtime: runtime.clone(),
1008            import_policy: import_policy.into(),
1009        }
1010    }
1011}
1012
1013#[derive(Debug, Clone, Trace)]
1014pub enum Definition {
1015    DefineVar(DefineVar),
1016    DefineFunc(DefineFunc),
1017}
1018
1019#[derive(Debug, Clone, Trace)]
1020pub struct DefineVar {
1021    pub var: Var,
1022    pub val: Arc<Expression>,
1023    pub next: Option<Either<Box<Definition>, ExprBody>>,
1024}
1025
1026#[derive(Debug, Clone, Trace)]
1027pub struct DefineFunc {
1028    pub var: Var,
1029    pub args: Formals,
1030    pub body: Box<DefinitionBody>,
1031    pub next: Option<Either<Box<Definition>, ExprBody>>,
1032    pub span: Span,
1033}
1034
1035impl Definition {
1036    fn set_next(self, next: Either<Box<Definition>, ExprBody>) -> Self {
1037        match self {
1038            Self::DefineVar(mut def_var) => {
1039                def_var.next = Some(next);
1040                Self::DefineVar(def_var)
1041            }
1042            Self::DefineFunc(mut def_func) => {
1043                def_func.next = Some(next);
1044                Self::DefineFunc(def_func)
1045            }
1046        }
1047    }
1048
1049    #[maybe_async]
1050    pub(crate) fn parse(
1051        ctxt: &ParseContext,
1052        syn: &[Syntax],
1053        env: &Environment,
1054        form: &Syntax,
1055    ) -> Result<Self, Exception> {
1056        match syn {
1057            [_, Syntax::Identifier { ident, .. }, expr, end] if end.is_null() => {
1058                Ok(Definition::DefineVar(DefineVar {
1059                    var: maybe_await!(env.lookup_var(ident.bind()))?.unwrap(),
1060                    val: Arc::new(maybe_await!(Expression::parse(ctxt, expr.clone(), env))?),
1061                    next: None,
1062                }))
1063            }
1064            [_, Syntax::List { list, .. }, body @ .., end] if end.is_null() => {
1065                if body.is_empty() {
1066                    return Err(error::expected_body(form));
1067                }
1068                match list.as_slice() {
1069                    [
1070                        Syntax::Identifier {
1071                            ident: func_name,
1072                            span: func_span,
1073                            ..
1074                        },
1075                        args @ ..,
1076                    ] => {
1077                        let var = maybe_await!(env.lookup_var(func_name.bind()))?.unwrap();
1078                        let mut bound = HashSet::<&Identifier>::default();
1079                        let mut fixed = Vec::new();
1080                        let func_scope = Scope::new();
1081                        let new_env = env.new_lexical_contour(func_scope);
1082                        let mut arg_names = Vec::new();
1083
1084                        // Bind the arguments to a new environment:
1085                        for arg in &args[..args.len() - 1] {
1086                            match arg {
1087                                Syntax::Identifier { ident, .. } => {
1088                                    if bound.contains(ident) {
1089                                        return Err(error::name_previously_bound(form, arg));
1090                                    }
1091                                    bound.insert(ident);
1092                                    arg_names.push(ident.sym);
1093                                    let mut arg = ident.clone();
1094                                    arg.add_scope(func_scope);
1095                                    let local = new_env
1096                                        .def_var(arg.new_bind(), arg.sym)
1097                                        .as_local()
1098                                        .unwrap();
1099                                    fixed.push(local);
1100                                }
1101                                x => return Err(error::expected_identifier(form, Some(x))),
1102                            }
1103                        }
1104
1105                        let args = if let Some(last) = args.last() {
1106                            match last {
1107                                empty if empty.is_null() => {
1108                                    Formals::FixedArgs(fixed.into_iter().collect())
1109                                }
1110                                Syntax::Identifier { ident, .. } => {
1111                                    if bound.contains(ident) {
1112                                        return Err(error::name_previously_bound(form, last));
1113                                    }
1114                                    bound.insert(ident);
1115                                    arg_names.push(ident.sym);
1116                                    let mut remaining = ident.clone();
1117                                    remaining.add_scope(func_scope);
1118                                    let remaining = new_env
1119                                        .def_var(remaining.new_bind(), remaining.sym)
1120                                        .as_local()
1121                                        .unwrap();
1122                                    Formals::VarArgs {
1123                                        fixed: fixed.into_iter().collect(),
1124                                        remaining,
1125                                    }
1126                                }
1127                                x => return Err(error::expected_identifier(form, Some(x))),
1128                            }
1129                        } else {
1130                            // If there is no last argument, there are no arguments
1131                            Formals::FixedArgs(Vec::new())
1132                        };
1133
1134                        // Parse the body:
1135                        let mut body = body.to_vec();
1136                        body.iter_mut().for_each(|s| s.add_scope(func_scope));
1137                        let body =
1138                            maybe_await!(DefinitionBody::parse(ctxt, &body, &new_env, form))?;
1139
1140                        Ok(Self::DefineFunc(DefineFunc {
1141                            var,
1142                            args,
1143                            body: Box::new(body),
1144                            next: None,
1145                            span: func_span.clone(),
1146                        }))
1147                    }
1148                    _ => Err(error::bad_form(form, None)),
1149                }
1150            }
1151            _ => Err(error::bad_form(form, None)),
1152        }
1153    }
1154}
1155
1156#[maybe_async]
1157pub(super) fn define_syntax(
1158    ctxt: &ParseContext,
1159    binding: Binding,
1160    expr: Syntax,
1161    env: &Environment,
1162) -> Result<(), Exception> {
1163    let expanded = maybe_await!(expr.expand(env))?;
1164    let expr = maybe_await!(Expression::parse(ctxt, expanded, env))?;
1165    let cps_expr = expr.compile_top_level();
1166    let values = maybe_await!(
1167        maybe_await!(ctxt.runtime.compile_expr(cps_expr)).call(&[], &mut ContBarrier::new())
1168    )?;
1169    let transformer: Procedure = values.expect1()?;
1170    env.def_keyword(binding, transformer);
1171    Ok(())
1172}
1173
1174#[derive(Debug, Clone, Trace)]
1175pub enum Expression {
1176    Undefined,
1177    Literal(Value),
1178    Quote(Quote),
1179    SyntaxQuote(SyntaxQuote),
1180    SyntaxCase(SyntaxCase),
1181    Apply(Apply),
1182    Let(Let),
1183    If(If),
1184    And(And),
1185    Or(Or),
1186    Lambda(Lambda),
1187    Set(Set),
1188    Var(Var),
1189    Vector(Vector),
1190    Begin(ExprBody),
1191}
1192
1193impl Expression {
1194    #[maybe_async]
1195    pub(crate) fn parse(
1196        ctxt: &ParseContext,
1197        form: Syntax,
1198        env: &Environment,
1199    ) -> Result<Self, Exception> {
1200        let expanded = maybe_await!(form.expand(env))?;
1201        maybe_await!(Self::parse_expanded(ctxt, expanded, env))
1202    }
1203
1204    #[cfg(not(feature = "async"))]
1205    fn parse_expanded(
1206        ctxt: &ParseContext,
1207        form: Syntax,
1208        env: &Environment,
1209    ) -> Result<Self, Exception> {
1210        Self::parse_expanded_inner(ctxt, form, env)
1211    }
1212
1213    #[cfg(feature = "async")]
1214    fn parse_expanded<'a>(
1215        ctxt: &'a ParseContext,
1216        form: Syntax,
1217        env: &'a Environment,
1218    ) -> BoxFuture<'a, Result<Self, Exception>> {
1219        Box::pin(Self::parse_expanded_inner(ctxt, form, env))
1220    }
1221
1222    #[maybe_async]
1223    fn parse_expanded_inner(
1224        ctxt: &ParseContext,
1225        form: Syntax,
1226        env: &Environment,
1227    ) -> Result<Self, Exception> {
1228        match &form {
1229            syn if syn.is_null() => Err(error::unexpected_empty_list(&form, None)),
1230
1231            // Regular identifiers:
1232            Syntax::Identifier { ident, .. } => {
1233                if let Some(binding) = ident.resolve() {
1234                    if let Some(primitive) = env.lookup_primitive(binding) {
1235                        match primitive {
1236                            Primitive::Undefined => Ok(Self::Undefined),
1237                            _ => Err(error::bad_form(&form, None)),
1238                        }
1239                    } else if let Some(var) = maybe_await!(env.lookup_var(binding))? {
1240                        Ok(Self::Var(var))
1241                    } else {
1242                        Err(error::undefined_variable(&form, None))
1243                    }
1244                } else {
1245                    Err(error::undefined_variable(&form, None))
1246                }
1247            }
1248
1249            // Literals:
1250            Syntax::Wrapped { value, .. } => Ok(Self::Literal(value.clone())),
1251
1252            // Vector literals:
1253            Syntax::Vector { vector, .. } => Ok(Self::Vector(Vector::parse(vector))),
1254
1255            // Functional forms:
1256            Syntax::List { list: exprs, .. } => match exprs.as_slice() {
1257                // Special forms:
1258                [
1259                    ident_form @ Syntax::Identifier { ident, .. },
1260                    tail @ ..,
1261                    end,
1262                ] if end.is_null() => {
1263                    let Some(binding) = ident.resolve() else {
1264                        return Err(error::undefined_variable(&form, Some(ident_form)));
1265                    };
1266                    if let Some(primitive) = env.lookup_primitive(binding) {
1267                        match primitive {
1268                            Primitive::Begin => maybe_await!(ExprBody::parse(ctxt, tail, env))
1269                                .map(Expression::Begin),
1270                            Primitive::Lambda => {
1271                                maybe_await!(Lambda::parse(ctxt, tail, env, &form))
1272                                    .map(Expression::Lambda)
1273                            }
1274                            Primitive::Let => maybe_await!(Let::parse(ctxt, tail, env, &form))
1275                                .map(Expression::Let),
1276                            Primitive::If => {
1277                                maybe_await!(If::parse(ctxt, tail, env, &form)).map(Expression::If)
1278                            }
1279                            Primitive::And => {
1280                                maybe_await!(And::parse(ctxt, tail, env)).map(Expression::And)
1281                            }
1282                            Primitive::Or => {
1283                                maybe_await!(Or::parse(ctxt, tail, env)).map(Expression::Or)
1284                            }
1285                            Primitive::Quote => Quote::parse(tail, &form).map(Expression::Quote),
1286                            Primitive::Syntax => {
1287                                SyntaxQuote::parse(tail, env, &form).map(Expression::SyntaxQuote)
1288                            }
1289                            Primitive::SyntaxCase => {
1290                                maybe_await!(SyntaxCase::parse(ctxt, tail, env, &form))
1291                                    .map(Expression::SyntaxCase)
1292                            }
1293                            Primitive::Set => maybe_await!(Set::parse(ctxt, tail, env, &form))
1294                                .map(Expression::Set),
1295                            Primitive::LetSyntax if !tail.is_empty() => {
1296                                let (form, env) = maybe_await!(parse_let_syntax(
1297                                    ctxt,
1298                                    false,
1299                                    &tail[0],
1300                                    &tail[1..],
1301                                    env,
1302                                    &mut Vec::new(),
1303                                ))?;
1304                                maybe_await!(ExprBody::parse(ctxt, &form, &env))
1305                                    .map(Expression::Begin)
1306                            }
1307                            Primitive::LetRecSyntax if !tail.is_empty() => {
1308                                let (form, env) = maybe_await!(parse_let_syntax(
1309                                    ctxt,
1310                                    true,
1311                                    &tail[0],
1312                                    &tail[1..],
1313                                    env,
1314                                    &mut Vec::new(),
1315                                ))?;
1316                                maybe_await!(ExprBody::parse(ctxt, &form, &env))
1317                                    .map(Expression::Begin)
1318                            }
1319                            Primitive::Import => Err(error::unexpected_import(&form)),
1320                            Primitive::Define => Err(error::unexpected_define(&form)),
1321                            _ => Err(error::bad_form(&form, None)),
1322                        }
1323                    } else if let Some(var) = maybe_await!(env.lookup_var(binding))? {
1324                        maybe_await!(Apply::parse(ctxt, Expression::Var(var), tail, env, &form))
1325                            .map(Expression::Apply)
1326                    } else {
1327                        Err(error::undefined_variable(&form, Some(ident_form)))
1328                    }
1329                }
1330                [expr, args @ .., end] if end.is_null() => maybe_await!(Apply::parse(
1331                    ctxt,
1332                    maybe_await!(Expression::parse(ctxt, expr.clone(), env))?,
1333                    args,
1334                    env,
1335                    &form
1336                ))
1337                .map(Expression::Apply),
1338                _ => Err(error::bad_form(&form, None)),
1339            },
1340        }
1341    }
1342
1343    // These function pointer comparisons are guaranteed to be meaningful since
1344    // they are returned from a store.
1345    pub fn to_primop(&self) -> Option<PrimOp> {
1346        use crate::{
1347            lists::{car, cdr, cons, list},
1348            num::{add, div, equal, greater, greater_equal, lesser, lesser_equal, mul, sub},
1349            proc::{BridgePtr, FuncPtr::Bridge, Procedure},
1350            value::{not, null_pred, pair_pred},
1351        };
1352        use std::ptr::fn_addr_eq;
1353
1354        const PRIMOP_TAB: &[(BridgePtr, PrimOp)] = &[
1355            (add, PrimOp::Add),
1356            (sub, PrimOp::Sub),
1357            (mul, PrimOp::Mul),
1358            (div, PrimOp::Div),
1359            (equal, PrimOp::Equal),
1360            (greater, PrimOp::Greater),
1361            (greater_equal, PrimOp::GreaterEqual),
1362            (lesser, PrimOp::Lesser),
1363            (lesser_equal, PrimOp::LesserEqual),
1364            (cons, PrimOp::Cons),
1365            (list, PrimOp::List),
1366            (car, PrimOp::Car),
1367            (cdr, PrimOp::Cdr),
1368            (not, PrimOp::Not),
1369            (null_pred, PrimOp::IsNull),
1370            (pair_pred, PrimOp::IsPair),
1371        ];
1372
1373        let Expression::Var(Var::Global(global)) = self else {
1374            return None;
1375        };
1376        let val: Procedure = global.read().try_into().ok()?;
1377
1378        let Bridge(ptr) = val.0.func else {
1379            return None;
1380        };
1381
1382        for (builtin, primop) in PRIMOP_TAB.iter().copied() {
1383            if fn_addr_eq(ptr, builtin) {
1384                return Some(primop);
1385            }
1386        }
1387
1388        None
1389    }
1390}
1391
1392/*
1393#[derive(Debug, Clone, PartialEq, Trace)]
1394pub enum Literal {
1395    Number(Number),
1396    Boolean(bool),
1397    Character(char),
1398    String(String),
1399}
1400
1401impl fmt::Display for Literal {
1402    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1403        match self {
1404            Self::Number(num) => write!(f, "{num}"),
1405            Self::Boolean(true) => write!(f, "#t"),
1406            Self::Boolean(false) => write!(f, "#f"),
1407            Self::Character(chr) => write!(f, "{chr}"),
1408            Self::String(str) => write!(f, "{str:?}"),
1409        }
1410    }
1411}
1412*/
1413
1414#[derive(Debug, Clone, Trace)]
1415pub struct Quote {
1416    pub val: Value,
1417}
1418
1419impl Quote {
1420    fn parse(exprs: &[Syntax], form: &Syntax) -> Result<Self, Exception> {
1421        match exprs {
1422            [] => Err(error::expected_more_arguments(form)),
1423            [expr] => Ok(Quote {
1424                val: Value::datum_from_syntax(expr),
1425            }),
1426            [_, arg, ..] => Err(error::unexpected_argument(form, arg)),
1427        }
1428    }
1429}
1430
1431#[derive(Debug, Clone, Trace)]
1432pub struct SyntaxQuote {
1433    pub template: Template,
1434    pub expansions: HashMap<Binding, Local>,
1435}
1436
1437impl SyntaxQuote {
1438    fn parse(exprs: &[Syntax], env: &Environment, form: &Syntax) -> Result<Self, Exception> {
1439        match exprs {
1440            [] => Err(error::expected_more_arguments(form)),
1441            [expr] => {
1442                let mut expansions = HashMap::default();
1443                let template = Template::compile(expr, env, &mut expansions)?;
1444                Ok(SyntaxQuote {
1445                    template,
1446                    expansions,
1447                })
1448            }
1449            [_, arg, ..] => Err(error::unexpected_argument(form, arg)),
1450        }
1451    }
1452}
1453
1454#[derive(Debug, Clone, Trace)]
1455pub struct Apply {
1456    pub operator: Box<Expression>,
1457    pub args: Vec<Expression>,
1458    pub span: Span,
1459}
1460
1461impl Apply {
1462    #[maybe_async]
1463    fn parse(
1464        ctxt: &ParseContext,
1465        operator: Expression,
1466        args: &[Syntax],
1467        env: &Environment,
1468        form: &Syntax,
1469    ) -> Result<Self, Exception> {
1470        let mut parsed_args = Vec::new();
1471        for arg in args {
1472            parsed_args.push(maybe_await!(Expression::parse(ctxt, arg.clone(), env))?);
1473        }
1474        Ok(Apply {
1475            operator: Box::new(operator),
1476            args: parsed_args,
1477            span: form.span().clone(),
1478        })
1479    }
1480}
1481
1482#[derive(Debug, Clone, Trace)]
1483pub struct Lambda {
1484    pub args: Formals,
1485    pub body: DefinitionBody,
1486    pub span: Span,
1487}
1488
1489impl Lambda {
1490    #[maybe_async]
1491    fn parse(
1492        ctxt: &ParseContext,
1493        sexprs: &[Syntax],
1494        env: &Environment,
1495        form: &Syntax,
1496    ) -> Result<Self, Exception> {
1497        match sexprs {
1498            [null, body @ ..] if null.is_null() => {
1499                maybe_await!(parse_lambda(ctxt, &[], body, env, form))
1500            }
1501            [Syntax::List { list: args, .. }, body @ ..] => {
1502                maybe_await!(parse_lambda(ctxt, args, body, env, form))
1503            }
1504            [ident @ Syntax::Identifier { .. }, body @ ..] => {
1505                maybe_await!(parse_lambda(
1506                    ctxt,
1507                    std::slice::from_ref(ident),
1508                    body,
1509                    env,
1510                    form,
1511                ))
1512            }
1513            _ => Err(error::expected_more_arguments(form)),
1514        }
1515    }
1516}
1517
1518#[maybe_async]
1519fn parse_lambda(
1520    ctxt: &ParseContext,
1521    args: &[Syntax],
1522    body: &[Syntax],
1523    env: &Environment,
1524    form: &Syntax,
1525) -> Result<Lambda, Exception> {
1526    let mut bound = HashSet::<&Identifier>::default();
1527    let mut fixed = Vec::new();
1528    let lambda_scope = Scope::new();
1529    let new_contour = env.new_lexical_contour(lambda_scope);
1530    let mut arg_names = Vec::new();
1531
1532    if !args.is_empty() {
1533        for arg in &args[..args.len() - 1] {
1534            match arg {
1535                Syntax::Identifier { ident, .. } => {
1536                    if bound.contains(ident) {
1537                        return Err(error::name_previously_bound(form, arg));
1538                    }
1539                    arg_names.push(ident.sym);
1540                    bound.insert(ident);
1541                    let mut arg = ident.clone();
1542                    arg.add_scope(lambda_scope);
1543                    let local = new_contour
1544                        .def_var(arg.new_bind(), arg.sym)
1545                        .as_local()
1546                        .unwrap();
1547                    fixed.push(local);
1548                }
1549                x => return Err(error::expected_identifier(form, Some(x))),
1550            }
1551        }
1552    }
1553
1554    let args = if let Some(last) = args.last() {
1555        match last {
1556            empty if empty.is_null() => Formals::FixedArgs(fixed.into_iter().collect()),
1557            // Syntax::Null { .. } => Formals::FixedArgs(fixed.into_iter().collect()),
1558            Syntax::Identifier { ident, .. } => {
1559                if bound.contains(ident) {
1560                    return Err(error::name_previously_bound(form, last));
1561                }
1562                arg_names.push(ident.sym);
1563                let mut remaining = ident.clone();
1564                remaining.add_scope(lambda_scope);
1565                let remaining = new_contour
1566                    .def_var(remaining.new_bind(), remaining.sym)
1567                    .as_local()
1568                    .unwrap();
1569                Formals::VarArgs {
1570                    fixed: fixed.into_iter().collect(),
1571                    remaining,
1572                }
1573            }
1574            x => return Err(error::expected_identifier(form, Some(x))),
1575        }
1576    } else {
1577        // If there is no last argument, there are no arguments
1578        Formals::FixedArgs(Vec::new())
1579    };
1580
1581    let mut body = body.to_vec();
1582    body.iter_mut().for_each(|s| s.add_scope(lambda_scope));
1583    let body = maybe_await!(DefinitionBody::parse(ctxt, &body, &new_contour, form))?;
1584
1585    Ok(Lambda {
1586        args,
1587        body,
1588        span: form.span().clone(),
1589    })
1590}
1591
1592#[derive(Debug, Clone, Trace)]
1593pub struct Let {
1594    pub bindings: Vec<(Local, Expression)>,
1595    pub body: DefinitionBody,
1596}
1597
1598impl Let {
1599    #[maybe_async]
1600    fn parse(
1601        ctxt: &ParseContext,
1602        syn: &[Syntax],
1603        env: &Environment,
1604        form: &Syntax,
1605    ) -> Result<Self, Exception> {
1606        match syn {
1607            [empty, body @ ..] if empty.is_null() => {
1608                maybe_await!(parse_let(ctxt, &[], body, env, form))
1609            }
1610            [Syntax::List { list: bindings, .. }, body @ ..] => {
1611                maybe_await!(parse_let(ctxt, bindings, body, env, form))
1612            }
1613            // Named let:
1614            [
1615                Syntax::Identifier { ident, .. },
1616                Syntax::List { list: bindings, .. },
1617                body @ ..,
1618            ] => maybe_await!(parse_named_let(ctxt, ident, bindings, body, env, form)),
1619            [Syntax::Identifier { ident, .. }, empty, body @ ..] if empty.is_null() => {
1620                maybe_await!(parse_named_let(ctxt, ident, &[], body, env, form))
1621            }
1622            _ => Err(error::expected_more_arguments(form)),
1623        }
1624    }
1625}
1626
1627#[maybe_async]
1628fn parse_let(
1629    ctxt: &ParseContext,
1630    bindings: &[Syntax],
1631    body: &[Syntax],
1632    env: &Environment,
1633    form: &Syntax,
1634) -> Result<Let, Exception> {
1635    let mut previously_bound = HashSet::default();
1636    let mut parsed_bindings = Vec::new();
1637
1638    let new_scope = Scope::new();
1639    let new_contour = env.new_lexical_contour(new_scope);
1640
1641    match bindings {
1642        [] => (),
1643        [empty] if empty.is_null() => (),
1644        [bindings @ .., end] if end.is_null() => {
1645            for binding in bindings {
1646                let binding = maybe_await!(LetBinding::parse(
1647                    ctxt,
1648                    binding,
1649                    env,
1650                    &previously_bound,
1651                    form
1652                ))?;
1653                previously_bound.insert(binding.ident);
1654                let mut var = binding.ident.clone();
1655                var.add_scope(new_scope);
1656                let var = new_contour
1657                    .def_var(var.new_bind(), var.sym)
1658                    .as_local()
1659                    .unwrap();
1660                parsed_bindings.push((var, binding.expr));
1661            }
1662        }
1663        _ => {
1664            return Err(error::expected_list(form));
1665        }
1666    }
1667
1668    let mut body = body.to_vec();
1669    body.iter_mut().for_each(|s| s.add_scope(new_scope));
1670    let body = maybe_await!(DefinitionBody::parse(ctxt, &body, &new_contour, form))?;
1671
1672    Ok(Let {
1673        bindings: parsed_bindings,
1674        body,
1675    })
1676}
1677
1678#[maybe_async]
1679fn parse_named_let(
1680    ctxt: &ParseContext,
1681    name: &Identifier,
1682    bindings: &[Syntax],
1683    body: &[Syntax],
1684    env: &Environment,
1685    form: &Syntax,
1686) -> Result<Let, Exception> {
1687    let mut previously_bound = HashSet::default();
1688    let mut formals = Vec::new();
1689    let mut args = Vec::new();
1690
1691    let func_scope = Scope::new();
1692    let func_contour = env.new_lexical_contour(func_scope);
1693
1694    let mut func_name = name.clone();
1695    func_name.add_scope(func_scope);
1696    let func = func_contour.def_var(func_name.new_bind(), func_name.sym);
1697
1698    let body_scope = Scope::new();
1699    let body_contour = func_contour.new_lexical_contour(body_scope);
1700
1701    match bindings {
1702        [] => (),
1703        [empty] if empty.is_null() => (),
1704        [bindings @ .., end] if end.is_null() => {
1705            for binding in bindings {
1706                let binding = maybe_await!(LetBinding::parse(
1707                    ctxt,
1708                    binding,
1709                    env,
1710                    &previously_bound,
1711                    form
1712                ))?;
1713                previously_bound.insert(binding.ident);
1714                args.push(binding.expr);
1715                let mut arg = binding.ident.clone();
1716                arg.add_scope(func_scope);
1717                arg.add_scope(body_scope);
1718                let var = body_contour
1719                    .def_var(arg.new_bind(), arg.sym)
1720                    .as_local()
1721                    .unwrap();
1722                formals.push(var);
1723            }
1724        }
1725        _ => {
1726            return Err(error::expected_list(form));
1727        }
1728    }
1729
1730    let mut body = body.to_vec();
1731    body.iter_mut().for_each(|s| {
1732        s.add_scope(func_scope);
1733        s.add_scope(body_scope);
1734    });
1735    let body = maybe_await!(DefinitionBody::parse(ctxt, &body, &body_contour, form))?;
1736
1737    let func = DefineFunc {
1738        var: func.clone(),
1739        args: Formals::FixedArgs(formals),
1740        body: Box::new(body),
1741        next: Some(Either::Right(ExprBody::new(vec![Expression::Apply(
1742            Apply {
1743                operator: Box::new(Expression::Var(func)),
1744                args,
1745                span: form.span().clone(),
1746            },
1747        )]))),
1748        span: form.span().clone(),
1749    };
1750
1751    Ok(Let {
1752        bindings: Vec::new(),
1753        body: DefinitionBody::new(Either::Left(Definition::DefineFunc(func))),
1754    })
1755}
1756
1757struct LetBinding<'a> {
1758    ident: &'a Identifier,
1759    expr: Expression,
1760}
1761
1762impl<'a> LetBinding<'a> {
1763    #[maybe_async]
1764    fn parse(
1765        ctxt: &ParseContext,
1766        binding: &'a Syntax,
1767        env: &Environment,
1768        previously_bound: &HashSet<&'a Identifier>,
1769        form: &'a Syntax,
1770    ) -> Result<LetBinding<'a>, Exception> {
1771        if let Some(
1772            [
1773                subform @ Syntax::Identifier { ident, .. },
1774                expr,
1775                end, // Syntax::Null { .. },
1776            ],
1777        ) = binding.as_list()
1778            && end.is_null()
1779        {
1780            if previously_bound.contains(ident) {
1781                return Err(error::name_previously_bound(form, subform));
1782            }
1783
1784            let expr = maybe_await!(Expression::parse(ctxt, expr.clone(), env))?;
1785
1786            Ok(LetBinding { ident, expr })
1787        } else {
1788            Err(error::expected_list(binding))
1789        }
1790    }
1791}
1792
1793#[derive(Debug, Clone, Trace)]
1794pub struct Set {
1795    pub var: Var,
1796    pub val: Arc<Expression>,
1797}
1798
1799impl Set {
1800    #[maybe_async]
1801    fn parse(
1802        ctxt: &ParseContext,
1803        exprs: &[Syntax],
1804        env: &Environment,
1805        form: &Syntax,
1806    ) -> Result<Self, Exception> {
1807        match exprs {
1808            [] | [_] => Err(error::expected_more_arguments(form)),
1809            [subform @ Syntax::Identifier { ident, .. }, expr] => Ok(Set {
1810                var: {
1811                    if let Some(binding) = ident.resolve() {
1812                        match maybe_await!(env.lookup_var(binding))? {
1813                            Some(Var::Global(global)) if !global.mutable => {
1814                                return Err(error::immutable_variable(form, subform));
1815                            }
1816                            Some(var) => var,
1817                            None => {
1818                                return Err(error::undefined_variable(form, Some(subform)));
1819                            }
1820                        }
1821                    } else {
1822                        return Err(error::undefined_variable(form, Some(subform)));
1823                    }
1824                },
1825                val: Arc::new(maybe_await!(Expression::parse(ctxt, expr.clone(), env))?),
1826            }),
1827            [arg1, _] => Err(error::expected_identifier(form, Some(arg1))),
1828            [_, _, arg3, ..] => Err(error::unexpected_argument(form, arg3)),
1829        }
1830    }
1831}
1832
1833#[derive(Debug, Clone, Trace)]
1834pub struct If {
1835    pub cond: Arc<Expression>,
1836    pub success: Arc<Expression>,
1837    pub failure: Option<Arc<Expression>>,
1838}
1839
1840impl If {
1841    #[maybe_async]
1842    fn parse(
1843        ctxt: &ParseContext,
1844        exprs: &[Syntax],
1845        env: &Environment,
1846        form: &Syntax,
1847    ) -> Result<Self, Exception> {
1848        match exprs {
1849            [cond, success] => Ok(If {
1850                cond: Arc::new(maybe_await!(Expression::parse(ctxt, cond.clone(), env))?),
1851                success: Arc::new(maybe_await!(Expression::parse(ctxt, success.clone(), env))?),
1852                failure: None,
1853            }),
1854            [cond, success, failure] => Ok(If {
1855                cond: Arc::new(maybe_await!(Expression::parse(ctxt, cond.clone(), env))?),
1856                success: Arc::new(maybe_await!(Expression::parse(ctxt, success.clone(), env))?),
1857                failure: Some(Arc::new(maybe_await!(Expression::parse(
1858                    ctxt,
1859                    failure.clone(),
1860                    env
1861                ))?)),
1862            }),
1863            [] => Err(error::expected_more_arguments(form)),
1864            [_] => Err(error::expected_more_arguments(form)),
1865            [_, _, _, unexpected, ..] => Err(error::unexpected_argument(form, unexpected)),
1866        }
1867    }
1868}
1869
1870#[derive(Debug, Clone, Trace)]
1871pub enum Formals {
1872    FixedArgs(Vec<Local>),
1873    VarArgs { fixed: Vec<Local>, remaining: Local },
1874}
1875
1876impl Formals {
1877    pub fn iter(&self) -> impl Iterator<Item = &'_ Local> {
1878        let fixed_iter = match self {
1879            Self::FixedArgs(fixed) => fixed.iter(),
1880            Self::VarArgs { fixed, .. } => fixed.iter(),
1881        };
1882        let remaining = match self {
1883            Self::FixedArgs(_) => None,
1884            Self::VarArgs { remaining, .. } => Some(remaining),
1885        };
1886        fixed_iter.chain(remaining)
1887    }
1888
1889    pub fn is_variadic(&self) -> bool {
1890        matches!(self, Self::VarArgs { .. })
1891    }
1892}
1893
1894#[derive(Debug, Clone, Trace)]
1895pub struct DefinitionBody {
1896    pub first: Either<Definition, ExprBody>,
1897}
1898
1899impl DefinitionBody {
1900    pub fn new(first: Either<Definition, ExprBody>) -> Self {
1901        Self { first }
1902    }
1903
1904    #[maybe_async]
1905    pub(crate) fn parse_lib_body(
1906        runtime: &Runtime,
1907        form: &Syntax,
1908        env: &Environment,
1909    ) -> Result<Self, Exception> {
1910        let ctxt = ParseContext {
1911            runtime: runtime.clone(),
1912            import_policy: ImportPolicy::Allow,
1913        };
1914        // No explanation needed
1915        match form.as_list() {
1916            Some([list @ .., end]) if end.is_null() => {
1917                maybe_await!(Self::parse_helper(&ctxt, list, true, env, form))
1918            }
1919            _ => Err(error::bad_form(form, None)),
1920        }
1921    }
1922
1923    #[maybe_async]
1924    pub(crate) fn parse(
1925        ctxt: &ParseContext,
1926        body: &[Syntax],
1927        env: &Environment,
1928        form: &Syntax,
1929    ) -> Result<Self, Exception> {
1930        maybe_await!(Self::parse_helper(ctxt, body, false, env, form))
1931    }
1932
1933    /// Parse the body. body is expected to be a list of valid syntax objects, and should not include
1934    /// _any_ nulls, including one at the end.
1935    #[cfg(not(feature = "async"))]
1936    fn parse_helper(
1937        ctxt: &ParseContext,
1938        body: &[Syntax],
1939        permissive: bool,
1940        env: &Environment,
1941        form: &Syntax,
1942    ) -> Result<Self, Exception> {
1943        Self::parse_helper_inner(ctxt, body, permissive, env, form)
1944    }
1945
1946    /// Parse the body. body is expected to be a list of valid syntax objects, and should not include
1947    /// _any_ nulls, including one at the end.
1948    #[cfg(feature = "async")]
1949    fn parse_helper<'a>(
1950        ctxt: &'a ParseContext,
1951        body: &'a [Syntax],
1952        permissive: bool,
1953        env: &'a Environment,
1954        form: &'a Syntax,
1955    ) -> BoxFuture<'a, Result<Self, Exception>> {
1956        Box::pin(Self::parse_helper_inner(ctxt, body, permissive, env, form))
1957    }
1958
1959    #[maybe_async]
1960    fn parse_helper_inner(
1961        runtime: &ParseContext,
1962        body: &[Syntax],
1963        permissive: bool,
1964        env: &Environment,
1965        form: &Syntax,
1966    ) -> Result<Self, Exception> {
1967        let mut defs = Vec::new();
1968        let mut exprs = Vec::new();
1969        let mut introduced_scopes = Vec::new();
1970
1971        maybe_await!(splice_in(
1972            runtime,
1973            permissive,
1974            body,
1975            env,
1976            form,
1977            &mut defs,
1978            &mut exprs,
1979            &mut introduced_scopes,
1980        ))?;
1981
1982        let mut defs_parsed = Vec::new();
1983        let mut exprs_parsed = Vec::new();
1984
1985        // Mark all of the defs as defined:
1986        for (def_form, _) in defs.iter() {
1987            if let Some([_, def, ..]) = def_form.as_list() {
1988                let ident = match def.as_list() {
1989                    Some([Syntax::Identifier { ident, .. }, ..]) => ident,
1990                    _ => def
1991                        .as_ident()
1992                        .ok_or_else(|| error::bad_form(def_form, None))?,
1993                };
1994                let mut ident = ident.clone();
1995                // Remove any scopes introduced by a let-syntax or
1996                // letrec-syntax form
1997                for scope in &introduced_scopes {
1998                    ident.remove_scope(*scope);
1999                }
2000                let binding = ident.bind();
2001                env.def_var(binding, ident.sym);
2002            }
2003        }
2004
2005        for (def, env) in defs.into_iter() {
2006            let def = maybe_await!(Definition::parse(
2007                runtime,
2008                def.as_list().unwrap(),
2009                &env,
2010                &def,
2011            ))?;
2012            defs_parsed.push(def);
2013        }
2014
2015        for (expr, env) in exprs.into_iter() {
2016            exprs_parsed.push(maybe_await!(Expression::parse_expanded(
2017                runtime, expr, &env,
2018            ))?);
2019        }
2020
2021        let expr_body = ExprBody::new(exprs_parsed);
2022        match defs_parsed.pop() {
2023            Some(last_def) => {
2024                let mut last_def = last_def.set_next(Either::Right(expr_body));
2025                for next_def in defs_parsed.into_iter().rev() {
2026                    last_def = next_def.set_next(Either::Left(Box::new(last_def)));
2027                }
2028                Ok(Self::new(Either::Left(last_def)))
2029            }
2030            _ => Ok(Self::new(Either::Right(expr_body))),
2031        }
2032    }
2033}
2034
2035#[derive(Debug, Clone, Trace)]
2036pub struct ExprBody {
2037    pub exprs: Vec<Expression>,
2038}
2039
2040impl ExprBody {
2041    pub fn new(exprs: Vec<Expression>) -> Self {
2042        Self { exprs }
2043    }
2044
2045    /// Differs from Body by being purely expression based. No definitions allowed.
2046    #[maybe_async]
2047    fn parse(ctxt: &ParseContext, body: &[Syntax], env: &Environment) -> Result<Self, Exception> {
2048        let mut exprs = Vec::new();
2049        for sexpr in body {
2050            let parsed = maybe_await!(Expression::parse(ctxt, sexpr.clone(), env))?;
2051            exprs.push(parsed);
2052        }
2053        Ok(Self { exprs })
2054    }
2055}
2056
2057#[cfg(not(feature = "async"))]
2058#[allow(clippy::too_many_arguments)]
2059fn splice_in(
2060    ctxt: &ParseContext,
2061    permissive: bool,
2062    body: &[Syntax],
2063    env: &Environment,
2064    form: &Syntax,
2065    defs: &mut Vec<(Syntax, Environment)>,
2066    exprs: &mut Vec<(Syntax, Environment)>,
2067    introduced_scopes: &mut Vec<Scope>,
2068) -> Result<(), Exception> {
2069    splice_in_inner(
2070        ctxt,
2071        permissive,
2072        body,
2073        env,
2074        form,
2075        defs,
2076        exprs,
2077        introduced_scopes,
2078    )
2079}
2080
2081#[cfg(feature = "async")]
2082#[allow(clippy::too_many_arguments)]
2083fn splice_in<'a>(
2084    ctxt: &'a ParseContext,
2085    permissive: bool,
2086    body: &'a [Syntax],
2087    env: &'a Environment,
2088    form: &'a Syntax,
2089    defs: &'a mut Vec<(Syntax, Environment)>,
2090    exprs: &'a mut Vec<(Syntax, Environment)>,
2091    introduced_scopes: &'a mut Vec<Scope>,
2092) -> BoxFuture<'a, Result<(), Exception>> {
2093    Box::pin(splice_in_inner(
2094        ctxt,
2095        permissive,
2096        body,
2097        env,
2098        form,
2099        defs,
2100        exprs,
2101        introduced_scopes,
2102    ))
2103}
2104
2105#[maybe_async]
2106#[allow(clippy::too_many_arguments)]
2107fn splice_in_inner(
2108    ctxt: &ParseContext,
2109    permissive: bool,
2110    body: &[Syntax],
2111    env: &Environment,
2112    form: &Syntax,
2113    defs: &mut Vec<(Syntax, Environment)>,
2114    exprs: &mut Vec<(Syntax, Environment)>,
2115    introduced_scopes: &mut Vec<Scope>,
2116) -> Result<(), Exception> {
2117    if body.is_empty() {
2118        return Err(error::expected_body(form));
2119    }
2120    for unexpanded in body {
2121        let expanded = maybe_await!(unexpanded.clone().expand(env))?;
2122        let is_def = {
2123            if let Some([Syntax::Identifier { ident, .. }, tail @ .., end]) = expanded.as_list()
2124                && end.is_null()
2125            {
2126                let primitive = ident
2127                    .resolve()
2128                    .and_then(|binding| env.lookup_primitive(binding));
2129                match (primitive, tail) {
2130                    (Some(Primitive::Begin), []) => {
2131                        continue;
2132                    }
2133                    (Some(Primitive::Begin), body) => {
2134                        maybe_await!(splice_in(
2135                            ctxt,
2136                            permissive,
2137                            body,
2138                            env,
2139                            &expanded,
2140                            defs,
2141                            exprs,
2142                            introduced_scopes,
2143                        ))?;
2144                        continue;
2145                    }
2146                    (
2147                        Some(Primitive::DefineSyntax),
2148                        [Syntax::Identifier { ident: name, .. }, expr],
2149                    ) => {
2150                        maybe_await!(define_syntax(ctxt, name.bind(), expr.clone(), env))?;
2151                        continue;
2152                    }
2153                    (Some(Primitive::DefineSyntax), _) => {
2154                        return Err(error::unexpected_define_syntax(&expanded));
2155                    }
2156                    (Some(Primitive::LetSyntax), [bindings, form @ ..]) => {
2157                        let (form, env) = maybe_await!(parse_let_syntax(
2158                            ctxt,
2159                            false,
2160                            bindings,
2161                            form,
2162                            env,
2163                            introduced_scopes
2164                        ))?;
2165                        if !form.is_empty() {
2166                            maybe_await!(splice_in(
2167                                ctxt,
2168                                permissive,
2169                                &form,
2170                                &env,
2171                                &expanded,
2172                                defs,
2173                                exprs,
2174                                introduced_scopes
2175                            ))?;
2176                        }
2177                        continue;
2178                    }
2179                    (Some(Primitive::LetRecSyntax), [bindings, form @ ..]) => {
2180                        let (form, env) = maybe_await!(parse_let_syntax(
2181                            ctxt,
2182                            true,
2183                            bindings,
2184                            form,
2185                            env,
2186                            introduced_scopes
2187                        ))?;
2188                        if !form.is_empty() {
2189                            maybe_await!(splice_in(
2190                                ctxt,
2191                                permissive,
2192                                &form,
2193                                &env,
2194                                &expanded,
2195                                defs,
2196                                exprs,
2197                                introduced_scopes
2198                            ))?;
2199                        }
2200                        continue;
2201                    }
2202                    (Some(Primitive::Import), imports) => {
2203                        if !permissive && !exprs.is_empty() {
2204                            return Err(error::unexpected_import(&expanded));
2205                        }
2206                        // First pass: parse all import sets and validate against
2207                        // our import policy before executing any of them.
2208                        let mut parsed_imports = Vec::new();
2209                        for import in imports {
2210                            let import_set = ImportSet::parse(discard_for(import))?;
2211                            if !ctxt.import_policy.is_allowed(&import_set) {
2212                                return Err(error::import_not_permitted(
2213                                    &expanded,
2214                                    import_set.library_name(),
2215                                ));
2216                            }
2217                            parsed_imports.push(import_set);
2218                        }
2219                        // Second pass: execute all imports (all have been validated)
2220                        for import_set in parsed_imports {
2221                            maybe_await!(env.import(import_set))?;
2222                        }
2223                        continue;
2224                    }
2225                    (Some(Primitive::Define), _) => {
2226                        if !permissive && !exprs.is_empty() {
2227                            return Err(error::unexpected_define(&expanded));
2228                        }
2229                        true
2230                    }
2231                    _ => false,
2232                }
2233            } else {
2234                false
2235            }
2236        };
2237
2238        if is_def {
2239            defs.push((expanded, env.clone()));
2240        } else {
2241            exprs.push((expanded, env.clone()));
2242        }
2243    }
2244
2245    Ok(())
2246}
2247
2248#[maybe_async]
2249fn parse_let_syntax(
2250    ctxt: &ParseContext,
2251    recursive: bool,
2252    bindings: &Syntax,
2253    exprs: &[Syntax],
2254    env: &Environment,
2255    introduced_scopes: &mut Vec<Scope>,
2256) -> Result<(Vec<Syntax>, Environment), Exception> {
2257    let new_scope = Scope::new();
2258    let new_env = env.new_lexical_contour(new_scope);
2259    let mut body = exprs.to_vec();
2260
2261    if bindings.is_null() {
2262        return Ok((body, new_env));
2263    }
2264
2265    let Some([keyword_bindings @ .., end]) = bindings.as_list() else {
2266        return Err(error::expected_list(bindings));
2267    };
2268
2269    if !end.is_null() {
2270        return Err(error::expected_list(bindings));
2271    }
2272
2273    introduced_scopes.push(new_scope);
2274
2275    for binding in keyword_bindings {
2276        if let Some([Syntax::Identifier { ident, .. }, expr, end]) = binding.as_list()
2277            && end.is_null()
2278        {
2279            let mut name = ident.clone();
2280            name.add_scope(new_scope);
2281            let mut expr = expr.clone();
2282            if recursive {
2283                expr.add_scope(new_scope);
2284            }
2285            let bind = name.new_bind();
2286            maybe_await!(define_syntax(ctxt, bind, expr, &new_env))?;
2287        } else {
2288            return Err(error::bad_form(bindings, Some(binding)));
2289        }
2290    }
2291
2292    body.iter_mut().for_each(|s| s.add_scope(new_scope));
2293    if recursive {
2294        let disambig_scope = Scope::new();
2295        introduced_scopes.push(disambig_scope);
2296        body.iter_mut().for_each(|s| s.add_scope(disambig_scope));
2297    }
2298
2299    Ok((body, new_env))
2300}
2301
2302#[derive(Debug, Clone, Trace)]
2303pub struct And {
2304    pub args: Vec<Expression>,
2305}
2306
2307impl And {
2308    pub fn new(args: Vec<Expression>) -> Self {
2309        Self { args }
2310    }
2311}
2312
2313impl And {
2314    #[maybe_async]
2315    fn parse(ctxt: &ParseContext, exprs: &[Syntax], env: &Environment) -> Result<Self, Exception> {
2316        let mut output = Vec::new();
2317        for expr in exprs {
2318            let expr = maybe_await!(Expression::parse(ctxt, expr.clone(), env))?;
2319            output.push(expr);
2320        }
2321        Ok(Self::new(output))
2322    }
2323}
2324
2325#[derive(Debug, Clone, Trace)]
2326pub struct Or {
2327    pub args: Vec<Expression>,
2328}
2329
2330impl Or {
2331    pub fn new(args: Vec<Expression>) -> Self {
2332        Self { args }
2333    }
2334
2335    #[maybe_async]
2336    fn parse(ctxt: &ParseContext, exprs: &[Syntax], env: &Environment) -> Result<Self, Exception> {
2337        let mut output = Vec::new();
2338        for expr in exprs {
2339            let expr = maybe_await!(Expression::parse(ctxt, expr.clone(), env))?;
2340            output.push(expr);
2341        }
2342        Ok(Self::new(output))
2343    }
2344}
2345
2346#[derive(Debug, Clone, Trace)]
2347pub struct Vector {
2348    pub vals: Vec<Value>,
2349}
2350
2351impl Vector {
2352    fn parse(exprs: &[Syntax]) -> Self {
2353        let mut vals = Vec::new();
2354        for expr in exprs {
2355            vals.push(Value::datum_from_syntax(expr));
2356        }
2357        Self { vals }
2358    }
2359}
2360
2361#[derive(Clone, Trace, Debug)]
2362pub struct SyntaxCase {
2363    pub arg: Arc<Expression>,
2364    pub rules: Vec<SyntaxRule>,
2365}
2366
2367impl SyntaxCase {
2368    #[maybe_async]
2369    fn parse(
2370        ctxt: &ParseContext,
2371        exprs: &[Syntax],
2372        env: &Environment,
2373        form: &Syntax,
2374    ) -> Result<Self, Exception> {
2375        let (arg, keywords, mut rules) = match exprs {
2376            [arg, Syntax::List { list, .. }, rules @ ..] => {
2377                let mut keywords = HashSet::default();
2378                // TODO: ensure keywords_list is proper
2379                for keyword in &list[..list.len() - 1] {
2380                    if let Syntax::Identifier { ident, .. } = keyword {
2381                        keywords.insert(ident);
2382                    } else {
2383                        return Err(error::expected_identifier(form, Some(keyword)));
2384                    }
2385                }
2386                (arg, keywords, rules)
2387            }
2388            [arg, empty, rules @ ..] if empty.is_null() => (arg, HashSet::default(), rules),
2389            _ => return Err(error::bad_form(form, None)),
2390        };
2391        let mut syntax_rules = Vec::new();
2392        loop {
2393            match rules {
2394                [] => break,
2395                [Syntax::List { list, .. }, tail @ ..] => match &list[..] {
2396                    [pattern, output_expression, end] if end.is_null() => {
2397                        syntax_rules.push(maybe_await!(SyntaxRule::compile(
2398                            ctxt,
2399                            &keywords,
2400                            pattern,
2401                            None,
2402                            output_expression,
2403                            env,
2404                        ))?);
2405                        rules = tail;
2406                    }
2407                    [pattern, fender, output_expression, end] if end.is_null() => {
2408                        syntax_rules.push(maybe_await!(SyntaxRule::compile(
2409                            ctxt,
2410                            &keywords,
2411                            pattern,
2412                            Some(fender),
2413                            output_expression,
2414                            env,
2415                        ))?);
2416                        rules = tail;
2417                    }
2418                    _ => return Err(error::bad_form(form, None)),
2419                },
2420                _ => return Err(error::bad_form(form, None)),
2421            }
2422        }
2423        Ok(SyntaxCase {
2424            arg: Arc::new(maybe_await!(Expression::parse(ctxt, arg.clone(), env))?),
2425            rules: syntax_rules,
2426        })
2427    }
2428}