1use 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
29mod 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#[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#[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 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 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 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#[derive(Clone, Debug, Default)]
886pub struct AllowList(HashSet<Vec<Symbol>>);
887
888impl AllowList {
889 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 pub fn add_lib(&mut self, lib: Vec<Symbol>) {
903 self.0.insert(lib);
904 }
905
906 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 fn from_str(s: &str) -> Result<Self, Self::Err> {
920 let form = Syntax::from_str(s, None)?;
921 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#[derive(Clone, Debug)]
961pub enum ImportPolicy {
962 Allow,
964 AllowList(AllowList),
967}
968
969impl ImportPolicy {
970 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 pub fn allow_only(allow_list: AllowList) -> Self {
980 ImportPolicy::AllowList(allow_list)
981 }
982
983 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 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 Formals::FixedArgs(Vec::new())
1132 };
1133
1134 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 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 Syntax::Wrapped { value, .. } => Ok(Self::Literal(value.clone())),
1251
1252 Syntax::Vector { vector, .. } => Ok(Self::Vector(Vector::parse(vector))),
1254
1255 Syntax::List { list: exprs, .. } => match exprs.as_slice() {
1257 [
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 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#[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::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 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 [
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, ],
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 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 #[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 #[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 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 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 #[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 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 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 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}