1use crate::{
4 ast::Primitive,
5 env::{Binding, Environment, Scope, add_binding, resolve},
6 exceptions::{CompoundCondition, Exception, Message, SyntaxViolation, Who},
7 gc::{Gc, Trace},
8 ports::Port,
9 proc::{ContBarrier, Procedure},
10 records::{RecordTypeDescriptor, SchemeCompatible, rtd},
11 registry::bridge,
12 symbols::Symbol,
13 syntax::parse::ParseSyntaxError,
14 value::{Expect1, UnpackedValue, Value},
15};
16use scheme_rs_macros::{maybe_async, maybe_await};
17use std::{
18 collections::BTreeSet,
19 fmt,
20 hash::Hash,
21 io::Cursor,
22 sync::{Arc, LazyLock},
23};
24
25#[cfg(feature = "async")]
26use futures::future::BoxFuture;
27
28pub mod lex;
29pub mod parse;
30
31#[derive(Debug, Clone, PartialEq, Eq, Hash, Trace)]
33pub struct Span {
34 pub line: u32,
35 pub column: usize,
36 pub offset: usize,
37 pub file: Arc<str>,
38}
39
40impl Span {
41 pub fn new(file: &str) -> Self {
42 Self {
43 file: Arc::from(file.to_string()),
44 ..Default::default()
45 }
46 }
47}
48
49impl fmt::Display for Span {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 write!(f, "{}:{}:{}", self.file, self.line, self.column)
52 }
53}
54
55impl Default for Span {
56 fn default() -> Self {
57 static UNKNOWN: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("<unknown>".to_string()));
58 Self {
59 line: 1,
60 column: 0,
61 offset: 0,
62 file: UNKNOWN.clone(),
63 }
64 }
65}
66
67impl SchemeCompatible for Span {
68 fn rtd() -> Arc<RecordTypeDescriptor> {
69 rtd!(name: "span", sealed: true, opaque: true)
70 }
71}
72
73#[derive(Clone, Trace)]
75#[repr(align(16))]
76pub enum Syntax {
77 Wrapped {
79 value: Value,
80 span: Span,
81 },
82 List {
86 list: Vec<Syntax>,
87 span: Span,
88 },
89 Vector {
90 vector: Vec<Syntax>,
91 span: Span,
92 },
93 Identifier {
94 ident: Identifier,
95 span: Span,
96 },
97}
98
99impl Syntax {
100 pub(crate) fn adjust_scope(&mut self, scope: Scope, op: fn(&mut Identifier, Scope)) {
101 match self {
102 Self::List { list, .. } => {
103 for item in list {
104 item.adjust_scope(scope, op);
105 }
106 }
107 Self::Vector { vector, .. } => {
108 for item in vector {
109 item.adjust_scope(scope, op);
110 }
111 }
112 Self::Identifier { ident, .. } => op(ident, scope),
113 _ => (),
114 }
115 }
116
117 pub fn add_scope(&mut self, scope: Scope) {
118 self.adjust_scope(scope, Identifier::add_scope)
119 }
120
121 pub fn flip_scope(&mut self, scope: Scope) {
122 self.adjust_scope(scope, Identifier::flip_scope)
123 }
124
125 pub fn remove_scope(&mut self, scope: Scope) {
126 self.adjust_scope(scope, Identifier::remove_scope)
127 }
128
129 pub fn wrap(value: Value, span: &Span) -> Syntax {
130 match value.unpack() {
131 UnpackedValue::Pair(pair) => {
132 let (car, cdr) = pair.into();
133 let car = Self::wrap(car, span);
134 let cdr = Self::wrap(cdr, span);
135 match cdr {
136 Syntax::List { mut list, span } => {
137 list.insert(0, car);
138 Syntax::List { list, span }
139 }
140 _ => Syntax::List {
141 list: vec![car, cdr],
142 span: span.clone(),
143 },
144 }
145 }
146 UnpackedValue::Vector(vec) => Syntax::Vector {
147 vector: vec.iter().map(|value| Syntax::wrap(value, span)).collect(),
148 span: span.clone(),
149 },
150 UnpackedValue::Syntax(syn) => syn.as_ref().clone(),
151 value => Syntax::Wrapped {
152 value: value.into_value(),
153 span: Span::default(),
154 },
155 }
156 }
157
158 pub fn unwrap(self) -> Value {
159 match self {
160 Self::Wrapped { value, .. } => value,
161 Self::List { mut list, .. } => {
162 let mut cdr = Self::unwrap(list.pop().unwrap());
163 for car in list.into_iter().map(Self::unwrap).rev() {
164 cdr = Value::from((car, cdr));
165 }
166 cdr
167 }
168 Self::Vector { vector, .. } => {
169 Value::from(vector.into_iter().map(Syntax::unwrap).collect::<Vec<_>>())
170 }
171 _ => Value::from(self),
172 }
173 }
174
175 pub fn datum_to_syntax(scopes: &BTreeSet<Scope>, value: Value, span: &Span) -> Syntax {
176 match value.unpack() {
177 UnpackedValue::Pair(pair) => {
178 let (car, cdr) = pair.into();
179 let car = Self::datum_to_syntax(scopes, car, span);
180 let cdr = Self::datum_to_syntax(scopes, cdr, span);
181 match cdr {
182 Syntax::List { mut list, span } => {
183 list.insert(0, car);
184 Syntax::List { list, span }
185 }
186 _ => Syntax::List {
187 list: vec![car, cdr],
188 span: span.clone(),
189 },
190 }
191 }
192 UnpackedValue::Vector(vec) => Syntax::Vector {
193 vector: vec
194 .iter()
195 .map(|value| Syntax::datum_to_syntax(scopes, value, span))
196 .collect(),
197 span: Span::default(),
198 },
199 UnpackedValue::Syntax(syn) => {
200 let mut syn = syn.as_ref().clone();
201 for scope in scopes {
202 syn.add_scope(*scope);
203 }
204 syn
205 }
206 UnpackedValue::Symbol(sym) => Syntax::Identifier {
207 ident: Identifier {
208 sym,
209 scopes: scopes.clone(),
210 },
211 span: Span::default(),
212 },
213 value => Syntax::Wrapped {
214 value: value.into_value(),
215 span: span.clone(),
216 },
217 }
218 }
219
220 pub fn syntax_to_datum(value: Value) -> Value {
221 match value.unpack() {
222 UnpackedValue::Pair(pair) => {
223 let (car, cdr) = pair.into();
224 Value::from((Self::syntax_to_datum(car), Self::syntax_to_datum(cdr)))
225 }
226 UnpackedValue::Vector(vec) => {
227 Value::from(vec.iter().map(Self::syntax_to_datum).collect::<Vec<_>>())
228 }
229 UnpackedValue::Syntax(syn) => match syn.as_ref() {
230 Syntax::Identifier { ident, .. } => Value::from(ident.sym),
231 Syntax::Wrapped { value, .. } => value.clone(),
232 syn => Syntax::syntax_to_datum(Self::unwrap(syn.clone())),
233 },
234 unpacked => unpacked.into_value(),
235 }
236 }
237
238 #[maybe_async]
239 fn apply_transformer(&self, transformer: &Procedure) -> Result<Expansion, Exception> {
240 let intro_scope = Scope::new();
242
243 let mut input = self.clone();
245 input.add_scope(intro_scope);
246
247 let transformer_output =
249 maybe_await!(transformer.call(&[Value::from(input)], &mut ContBarrier::new()))?;
250
251 let output: Value = transformer_output.expect1()?;
252 let mut output = Syntax::wrap(output, self.span());
253 output.flip_scope(intro_scope);
254
255 Ok(Expansion::Expanded(output))
256 }
257
258 #[cfg(not(feature = "async"))]
259 fn expand_once(&self, env: &Environment) -> Result<Expansion, Exception> {
260 self.expand_once_inner(env)
261 }
262
263 #[cfg(feature = "async")]
264 fn expand_once<'a>(
265 &'a self,
266 env: &'a Environment,
267 ) -> BoxFuture<'a, Result<Expansion, Exception>> {
268 Box::pin(self.expand_once_inner(env))
269 }
270
271 #[maybe_async]
272 fn expand_once_inner(&self, env: &Environment) -> Result<Expansion, Exception> {
273 match self {
274 Self::List { list, .. } => {
275 let ident = match list.first() {
276 Some(Self::Identifier { ident, .. }) => ident,
277 _ => return Ok(Expansion::Unexpanded),
278 };
279 if let Some(binding) = ident.resolve() {
280 if let Some(transformer) = maybe_await!(env.lookup_keyword(binding))? {
281 return maybe_await!(self.apply_transformer(&transformer));
282 } else if let Some(Primitive::Set) = env.lookup_primitive(binding)
283 && let [Syntax::Identifier { ident, .. }, ..] = &list.as_slice()[1..]
284 {
285 if let Some(binding) = ident.resolve()
288 && let Some(transformer) = maybe_await!(env.lookup_keyword(binding))?
289 {
290 if !transformer.is_variable_transformer() {
291 return Err(Exception::error(format!(
292 "{} is not a variable transformer",
293 ident.sym
294 )));
295 }
296 return maybe_await!(self.apply_transformer(&transformer));
297 }
298 }
299 }
300 }
301 Self::Identifier { ident, .. } => {
302 if let Some(binding) = ident.resolve()
303 && let Some(transformer) = maybe_await!(env.lookup_keyword(binding))?
304 {
305 return maybe_await!(self.apply_transformer(&transformer));
306 }
307 }
308 _ => (),
309 }
310 Ok(Expansion::Unexpanded)
311 }
312
313 #[maybe_async]
315 pub(crate) fn expand(mut self, env: &Environment) -> Result<Syntax, Exception> {
316 loop {
317 match maybe_await!(self.expand_once(env)) {
318 Ok(Expansion::Unexpanded) => {
319 return Ok(self);
320 }
321 Ok(Expansion::Expanded(syntax)) => {
322 self = syntax;
323 }
324 Err(condition) => {
325 return Err(condition.add_condition(SyntaxViolation::new(self, None)));
326 }
327 }
328 }
329 }
330
331 #[cfg(not(feature = "async"))]
332 pub fn from_str(s: &str, file_name: Option<&str>) -> Result<Self, ParseSyntaxError> {
333 use crate::ports::{BufferMode, Transcoder};
334
335 let file_name = file_name.unwrap_or("<unknown>");
336 let bytes = Cursor::new(s.as_bytes().to_vec());
337 let port = Port::new(
338 file_name,
339 bytes,
340 BufferMode::Block,
341 Some(Transcoder::native()),
342 );
343 port.all_sexprs(Span::new(file_name))
344 }
345
346 #[cfg(feature = "async")]
347 pub fn from_str(s: &str, file_name: Option<&str>) -> Result<Self, ParseSyntaxError> {
348 use crate::ports::{BufferMode, Transcoder};
349
350 let file_name = file_name.unwrap_or("<unknown>");
351 let bytes = Cursor::new(s.as_bytes().to_vec());
352
353 let port = Arc::into_inner(
355 Port::new(
356 file_name,
357 bytes,
358 BufferMode::Block,
359 Some(Transcoder::native()),
360 )
361 .0,
362 )
363 .unwrap();
364 let info = port.info;
365 let mut data = port.data.into_inner();
366
367 futures::executor::block_on(async move {
370 use crate::syntax::parse::Parser;
371
372 let mut parser = Parser::new(&mut data, &info, Span::new(file_name));
373 parser.all_sexprs().await
374 })
375 }
376
377 pub(crate) fn has_car(&self, car: &str) -> bool {
380 matches!(self.as_list(), Some([Self::Identifier { ident, .. }, .. ]) if ident == car)
381 }
382
383 pub fn span(&self) -> &Span {
384 match self {
385 Self::Wrapped { span, .. } => span,
386 Self::List { span, .. } => span,
387 Self::Vector { span, .. } => span,
388 Self::Identifier { span, .. } => span,
389 }
390 }
391
392 pub fn as_ident(&self) -> Option<&Identifier> {
393 if let Syntax::Identifier { ident, .. } = self {
394 Some(ident)
395 } else {
396 None
397 }
398 }
399
400 pub fn new_list(list: Vec<Syntax>, span: impl Into<Span>) -> Self {
401 Self::List {
402 list,
403 span: span.into(),
404 }
405 }
406
407 pub fn as_list(&self) -> Option<&[Syntax]> {
408 if let Syntax::List { list, .. } = self {
409 Some(list)
410 } else {
411 None
412 }
413 }
414
415 pub fn as_list_mut(&mut self) -> Option<&mut [Syntax]> {
416 if let Syntax::List { list, .. } = self {
417 Some(list)
418 } else {
419 None
420 }
421 }
422
423 pub fn is_list(&self) -> bool {
424 matches!(self, Self::List { .. })
425 }
426
427 pub fn car(&self) -> Option<&Syntax> {
428 if let Syntax::List { list, .. } = self {
429 list.first()
430 } else {
431 None
432 }
433 }
434
435 pub fn new_vector(vector: Vec<Syntax>, span: impl Into<Span>) -> Self {
436 Self::Vector {
437 vector,
438 span: span.into(),
439 }
440 }
441
442 pub fn is_vector(&self) -> bool {
443 matches!(self, Self::Vector { .. })
444 }
445
446 pub fn new_wrapped(value: Value, span: impl Into<Span>) -> Self {
447 Self::Wrapped {
448 value,
449 span: span.into(),
450 }
451 }
452
453 pub fn new_identifier(name: &str, span: impl Into<Span>) -> Self {
454 Self::Identifier {
455 ident: Identifier::new(name),
456 span: span.into(),
457 }
458 }
459
460 pub fn is_identifier(&self) -> bool {
461 matches!(self, Self::Identifier { .. })
462 }
463
464 pub fn is_null(&self) -> bool {
465 matches!(self, Self::Wrapped { value, .. } if value.is_null())
466 }
467}
468
469impl fmt::Debug for Syntax {
470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471 match self {
472 Syntax::List { list, .. } => {
473 let proper_list = list.last().unwrap().is_null();
474 let len = list.len();
475 write!(f, "(")?;
476 for (i, item) in list.iter().enumerate() {
477 if i == len - 1 {
478 if proper_list {
479 break;
480 } else {
481 write!(f, " . {item:?}")?;
482 }
483 } else {
484 if i > 0 {
485 write!(f, " ")?;
486 }
487 write!(f, "{item:?}")?;
488 }
489 }
490 write!(f, ")")
491 }
492 Syntax::Wrapped { value, .. } => {
493 write!(f, "{value:?}")
494 }
495 Syntax::Vector { vector, .. } => {
496 write!(f, "#(")?;
497 for (i, item) in vector.iter().enumerate() {
498 if i > 0 {
499 write!(f, " ")?;
500 }
501 write!(f, "{item:?}")?;
502 }
503 write!(f, ")")
504 }
505 Syntax::Identifier { ident, .. } => {
506 write!(f, "{}", ident.sym)
507 }
508 }
509 }
510}
511
512pub(crate) enum Expansion {
513 Unexpanded,
515 Expanded(Syntax),
517}
518
519#[derive(Clone, Trace, PartialEq, Eq, Hash)]
520pub struct Identifier {
521 pub(crate) sym: Symbol,
522 pub(crate) scopes: BTreeSet<Scope>,
523}
524
525impl fmt::Debug for Identifier {
526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527 write!(f, "{} ({:?})", self.sym, self.scopes)
528 }
529}
530
531impl Identifier {
532 pub fn new(name: &str) -> Self {
533 Self {
534 sym: Symbol::intern(name),
535 scopes: BTreeSet::new(),
536 }
537 }
538
539 pub fn symbol(&self) -> Symbol {
540 self.sym
541 }
542
543 pub fn from_symbol(sym: Symbol, scope: Scope) -> Self {
544 Self {
545 sym,
546 scopes: BTreeSet::from([scope]),
547 }
548 }
549
550 pub fn add_scope(&mut self, scope: Scope) {
551 self.scopes.insert(scope);
552 }
553
554 pub fn remove_scope(&mut self, scope: Scope) {
555 self.scopes.remove(&scope);
556 }
557
558 pub fn flip_scope(&mut self, scope: Scope) {
559 if self.scopes.contains(&scope) {
560 self.scopes.remove(&scope);
561 } else {
562 self.scopes.insert(scope);
563 }
564 }
565
566 pub fn free_identifier_equal(&self, rhs: &Self) -> bool {
567 match (self.resolve(), rhs.resolve()) {
568 (Some(lhs), Some(rhs)) => lhs == rhs,
569 (None, None) => self.sym == rhs.sym,
570 _ => false,
571 }
572 }
573
574 pub fn resolve(&self) -> Option<Binding> {
575 resolve(self)
576 }
577
578 pub(crate) fn bind(&self) -> Binding {
579 if let Some(binding) = self.resolve() {
580 binding
581 } else {
582 self.new_bind()
583 }
584 }
585
586 pub(crate) fn new_bind(&self) -> Binding {
587 let new_binding = Binding::new();
588 add_binding(self.clone(), new_binding);
589 new_binding
590 }
591}
592
593impl PartialEq<str> for Identifier {
594 fn eq(&self, rhs: &str) -> bool {
595 self.sym.to_str().as_ref() == rhs
596 }
597}
598
599#[bridge(name = "syntax->datum", lib = "(rnrs syntax-case builtins (6))")]
600pub fn syntax_to_datum(value: &Value) -> Result<Vec<Value>, Exception> {
601 Ok(vec![Syntax::syntax_to_datum(value.clone())])
603}
604
605#[bridge(name = "datum->syntax", lib = "(rnrs syntax-case builtins (6))")]
606pub fn datum_to_syntax(template_id: Identifier, datum: &Value) -> Result<Vec<Value>, Exception> {
607 Ok(vec![Value::from(Syntax::datum_to_syntax(
608 &template_id.scopes,
609 datum.clone(),
610 &Span::default(),
611 ))])
612}
613
614#[bridge(name = "identifier?", lib = "(rnrs syntax-case builtins (6))")]
615pub fn identifier_pred(obj: &Value) -> Result<Vec<Value>, Exception> {
616 Ok(vec![Value::from(
617 obj.cast_to_scheme_type::<Identifier>().is_some(),
618 )])
619}
620
621#[bridge(name = "bound-identifier=?", lib = "(rnrs syntax-case builtins (6))")]
622pub fn bound_identifier_eq_pred(id1: Identifier, id2: Identifier) -> Result<Vec<Value>, Exception> {
623 Ok(vec![Value::from(id1 == id2)])
624}
625
626#[bridge(name = "free-identifier=?", lib = "(rnrs syntax-case builtins (6))")]
627pub fn free_identifier_eq_pred(id1: Identifier, id2: Identifier) -> Result<Vec<Value>, Exception> {
628 Ok(vec![Value::from(id1.free_identifier_equal(&id2))])
629}
630
631#[bridge(name = "generate-temporaries", lib = "(rnrs syntax-case builtins (6))")]
632pub fn generate_temporaries(list: &Value) -> Result<Vec<Value>, Exception> {
633 let length = if let Syntax::List { list, .. } = Syntax::wrap(list.clone(), &Span::default())
634 && list.last().unwrap().is_null()
635 {
636 list.len() - 1
637 } else {
638 return Err(Exception::error("expected proper list"));
639 };
640
641 let mut temporaries = Value::null();
642 for _ in 0..length {
643 let ident = Syntax::Identifier {
644 ident: Identifier {
645 sym: Symbol::gensym(),
646 scopes: BTreeSet::new(),
647 },
648 span: Span::default(),
649 };
650 temporaries = Value::from((Value::from(ident), temporaries));
651 }
652
653 Ok(vec![temporaries])
654}
655
656#[bridge(name = "syntax-violation", lib = "(rnrs base builtins (6))")]
657pub fn syntax_violation(
658 who: &Value,
659 message: &Value,
660 form: &Value,
661 subform: &[Value],
662) -> Result<Vec<Value>, Exception> {
663 let subform = match subform {
664 [] => None,
665 [subform] => Some(subform.clone()),
666 _ => return Err(Exception::wrong_num_of_var_args(3..4, 3 + subform.len())),
667 };
668 let mut conditions = Vec::new();
669 if who.is_true() {
670 conditions.push(Value::from_rust_type(Who::new(who.clone())));
671 } else if let Some(syntax) = form.cast_to_scheme_type::<Gc<Syntax>>() {
672 let who = if let Syntax::Identifier { ident, .. } = syntax.as_ref() {
673 Some(ident.sym)
674 } else if let Some([Syntax::Identifier { ident, .. }, ..]) = syntax.as_list() {
675 Some(ident.sym)
676 } else {
677 None
678 };
679 conditions.push(Value::from_rust_type(Who::new(Value::from(who))));
680 }
681 conditions.push(Value::from_rust_type(Message::new(message)));
682 conditions.push(Value::from_rust_type(SyntaxViolation::new_from_values(
683 form.clone(),
684 subform,
685 )));
686 Err(Exception(Value::from(Exception::from(CompoundCondition(
687 conditions,
688 )))))
689}