1use crate::{
2 ast,
3 continuation::Continuation,
4 env::Env,
5 error::RuntimeError,
6 eval::Eval,
7 expand::{SyntaxRule, Transformer},
8 gc::Gc,
9 syntax::{Identifier, Span, Syntax},
10 util::{ArcSlice, RequireOne},
11 value::Value,
12};
13use async_trait::async_trait;
14use derive_more::From;
15use std::{
16 collections::{HashMap, HashSet},
17 sync::Arc,
18};
19
20#[derive(From, Debug, Clone)]
21pub enum CompileError {
22 UnexpectedEmptyList(Span),
23 UndefinedVariable(Identifier),
24 RuntimeError(Box<RuntimeError>),
25 NotVariableTransformer,
26 CompileBodyError(CompileBodyError),
27 CompileLetError(CompileLetError),
28 CompileFuncCallError(CompileFuncCallError),
29 CompileIfError(CompileIfError),
30 CompileDefineError(CompileDefineError),
31 CompileDefineSyntaxError(CompileDefineSyntaxError),
32 CompileQuoteError(CompileQuoteError),
33 CompileSetError(CompileSetError),
34 CompileLambdaError(CompileLambdaError),
35 CompileSyntaxError(CompileSyntaxError),
36 CompileSyntaxCaseError(CompileSyntaxCaseError),
37 CompileSyntaxRulesError(CompileSyntaxRulesError),
38 CompileApplyError(CompileApplyError),
39}
40
41impl From<RuntimeError> for CompileError {
42 fn from(re: RuntimeError) -> Self {
43 Self::RuntimeError(Box::new(re))
44 }
45}
46
47macro_rules! impl_from_compile_error {
48 ( $error:ident ) => {
49 impl From<CompileError> for $error {
50 fn from(ce: CompileError) -> Self {
51 Self::CompileError(Box::new(ce))
52 }
53 }
54 };
55}
56
57#[async_trait]
58pub trait Compile: Eval + Sized + 'static
59where
60 CompileError: From<Self::Error>,
61{
62 type Error;
63
64 async fn compile(
65 exprs: &[Syntax],
66 env: &Env,
67 cont: &Option<Arc<Continuation>>,
68 span: &Span,
69 ) -> Result<Self, Self::Error>;
70
71 async fn compile_to_expr(
72 exprs: &[Syntax],
73 env: &Env,
74 cont: &Option<Arc<Continuation>>,
75 span: &Span,
76 ) -> Result<Arc<dyn Eval>, CompileError> {
77 Ok(Arc::new(Self::compile(exprs, env, cont, span).await?))
78 }
79}
80
81#[derive(Debug, Clone)]
82pub enum CompileBodyError {
83 EmptyBody(Span),
84 CompileError(Box<CompileError>),
85}
86
87impl_from_compile_error!(CompileBodyError);
88
89#[async_trait]
90impl Compile for ast::Body {
91 type Error = CompileBodyError;
92
93 async fn compile(
94 exprs: &[Syntax],
95 env: &Env,
96 cont: &Option<Arc<Continuation>>,
97 span: &Span,
98 ) -> Result<Self, CompileBodyError> {
99 if exprs.is_empty() {
100 return Err(CompileBodyError::EmptyBody(span.clone()));
101 }
102 let mut output = Vec::new();
103 for expr in &exprs[..exprs.len() - 1] {
104 output.push(expr.compile(env, cont).await?);
105 }
106 Ok(ast::Body::new(output))
108 }
109}
110
111#[derive(Debug, Clone)]
112pub enum CompileLetError {
113 BadForm(Span),
114 CompileBodyError(CompileBodyError),
115 CompileLetBindingError(CompileLetBindingError),
116}
117
118#[async_trait]
119impl Compile for ast::Let {
120 type Error = CompileLetError;
121
122 async fn compile(
123 expr: &[Syntax],
124 env: &Env,
125 cont: &Option<Arc<Continuation>>,
126 span: &Span,
127 ) -> Result<Self, CompileLetError> {
128 match expr {
129 [Syntax::Null { .. }, body @ ..] => compile_let(&[], body, env, cont, span).await,
130 [Syntax::List { list: bindings, .. }, body @ ..] => {
131 compile_let(bindings, body, env, cont, span).await
132 }
133 _ => Err(CompileLetError::BadForm(span.clone())),
134 }
135 }
136}
137
138async fn compile_let(
139 bindings: &[Syntax],
140 body: &[Syntax],
141 env: &Env,
142 cont: &Option<Arc<Continuation>>,
143 span: &Span,
144) -> Result<ast::Let, CompileLetError> {
145 let mut previously_bound = HashMap::new();
146 let mut new_contour = env.new_lexical_contour();
147 let mut compiled_bindings = Vec::new();
148 if !bindings.is_empty() {
150 for binding in &bindings[..bindings.len() - 1] {
151 let binding = LetBinding::compile(binding, env, cont, &previously_bound)
152 .await
153 .map_err(CompileLetError::CompileLetBindingError)?;
154 previously_bound.insert(binding.ident.clone(), binding.span.clone());
155 new_contour.def_var(&binding.ident, Gc::new(Value::Undefined));
156 compiled_bindings.push(binding);
157 }
158 }
159
160 let env = Gc::new(new_contour);
161 let body = ast::Body::compile(body, &Env::from(env.clone()), cont, span)
162 .await
163 .map_err(CompileLetError::CompileBodyError)?;
164 Ok(ast::Let {
165 bindings: compiled_bindings
166 .into_iter()
167 .map(|binding| (binding.ident, binding.expr))
168 .collect(),
169 body,
170 })
171}
172
173#[derive(Debug, Clone)]
174pub enum CompileLetBindingError {
175 BadForm(Span),
176 PreviouslyBound {
177 ident: Identifier,
178 first: Span,
179 second: Span,
180 },
181 NotAList(Span),
182 CompileError(Box<CompileError>),
183}
184
185impl_from_compile_error!(CompileLetBindingError);
186
187struct LetBinding {
188 ident: Identifier,
189 span: Span,
190 expr: Arc<dyn Eval>,
191}
192
193impl LetBinding {
194 async fn compile(
195 expr: &Syntax,
196 env: &Env,
197 cont: &Option<Arc<Continuation>>,
198 previously_bound: &HashMap<Identifier, Span>,
199 ) -> Result<LetBinding, CompileLetBindingError> {
200 match expr {
201 Syntax::List { list, span } => match &list[..] {
202 [Syntax::Identifier {
203 ident,
204 span: bind_span,
205 ..
206 }, expr, Syntax::Null { .. }] => {
207 if let Some(prev_bind) = previously_bound.get(ident) {
208 return Err(CompileLetBindingError::PreviouslyBound {
209 ident: ident.clone(),
210 first: prev_bind.clone(),
211 second: bind_span.clone(),
212 });
213 }
214
215 let expr = expr.compile(env, cont).await?;
216
217 Ok(LetBinding {
218 ident: ident.clone(),
219 span: bind_span.clone(),
220 expr,
221 })
222 }
223 _ => Err(CompileLetBindingError::BadForm(span.clone())),
224 },
225 expr => Err(CompileLetBindingError::NotAList(expr.span().clone())),
226 }
227 }
228}
229
230#[derive(From, Debug, Clone)]
231pub enum CompileFuncCallError {
232 EmptyFunctionCall(Span),
233 CompileError(Box<CompileError>),
234}
235
236impl_from_compile_error!(CompileFuncCallError);
237
238#[async_trait]
239impl Compile for ast::Call {
240 type Error = CompileFuncCallError;
241
242 async fn compile(
243 exprs: &[Syntax],
244 env: &Env,
245 cont: &Option<Arc<Continuation>>,
246 span: &Span,
247 ) -> Result<ast::Call, CompileFuncCallError> {
248 match exprs {
249 [operator, args @ ..] => {
250 let proc_name = match operator {
253 Syntax::Identifier { ident, .. } => ident.name.clone(),
254 _ => String::from("<lambda>"),
255 };
256 let operator = operator.compile(env, cont).await?;
257 let mut compiled_args = vec![operator];
258 for arg in &args[..args.len() - 1] {
259 compiled_args.push(arg.compile(env, cont).await?);
260 }
261 Ok(ast::Call {
263 args: ArcSlice::from(compiled_args),
265 location: span.clone(),
266 proc_name,
267 })
268 }
269 [] => Err(CompileFuncCallError::EmptyFunctionCall(span.clone())),
270 }
271 }
272}
273
274#[derive(Debug, Clone)]
275pub enum CompileIfError {
276 ExpectedConditional(Span),
277 ExpectedArgumentAfterConditional(Span),
278 UnexpectedArgument(Span),
279 CompileError(Box<CompileError>),
280}
281
282impl_from_compile_error!(CompileIfError);
283
284#[async_trait]
285impl Compile for ast::If {
286 type Error = CompileIfError;
287
288 async fn compile(
289 exprs: &[Syntax],
290 env: &Env,
291 cont: &Option<Arc<Continuation>>,
292 span: &Span,
293 ) -> Result<Self, CompileIfError> {
294 match exprs {
295 [cond, success, Syntax::Null { .. }] => Ok(ast::If {
296 cond: cond.compile(env, cont).await?,
297 success: success.compile(env, cont).await?,
298 failure: None,
299 }),
300 [cond, success, failure, Syntax::Null { .. }] => Ok(ast::If {
301 cond: cond.compile(env, cont).await?,
302 success: success.compile(env, cont).await?,
303 failure: Some(failure.compile(env, cont).await?),
304 }),
305 [] => Err(CompileIfError::ExpectedConditional(span.clone())),
306 [a1] => Err(CompileIfError::ExpectedArgumentAfterConditional(
307 a1.span().clone(),
308 )),
309 [_, _, _, unexpected, ..] => Err(CompileIfError::UnexpectedArgument(
310 unexpected.span().clone(),
311 )),
312 _ => unreachable!(),
313 }
314 }
315}
316
317#[derive(Debug, Clone)]
318pub enum CompileDefineError {
319 ParameterDefinedMultipleTimes {
320 ident: Identifier,
321 first: Span,
322 second: Span,
323 },
324 ExpectedIdentifier(Span),
325 CompileBodyError(CompileBodyError),
326 BadForm(Span),
327 CompileError(Box<CompileError>),
328}
329
330impl_from_compile_error!(CompileDefineError);
331
332#[async_trait]
333impl Compile for ast::Define {
334 type Error = CompileDefineError;
335
336 async fn compile(
337 exprs: &[Syntax],
338 env: &Env,
339 cont: &Option<Arc<Continuation>>,
340 span: &Span,
341 ) -> Result<Self, Self::Error> {
342 match exprs {
343 [Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => {
344 Ok(ast::Define::DefineVar(ast::DefineVar {
345 name: ident.clone(),
346 val: expr.compile(env, cont).await?,
347 }))
348 }
349 [Syntax::List { list, span }, body @ ..] => {
350 match &list[..] {
351 [] => Err(CompileDefineError::ExpectedIdentifier(span.clone())),
352 [Syntax::Identifier {
353 ident: func_name,
354 span: func_span,
355 ..
356 }, args @ ..] => {
357 let mut bound = HashMap::<Identifier, Span>::new();
358 let mut fixed = Vec::new();
359 for arg in &args[..args.len() - 1] {
360 match arg {
361 Syntax::Identifier { ident, span, .. } => {
362 if let Some(prev_span) = bound.get(ident) {
363 return Err(
364 CompileDefineError::ParameterDefinedMultipleTimes {
365 ident: ident.clone(),
366 first: prev_span.clone(),
367 second: span.clone(),
368 },
369 );
370 }
371 bound.insert(ident.clone(), span.clone());
372 fixed.push(ident.clone());
373 }
374 x => {
375 return Err(CompileDefineError::ExpectedIdentifier(
376 x.span().clone(),
377 ))
378 }
379 }
380 }
381
382 let args = if let Some(last) = args.last() {
383 match last {
384 Syntax::Null { .. } => {
385 ast::Formals::FixedArgs(fixed.into_iter().collect())
386 }
387 Syntax::Identifier { ident, span, .. } => {
388 if let Some(prev_span) = bound.get(ident) {
389 return Err(
390 CompileDefineError::ParameterDefinedMultipleTimes {
391 ident: ident.clone(),
392 first: prev_span.clone(),
393 second: span.clone(),
394 },
395 );
396 }
397 let remaining = ident.clone();
398 ast::Formals::VarArgs {
399 fixed: fixed.into_iter().collect(),
400 remaining,
401 }
402 }
403 x => {
404 return Err(CompileDefineError::ExpectedIdentifier(
405 x.span().clone(),
406 ))
407 }
408 }
409 } else {
410 ast::Formals::FixedArgs(Vec::new())
412 };
413 let body = ast::Body::compile(body, env, cont, func_span)
414 .await
415 .map_err(CompileDefineError::CompileBodyError)?;
416 Ok(ast::Define::DefineFunc(ast::DefineFunc {
417 name: func_name.clone(),
418 args,
419 body,
420 }))
421 }
422 [x, ..] => Err(CompileDefineError::BadForm(x.span().clone())),
423 }
424 }
425 _ => Err(CompileDefineError::BadForm(span.clone())),
426 }
427 }
428}
429
430#[derive(Debug, Clone)]
431pub enum CompileDefineSyntaxError {
432 BadForm(Span),
433 CompileError(Box<CompileError>),
434 RuntimeError(Box<RuntimeError>),
435}
436
437impl_from_compile_error!(CompileDefineSyntaxError);
438
439impl From<RuntimeError> for CompileDefineSyntaxError {
440 fn from(value: RuntimeError) -> Self {
441 Self::RuntimeError(Box::new(value))
442 }
443}
444
445#[async_trait]
446impl Compile for ast::DefineSyntax {
447 type Error = CompileDefineSyntaxError;
448
449 async fn compile(
450 expr: &[Syntax],
451 env: &Env,
452 cont: &Option<Arc<Continuation>>,
453 span: &Span,
454 ) -> Result<ast::DefineSyntax, CompileDefineSyntaxError> {
455 match expr {
456 [Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => {
457 env.def_macro(
458 ident,
459 expr.compile(env, cont)
460 .await?
461 .eval(env, cont)
462 .await?
463 .require_one()?,
464 )
465 .await;
466 Ok(ast::DefineSyntax)
467 }
468 _ => Err(CompileDefineSyntaxError::BadForm(span.clone())),
469 }
470 }
471}
472
473#[derive(Debug, Clone)]
474pub enum CompileQuoteError {
475 ExpectedArgument(Span),
476 UnexpectedArgument(Span),
477 BadForm(Span),
478}
479
480#[async_trait]
481impl Compile for ast::Quote {
482 type Error = CompileQuoteError;
483
484 async fn compile(
485 exprs: &[Syntax],
486 _env: &Env,
487 _cont: &Option<Arc<Continuation>>,
488 span: &Span,
489 ) -> Result<Self, CompileQuoteError> {
490 match exprs {
491 [] => Err(CompileQuoteError::ExpectedArgument(span.clone())),
492 [Syntax::Null { .. }] => Ok(ast::Quote { val: Value::Null }),
493 [expr, Syntax::Null { .. }] => Ok(ast::Quote {
494 val: Value::from_syntax(expr),
495 }),
496 [_, arg, ..] => Err(CompileQuoteError::UnexpectedArgument(arg.span().clone())),
497 _ => Err(CompileQuoteError::BadForm(span.clone())),
498 }
499 }
500}
501
502#[async_trait]
503impl Compile for ast::And {
504 type Error = CompileError;
505
506 async fn compile(
507 exprs: &[Syntax],
508 env: &Env,
509 cont: &Option<Arc<Continuation>>,
510 _span: &Span,
511 ) -> Result<Self, CompileError> {
512 let mut output = Vec::new();
513 for expr in &exprs[..exprs.len() - 1] {
515 let expr = expr.compile(env, cont).await?;
516 output.push(expr);
517 }
518 Ok(Self::new(output))
519 }
520}
521
522#[async_trait]
523impl Compile for ast::Or {
524 type Error = CompileError;
525
526 async fn compile(
527 exprs: &[Syntax],
528 env: &Env,
529 cont: &Option<Arc<Continuation>>,
530 _span: &Span,
531 ) -> Result<Self, CompileError> {
532 let mut output = Vec::new();
533 for expr in &exprs[..exprs.len() - 1] {
535 let expr = expr.compile(env, cont).await?;
536 output.push(expr);
537 }
538 Ok(Self::new(output))
539 }
540}
541
542#[derive(Debug, Clone)]
543pub enum CompileSetError {
544 ExpectedArgument(Span),
545 ExpectedIdent(Span),
546 UnexpectedArgument(Span),
547 BadForm(Span),
548 CompileError(Box<CompileError>),
549}
550
551impl_from_compile_error!(CompileSetError);
552
553#[async_trait]
554impl Compile for ast::Set {
555 type Error = CompileSetError;
556
557 async fn compile(
558 exprs: &[Syntax],
559 env: &Env,
560 cont: &Option<Arc<Continuation>>,
561 span: &Span,
562 ) -> Result<Self, CompileSetError> {
563 match exprs {
565 [] => Err(CompileSetError::ExpectedArgument(span.clone())),
566 [Syntax::Identifier { ident, .. }, expr, Syntax::Null { .. }] => Ok(ast::Set {
567 var: ident.clone(),
568 val: expr.compile(env, cont).await?,
569 }),
570 [arg1, _, Syntax::Null { .. }] => {
571 Err(CompileSetError::ExpectedIdent(arg1.span().clone()))
572 }
573 [_, _, arg3, ..] => Err(CompileSetError::UnexpectedArgument(arg3.span().clone())),
574 _ => Err(CompileSetError::BadForm(span.clone())),
575 }
576 }
577}
578
579#[derive(Debug, Clone)]
580pub enum CompileSyntaxError {
581 ExpectedArgument(Span),
582 UnexpectedArgument(Span),
583 BadForm(Span),
584}
585
586#[async_trait]
587impl Compile for ast::SyntaxQuote {
588 type Error = CompileSyntaxError;
589
590 async fn compile(
591 exprs: &[Syntax],
592 env: &Env,
593 _cont: &Option<Arc<Continuation>>,
594 span: &Span,
595 ) -> Result<Self, CompileSyntaxError> {
596 match exprs {
597 [] => Err(CompileSyntaxError::ExpectedArgument(span.clone())),
598 [expr, Syntax::Null { .. }] => Ok(ast::SyntaxQuote {
599 syn: expr.clone(),
600 env: env.clone(),
601 }),
602 [_, arg, ..] => Err(CompileSyntaxError::UnexpectedArgument(arg.span().clone())),
603 _ => Err(CompileSyntaxError::BadForm(span.clone())),
604 }
605 }
606}
607
608#[derive(Debug, Clone)]
609pub enum CompileLambdaError {
610 ExpectedList(Span),
611 ExpectedIdentifier(Span),
612 CompileBodyError(CompileBodyError),
613 ParameterDefinedMultipleTimes {
614 ident: Identifier,
615 first: Span,
616 second: Span,
617 },
618}
619
620#[async_trait]
621impl Compile for ast::Lambda {
622 type Error = CompileLambdaError;
623
624 async fn compile(
625 exprs: &[Syntax],
626 env: &Env,
627 cont: &Option<Arc<Continuation>>,
628 span: &Span,
629 ) -> Result<Self, CompileLambdaError> {
630 match exprs {
631 [Syntax::Null { .. }, body @ ..] => compile_lambda(&[], body, env, cont, span).await,
632 [Syntax::List { list: args, .. }, body @ ..] => {
633 compile_lambda(args, body, env, cont, span).await
634 }
635 [Syntax::Identifier { ident, .. }, body @ ..] => {
636 let mut env = env.new_lexical_contour();
637 env.def_var(ident, Gc::new(Value::Undefined));
638
639 let body = ast::Body::compile(body, &Env::from(Gc::new(env)), cont, span)
640 .await
641 .map_err(CompileLambdaError::CompileBodyError)?;
642
643 Ok(ast::Lambda {
644 args: ast::Formals::VarArgs {
645 fixed: Vec::new(),
646 remaining: ident.clone(),
647 },
648 body,
649 })
650 }
651 _ => todo!(),
652 }
653 }
654}
655
656async fn compile_lambda(
657 args: &[Syntax],
658 body: &[Syntax],
659 env: &Env,
660 cont: &Option<Arc<Continuation>>,
661 span: &Span,
662) -> Result<ast::Lambda, CompileLambdaError> {
663 let mut bound = HashMap::<Identifier, Span>::new();
664 let mut fixed = Vec::new();
665 if !args.is_empty() {
666 for arg in &args[..args.len() - 1] {
667 match arg {
668 Syntax::Identifier { ident, span, .. } => {
669 if let Some(prev_span) = bound.get(ident) {
670 return Err(CompileLambdaError::ParameterDefinedMultipleTimes {
671 ident: ident.clone(),
672 first: prev_span.clone(),
673 second: span.clone(),
674 });
675 }
676 bound.insert(ident.clone(), span.clone());
677 fixed.push(ident.clone());
678 }
679 x => return Err(CompileLambdaError::ExpectedIdentifier(x.span().clone())),
680 }
681 }
682 }
683 let args = if let Some(last) = args.last() {
684 match last {
685 Syntax::Null { .. } => ast::Formals::FixedArgs(fixed.into_iter().collect()),
686 Syntax::Identifier { ident, span, .. } => {
687 if let Some(prev_span) = bound.get(ident) {
688 return Err(CompileLambdaError::ParameterDefinedMultipleTimes {
689 ident: ident.clone(),
690 first: prev_span.clone(),
691 second: span.clone(),
692 });
693 }
694 let remaining = ident.clone();
695 ast::Formals::VarArgs {
696 fixed: fixed.into_iter().collect(),
697 remaining,
698 }
699 }
700 x => return Err(CompileLambdaError::ExpectedIdentifier(x.span().clone())),
701 }
702 } else {
703 ast::Formals::FixedArgs(Vec::new())
705 };
706
707 let mut env = env.new_lexical_contour();
708 for bound in bound.into_keys() {
709 env.def_var(&bound, Gc::new(Value::Undefined));
710 }
711
712 let body = ast::Body::compile(body, &Env::from(Gc::new(env)), cont, span)
713 .await
714 .map_err(CompileLambdaError::CompileBodyError)?;
715 Ok(ast::Lambda { args, body })
716}
717
718#[derive(Debug, Clone)]
719pub enum CompileSyntaxCaseError {
720 CompileError(Box<CompileError>),
721 BadForm(Span),
722}
723
724impl_from_compile_error!(CompileSyntaxCaseError);
725
726#[async_trait]
727impl Compile for ast::SyntaxCase {
728 type Error = CompileSyntaxCaseError;
729
730 async fn compile(
731 exprs: &[Syntax],
732 env: &Env,
733 cont: &Option<Arc<Continuation>>,
734 span: &Span,
735 ) -> Result<Self, CompileSyntaxCaseError> {
736 let (arg, keywords, mut rules) = match exprs {
737 [arg, Syntax::List { list, .. }, rules @ ..] => {
738 let mut keywords = HashSet::default();
739 for keyword in &list[..list.len() - 1] {
741 if let Syntax::Identifier { ident, .. } = keyword {
742 keywords.insert(ident.name.clone());
743 } else {
744 return Err(CompileSyntaxCaseError::BadForm(keyword.span().clone()));
745 }
746 }
747 (arg, keywords, rules)
748 }
749 [arg, Syntax::Null { .. }, rules @ ..] => (arg, HashSet::default(), rules),
750 _ => return Err(CompileSyntaxCaseError::BadForm(span.clone())),
751 };
752 let mut syntax_rules = Vec::new();
753 loop {
754 match rules {
755 [Syntax::Null { .. }] => break,
756 [Syntax::List { list, .. }, tail @ ..] => match &list[..] {
757 [pattern, template, Syntax::Null { .. }] => {
758 syntax_rules.push(SyntaxRule::compile(&keywords, pattern, template));
759 rules = tail;
760 }
761 _ => return Err(CompileSyntaxCaseError::BadForm(span.clone())),
762 },
763 _ => return Err(CompileSyntaxCaseError::BadForm(span.clone())),
764 }
765 }
766 Ok(ast::SyntaxCase {
767 arg: arg.compile(env, cont).await?,
768 transformer: Transformer {
769 rules: syntax_rules,
770 is_variable_transformer: false,
771 },
772 })
773 }
774}
775
776#[derive(Debug, Clone)]
777pub enum CompileSyntaxRulesError {
778 BadForm(Span),
779}
780
781#[async_trait]
782impl Compile for ast::SyntaxRules {
783 type Error = CompileSyntaxRulesError;
784
785 async fn compile(
786 exprs: &[Syntax],
787 _env: &Env,
788 _cont: &Option<Arc<Continuation>>,
789 span: &Span,
790 ) -> Result<Self, CompileSyntaxRulesError> {
791 let (keywords, mut rules) = match exprs {
792 [Syntax::List { list, .. }, rules @ ..] => {
793 let mut keywords = HashSet::default();
794 for keyword in &list[..list.len() - 1] {
796 if let Syntax::Identifier { ident, .. } = keyword {
797 keywords.insert(ident.name.clone());
798 } else {
799 return Err(CompileSyntaxRulesError::BadForm(keyword.span().clone()));
800 }
801 }
802 (keywords, rules)
803 }
804 [Syntax::Null { .. }, rules @ ..] => (HashSet::default(), rules),
805 _ => return Err(CompileSyntaxRulesError::BadForm(span.clone())),
806 };
807 let mut syntax_rules = Vec::new();
808 loop {
809 match rules {
810 [Syntax::Null { .. }] => break,
811 [Syntax::List { list, .. }, tail @ ..] => match &list[..] {
812 [pattern, template, Syntax::Null { .. }] => {
813 syntax_rules.push(SyntaxRule::compile(&keywords, pattern, template));
814 rules = tail;
815 }
816 _ => return Err(CompileSyntaxRulesError::BadForm(span.clone())),
817 },
818 _ => return Err(CompileSyntaxRulesError::BadForm(span.clone())),
819 }
820 }
821
822 Ok(Self {
823 transformer: Transformer {
824 rules: syntax_rules,
825 is_variable_transformer: false,
826 },
827 })
828 }
829}
830
831#[derive(From, Debug, Clone)]
832pub enum CompileApplyError {
833 BadForm(Span),
834 CompileError(Box<CompileError>),
835}
836
837impl_from_compile_error!(CompileApplyError);
838
839#[async_trait]
840impl Compile for ast::Apply {
841 type Error = CompileApplyError;
842
843 async fn compile(
844 exprs: &[Syntax],
845 env: &Env,
846 cont: &Option<Arc<Continuation>>,
847 span: &Span,
848 ) -> Result<Self, CompileApplyError> {
849 match exprs {
850 [operator, args @ .., rest_args, Syntax::Null { .. }] => {
851 let proc_name = match operator {
852 Syntax::Identifier { ident, .. } => ident.name.clone(),
853 _ => String::from("<lambda>"),
854 };
855 let operator = operator.compile(env, cont).await?;
856 let mut compiled_args = vec![operator];
857 for arg in args {
858 compiled_args.push(arg.compile(env, cont).await?);
859 }
860 let rest_args = rest_args.compile(env, cont).await?;
861 Ok(ast::Apply {
862 proc_name,
863 location: span.clone(),
864 args: ArcSlice::from(compiled_args),
865 rest_args,
866 })
867 }
868 _ => Err(CompileApplyError::BadForm(span.clone())),
869 }
870 }
871}