steel_parser/
parser.rs

1use std::{
2    borrow::Cow,
3    path::PathBuf,
4    rc::Rc,
5    result,
6    sync::atomic::{AtomicUsize, Ordering},
7};
8
9use serde::{Deserialize, Serialize};
10
11use crate::{
12    ast::{
13        self, parse_begin, parse_define, parse_if, parse_lambda, parse_let, parse_new_let,
14        parse_require, parse_set, parse_single_argument, Atom, ExprKind, List, Macro, PatternPair,
15        SyntaxRules, Vector, BEGIN, DEFINE, IF, LAMBDA, LAMBDA_FN, LAMBDA_SYMBOL, LET, PLAIN_LET,
16        QUASIQUOTE, QUASISYNTAX, QUOTE, RAW_UNQUOTE, RAW_UNQUOTE_SPLICING, RAW_UNSYNTAX,
17        RAW_UNSYNTAX_SPLICING, REQUIRE, RETURN, SET, SYNTAX_QUOTE, UNQUOTE, UNQUOTE_SPLICING,
18    },
19    interner::InternedString,
20    lexer::{OwnedTokenStream, ToOwnedString, TokenStream},
21    span::Span,
22    tokens::{Paren, ParenMod, Token, TokenType},
23};
24
25#[derive(
26    Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
27)]
28#[repr(C)]
29pub struct SourceId(pub u32);
30
31impl SourceId {
32    pub const fn none() -> Option<Self> {
33        None
34    }
35}
36
37// TODO: Fix the visibility here
38pub static SYNTAX_OBJECT_ID: AtomicUsize = AtomicUsize::new(0);
39
40// thread_local! {
41//     pub static TL_SYNTAX_OBJECT_ID: Cell<u32> = Cell::new(0);
42// }
43
44#[derive(
45    Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
46)]
47pub struct SyntaxObjectId(pub u32);
48
49impl SyntaxObjectId {
50    #[inline]
51    pub fn fresh() -> Self {
52        SyntaxObjectId(SYNTAX_OBJECT_ID.fetch_add(1, Ordering::Relaxed) as _)
53        // TODO: Revisit why we're using this here
54        // SyntaxObjectId(TL_SYNTAX_OBJECT_ID.with(|x| {
55        //     let value = x.get();
56        //     x.set(value + 1);
57        //     value
58        // }))
59    }
60}
61
62impl From<SyntaxObjectId> for u32 {
63    fn from(value: SyntaxObjectId) -> Self {
64        value.0
65    }
66}
67
68impl std::fmt::Display for SyntaxObjectId {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        write!(f, "{self:?}")
71    }
72}
73
74#[derive(
75    Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
76)]
77pub struct ListId(usize);
78
79#[derive(
80    Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Debug, Ord, PartialOrd,
81)]
82pub struct FunctionId(usize);
83
84/// A syntax object that can hold anything as the syntax
85/// In this case, we're using the token type emitted by logos
86///
87/// This should open the door to interning our strings to make
88/// parsing (and optimizations later) faster
89#[derive(Serialize, Deserialize)]
90pub struct RawSyntaxObject<T> {
91    pub ty: T,
92    pub span: Span,
93    pub syntax_object_id: SyntaxObjectId,
94    // TODO: @Matt
95    // This is a hack. More or less, we need a way to mark that
96    // this particular syntax object is "unresolved" - and thus
97    // should mangle its usage. This can also be done by using
98    // the syntax object ID separately, but there is enough
99    // space on the object itself that keeping it alongside the
100    // object seemed to make sense. What we're going to do is mark
101    // any unresolved references to variables found in macro expansion.
102    // So, for example, consider the following:
103    //
104    // (define bound-x (vector 10 20 30 40))
105    //
106    // (define-syntax lexical-capture
107    //   (syntax-rules ()
108    //     [(_) (list bound-x)]))
109    //
110    // (let ([bound-x 'inner]) (lexical-capture))
111    //
112    // The define syntax is expanded without the context of knowing
113    // the globals, and as a result isn't aware that bound-x should
114    // refer to the local. However, we can expand and see that both
115    // `list` and `bound-x` don't refer to anything in the patterns,
116    // and so as a result, should be marked as "unresolved". Since
117    // they are unresolved, we can conclude that either they're
118    // global variables, or a free identifier.
119    //
120    // Then, when handling shadowed local variables, when we come across
121    // a local variable that we'd like to mangle, if its unresolved, we
122    // just leave it alone, and otherwise we should treat all locals as
123    // variables to be mangled.
124    //
125    // Then, once we're done with all macro expansion, all variables themselves
126    // should be "resolved" since either they refer to an individual variable,
127    // or nothing at all.
128    pub unresolved: bool,
129    pub introduced_via_macro: bool,
130}
131
132impl<T: Clone> Clone for RawSyntaxObject<T> {
133    fn clone(&self) -> Self {
134        Self {
135            ty: self.ty.clone(),
136            span: self.span,
137            syntax_object_id: SyntaxObjectId::fresh(),
138            unresolved: self.unresolved,
139            introduced_via_macro: self.introduced_via_macro,
140        }
141    }
142}
143
144impl<T: std::fmt::Debug> std::fmt::Debug for RawSyntaxObject<T> {
145    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146        f.debug_struct("RawSyntaxObject")
147            .field("ty", &self.ty)
148            .field("span", &self.span)
149            .finish()
150    }
151}
152
153// Implementing hash here just on the token type - we dont want the span included
154// For determining the hash here
155impl<T: std::hash::Hash> std::hash::Hash for RawSyntaxObject<T> {
156    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
157        self.ty.hash(state);
158        self.span.hash(state);
159    }
160}
161
162pub type SyntaxObject = RawSyntaxObject<TokenType<InternedString>>;
163
164impl PartialEq for SyntaxObject {
165    fn eq(&self, other: &Self) -> bool {
166        self.ty == other.ty
167    }
168}
169
170impl SyntaxObject {
171    pub fn new(ty: TokenType<InternedString>, span: Span) -> Self {
172        SyntaxObject {
173            ty,
174            span,
175            // source: None,
176            syntax_object_id: SyntaxObjectId::fresh(),
177            unresolved: false,
178            introduced_via_macro: false,
179        }
180    }
181
182    pub fn default(ty: TokenType<InternedString>) -> Self {
183        SyntaxObject {
184            ty,
185            span: Span::new(0, 0, SourceId::none()),
186            // source: None,
187            syntax_object_id: SyntaxObjectId::fresh(),
188            unresolved: false,
189            introduced_via_macro: false,
190        }
191    }
192
193    pub fn set_span(&mut self, span: Span) {
194        self.span = span
195    }
196
197    pub fn from_token_with_source(
198        val: &Token<'_, InternedString>,
199        _source: &Option<Rc<PathBuf>>,
200    ) -> Self {
201        SyntaxObject {
202            ty: val.ty.clone(),
203            span: val.span,
204            syntax_object_id: SyntaxObjectId::fresh(),
205            unresolved: false,
206            introduced_via_macro: false,
207        }
208    }
209}
210
211impl From<&Token<'_, InternedString>> for SyntaxObject {
212    fn from(val: &Token<'_, InternedString>) -> SyntaxObject {
213        SyntaxObject::new(val.ty.clone(), val.span)
214    }
215}
216
217#[derive(Clone, Debug, PartialEq)]
218pub enum ParseError {
219    Unexpected(TokenType<String>, Span, Option<Rc<PathBuf>>),
220    UnexpectedEOF(Option<Rc<PathBuf>>),
221    UnexpectedChar(char, Span, Option<Rc<PathBuf>>),
222    IncompleteString(String, Span, Option<Rc<PathBuf>>),
223    SyntaxError(String, Span, Option<Rc<PathBuf>>),
224    ArityMismatch(String, Span, Option<Rc<PathBuf>>),
225}
226
227impl std::fmt::Display for ParseError {
228    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229        match self {
230            ParseError::Unexpected(l, _, _) => write!(f, "Parse: Unexpected token: {:?}", l),
231            ParseError::UnexpectedEOF(_) => write!(f, "Parse: Unexpected EOF"),
232            ParseError::UnexpectedChar(l, _, _) => {
233                write!(f, "Parse: Unexpected character: {:?}", l)
234            }
235            ParseError::IncompleteString(l, _, _) => write!(f, "Parse: Incomplete String: {}", l),
236            ParseError::SyntaxError(l, _, _) => write!(f, "Parse: Syntax Error: {}", l),
237            ParseError::ArityMismatch(l, _, _) => write!(f, "Parse: Arity mismatch: {}", l),
238        }
239    }
240}
241
242impl std::error::Error for ParseError {}
243
244impl ParseError {
245    pub fn span(&self) -> Option<Span> {
246        match self {
247            // ParseError::TokenError(_) => None,
248            ParseError::Unexpected(_, s, _) => Some(*s),
249            ParseError::UnexpectedEOF(_) => None,
250            ParseError::UnexpectedChar(_, s, _) => Some(*s),
251            ParseError::IncompleteString(_, s, _) => Some(*s),
252            ParseError::SyntaxError(_, s, _) => Some(*s),
253            ParseError::ArityMismatch(_, s, _) => Some(*s),
254        }
255    }
256
257    pub fn set_source(self, source: Option<Rc<PathBuf>>) -> Self {
258        use ParseError::*;
259        match self {
260            ParseError::Unexpected(l, s, _) => Unexpected(l, s, source),
261            ParseError::UnexpectedEOF(_) => UnexpectedEOF(source),
262            ParseError::UnexpectedChar(l, s, _) => UnexpectedChar(l, s, source),
263            ParseError::IncompleteString(l, s, _) => IncompleteString(l, s, source),
264            ParseError::SyntaxError(l, s, _) => SyntaxError(l, s, source),
265            ParseError::ArityMismatch(l, s, _) => ArityMismatch(l, s, source),
266        }
267    }
268}
269
270pub struct InternString;
271
272impl ToOwnedString<InternedString> for InternString {
273    fn own(&self, s: Cow<str>) -> InternedString {
274        (&*s).into()
275    }
276}
277
278// #[derive(Debug)]
279pub struct Parser<'a> {
280    tokenizer: OwnedTokenStream<'a, InternedString, InternString>,
281    quote_stack: Vec<usize>,
282    quasiquote_depth: isize,
283    quote_context: bool,
284    shorthand_quote_stack: Vec<usize>,
285    source_name: Option<Rc<PathBuf>>,
286    context: Vec<ParsingContext>,
287    comment_buffer: Vec<&'a str>,
288    collecting_comments: bool,
289    keep_lists: bool,
290}
291
292#[derive(Debug, Copy, Clone, PartialEq)]
293enum ParsingContext {
294    // Inside of a quote. Expressions should be parsed without being coerced into a typed variant of the AST
295    Quote(usize),
296    // Shortened version of a quote
297    QuoteTick(usize),
298    // Inside of an unquote - expressions should actually be parsed as usual
299    Unquote(usize),
300    // Shortened version of unquote
301    UnquoteTick(usize),
302    // Treat this like a normal quote
303    Quasiquote(usize),
304    // Shortened version of quasiquote
305    QuasiquoteTick(usize),
306    // expressions should parsed as normal
307    UnquoteSplicing(usize),
308    // Shorted version of Unquote Splicing
309    UnquoteSplicingTick(usize),
310}
311
312impl<'a> Parser<'a> {
313    pub fn parse(expr: &str) -> Result<Vec<ExprKind>> {
314        Parser::new(expr, SourceId::none()).collect()
315    }
316
317    pub fn parse_without_lowering(expr: &str) -> Result<Vec<ExprKind>> {
318        Parser::new(expr, SourceId::none())
319            .without_lowering()
320            .collect()
321    }
322
323    pub fn offset(&self) -> usize {
324        self.tokenizer.offset()
325    }
326}
327
328pub type Result<T> = result::Result<T, ParseError>;
329
330fn tokentype_error_to_parse_error(t: &Token<'_, InternedString>) -> ParseError {
331    if let TokenType::Error = t.ty {
332        if t.source.starts_with('\"') {
333            ParseError::IncompleteString(t.source.to_string(), t.span, None)
334        } else {
335            ParseError::UnexpectedChar(t.source.chars().next().unwrap(), t.span, None)
336        }
337    } else {
338        ParseError::UnexpectedEOF(None)
339    }
340}
341
342impl<'a> Parser<'a> {
343    pub fn new(input: &'a str, source_id: Option<SourceId>) -> Self {
344        Parser {
345            tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
346            quote_stack: Vec::new(),
347            quasiquote_depth: 0,
348            quote_context: false,
349            shorthand_quote_stack: Vec::new(),
350            source_name: None,
351            context: Vec::new(),
352            comment_buffer: Vec::new(),
353            collecting_comments: false,
354            keep_lists: false,
355        }
356    }
357
358    pub fn without_lowering(mut self) -> Self {
359        self.keep_lists = true;
360        self
361    }
362
363    pub fn new_flat(input: &'a str, source_id: Option<SourceId>) -> Self {
364        Parser {
365            tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
366            quote_stack: Vec::new(),
367            quasiquote_depth: 0,
368            quote_context: false,
369            shorthand_quote_stack: Vec::new(),
370            source_name: None,
371            context: Vec::new(),
372            comment_buffer: Vec::new(),
373            collecting_comments: false,
374            keep_lists: true,
375        }
376    }
377
378    pub fn new_from_source(
379        input: &'a str,
380        source_name: PathBuf,
381        source_id: Option<SourceId>,
382    ) -> Self {
383        Parser {
384            tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
385            quote_stack: Vec::new(),
386            quasiquote_depth: 0,
387            quote_context: false,
388            shorthand_quote_stack: Vec::new(),
389            source_name: Some(Rc::from(source_name)),
390            context: Vec::new(),
391            comment_buffer: Vec::new(),
392            collecting_comments: false,
393            keep_lists: false,
394        }
395    }
396
397    // Attach comments!
398    pub fn doc_comment_parser(input: &'a str, source_id: Option<SourceId>) -> Self {
399        Parser {
400            tokenizer: TokenStream::new(input, false, source_id).into_owned(InternString),
401            quote_stack: Vec::new(),
402            quasiquote_depth: 0,
403            quote_context: false,
404            shorthand_quote_stack: Vec::new(),
405            source_name: None,
406            context: Vec::new(),
407            comment_buffer: Vec::new(),
408            collecting_comments: false,
409            keep_lists: false,
410        }
411    }
412
413    fn construct_quote(&mut self, val: ExprKind, span: Span) -> ExprKind {
414        ExprKind::Quote(Box::new(ast::Quote::new(
415            val,
416            SyntaxObject::new(TokenType::Quote, span),
417        )))
418    }
419
420    fn _expand_reader_macro(
421        &mut self,
422        token: TokenType<InternedString>,
423        val: ExprKind,
424        span: Span,
425    ) -> ExprKind {
426        let q = ExprKind::Atom(Atom::new(SyntaxObject::new(token, span)));
427
428        ExprKind::List(List::new(vec![q, val]))
429    }
430
431    fn construct_quote_vec(&mut self, val: ExprKind, span: Span) -> Vec<ExprKind> {
432        // println!("Inside construct quote vec with: {:?}", val);
433
434        let q = {
435            let rc_val = TokenType::Quote;
436            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
437            // let val = ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)));
438            // // self.intern.insert("quote".to_string(), rc_val);
439            // val
440        };
441
442        vec![q, val]
443    }
444
445    // Reader macro for #'
446    fn construct_syntax(&mut self, val: ExprKind, span: Span) -> ExprKind {
447        let q = {
448            let rc_val = TokenType::Identifier(*SYNTAX_QUOTE);
449            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
450        };
451
452        ExprKind::List(List::new(vec![q, val]))
453    }
454
455    // Reader macro for #'
456    fn construct_quasiquote_syntax(&mut self, val: ExprKind, span: Span) -> ExprKind {
457        let q = {
458            let rc_val = TokenType::Identifier(*QUASISYNTAX);
459            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
460        };
461
462        ExprKind::List(List::new(vec![q, val]))
463    }
464
465    fn construct_quasiunquote_syntax(&mut self, val: ExprKind, span: Span) -> ExprKind {
466        let q = {
467            let rc_val = TokenType::Identifier(*RAW_UNSYNTAX);
468            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
469        };
470
471        ExprKind::List(List::new(vec![q, val]))
472    }
473
474    fn construct_quasiunquote_syntax_splicing(&mut self, val: ExprKind, span: Span) -> ExprKind {
475        let q = {
476            let rc_val = TokenType::Identifier(*RAW_UNSYNTAX_SPLICING);
477            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
478        };
479
480        ExprKind::List(List::new(vec![q, val]))
481    }
482
483    // Reader macro for `
484    fn construct_quasiquote(&mut self, val: ExprKind, span: Span) -> ExprKind {
485        let q = {
486            let rc_val = TokenType::Identifier(*QUASIQUOTE);
487            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
488        };
489
490        ExprKind::List(List::new(vec![q, val]))
491    }
492
493    // Reader macro for ,
494    fn construct_unquote(&mut self, val: ExprKind, span: Span) -> ExprKind {
495        let q = {
496            let rc_val = TokenType::Identifier(*UNQUOTE);
497            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
498        };
499
500        ExprKind::List(List::new(vec![q, val]))
501    }
502
503    fn construct_raw_unquote(&mut self, val: ExprKind, span: Span) -> ExprKind {
504        let q = {
505            // let rc_val = TokenType::Identifier(*UNQUOTE);
506            let rc_val = TokenType::Identifier(*RAW_UNQUOTE);
507            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
508        };
509
510        ExprKind::List(List::new(vec![q, val]))
511    }
512    // Reader macro for ,@
513    fn construct_unquote_splicing(&mut self, val: ExprKind, span: Span) -> ExprKind {
514        let q = {
515            let rc_val = TokenType::Identifier(*UNQUOTE_SPLICING);
516            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
517        };
518
519        ExprKind::List(List::new(vec![q, val]))
520    }
521
522    // Reader macro for ,@
523    fn construct_raw_unquote_splicing(&mut self, val: ExprKind, span: Span) -> ExprKind {
524        let q = {
525            let rc_val = TokenType::Identifier(*RAW_UNQUOTE_SPLICING);
526            ExprKind::Atom(Atom::new(SyntaxObject::new(rc_val, span)))
527        };
528
529        ExprKind::List(List::new(vec![q, val]))
530    }
531
532    fn increment_quasiquote_context_if_not_in_quote_context(&mut self) {
533        // println!("INCREMENTING");
534        if !self.quote_context {
535            self.quasiquote_depth += 1;
536        }
537    }
538
539    fn decrement_quasiquote_context_if_not_in_quote_context(&mut self) {
540        // println!("DECREMENTING");
541        if !self.quote_context {
542            self.quasiquote_depth -= 1;
543        }
544    }
545
546    fn maybe_lower(&self, exprs: Vec<ExprKind>) -> Result<ExprKind> {
547        if self.keep_lists {
548            Ok(ExprKind::List(List::new(exprs)))
549        } else {
550            ExprKind::try_from(exprs)
551        }
552    }
553
554    fn maybe_lower_frame(&self, frame: Frame, close: Span) -> Result<ExprKind> {
555        frame.build_expr(close, |exprs| self.maybe_lower(exprs))
556    }
557
558    fn read_from_tokens(
559        &mut self,
560        (open, paren, paren_mod): (Span, Paren, Option<ParenMod>),
561    ) -> Result<ExprKind> {
562        let mut stack: Vec<Frame> = Vec::new();
563
564        let mut current_frame = Frame {
565            open,
566            paren,
567            paren_mod,
568            exprs: vec![],
569            dot: None,
570            comment: 0,
571        };
572
573        self.quote_stack = Vec::new();
574
575        // println!("READING FROM TOKENS");
576        // self.quasiquote_depth = 0;
577
578        while let Some(token) = self.tokenizer.next() {
579            match token.ty {
580                TokenType::Dot => {
581                    if current_frame.dot.is_some() {
582                        return Err(ParseError::SyntaxError(
583                            "improper lists can only have a single dot".into(),
584                            token.span,
585                            None,
586                        ));
587                    } else if current_frame.exprs.is_empty() {
588                        return Err(ParseError::SyntaxError(
589                            "improper lists must have a car element before the dot".into(),
590                            token.span,
591                            None,
592                        ));
593                    } else if current_frame.paren_mod.is_some() {
594                        let paren_mod = current_frame.paren_mod.unwrap();
595                        let object = match paren_mod {
596                            ParenMod::Vector => "vector",
597                            ParenMod::Bytes => "bytevector",
598                        };
599
600                        return Err(ParseError::SyntaxError(
601                            format!("{object} literals cannot contain dots"),
602                            token.span,
603                            None,
604                        ));
605                    } else if current_frame.comment > 0 {
606                        return Err(ParseError::SyntaxError(
607                            "commented-out datum cannot start with a dot".into(),
608                            token.span,
609                            None,
610                        ));
611                    } else {
612                        current_frame.dot = Some((current_frame.exprs.len(), token.span));
613                    }
614                }
615                TokenType::Comment => {
616                    // println!("Found a comment!");
617                    // Internal comments, we're gonna skip for now
618                }
619                TokenType::DatumComment => {
620                    current_frame.comment += 1;
621                }
622                TokenType::Error => return Err(tokentype_error_to_parse_error(&token)), // TODO
623
624                TokenType::QuoteSyntax => {
625                    let quote_inner = self
626                        .next()
627                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
628                        .map(|x| self.construct_syntax(x, token.span))?;
629
630                    current_frame.push(quote_inner)?
631                }
632
633                TokenType::QuasiQuoteSyntax => {
634                    let quote_inner = self
635                        .next()
636                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
637                        .map(|x| self.construct_quasiquote_syntax(x, token.span))?;
638
639                    current_frame.push(quote_inner)?
640                }
641
642                TokenType::UnquoteSyntax => {
643                    let quote_inner = self
644                        .next()
645                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
646                        .map(|x| self.construct_quasiunquote_syntax(x, token.span))?;
647
648                    current_frame.push(quote_inner)?
649                }
650
651                TokenType::UnquoteSpliceSyntax => {
652                    let quote_inner = self
653                        .next()
654                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
655                        .map(|x| self.construct_quasiunquote_syntax_splicing(x, token.span))?;
656
657                    current_frame.push(quote_inner)?
658                }
659
660                TokenType::QuoteTick => {
661                    // quote_count += 1;
662                    // self.quote_stack.push(current_frame.exprs.len());
663                    self.shorthand_quote_stack.push(stack.len());
664
665                    let last_context = self.quote_context;
666
667                    if self.quasiquote_depth == 0 {
668                        self.quote_context = true;
669                    }
670
671                    // println!("Entering context: Quote Tick in read from tokens");
672
673                    self.context.push(ParsingContext::QuoteTick(stack.len()));
674
675                    let quote_inner = self
676                        .next()
677                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
678                        .map(|x| {
679                            // if self.quasiquote_depth == 0 {
680                            self.construct_quote(x, token.span)
681                            // } else {
682                            // self.construct_fake_quote(x, token.span)
683                            // }
684                        });
685                    // self.quote_stack.pop();
686                    self.shorthand_quote_stack.pop();
687
688                    self.quote_context = last_context;
689
690                    // println!(
691                    //     "Exiting Context: {:?} in read from tokens",
692                    //     self.context.pop()
693                    // );
694
695                    // self.context.pop();
696
697                    let popped_value = self.context.pop();
698
699                    if let Some(popped) = popped_value {
700                        // dbg!(&popped);
701                        debug_assert!(matches!(popped, ParsingContext::QuoteTick(_)))
702                    }
703
704                    current_frame.push(quote_inner?)?;
705                }
706                TokenType::Unquote => {
707                    // println!("Entering context: Unquote");
708
709                    // This could underflow and panic - if its negative then we have a problem. Maybe just use an isize and let it underflow?
710                    self.decrement_quasiquote_context_if_not_in_quote_context();
711
712                    self.context.push(ParsingContext::UnquoteTick(stack.len()));
713
714                    let quote_inner = self
715                        .next()
716                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
717                        .map(|x| {
718                            // dbg!(self.quasiquote_depth);
719                            // dbg!(self.quote_context);
720                            if self.quasiquote_depth == 0 && !self.quote_context {
721                                self.construct_raw_unquote(x, token.span)
722                            } else {
723                                self.construct_unquote(x, token.span)
724                            }
725                        });
726
727                    let popped_value = self.context.pop();
728
729                    self.increment_quasiquote_context_if_not_in_quote_context();
730
731                    if let Some(popped) = popped_value {
732                        debug_assert!(matches!(popped, ParsingContext::UnquoteTick(_)))
733                    }
734                    // println!("Exiting Context: {:?}", self.context.pop());
735                    current_frame.push(quote_inner?)?;
736                }
737                TokenType::QuasiQuote => {
738                    // println!("Entering context: Quasiquote");
739
740                    self.increment_quasiquote_context_if_not_in_quote_context();
741
742                    self.context
743                        .push(ParsingContext::QuasiquoteTick(stack.len()));
744
745                    let quote_inner = self
746                        .next()
747                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
748                        .map(|x| self.construct_quasiquote(x, token.span));
749
750                    // self.context.pop();
751                    // println!(
752                    //     ">>>>>>>>>>>>>>>>>>> Exiting Context: {:?}",
753                    //     self.context.pop()
754                    // );
755
756                    let popped_value = self.context.pop();
757
758                    self.decrement_quasiquote_context_if_not_in_quote_context();
759
760                    if let Some(popped) = popped_value {
761                        debug_assert!(matches!(popped, ParsingContext::QuasiquoteTick(_)))
762                    }
763
764                    current_frame.push(quote_inner?)?;
765                }
766                TokenType::UnquoteSplice => {
767                    // println!("Entering context: UnquoteSplicing");
768
769                    self.decrement_quasiquote_context_if_not_in_quote_context();
770
771                    self.context
772                        .push(ParsingContext::UnquoteSplicingTick(stack.len()));
773
774                    let quote_inner = self
775                        .next()
776                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
777                        .map(|x| {
778                            if self.quasiquote_depth == 0 && !self.quote_context {
779                                self.construct_raw_unquote_splicing(x, token.span)
780                            } else {
781                                self.construct_unquote_splicing(x, token.span)
782                            }
783                        });
784
785                    // self.context.pop();
786
787                    let popped_value = self.context.pop();
788
789                    self.increment_quasiquote_context_if_not_in_quote_context();
790
791                    if let Some(popped) = popped_value {
792                        debug_assert!(matches!(popped, ParsingContext::UnquoteSplicingTick(_)))
793                    }
794
795                    // println!("Exiting Context: {:?}", self.context.pop());
796                    current_frame.push(quote_inner?)?;
797                }
798                TokenType::OpenParen(paren, paren_mod) => {
799                    stack.push(current_frame);
800
801                    current_frame = Frame {
802                        open: token.span,
803                        paren_mod,
804                        exprs: vec![],
805                        dot: None,
806                        paren,
807                        comment: 0,
808                    };
809                }
810                TokenType::CloseParen(paren) => {
811                    let close = token.span;
812                    // This is the match that we'll want to move inside the below stack.pop() match statement
813                    // As we close the current context, we check what our current state is -
814
815                    if paren != current_frame.paren {
816                        return Err(ParseError::Unexpected(
817                            TokenType::CloseParen(paren),
818                            token.span,
819                            self.source_name.clone(),
820                        ));
821                    }
822
823                    if let Some(mut prev_frame) = stack.pop() {
824                        match prev_frame
825                            .exprs
826                            .first_mut()
827                            .and_then(|x| x.atom_identifier_mut())
828                        {
829                            Some(ident) if *ident == *UNQUOTE => {
830                                // self.increment_quasiquote_context_if_not_in_quote_context();
831                                if self.quasiquote_depth == 0 && !self.quote_context {
832                                    *ident = *RAW_UNQUOTE;
833                                }
834                                self.increment_quasiquote_context_if_not_in_quote_context();
835
836                                // println!("Exiting unquote");
837                            }
838                            Some(ident) if *ident == *QUASIQUOTE => {
839                                self.decrement_quasiquote_context_if_not_in_quote_context();
840
841                                // println!("Exiting quasiquote");
842                            }
843                            Some(ident) if *ident == *UNQUOTE_SPLICING => {
844                                // self.increment_quasiquote_context_if_not_in_quote_context();
845
846                                if self.quasiquote_depth == 0 && !self.quote_context {
847                                    *ident = *RAW_UNQUOTE_SPLICING;
848                                }
849                                self.increment_quasiquote_context_if_not_in_quote_context();
850
851                                // println!("Exiting unquote");
852                            }
853                            _ => {}
854                        }
855
856                        match self.context.last().copied() {
857                            // TODO: Change this -> This should really be just Some(ParsingContext::Quote)
858                            // If we have _anything_ then we should check if we need to parse it differently. If we're at the last_quote_index,
859                            // then we can pop it off inside there.
860                            Some(ParsingContext::Quote(last_quote_index))
861                            | Some(ParsingContext::Quasiquote(last_quote_index)) => {
862                                if stack.len() <= last_quote_index {
863                                    self.context.pop();
864                                }
865
866                                match current_frame.exprs.first() {
867                                    Some(ExprKind::Atom(Atom {
868                                        syn:
869                                            SyntaxObject {
870                                                ty: TokenType::Quote,
871                                                ..
872                                            },
873                                    })) => match self.context.last() {
874                                        Some(
875                                            ParsingContext::Quasiquote(_)
876                                            | ParsingContext::QuasiquoteTick(_)
877                                            | ParsingContext::Quote(_)
878                                            | ParsingContext::QuoteTick(_),
879                                        ) => prev_frame.push(current_frame.to_expr(close)?)?,
880                                        _ => {
881                                            prev_frame.push(
882                                                self.maybe_lower_frame(current_frame, close)?,
883                                            )?;
884                                        }
885                                    },
886                                    _ => {
887                                        // println!("Converting to list");
888                                        // println!("Context here: {:?}", self.context);
889                                        prev_frame.push(current_frame.to_expr(close)?)?
890                                    }
891                                }
892                            }
893
894                            Some(ParsingContext::QuoteTick(_))
895                            | Some(ParsingContext::QuasiquoteTick(_)) => {
896                                match current_frame.exprs.first() {
897                                    Some(ExprKind::Atom(Atom {
898                                        syn:
899                                            SyntaxObject {
900                                                ty: TokenType::Quote,
901                                                ..
902                                            },
903                                    })) => {
904                                        // println!("Converting to quote inside quote tick");
905                                        prev_frame
906                                            .push(self.maybe_lower_frame(current_frame, close)?)?;
907                                    }
908                                    _ => {
909                                        // if let Some(ParsingContext::QuasiquoteTick(_)) =
910                                        //     self.context.last()
911                                        // {
912                                        //     self.decrement_quasiquote_context_if_not_in_quote_context();
913                                        // }
914
915                                        // println!("Converting to list inside quote tick");
916                                        prev_frame.push(current_frame.to_expr(close)?)?
917                                    }
918                                }
919                            }
920
921                            // If we're in the short hand reader world, just ignore popping off the stack
922                            // but still treat it as a normal expression
923                            Some(ParsingContext::UnquoteTick(_))
924                            | Some(ParsingContext::UnquoteSplicingTick(_)) => {
925                                // self.quasiquote_depth += 1;
926
927                                // self.increment_quasiquote_context_if_not_in_quote_context();
928
929                                // println!(
930                                //     "UQ/UQS: Stack length: {:?}, last_quote_index: {:?}",
931                                //     stack.len(),
932                                //     last_quote_index
933                                // );
934
935                                // if stack.len() <= *last_quote_index {
936                                //     // println!("Exiting Context: {:?}", self.context.pop());
937                                //     self.context.pop();
938                                // }
939
940                                prev_frame.push(self.maybe_lower_frame(current_frame, close)?)?;
941                            }
942
943                            Some(ParsingContext::Unquote(last_quote_index))
944                            | Some(ParsingContext::UnquoteSplicing(last_quote_index)) => {
945                                // self.quasiquote_depth += 1;
946
947                                // self.increment_quasiquote_context_if_not_in_quote_context();
948
949                                // println!(
950                                //     "UQ/UQS: Stack length: {:?}, last_quote_index: {:?}",
951                                //     stack.len(),
952                                //     last_quote_index
953                                // );
954
955                                if stack.len() <= last_quote_index {
956                                    // println!("{} - {}", stack.len(), last_quote_index);
957                                    // println!("Exiting Context: {:?}", self.context.pop());
958                                    self.context.pop();
959                                }
960
961                                prev_frame.push(self.maybe_lower_frame(current_frame, close)?)?;
962                            }
963
964                            // Else case, just go ahead and assume it is a normal frame
965                            _ => prev_frame.push(self.maybe_lower_frame(current_frame, close)?)?,
966                        }
967
968                        // Reinitialize current frame here
969                        current_frame = prev_frame;
970                    } else {
971                        // println!("Else case: {:?}", current_frame.exprs);
972                        // println!("Context: {:?}", self.context);
973
974                        // dbg!(&self.quote_stack);
975                        // dbg!(&self.context);
976                        // dbg!(&self.shorthand_quote_stack);
977                        match self.context.last() {
978                            Some(ParsingContext::QuoteTick(_))
979                            | Some(ParsingContext::QuasiquoteTick(_)) => {
980                                // | Some(ParsingContext::Quote(d)) && d > 0 => {
981
982                                return current_frame.to_expr(close);
983                            }
984                            Some(ParsingContext::Quote(x)) if *x > 0 => {
985                                self.context.pop();
986
987                                return current_frame.to_expr(close);
988                            }
989                            Some(ParsingContext::Quote(0)) => {
990                                self.context.pop();
991
992                                return self.maybe_lower_frame(current_frame, close);
993                            }
994                            _ => {
995                                // dbg!(self.quasiquote_depth);
996                                // println!("=> {}", List::new(current_frame.exprs.clone()));
997                                // println!("----------------------------------------");
998
999                                if self.quasiquote_depth > 0 {
1000                                    // TODO/HACK - @Matt
1001                                    // If we're in a define syntax situation, go ahead and just return a normal one
1002                                    if current_frame
1003                                        .exprs
1004                                        .first()
1005                                        .map(|x| x.define_syntax_ident())
1006                                        .unwrap_or_default()
1007                                    {
1008                                        return self.maybe_lower_frame(current_frame, close);
1009                                    }
1010
1011                                    // println!("Should still be quoted here");
1012
1013                                    return current_frame.to_expr(close);
1014                                }
1015
1016                                return self.maybe_lower_frame(current_frame, close);
1017                            }
1018                        }
1019                    }
1020                }
1021
1022                _ => {
1023                    if let TokenType::Quote = &token.ty {
1024                        // self.quote_stack.push(current_frame.exprs.len());
1025                        self.quote_stack.push(stack.len());
1026                    }
1027
1028                    // dbg!(&self.context);
1029
1030                    // Mark what context we're inside with the context stack:
1031                    // This only works when its the first argument - check the function call in open paren?
1032                    if current_frame.exprs.is_empty() {
1033                        match &token.ty {
1034                            TokenType::Quote => {
1035                                if self.context == [ParsingContext::QuoteTick(0)] {
1036                                    self.context.push(ParsingContext::Quote(1))
1037                                } else {
1038                                    self.context.push(ParsingContext::Quote(stack.len()))
1039                                }
1040
1041                                // self.context.push(ParsingContext::Quote(stack.len()))
1042                            }
1043                            TokenType::Identifier(ident) if *ident == *UNQUOTE => {
1044                                // println!("Entering unquote");
1045
1046                                self.context.push(ParsingContext::Unquote(stack.len()));
1047                                self.decrement_quasiquote_context_if_not_in_quote_context();
1048                            }
1049                            TokenType::Identifier(ident) if *ident == *QUASIQUOTE => {
1050                                // println!("Entering quasiquote");
1051
1052                                self.context.push(ParsingContext::Quasiquote(stack.len()));
1053                                self.increment_quasiquote_context_if_not_in_quote_context();
1054                            }
1055                            TokenType::Identifier(ident) if *ident == *UNQUOTE_SPLICING => {
1056                                self.context
1057                                    .push(ParsingContext::UnquoteSplicing(stack.len()));
1058                                self.decrement_quasiquote_context_if_not_in_quote_context();
1059                            }
1060                            _ => {}
1061                        }
1062
1063                        // println!("Context on application: {:?}", self.context);
1064                    }
1065
1066                    // println!("{}", token);
1067
1068                    let atom = Atom::new(SyntaxObject::from_token_with_source(
1069                        &token,
1070                        &self.source_name.clone(),
1071                    ));
1072
1073                    current_frame.push(ExprKind::Atom(atom))?
1074                }
1075            }
1076        }
1077
1078        Err(ParseError::UnexpectedEOF(self.source_name.clone()))
1079    }
1080}
1081
1082fn wrap_in_doc_function(expr: ExprKind, comment: String) -> ExprKind {
1083    // println!("Found comment : {} for expr {}", comment, expr);
1084
1085    ExprKind::List(List::new(vec![
1086        ExprKind::ident("@doc"),
1087        ExprKind::string_lit(comment),
1088        expr,
1089    ]))
1090}
1091
1092impl<'a> Parser<'a> {
1093    fn get_next_and_maybe_wrap_in_doc(&mut self) -> Option<Result<ExprKind>> {
1094        let mut datum_comments = vec![];
1095
1096        macro_rules! maybe_return {
1097            ($value:expr) => {{
1098                let value = $value;
1099
1100                if value.is_ok() {
1101                    if datum_comments.len() > 0 {
1102                        let _ = datum_comments.pop();
1103
1104                        continue;
1105                    }
1106                }
1107
1108                return Some(value);
1109            }};
1110        }
1111
1112        while let Some(res) = self.tokenizer.next() {
1113            match res.ty {
1114                TokenType::Comment => {
1115                    if self.comment_buffer.is_empty()
1116                        && !self.collecting_comments
1117                        && res.source().trim_start_matches(';').starts_with("@doc")
1118                    {
1119                        self.collecting_comments = true;
1120
1121                        continue;
1122                    }
1123
1124                    if self.collecting_comments {
1125                        let doc_line = res.source().trim_start_matches(';');
1126
1127                        // If we hit another comment, clear it
1128                        if doc_line.starts_with("@doc") {
1129                            // println!("Clearing buffer");
1130
1131                            self.comment_buffer.clear();
1132                            continue;
1133                        }
1134
1135                        // println!("Collecting line: {}", doc_line);
1136
1137                        let line = doc_line
1138                            .strip_prefix(" ")
1139                            .unwrap_or(doc_line)
1140                            .trim_end_matches(['\n', '\r']);
1141                        self.comment_buffer.push(line);
1142                    }
1143
1144                    continue;
1145                }
1146
1147                TokenType::DatumComment => {
1148                    datum_comments.push(res.span);
1149                }
1150
1151                // Just turn this into `syntax`
1152                TokenType::QuoteSyntax => {
1153                    let value = self
1154                        .next()
1155                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1156                        .map(|x| self.construct_syntax(x, res.span));
1157
1158                    maybe_return![value];
1159                }
1160
1161                TokenType::QuasiQuoteSyntax => {
1162                    let value = self
1163                        .next()
1164                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1165                        .map(|x| self.construct_quasiquote_syntax(x, res.span));
1166
1167                    maybe_return![value];
1168                }
1169
1170                TokenType::UnquoteSyntax => {
1171                    let quote_inner = self
1172                        .next()
1173                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1174                        .map(|x| self.construct_quasiunquote_syntax(x, res.span));
1175
1176                    maybe_return!(quote_inner);
1177                }
1178
1179                TokenType::UnquoteSpliceSyntax => {
1180                    let quote_inner = self
1181                        .next()
1182                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1183                        .map(|x| self.construct_quasiunquote_syntax_splicing(x, res.span));
1184
1185                    maybe_return!(quote_inner);
1186                }
1187
1188                TokenType::QuoteTick => {
1189                    // See if this does the job
1190                    self.shorthand_quote_stack.push(0);
1191
1192                    let last = self.quote_context;
1193
1194                    if self.quasiquote_depth == 0 {
1195                        self.quote_context = true;
1196                    }
1197
1198                    // self.quote_context = true;
1199
1200                    // println!("Entering Context: Quote Tick");
1201                    self.context.push(ParsingContext::QuoteTick(0));
1202
1203                    let value = self
1204                        .next()
1205                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1206                        .map(|x| self.construct_quote_vec(x, res.span));
1207
1208                    self.shorthand_quote_stack.pop();
1209
1210                    let popped_value = self.context.pop();
1211
1212                    if let Some(popped) = popped_value {
1213                        // dbg!(&popped);
1214                        debug_assert!(matches!(popped, ParsingContext::QuoteTick(_)))
1215                    }
1216
1217                    self.quote_context = last;
1218
1219                    // println!("Exiting context: {:?}", self.context.pop());
1220                    // println!("Result: {:?}", value);
1221
1222                    // println!("{}", List::new(value.clone().unwrap()));
1223
1224                    maybe_return!(match value {
1225                        Ok(v) => {
1226                            // Ok(ExprKind::List(List::new(v)))
1227
1228                            self.maybe_lower(v)
1229                        }
1230                        Err(e) => Err(e),
1231                    });
1232                }
1233
1234                TokenType::Unquote => {
1235                    // println!("Entering Context: Unquote");
1236                    self.context.push(ParsingContext::UnquoteTick(0));
1237
1238                    self.decrement_quasiquote_context_if_not_in_quote_context();
1239
1240                    let value = self
1241                        .next()
1242                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1243                        .map(|x| {
1244                            // dbg!(&self.quasiquote_depth);
1245                            if self.quasiquote_depth == 0 && !self.quote_context {
1246                                self.construct_raw_unquote(x, res.span)
1247                            } else {
1248                                self.construct_unquote(x, res.span)
1249                            }
1250                        });
1251
1252                    let popped_value = self.context.pop();
1253
1254                    self.increment_quasiquote_context_if_not_in_quote_context();
1255
1256                    if let Some(popped) = popped_value {
1257                        debug_assert!(matches!(popped, ParsingContext::UnquoteTick(_)))
1258                    }
1259                    // println!("Exiting context: {:?}", self.context.pop());
1260
1261                    maybe_return!(value);
1262                }
1263
1264                TokenType::UnquoteSplice => {
1265                    // println!("Entering Context: Unquotesplicing");
1266                    self.context.push(ParsingContext::UnquoteSplicingTick(0));
1267
1268                    self.decrement_quasiquote_context_if_not_in_quote_context();
1269
1270                    let value = self
1271                        .next()
1272                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1273                        .map(|x| {
1274                            if self.quasiquote_depth == 0 && !self.quote_context {
1275                                self.construct_raw_unquote_splicing(x, res.span)
1276                            } else {
1277                                self.construct_unquote_splicing(x, res.span)
1278                            }
1279                        });
1280
1281                    let popped_value = self.context.pop();
1282
1283                    self.increment_quasiquote_context_if_not_in_quote_context();
1284
1285                    if let Some(popped) = popped_value {
1286                        debug_assert!(matches!(popped, ParsingContext::UnquoteSplicingTick(_)))
1287                    }
1288
1289                    // println!("Exiting context: {:?}", self.context.pop());
1290
1291                    maybe_return!(value);
1292                }
1293                // Make this also handle quasisyntax
1294                TokenType::QuasiQuote => {
1295                    self.context.push(ParsingContext::QuasiquoteTick(0));
1296
1297                    self.increment_quasiquote_context_if_not_in_quote_context();
1298
1299                    let value = self
1300                        .next()
1301                        .unwrap_or(Err(ParseError::UnexpectedEOF(self.source_name.clone())))
1302                        .map(|x| self.construct_quasiquote(x, res.span));
1303
1304                    let popped_value = self.context.pop();
1305
1306                    if let Some(popped) = popped_value {
1307                        debug_assert!(matches!(popped, ParsingContext::QuasiquoteTick(_)))
1308                    }
1309
1310                    self.decrement_quasiquote_context_if_not_in_quote_context();
1311
1312                    maybe_return![value];
1313                }
1314
1315                TokenType::OpenParen(paren, paren_mod) => {
1316                    let value = self
1317                        .read_from_tokens((res.span, paren, paren_mod))
1318                        .map_err(|err| err.set_source(self.source_name.clone()));
1319
1320                    // self.quote_stack.clear();
1321                    // self.context.clear();
1322
1323                    maybe_return![value];
1324                }
1325                TokenType::CloseParen(paren) => {
1326                    maybe_return!(Err(ParseError::Unexpected(
1327                        TokenType::CloseParen(paren),
1328                        res.span,
1329                        self.source_name.clone(),
1330                    )))
1331                }
1332                TokenType::Error => maybe_return!(Err(tokentype_error_to_parse_error(&res))),
1333                _ => {
1334                    maybe_return![Ok(ExprKind::Atom(Atom::new(SyntaxObject::from(&res))))];
1335                }
1336            };
1337        }
1338
1339        if !datum_comments.is_empty() {
1340            return Some(Err(ParseError::SyntaxError(
1341                "unfinished commented-out expression".into(),
1342                datum_comments.pop().unwrap(),
1343                None,
1344            )));
1345        }
1346
1347        // We're done consuming input
1348        None
1349    }
1350}
1351
1352impl<'a> Iterator for Parser<'a> {
1353    type Item = Result<ExprKind>;
1354
1355    // TODO -> put the
1356    fn next(&mut self) -> Option<Self::Item> {
1357        if self.quote_stack.is_empty()
1358            && self.shorthand_quote_stack.is_empty()
1359            && self.context.is_empty()
1360        {
1361            self.quasiquote_depth = 0;
1362            self.comment_buffer.clear();
1363        }
1364
1365        self.get_next_and_maybe_wrap_in_doc().map(|res| {
1366            if self.comment_buffer.is_empty() || !self.context.is_empty() {
1367                res
1368            } else {
1369                // Reset the comment collection until next @doc statement
1370                self.collecting_comments = false;
1371                res.map(|x| {
1372                    // println!("Wrapping in doc: {}", x);
1373                    let result = wrap_in_doc_function(
1374                        x,
1375                        self.comment_buffer.drain(..).collect::<Vec<_>>().join("\n"),
1376                    );
1377
1378                    result
1379                })
1380            }
1381        })
1382    }
1383}
1384
1385// Lower the syntax rules down from the list representation
1386pub fn lower_syntax_rules(expr: ExprKind) -> Result<SyntaxRules> {
1387    let mut value_iter = expr.into_list().into_iter();
1388    let syn = value_iter
1389        .next()
1390        .unwrap()
1391        .into_atom_syntax_object()
1392        .unwrap();
1393
1394    let syntax_vec = if let Some(ExprKind::List(l)) = value_iter.next() {
1395        l.args
1396    } else {
1397        return Err(ParseError::SyntaxError(
1398            "syntax-rules expects a list of new syntax forms used in the macro".to_string(),
1399            syn.span,
1400            None,
1401        ));
1402    };
1403
1404    let mut pairs = Vec::new();
1405    let rest: Vec<_> = value_iter.collect();
1406
1407    for pair in rest {
1408        if let ExprKind::List(l) = pair {
1409            if l.args.len() != 2 {
1410                return Err(ParseError::SyntaxError(
1411                    "syntax-rules requires only one pattern to one body".to_string(),
1412                    syn.span,
1413                    None,
1414                ));
1415            }
1416
1417            let mut pair_iter = l.args.into_iter();
1418            let pair_object =
1419                PatternPair::new(pair_iter.next().unwrap(), pair_iter.next().unwrap());
1420            pairs.push(pair_object);
1421        } else {
1422            return Err(ParseError::SyntaxError(
1423                "syntax-rules requires pattern to expressions to be in a list".to_string(),
1424                syn.span,
1425                None,
1426            ));
1427        }
1428    }
1429
1430    Ok(SyntaxRules::new(syntax_vec, pairs, syn))
1431}
1432
1433// Lower define-syntax down from the list representation
1434pub fn lower_macro_and_require_definitions(expr: ExprKind) -> Result<ExprKind> {
1435    let as_list = expr.list();
1436
1437    // If this qualifies as
1438    if as_list.map(List::is_define_syntax).unwrap_or_default()
1439        && as_list
1440            .unwrap()
1441            .get(2)
1442            .and_then(ExprKind::list)
1443            .map(List::is_syntax_rules)
1444            .unwrap_or_default()
1445    {
1446        let mut value_iter = expr.into_list().into_iter();
1447
1448        let define_syntax = value_iter.next().unwrap();
1449
1450        let name = value_iter.next().unwrap();
1451        let syntax = lower_syntax_rules(value_iter.next().unwrap())?;
1452
1453        return Ok(ExprKind::Macro(Box::new(Macro::new(
1454            name,
1455            Box::new(syntax),
1456            define_syntax.into_atom_syntax_object().unwrap(),
1457        ))));
1458    }
1459
1460    if as_list.map(List::is_require).unwrap_or_default() {
1461        let mut raw = expr.into_list().args;
1462
1463        let syn = raw.remove(0).into_atom_syntax_object().unwrap();
1464
1465        if raw.is_empty() {
1466            return Err(ParseError::ArityMismatch(
1467                "require expects at least one identifier or string".to_string(),
1468                syn.span,
1469                None,
1470            ));
1471        }
1472
1473        return Ok(ExprKind::Require(Box::new(ast::Require::new(raw, syn))));
1474    }
1475
1476    let mut expr = expr;
1477
1478    // TODO: Here, we should lower syntax-case itself
1479    // to a defmacro, so that things seem to work out correctly.
1480
1481    // HACK:
1482    // If we get here, we can convert the define-syntax back into an identifier
1483    // so that other macro expansion can occur on it.
1484    if let Some(first) = expr
1485        .list_mut()
1486        .and_then(|x| x.args.first_mut().and_then(|x| x.atom_syntax_object_mut()))
1487    {
1488        if first.ty == TokenType::DefineSyntax {
1489            first.ty = TokenType::Identifier("define-syntax".into());
1490        }
1491    }
1492
1493    Ok(expr)
1494}
1495
1496struct ASTLowerPass {
1497    quote_depth: usize,
1498}
1499
1500impl ASTLowerPass {
1501    fn lower(&mut self, expr: &mut ExprKind) -> Result<()> {
1502        match expr {
1503            ExprKind::List(ref mut value) => {
1504                if value.is_quote() {
1505                    // println!("Found quote: {:?}", value);
1506                    self.quote_depth += 1;
1507                }
1508
1509                // Visit the children first, on the way back up, assign into the
1510                // correct AST node
1511                // value.args = value
1512                //     .args
1513                //     .into_iter()
1514                //     .map(|x| self.lower(x))
1515                //     .collect::<Result<_>>()?;
1516
1517                for expr in value.args.iter_mut() {
1518                    self.lower(expr)?;
1519                }
1520
1521                if value.is_quote() {
1522                    self.quote_depth -= 1;
1523                }
1524
1525                if let Some(f) = value.args.first_mut().and_then(|x| {
1526                    if let ExprKind::Atom(a) = x {
1527                        if a.syn.ty == TokenType::DefineSyntax {
1528                            a.syn.ty = TokenType::Identifier("define-syntax".into());
1529                        }
1530
1531                        Some(x.clone())
1532                    } else {
1533                        None
1534                    }
1535                }) {
1536                    match f {
1537                        ExprKind::Atom(a) if self.quote_depth == 0 && value.is_quote() => {
1538                            match &a.syn.ty {
1539                                TokenType::Quote => {
1540                                    *expr = parse_single_argument(
1541                                        std::mem::take(&mut value.args).into_iter(),
1542                                        a.syn.clone(),
1543                                        "quote",
1544                                        |expr, syn| ast::Quote::new(expr, syn).into(),
1545                                    )?;
1546
1547                                    Ok(())
1548                                }
1549                                _ => unreachable!(),
1550                            }
1551                        }
1552                        ExprKind::Atom(a) if self.quote_depth == 0 => {
1553                            let value = std::mem::replace(value, List::new(vec![]));
1554
1555                            *expr = match &a.syn.ty {
1556                                TokenType::If => {
1557                                    parse_if(value.args_proper(TokenType::If)?.into_iter(), a.syn)
1558                                }
1559                                TokenType::Identifier(expr) if *expr == *IF => {
1560                                    parse_if(value.args_proper(TokenType::If)?.into_iter(), a.syn)
1561                                }
1562
1563                                TokenType::Define => parse_define(
1564                                    value.args_proper(TokenType::Define)?.into_iter(),
1565                                    a.syn,
1566                                ),
1567                                TokenType::Identifier(expr) if *expr == *DEFINE => parse_define(
1568                                    value.args_proper(TokenType::Define)?.into_iter(),
1569                                    a.syn,
1570                                ),
1571
1572                                TokenType::Let => parse_let(
1573                                    value.args_proper(TokenType::Let)?.into_iter(),
1574                                    a.syn.clone(),
1575                                ),
1576                                TokenType::Identifier(expr) if *expr == *LET => {
1577                                    parse_let(value.args_proper(TokenType::Let)?.into_iter(), a.syn)
1578                                }
1579
1580                                // TODO: Deprecate
1581                                TokenType::TestLet => parse_new_let(
1582                                    value.args_proper(TokenType::TestLet)?.into_iter(),
1583                                    a.syn,
1584                                ),
1585                                TokenType::Identifier(expr) if *expr == *PLAIN_LET => {
1586                                    parse_new_let(
1587                                        value.args_proper(TokenType::TestLet)?.into_iter(),
1588                                        a.syn,
1589                                    )
1590                                }
1591
1592                                TokenType::Quote => parse_single_argument(
1593                                    value.args_proper(TokenType::Quote)?.into_iter(),
1594                                    a.syn,
1595                                    "quote",
1596                                    |expr, syn| ast::Quote::new(expr, syn).into(),
1597                                ),
1598                                TokenType::Identifier(expr) if *expr == *QUOTE => {
1599                                    parse_single_argument(
1600                                        value.args_proper(TokenType::Quote)?.into_iter(),
1601                                        a.syn,
1602                                        "quote",
1603                                        |expr, syn| ast::Quote::new(expr, syn).into(),
1604                                    )
1605                                }
1606
1607                                TokenType::Return => parse_single_argument(
1608                                    value.args_proper(TokenType::Return)?.into_iter(),
1609                                    a.syn,
1610                                    "return!",
1611                                    |expr, syn| ast::Return::new(expr, syn).into(),
1612                                ),
1613                                TokenType::Identifier(expr) if *expr == *RETURN => {
1614                                    parse_single_argument(
1615                                        value.args_proper(TokenType::Return)?.into_iter(),
1616                                        a.syn,
1617                                        "return!",
1618                                        |expr, syn| ast::Return::new(expr, syn).into(),
1619                                    )
1620                                }
1621
1622                                TokenType::Require => {
1623                                    parse_require(&a, value.args_proper(TokenType::Require)?)
1624                                }
1625                                TokenType::Identifier(expr) if *expr == *REQUIRE => {
1626                                    parse_require(&a, value.args_proper(TokenType::Require)?)
1627                                }
1628
1629                                TokenType::Set => parse_set(&a, value.args_proper(TokenType::Set)?),
1630                                TokenType::Identifier(expr) if *expr == *SET => {
1631                                    parse_set(&a, value.args_proper(TokenType::Set)?)
1632                                }
1633
1634                                TokenType::Begin => {
1635                                    parse_begin(a, value.args_proper(TokenType::Begin)?)
1636                                }
1637                                TokenType::Identifier(expr) if *expr == *BEGIN => {
1638                                    parse_begin(a, value.args_proper(TokenType::Begin)?)
1639                                }
1640
1641                                TokenType::Lambda => {
1642                                    parse_lambda(a, value.args_proper(TokenType::Lambda)?)
1643                                }
1644                                TokenType::Identifier(expr)
1645                                    if *expr == *LAMBDA
1646                                        || *expr == *LAMBDA_FN
1647                                        || *expr == *LAMBDA_SYMBOL =>
1648                                {
1649                                    parse_lambda(a, value.args_proper(TokenType::Lambda)?)
1650                                }
1651
1652                                _ => Ok(ExprKind::List(value)),
1653                            }?;
1654
1655                            Ok(())
1656                        }
1657                        _ => Ok(()),
1658                    }
1659                } else {
1660                    Ok(())
1661                }
1662            }
1663            ExprKind::Atom(_) => Ok(()),
1664            ExprKind::If(iff) => {
1665                self.lower(&mut iff.test_expr)?;
1666                self.lower(&mut iff.then_expr)?;
1667                self.lower(&mut iff.else_expr)?;
1668                Ok(())
1669            }
1670            ExprKind::Let(l) => {
1671                for (left, right) in l.bindings.iter_mut() {
1672                    self.lower(left)?;
1673                    self.lower(right)?;
1674                }
1675
1676                self.lower(&mut l.body_expr)?;
1677
1678                Ok(())
1679            }
1680            ExprKind::Define(d) => {
1681                self.lower(&mut d.name)?;
1682                self.lower(&mut d.body)?;
1683
1684                Ok(())
1685            }
1686
1687            ExprKind::LambdaFunction(f) => {
1688                for arg in f.args.iter_mut() {
1689                    self.lower(arg)?;
1690                }
1691
1692                self.lower(&mut f.body)?;
1693
1694                Ok(())
1695            }
1696            ExprKind::Begin(b) => {
1697                for expr in b.exprs.iter_mut() {
1698                    self.lower(expr)?;
1699                }
1700
1701                Ok(())
1702            }
1703            // Ok(ExprKind::Begin(ast::Begin::new(
1704            //     b.exprs
1705            //         .into_iter()
1706            //         .map(|x| self.lower(x))
1707            //         .collect::<Result<_>>()?,
1708            //     b.location,
1709            // ))),
1710            ExprKind::Return(r) => {
1711                self.lower(&mut r.expr)?;
1712                Ok(())
1713            }
1714            // Ok(ExprKind::Return(Box::new(ast::Return::new(
1715            //     self.lower(r.expr)?,
1716            //     r.location,
1717            // )))),
1718            ExprKind::Quote(_) => Ok(()),
1719            ExprKind::Macro(_) => Ok(()),
1720            ExprKind::SyntaxRules(_) => Ok(()),
1721            ExprKind::Set(s) => {
1722                self.lower(&mut s.variable)?;
1723                self.lower(&mut s.expr)?;
1724
1725                Ok(())
1726            }
1727            // Ok(ExprKind::Set(Box::new(ast::Set::new(
1728            //     self.lower(s.variable)?,
1729            //     self.lower(s.expr)?,
1730            //     s.location,
1731            // )))),
1732            ExprKind::Require(_) => Ok(()),
1733            ExprKind::Vector(v) => {
1734                for arg in &mut v.args {
1735                    self.lower(arg)?;
1736                }
1737
1738                Ok(())
1739            }
1740        }
1741    }
1742}
1743
1744// TODO: Lower the rest of the AST post expansion, such that
1745pub fn lower_entire_ast(expr: &mut ExprKind) -> Result<()> {
1746    ASTLowerPass { quote_depth: 0 }.lower(expr)
1747}
1748
1749struct Frame {
1750    open: Span,
1751    paren: Paren,
1752    paren_mod: Option<ParenMod>,
1753    exprs: Vec<ExprKind>,
1754    dot: Option<(usize, Span)>,
1755    comment: u8,
1756}
1757
1758impl Frame {
1759    fn to_expr(self, close: Span) -> Result<ExprKind> {
1760        self.build_expr(close, |exprs| Ok(List::new(exprs).into()))
1761    }
1762
1763    fn build_expr(
1764        self,
1765        close: Span,
1766        builder: impl FnOnce(Vec<ExprKind>) -> Result<ExprKind>,
1767    ) -> Result<ExprKind> {
1768        if self.comment > 0 {
1769            return Err(ParseError::SyntaxError(
1770                "invalid datum comment".into(),
1771                self.open,
1772                None,
1773            ));
1774        }
1775
1776        if let Some(paren_mod) = self.paren_mod {
1777            let bytes = matches!(paren_mod, ParenMod::Bytes);
1778
1779            return Ok(Vector {
1780                args: self.exprs,
1781                bytes,
1782                span: Span::merge(self.open, close),
1783            }
1784            .into());
1785        };
1786
1787        let improper = self.improper()?;
1788
1789        let mut expr = builder(self.exprs)?;
1790
1791        match &mut expr {
1792            ExprKind::List(list) => {
1793                list.location = Span::merge(self.open, close);
1794
1795                if improper {
1796                    list.make_improper();
1797                }
1798            }
1799            _ if improper => todo!(),
1800            _ => {}
1801        };
1802
1803        Ok(expr.into())
1804    }
1805
1806    fn push(&mut self, expr: ExprKind) -> Result<()> {
1807        if let Some((idx, _)) = self.dot {
1808            debug_assert!(!self.exprs.is_empty());
1809
1810            if idx != self.exprs.len() {
1811                debug_assert_eq!(idx + 1, self.exprs.len());
1812
1813                return Err(ParseError::SyntaxError(
1814                    "improper list must have a single cdr".to_owned(),
1815                    expr.span().unwrap_or_default(),
1816                    None,
1817                ));
1818            }
1819        }
1820
1821        let valid_for_bytes = match (self.paren_mod, &expr) {
1822            (Some(ParenMod::Bytes), ExprKind::Atom(atom)) if atom.byte().is_some() => true,
1823            (Some(ParenMod::Bytes), _) => false,
1824            _ => true,
1825        };
1826
1827        if !valid_for_bytes {
1828            return Err(ParseError::SyntaxError(
1829                "bytevector literals can only contain integer literals in the 0-255 range".into(),
1830                expr.span().unwrap_or_default(),
1831                None,
1832            ));
1833        }
1834
1835        if self.comment > 0 {
1836            self.comment -= 1;
1837
1838            return Ok(());
1839        }
1840
1841        self.exprs.push(expr);
1842
1843        Ok(())
1844    }
1845
1846    fn improper(&self) -> Result<bool> {
1847        match self.dot {
1848            Some((idx, _)) if idx + 1 == self.exprs.len() => Ok(true),
1849            Some((idx, span)) => {
1850                debug_assert_eq!(idx, self.exprs.len());
1851
1852                return Err(ParseError::SyntaxError(
1853                    "improper list must have a single cdr".into(),
1854                    span,
1855                    None,
1856                ));
1857            }
1858            None => Ok(false),
1859        }
1860    }
1861}
1862
1863#[cfg(test)]
1864mod parser_tests {
1865    // use super::TokenType::*;
1866    use super::*;
1867    use crate::parser::ast::{Begin, Define, If, LambdaFunction, Quote, Return};
1868    use crate::tokens::{Paren, RealLiteral};
1869    use crate::visitors::Eraser;
1870    use crate::{parser::ast::ExprKind, tokens::IntLiteral};
1871
1872    fn atom(ident: &str) -> ExprKind {
1873        ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::Identifier(
1874            ident.into(),
1875        ))))
1876    }
1877
1878    fn int(num: isize) -> ExprKind {
1879        ExprKind::Atom(Atom::new(SyntaxObject::default(
1880            IntLiteral::Small(num).into(),
1881        )))
1882    }
1883
1884    fn character(c: char) -> ExprKind {
1885        ExprKind::Atom(Atom::new(SyntaxObject::default(
1886            TokenType::CharacterLiteral(c),
1887        )))
1888    }
1889
1890    #[test]
1891    fn check_quote_parsing() {
1892        println!("{:?}", Parser::parse("'(a b 'c)"));
1893    }
1894
1895    fn parses(s: &str) {
1896        let a: Result<Vec<_>> = Parser::new(s, SourceId::none()).collect();
1897        a.unwrap();
1898    }
1899
1900    fn parse_err(s: &str) -> ParseError {
1901        let a: Result<Vec<_>> = Parser::new(s, SourceId::none()).collect();
1902        a.unwrap_err()
1903    }
1904
1905    fn assert_parse(s: &str, result: &[ExprKind]) {
1906        let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1907        let mut a = a.unwrap();
1908
1909        let mut eraser = Eraser;
1910
1911        eraser.visit_many(&mut a);
1912
1913        assert_eq!(a.as_slice(), result);
1914    }
1915
1916    fn assert_parse_err(s: &str, err: ParseError) {
1917        let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1918        assert_eq!(a, Err(err));
1919    }
1920
1921    fn assert_syntax_err(s: &str, expected: &str) {
1922        let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1923        let Err(ParseError::SyntaxError(err, _, _)) = a else {
1924            panic!("expected syntax error, got {a:?}");
1925        };
1926
1927        assert_eq!(err, expected);
1928    }
1929
1930    fn assert_parse_is_err(s: &str) {
1931        let a: Result<Vec<ExprKind>> = Parser::new(s, SourceId::none()).collect();
1932        assert!(a.is_err());
1933    }
1934
1935    #[test]
1936    fn check_resulting_parsing() {
1937        let expr = r#"`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)"#;
1938
1939        let a: Result<Vec<ExprKind>> = Parser::new(expr, SourceId::none()).collect();
1940        let a = a.unwrap();
1941
1942        println!("{}", a[0]);
1943    }
1944
1945    #[test]
1946    fn check_double_unquote_parsing() {
1947        let expr = r#"(let ([name1 'x] [name2 'y]) `(a `(b ,,name1 ,',name2 d) e))"#;
1948
1949        let a: Result<Vec<ExprKind>> = Parser::new(expr, SourceId::none()).collect();
1950        let a = a.unwrap();
1951
1952        println!("{}", a[0]);
1953    }
1954
1955    #[test]
1956    fn check_parser_with_doc_comments() {
1957        let expr = r#"
1958        ;;@doc
1959        ;; This is a fancy cool comment, that I want to attach to a top level definition!
1960        ;; This is the second line of the comment, I want this attached as well!
1961        ;; Macro for creating a new struct, in the form of:
1962        ;; `(struct <struct-name> (fields ...) options ...)`
1963        ;; The options can consist of the following:
1964        ;;
1965        ;; Single variable options (those which their presence indicates #true)
1966        ;; - #:mutable
1967        ;; - #:transparent
1968        ;;
1969        ;; Other options must be presented as key value pairs, and will get stored
1970        ;; in the struct instance. They will also be bound to the variable
1971        ;; ___<struct-name>-options___ in the same lexical environment where the
1972        ;; struct was defined. For example:
1973        ;;
1974        ;; (Applesauce (a b c) #:mutable #:transparent #:unrecognized-option 1234)
1975        ;;
1976        ;; Will result in the value `___Applesauce-options___` like so:
1977        ;; (hash #:mutable #true #:transparent #true #:unrecognized-option 1234)
1978        ;;
1979        ;; By default, structs are immutable, which means setter functions will not
1980        ;; be generated. Also by default, structs are not transparent, which means
1981        ;; printing them will result in an opaque struct that does not list the fields
1982        (define foo 12345)
1983        "#;
1984
1985        let parser = Parser::doc_comment_parser(expr, SourceId::none());
1986
1987        let result: Result<Vec<_>> = parser.collect();
1988
1989        println!("{:?}", result.unwrap());
1990    }
1991
1992    #[test]
1993    fn parses_make_struct() {
1994        parses("(define make-struct (lambda (struct-name fields) (map (lambda (field) (list (quote define) (concat-symbols struct-name field) (quote (lambda (this) (vector-ref this 0))))) fields)))")
1995    }
1996
1997    #[test]
1998    fn parses_quasiquote() {
1999        parses(r#"(quasiquote ((unquote x) xs ...)) "#);
2000    }
2001
2002    #[test]
2003    fn parse_syntax_rules() {
2004        parses(
2005            r#"
2006            (syntax-rules (unquote unquote-splicing)
2007              ((quasiquote ((unquote x) xs ...))          (cons x (quasiquote (xs ...))))
2008              ((quasiquote ((unquote-splicing x)))        (append (list x) '()))
2009              ((quasiquote ((unquote-splicing x) xs ...)) (append x (quasiquote (xs ...))))
2010              ((quasiquote (unquote x))                 x)
2011              ((quasiquote (x))                          '(x))
2012              ((quasiquote (x xs ...))                   (cons (quasiquote x) (quasiquote (xs ...))))
2013              ((quasiquote x)                           'x))
2014            "#,
2015        );
2016    }
2017
2018    #[test]
2019    fn parse_define_syntax() {
2020        parses(
2021            r#"
2022        (define-syntax quasiquote
2023            (syntax-rules (unquote unquote-splicing)
2024              ((quasiquote ((unquote x) xs ...))          (cons x (quasiquote (xs ...))))
2025              ((quasiquote ((unquote-splicing x)))        (append (list x) '()))
2026              ((quasiquote ((unquote-splicing x) xs ...)) (append x (quasiquote (xs ...))))
2027              ((quasiquote (unquote x))                 x)
2028              ((quasiquote (x))                          '(x))
2029              ((quasiquote (x xs ...))                   (cons (quasiquote x) (quasiquote (xs ...))))
2030              ((quasiquote x)                           'x)))
2031        "#,
2032        );
2033    }
2034
2035    #[test]
2036    fn parse_quote() {
2037        // parses("(displayln (match (quote (lambda y z)) '(x y z)))")
2038        parses("(displayln (match '(lambda y z) '(x y z)))")
2039    }
2040
2041    #[test]
2042    fn parse_unicode() {
2043        assert_parse("#\\¡", &[character('¡')]);
2044        assert_parse("#\\u{b}", &[character('\u{b}')]);
2045    }
2046
2047    #[test]
2048    fn parse_more_unicode() {
2049        assert_parse("#\\u{a0}", &[character('\u{a0}')]);
2050    }
2051
2052    #[test]
2053    fn parse_strange_characters() {
2054        assert_parse("#\\^", &[character('^')]);
2055    }
2056
2057    #[test]
2058    fn parse_character_sequence() {
2059        assert_parse(
2060            "#\\¡ #\\SPACE #\\g",
2061            &[character('¡'), character(' '), character('g')],
2062        )
2063    }
2064
2065    #[test]
2066    fn parse_character_sequence_inside_if() {
2067        assert_parse(
2068            "(if #\\¡ #\\SPACE #\\g)",
2069            &[ExprKind::If(Box::new(If::new(
2070                character('¡'),
2071                character(' '),
2072                character('g'),
2073                SyntaxObject::default(TokenType::If),
2074            )))],
2075        )
2076    }
2077
2078    #[test]
2079    fn parse_close_paren_character() {
2080        assert_parse("#\\)", &[character(')')]);
2081        assert_parse("#\\]", &[character(']')])
2082    }
2083
2084    #[test]
2085    fn parse_open_paren_character() {
2086        assert_parse("#\\(", &[character('(')])
2087    }
2088
2089    #[test]
2090    fn test_error() {
2091        assert_parse_err("(", ParseError::UnexpectedEOF(None));
2092        assert_parse_err("(abc", ParseError::UnexpectedEOF(None));
2093        assert_parse_err("(ab 1 2", ParseError::UnexpectedEOF(None));
2094        assert_parse_err("((((ab 1 2) (", ParseError::UnexpectedEOF(None));
2095        assert!(matches!(
2096            parse_err("())"),
2097            ParseError::Unexpected(TokenType::CloseParen(Paren::Round), _, None),
2098        ));
2099        assert_parse_err("() ((((", ParseError::UnexpectedEOF(None));
2100        assert!(matches!(
2101            parse_err("')"),
2102            ParseError::Unexpected(TokenType::CloseParen(Paren::Round), _, None),
2103        ));
2104        assert!(matches!(
2105            parse_err("(')"),
2106            ParseError::Unexpected(TokenType::CloseParen(Paren::Round), _, None),
2107        ));
2108        assert_parse_err("('", ParseError::UnexpectedEOF(None));
2109        assert!(matches!(
2110            parse_err(r#""abc"#),
2111            ParseError::IncompleteString(_, _, None),
2112        ));
2113        assert!(matches!(
2114            parse_err("(]"),
2115            ParseError::Unexpected(TokenType::CloseParen(Paren::Square), _, None)
2116        ));
2117    }
2118
2119    #[test]
2120    fn quote_multiple_args_should_err() {
2121        assert_parse_is_err("(quote a b c)");
2122    }
2123
2124    #[test]
2125    fn test_let_should_err() {
2126        assert_parse_is_err("(let)");
2127        assert_parse_is_err("(let (a) 10)");
2128    }
2129
2130    #[test]
2131    fn test_if_should_err() {
2132        assert_parse_is_err("(if)");
2133        assert_parse_is_err("(if 1)");
2134        // assert_parse_is_err("(if 1 2)");
2135        assert_parse_is_err("(if 1 2 3 4)");
2136    }
2137
2138    #[test]
2139    fn test_define_should_err() {
2140        assert_parse_is_err("(define)");
2141        assert_parse_is_err("(define blagh)");
2142        assert_parse_is_err("(define test 1 2)");
2143        assert_parse_is_err("(define () test");
2144    }
2145
2146    #[test]
2147    fn test_lambda_should_err() {
2148        assert_parse_is_err("(lambda)");
2149        assert_parse_is_err("(lambda (x))");
2150    }
2151
2152    #[test]
2153    fn test_empty() {
2154        assert_parse("", &[]);
2155        assert_parse("()", &[ExprKind::List(List::new(vec![]))]);
2156    }
2157
2158    #[test]
2159    fn test_empty_quote_inside_if() {
2160        assert_parse(
2161            "(if #\\¡ (quote ()) #\\g)",
2162            &[ExprKind::If(Box::new(If::new(
2163                character('¡'),
2164                ExprKind::Quote(
2165                    Quote::new(
2166                        List::new(vec![]).into(),
2167                        SyntaxObject::default(TokenType::Quote),
2168                    )
2169                    .into(),
2170                ),
2171                character('g'),
2172                SyntaxObject::default(TokenType::If),
2173            )))],
2174        )
2175    }
2176
2177    #[test]
2178    fn test_empty_quote() {
2179        assert_parse(
2180            "'()",
2181            &[ExprKind::Quote(
2182                Quote::new(
2183                    List::new(vec![]).into(),
2184                    SyntaxObject::default(TokenType::Quote),
2185                )
2186                .into(),
2187            )],
2188        )
2189    }
2190
2191    #[test]
2192    fn test_empty_quote_nested() {
2193        assert_parse(
2194            "(list '())",
2195            &[ExprKind::List(List::new(vec![
2196                atom("list"),
2197                ExprKind::Quote(
2198                    Quote::new(
2199                        List::new(vec![]).into(),
2200                        SyntaxObject::default(TokenType::Quote),
2201                    )
2202                    .into(),
2203                ),
2204            ]))],
2205        )
2206    }
2207
2208    #[test]
2209    fn test_multi_parse_simple() {
2210        assert_parse("a b +", &[atom("a"), atom("b"), atom("+")]);
2211    }
2212
2213    #[test]
2214    fn test_multi_parse_complicated() {
2215        assert_parse(
2216            "a b (funcall  1 (+ 2 3.5))",
2217            &[
2218                atom("a"),
2219                atom("b"),
2220                ExprKind::List(List::new(vec![
2221                    atom("funcall"),
2222                    int(1),
2223                    ExprKind::List(List::new(vec![
2224                        atom("+"),
2225                        int(2),
2226                        ExprKind::Atom(Atom::new(SyntaxObject::default(
2227                            RealLiteral::Float(3.5).into(),
2228                        ))),
2229                    ])),
2230                ])),
2231            ],
2232        )
2233    }
2234    #[test]
2235    fn test_parse_simple() {
2236        assert_parse(
2237            "(+ 1 2 3) (- 4 3)",
2238            &[
2239                ExprKind::List(List::new(vec![atom("+"), int(1), int(2), int(3)])),
2240                ExprKind::List(List::new(vec![atom("-"), int(4), int(3)])),
2241            ],
2242        );
2243    }
2244
2245    #[test]
2246    fn test_parse_nested() {
2247        assert_parse(
2248            "(+ 1 (foo (bar 2 3)))",
2249            &[ExprKind::List(List::new(vec![
2250                atom("+"),
2251                int(1),
2252                ExprKind::List(List::new(vec![
2253                    atom("foo"),
2254                    ExprKind::List(List::new(vec![atom("bar"), int(2), int(3)])),
2255                ])),
2256            ]))],
2257        );
2258        assert_parse(
2259            "(+ 1 (+ 2 3) (foo (bar 2 3)))",
2260            &[ExprKind::List(List::new(vec![
2261                atom("+"),
2262                int(1),
2263                ExprKind::List(List::new(vec![atom("+"), int(2), int(3)])),
2264                ExprKind::List(List::new(vec![
2265                    atom("foo"),
2266                    ExprKind::List(List::new(vec![atom("bar"), int(2), int(3)])),
2267                ])),
2268            ]))],
2269        );
2270    }
2271
2272    #[test]
2273    fn test_if() {
2274        assert_parse(
2275            "(+ 1 (if 2 3 4) (foo (+ (bar 1 1) 3) 5))",
2276            &[ExprKind::List(List::new(vec![
2277                atom("+"),
2278                int(1),
2279                ExprKind::If(Box::new(If::new(
2280                    int(2),
2281                    int(3),
2282                    int(4),
2283                    SyntaxObject::default(TokenType::If),
2284                ))),
2285                ExprKind::List(List::new(vec![
2286                    atom("foo"),
2287                    ExprKind::List(List::new(vec![
2288                        atom("+"),
2289                        ExprKind::List(List::new(vec![atom("bar"), int(1), int(1)])),
2290                        int(3),
2291                    ])),
2292                    int(5),
2293                ])),
2294            ]))],
2295        );
2296    }
2297
2298    #[test]
2299    fn test_quote() {
2300        assert_parse(
2301            "(quote (if 1 2))",
2302            &[ExprKind::Quote(Box::new(Quote::new(
2303                ExprKind::List(List::new(vec![
2304                    ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2305                    int(1),
2306                    int(2),
2307                ])),
2308                SyntaxObject::default(TokenType::Quote),
2309            )))],
2310        )
2311    }
2312
2313    #[test]
2314    fn test_quote_shorthand() {
2315        assert_parse(
2316            "'(if 1 2)",
2317            &[ExprKind::Quote(Box::new(Quote::new(
2318                ExprKind::List(List::new(vec![
2319                    ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2320                    int(1),
2321                    int(2),
2322                ])),
2323                SyntaxObject::default(TokenType::Quote),
2324            )))],
2325        )
2326    }
2327
2328    #[test]
2329    fn test_quote_nested() {
2330        assert_parse(
2331            "(quote (if (if 1 2) 3))",
2332            &[ExprKind::Quote(Box::new(Quote::new(
2333                ExprKind::List(List::new(vec![
2334                    ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2335                    ExprKind::List(List::new(vec![
2336                        ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2337                        int(1),
2338                        int(2),
2339                    ])),
2340                    int(3),
2341                ])),
2342                SyntaxObject::default(TokenType::Quote),
2343            )))],
2344        )
2345    }
2346
2347    #[test]
2348    fn test_quote_shorthand_nested() {
2349        assert_parse(
2350            "'(if (if 1 2) 3)",
2351            &[ExprKind::Quote(Box::new(Quote::new(
2352                ExprKind::List(List::new(vec![
2353                    ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2354                    ExprKind::List(List::new(vec![
2355                        ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2356                        int(1),
2357                        int(2),
2358                    ])),
2359                    int(3),
2360                ])),
2361                SyntaxObject::default(TokenType::Quote),
2362            )))],
2363        )
2364    }
2365
2366    #[test]
2367    fn test_quote_shorthand_multiple_exprs() {
2368        assert_parse(
2369            "'(if (if 1 2) 3) (+ 1 (if 2 3 4) (foo (+ (bar 1 1) 3) 5))",
2370            &[
2371                ExprKind::Quote(Box::new(Quote::new(
2372                    ExprKind::List(List::new(vec![
2373                        ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2374                        ExprKind::List(List::new(vec![
2375                            ExprKind::Atom(Atom::new(SyntaxObject::default(TokenType::If))),
2376                            int(1),
2377                            int(2),
2378                        ])),
2379                        int(3),
2380                    ])),
2381                    SyntaxObject::default(TokenType::Quote),
2382                ))),
2383                ExprKind::List(List::new(vec![
2384                    atom("+"),
2385                    int(1),
2386                    ExprKind::If(Box::new(If::new(
2387                        int(2),
2388                        int(3),
2389                        int(4),
2390                        SyntaxObject::default(TokenType::If),
2391                    ))),
2392                    ExprKind::List(List::new(vec![
2393                        atom("foo"),
2394                        ExprKind::List(List::new(vec![
2395                            atom("+"),
2396                            ExprKind::List(List::new(vec![atom("bar"), int(1), int(1)])),
2397                            int(3),
2398                        ])),
2399                        int(5),
2400                    ])),
2401                ])),
2402            ],
2403        )
2404    }
2405
2406    #[test]
2407    fn test_quote_inner() {
2408        assert_parse(
2409            "'(applesauce 'one)",
2410            &[ExprKind::Quote(Box::new(Quote::new(
2411                ExprKind::List(List::new(vec![
2412                    atom("applesauce"),
2413                    ExprKind::Quote(Box::new(Quote::new(
2414                        atom("one"),
2415                        SyntaxObject::default(TokenType::Quote),
2416                    ))),
2417                ])),
2418                SyntaxObject::default(TokenType::Quote),
2419            )))],
2420        )
2421    }
2422
2423    #[test]
2424    fn test_quote_inner_without_shorthand() {
2425        assert_parse(
2426            "(quote (applesauce 'one))",
2427            &[ExprKind::Quote(Box::new(Quote::new(
2428                ExprKind::List(List::new(vec![
2429                    atom("applesauce"),
2430                    ExprKind::Quote(Box::new(Quote::new(
2431                        atom("one"),
2432                        SyntaxObject::default(TokenType::Quote),
2433                    ))),
2434                ])),
2435                SyntaxObject::default(TokenType::Quote),
2436            )))],
2437        )
2438    }
2439
2440    #[test]
2441    fn test_quasiquote_shorthand() {
2442        assert_parse(
2443            "`(+ 1 2)",
2444            &[ExprKind::List(List::new(vec![
2445                atom("quasiquote"),
2446                ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2447            ]))],
2448        )
2449    }
2450
2451    #[test]
2452    fn test_quasiquote_normal() {
2453        assert_parse(
2454            "(quasiquote (+ 1 2))",
2455            &[ExprKind::List(List::new(vec![
2456                atom("quasiquote"),
2457                ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2458            ]))],
2459        )
2460    }
2461
2462    #[test]
2463    fn test_unquote_shorthand() {
2464        assert_parse(
2465            ",(+ 1 2)",
2466            &[ExprKind::List(List::new(vec![
2467                atom("unquote"),
2468                ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2469            ]))],
2470        )
2471    }
2472
2473    #[test]
2474    fn test_unquote_normal() {
2475        assert_parse(
2476            "(unquote (+ 1 2))",
2477            &[ExprKind::List(List::new(vec![
2478                atom("unquote"),
2479                ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2480            ]))],
2481        )
2482    }
2483
2484    #[test]
2485    fn test_unquote_splicing_shorthand() {
2486        assert_parse(
2487            ",@(+ 1 2)",
2488            &[ExprKind::List(List::new(vec![
2489                atom("unquote-splicing"),
2490                ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2491            ]))],
2492        )
2493    }
2494
2495    #[test]
2496    fn test_unquote_splicing_normal() {
2497        assert_parse(
2498            "(unquote-splicing (+ 1 2))",
2499            &[ExprKind::List(List::new(vec![
2500                atom("unquote-splicing"),
2501                ExprKind::List(List::new(vec![atom("+"), int(1), int(2)])),
2502            ]))],
2503        )
2504    }
2505
2506    #[test]
2507    fn test_define_simple() {
2508        assert_parse(
2509            "(define a 10)",
2510            &[ExprKind::Define(Box::new(Define::new(
2511                atom("a"),
2512                int(10),
2513                SyntaxObject::default(TokenType::Define),
2514            )))],
2515        )
2516    }
2517
2518    #[test]
2519    fn test_define_func_simple() {
2520        assert_parse(
2521            "(define (foo x) (+ x 10))",
2522            &[ExprKind::Define(Box::new(Define::new(
2523                atom("foo"),
2524                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2525                    vec![atom("x")],
2526                    ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
2527                    SyntaxObject::default(TokenType::Lambda),
2528                ))),
2529                SyntaxObject::default(TokenType::Define),
2530            )))],
2531        )
2532    }
2533
2534    #[test]
2535    fn test_define_func_multiple_args() {
2536        assert_parse(
2537            "(define (foo x y z) (+ x 10))",
2538            &[ExprKind::Define(Box::new(Define::new(
2539                atom("foo"),
2540                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2541                    vec![atom("x"), atom("y"), atom("z")],
2542                    ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
2543                    SyntaxObject::default(TokenType::Lambda),
2544                ))),
2545                SyntaxObject::default(TokenType::Define),
2546            )))],
2547        )
2548    }
2549
2550    #[test]
2551    fn test_define_func_multiple_args_multiple_body_exprs() {
2552        assert_parse(
2553            "(define (foo x y z) (+ x 10) (+ y 20) (+ z 30))",
2554            &[ExprKind::Define(Box::new(Define::new(
2555                atom("foo"),
2556                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2557                    vec![atom("x"), atom("y"), atom("z")],
2558                    ExprKind::Begin(Box::new(Begin::new(
2559                        vec![
2560                            ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
2561                            ExprKind::List(List::new(vec![atom("+"), atom("y"), int(20)])),
2562                            ExprKind::List(List::new(vec![atom("+"), atom("z"), int(30)])),
2563                        ],
2564                        SyntaxObject::default(TokenType::Begin),
2565                    ))),
2566                    SyntaxObject::default(TokenType::Lambda),
2567                ))),
2568                SyntaxObject::default(TokenType::Define),
2569            )))],
2570        )
2571    }
2572
2573    #[test]
2574    fn test_recursive_function() {
2575        assert_parse(
2576            "(define (test) (define (foo) (bar)) (define (bar) (foo)))",
2577            &[ExprKind::Define(Box::new(Define::new(
2578                atom("test"),
2579                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2580                    vec![],
2581                    ExprKind::Begin(Box::new(Begin::new(
2582                        vec![
2583                            ExprKind::Define(Box::new(Define::new(
2584                                atom("foo"),
2585                                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2586                                    vec![],
2587                                    ExprKind::List(List::new(vec![atom("bar")])),
2588                                    SyntaxObject::default(TokenType::Lambda),
2589                                ))),
2590                                SyntaxObject::default(TokenType::Define),
2591                            ))),
2592                            ExprKind::Define(Box::new(Define::new(
2593                                atom("bar"),
2594                                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2595                                    vec![],
2596                                    ExprKind::List(List::new(vec![atom("foo")])),
2597                                    SyntaxObject::default(TokenType::Lambda),
2598                                ))),
2599                                SyntaxObject::default(TokenType::Define),
2600                            ))),
2601                        ],
2602                        SyntaxObject::default(TokenType::Begin),
2603                    ))),
2604                    SyntaxObject::default(TokenType::Lambda),
2605                ))),
2606                SyntaxObject::default(TokenType::Define),
2607            )))],
2608        )
2609    }
2610
2611    #[test]
2612    fn test_return_normal() {
2613        assert_parse(
2614            "(return! 10)",
2615            &[ExprKind::Return(Box::new(Return::new(
2616                int(10),
2617                SyntaxObject::default(TokenType::Return),
2618            )))],
2619        )
2620    }
2621
2622    #[test]
2623    fn test_begin() {
2624        assert_parse(
2625            "(begin 1 2 3)",
2626            &[ExprKind::Begin(Box::new(Begin::new(
2627                vec![int(1), int(2), int(3)],
2628                SyntaxObject::default(TokenType::Begin),
2629            )))],
2630        )
2631    }
2632
2633    #[test]
2634    fn test_lambda_function() {
2635        assert_parse(
2636            "(lambda (x) 10)",
2637            &[ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2638                vec![atom("x")],
2639                int(10),
2640                SyntaxObject::default(TokenType::Lambda),
2641            )))],
2642        )
2643    }
2644
2645    #[test]
2646    fn test_lambda_function_with_rest() {
2647        assert_parse(
2648            "(lambda (x . y) 10)",
2649            &[ExprKind::LambdaFunction(Box::new(
2650                LambdaFunction::new_maybe_rest(
2651                    vec![atom("x"), atom("y")],
2652                    int(10),
2653                    SyntaxObject::default(TokenType::Lambda),
2654                    true,
2655                ),
2656            ))],
2657        )
2658    }
2659
2660    #[test]
2661    fn test_lambda_function_with_rest_only() {
2662        assert_parse(
2663            "(lambda x 10)",
2664            &[ExprKind::LambdaFunction(Box::new(
2665                LambdaFunction::new_maybe_rest(
2666                    vec![atom("x")],
2667                    int(10),
2668                    SyntaxObject::default(TokenType::Lambda),
2669                    true,
2670                ),
2671            ))],
2672        )
2673    }
2674
2675    #[test]
2676    fn test_lambda_matches_let() {
2677        assert_parse(
2678            "((lambda (a) (+ a 20)) 10)",
2679            &[ExprKind::List(List::new(vec![
2680                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2681                    vec![atom("a")],
2682                    ExprKind::List(List::new(vec![atom("+"), atom("a"), int(20)])),
2683                    SyntaxObject::default(TokenType::Lambda),
2684                ))),
2685                int(10),
2686            ]))],
2687        );
2688    }
2689
2690    #[test]
2691    fn test_let() {
2692        assert_parse(
2693            "(let ([a 10]) (+ a 20))",
2694            &[ExprKind::List(List::new(vec![
2695                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2696                    vec![atom("a")],
2697                    ExprKind::List(List::new(vec![atom("+"), atom("a"), int(20)])),
2698                    SyntaxObject::default(TokenType::Lambda),
2699                ))),
2700                int(10),
2701            ]))],
2702        )
2703    }
2704
2705    #[test]
2706    fn test_quote_with_inner_nested() {
2707        assert_parse(
2708            "'(#f '())",
2709            &[ExprKind::Quote(
2710                Quote::new(
2711                    ExprKind::List(List::new(vec![
2712                        ExprKind::Atom(Atom::new(SyntaxObject::default(
2713                            TokenType::BooleanLiteral(false),
2714                        ))),
2715                        ExprKind::Quote(
2716                            Quote::new(
2717                                List::new(vec![]).into(),
2718                                SyntaxObject::default(TokenType::Quote),
2719                            )
2720                            .into(),
2721                        ),
2722                    ])),
2723                    SyntaxObject::default(TokenType::Quote),
2724                )
2725                .into(),
2726            )],
2727        )
2728    }
2729
2730    #[test]
2731    fn test_quote_with_inner_nested_sub_expr() {
2732        assert_parse(
2733            "(if (null? contents)
2734                '(#f '())
2735                (list (car contents) (cdr contents)))",
2736            &[ExprKind::If(Box::new(If::new(
2737                ExprKind::List(List::new(vec![atom("null?"), atom("contents")])),
2738                ExprKind::Quote(
2739                    Quote::new(
2740                        ExprKind::List(List::new(vec![
2741                            ExprKind::Atom(Atom::new(SyntaxObject::default(
2742                                TokenType::BooleanLiteral(false),
2743                            ))),
2744                            ExprKind::Quote(
2745                                Quote::new(
2746                                    List::new(vec![]).into(),
2747                                    SyntaxObject::default(TokenType::Quote),
2748                                )
2749                                .into(),
2750                            ),
2751                        ])),
2752                        SyntaxObject::default(TokenType::Quote),
2753                    )
2754                    .into(),
2755                ),
2756                ExprKind::List(List::new(vec![
2757                    atom("list"),
2758                    ExprKind::List(List::new(vec![atom("car"), atom("contents")])),
2759                    ExprKind::List(List::new(vec![atom("cdr"), atom("contents")])),
2760                ])),
2761                SyntaxObject::default(TokenType::If),
2762            )))],
2763        );
2764    }
2765
2766    #[test]
2767    fn test_quote_normal_with_inner_nested_sub_expr() {
2768        assert_parse(
2769            "(if (null? contents)
2770                (quote (#f '()))
2771                (list (car contents) (cdr contents)))",
2772            &[ExprKind::If(Box::new(If::new(
2773                ExprKind::List(List::new(vec![atom("null?"), atom("contents")])),
2774                ExprKind::Quote(
2775                    Quote::new(
2776                        ExprKind::List(List::new(vec![
2777                            ExprKind::Atom(Atom::new(SyntaxObject::default(
2778                                TokenType::BooleanLiteral(false),
2779                            ))),
2780                            ExprKind::Quote(
2781                                Quote::new(
2782                                    List::new(vec![]).into(),
2783                                    SyntaxObject::default(TokenType::Quote),
2784                                )
2785                                .into(),
2786                            ),
2787                        ])),
2788                        SyntaxObject::default(TokenType::Quote),
2789                    )
2790                    .into(),
2791                ),
2792                ExprKind::List(List::new(vec![
2793                    atom("list"),
2794                    ExprKind::List(List::new(vec![atom("car"), atom("contents")])),
2795                    ExprKind::List(List::new(vec![atom("cdr"), atom("contents")])),
2796                ])),
2797                SyntaxObject::default(TokenType::If),
2798            )))],
2799        );
2800    }
2801
2802    #[test]
2803    fn test_quote_with_inner_sub_expr_even_more_nested() {
2804        assert_parse(
2805            "(list
2806                (if (null? contents)
2807                '(#f '())
2808                (list (car contents) (cdr contents))))",
2809            &[ExprKind::List(List::new(vec![
2810                atom("list"),
2811                ExprKind::If(Box::new(If::new(
2812                    ExprKind::List(List::new(vec![atom("null?"), atom("contents")])),
2813                    ExprKind::Quote(
2814                        Quote::new(
2815                            ExprKind::List(List::new(vec![
2816                                ExprKind::Atom(Atom::new(SyntaxObject::default(
2817                                    TokenType::BooleanLiteral(false),
2818                                ))),
2819                                ExprKind::Quote(
2820                                    Quote::new(
2821                                        List::new(vec![]).into(),
2822                                        SyntaxObject::default(TokenType::Quote),
2823                                    )
2824                                    .into(),
2825                                ),
2826                            ])),
2827                            SyntaxObject::default(TokenType::Quote),
2828                        )
2829                        .into(),
2830                    ),
2831                    ExprKind::List(List::new(vec![
2832                        atom("list"),
2833                        ExprKind::List(List::new(vec![atom("car"), atom("contents")])),
2834                        ExprKind::List(List::new(vec![atom("cdr"), atom("contents")])),
2835                    ])),
2836                    SyntaxObject::default(TokenType::If),
2837                ))),
2838            ]))],
2839        );
2840    }
2841
2842    #[test]
2843    fn test_define_with_datum_syntax_name() {
2844        assert_parse(
2845            "(define (datum->syntax var) (car ret-value))",
2846            &[ExprKind::Define(Box::new(Define::new(
2847                ExprKind::List(List::new(vec![atom("datum->syntax"), atom("var")])),
2848                ExprKind::List(List::new(vec![atom("car"), atom("ret-value")])),
2849                SyntaxObject::default(TokenType::Define),
2850            )))],
2851        )
2852    }
2853
2854    #[test]
2855    fn test_define_with_datum_syntax_function_name() {
2856        assert_parse(
2857            "(define ((datum->syntax var) arg) 10)",
2858            &[ExprKind::Define(Box::new(Define::new(
2859                ExprKind::List(List::new(vec![atom("datum->syntax"), atom("var")])),
2860                ExprKind::LambdaFunction(Box::new(LambdaFunction::new(
2861                    vec![atom("arg")],
2862                    int(10),
2863                    SyntaxObject::default(TokenType::Lambda),
2864                ))),
2865                SyntaxObject::default(TokenType::Define),
2866            )))],
2867        )
2868    }
2869
2870    #[test]
2871    fn test_parse_without_lowering_ast() {
2872        let a: Result<Vec<ExprKind>> =
2873            Parser::new_flat("(define (quote a) 10) (require foo bar)", SourceId::none())
2874                .map(|x| x.and_then(lower_macro_and_require_definitions))
2875                .collect();
2876
2877        let a = a.unwrap();
2878
2879        println!("{:#?}", a);
2880    }
2881
2882    #[test]
2883    fn test_delayed_lowering() {
2884        let a: Result<Vec<ExprKind>> = Parser::new_flat(
2885            r#"
2886            ;; (define foo (quote a)) (require foo bar)
2887
2888               ;;  (define (foo) (if 10 20 30))
2889
2890               ;; (define (foo) (quote (define 10 20)))
2891
2892               ;; (define foo '())
2893
2894            (define-syntax
2895   with-handler
2896   (syntax-rules
2897      ()
2898      ((with-handler handler expr)
2899         (reset
2900            (call-with-exception-handler
2901               (λ (err)
2902                 (begin (handler err) (shift k (k void))))
2903               (λ ()
2904                 expr))))
2905      ((with-handler handler expr ...)
2906         (reset
2907            (call-with-exception-handler
2908               (λ (err)
2909                 (begin (handler err) (shift k (k void))))
2910               (λ ()
2911                 (begin expr ...)))))))
2912
2913
2914
2915                "#,
2916            SourceId::none(),
2917        )
2918        .map(|x| x.and_then(lower_macro_and_require_definitions))
2919        .map(|x| {
2920            x.and_then(|mut expr| {
2921                lower_entire_ast(&mut expr)?;
2922                Ok(expr)
2923            })
2924        })
2925        .collect();
2926
2927        let a = a.unwrap();
2928
2929        println!("{:#?}", a);
2930    }
2931
2932    #[test]
2933    fn test_improper_list() {
2934        let mut pair = List::new(vec![atom("x"), atom("y")]);
2935        pair.make_improper();
2936
2937        assert_parse("(x . y)", &[ExprKind::List(pair)]);
2938
2939        assert_parse(
2940            "(x . (y . ()))",
2941            &[ExprKind::List(List::new(vec![atom("x"), atom("y")]))],
2942        )
2943    }
2944
2945    #[test]
2946    fn test_improper_list_failures() {
2947        assert_syntax_err(
2948            "(. a)",
2949            "improper lists must have a car element before the dot",
2950        );
2951        assert_syntax_err("(a .)", "improper list must have a single cdr");
2952        assert_syntax_err("(a . b . )", "improper lists can only have a single dot");
2953        assert_syntax_err("(a . b . c)", "improper lists can only have a single dot");
2954        assert_syntax_err("(a . b c)", "improper list must have a single cdr");
2955        assert_syntax_err("(a . b (c))", "improper list must have a single cdr");
2956    }
2957
2958    #[test]
2959    fn test_vectors() {
2960        assert_parse(
2961            "#(a b)",
2962            &[ExprKind::Vector(Vector {
2963                args: vec![atom("a"), atom("b")],
2964                bytes: false,
2965                span: Span::default(),
2966            })],
2967        );
2968
2969        assert_parse(
2970            "#u8(1 3)",
2971            &[ExprKind::Vector(Vector {
2972                args: vec![int(1), int(3)],
2973                bytes: true,
2974                span: Span::default(),
2975            })],
2976        );
2977    }
2978
2979    #[test]
2980    fn test_malformed_vectors() {
2981        assert_syntax_err(
2982            "#u8(#\\a)",
2983            "bytevector literals can only contain integer literals in the 0-255 range",
2984        );
2985
2986        assert_syntax_err(
2987            "#u8(())",
2988            "bytevector literals can only contain integer literals in the 0-255 range",
2989        );
2990
2991        assert_syntax_err("#u8(1 . 2)", "bytevector literals cannot contain dots");
2992
2993        assert_syntax_err("#(1 . 2)", "vector literals cannot contain dots");
2994    }
2995
2996    #[test]
2997    fn test_datum_comments() {
2998        assert_parse("#; 1 2", &[int(2)]);
2999
3000        assert_parse("#; #; #false (2) 3", &[int(3)]);
3001
3002        assert_parse("#; ,@foo 4", &[int(4)]);
3003
3004        assert_parse(
3005            "(1 #; #(a b c) 2)",
3006            &[ExprKind::List(List::new(vec![int(1), int(2)]))],
3007        )
3008    }
3009
3010    #[test]
3011    fn test_invalid_datum_comments() {
3012        assert_syntax_err("( 1 #; )", "invalid datum comment");
3013
3014        assert_syntax_err(
3015            "( 1 2 #; . b)",
3016            "commented-out datum cannot start with a dot",
3017        );
3018    }
3019}