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