1use super::functions::*;
6use crate::error_impl::ParseError;
7use crate::tokens::{Span, Token, TokenKind};
8use std::collections::HashMap;
9
10#[allow(dead_code)]
12#[allow(missing_docs)]
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct MacroVarExt {
15 pub name: String,
17 pub is_rep: bool,
19}
20impl MacroVarExt {
21 #[allow(dead_code)]
23 pub fn simple(name: &str) -> Self {
24 MacroVarExt {
25 name: name.to_string(),
26 is_rep: false,
27 }
28 }
29 #[allow(dead_code)]
31 pub fn rep(name: &str) -> Self {
32 MacroVarExt {
33 name: name.to_string(),
34 is_rep: true,
35 }
36 }
37}
38#[allow(dead_code)]
40#[allow(missing_docs)]
41pub struct MacroLibrary {
42 pub groups: std::collections::HashMap<String, Vec<MacroDefinitionExt>>,
44}
45impl MacroLibrary {
46 #[allow(dead_code)]
48 pub fn new() -> Self {
49 MacroLibrary {
50 groups: std::collections::HashMap::new(),
51 }
52 }
53 #[allow(dead_code)]
55 pub fn add_to_group(&mut self, group: &str, def: MacroDefinitionExt) {
56 self.groups.entry(group.to_string()).or_default().push(def);
57 }
58 #[allow(dead_code)]
60 pub fn group(&self, name: &str) -> &[MacroDefinitionExt] {
61 self.groups.get(name).map(|v| v.as_slice()).unwrap_or(&[])
62 }
63 #[allow(dead_code)]
65 pub fn total_macros(&self) -> usize {
66 self.groups.values().map(|v| v.len()).sum()
67 }
68}
69#[derive(Debug, Clone, PartialEq)]
71pub enum SyntaxItem {
72 Token(TokenKind),
74 Category(String),
76 Optional(Box<SyntaxItem>),
78 Many(Box<SyntaxItem>),
80 Group(Vec<SyntaxItem>),
82}
83#[allow(dead_code)]
85#[allow(missing_docs)]
86#[derive(Debug, Clone)]
87pub struct MacroSubst {
88 pub var: String,
90 pub value: String,
92}
93impl MacroSubst {
94 #[allow(dead_code)]
96 pub fn new(var: &str, value: &str) -> Self {
97 MacroSubst {
98 var: var.to_string(),
99 value: value.to_string(),
100 }
101 }
102}
103#[derive(Debug, Clone)]
105pub struct MacroDef {
106 pub name: String,
108 pub rules: Vec<MacroRule>,
110 pub doc: Option<String>,
112 pub hygiene: HygieneInfo,
114}
115impl MacroDef {
116 pub fn new(name: String, rules: Vec<MacroRule>, hygiene: HygieneInfo) -> Self {
118 Self {
119 name,
120 rules,
121 doc: None,
122 hygiene,
123 }
124 }
125 pub fn with_doc(mut self, doc: String) -> Self {
127 self.doc = Some(doc);
128 self
129 }
130 pub fn rule_count(&self) -> usize {
132 self.rules.len()
133 }
134}
135#[allow(dead_code)]
137#[allow(missing_docs)]
138#[derive(Debug, Clone)]
139pub enum MacroExpansionResult {
140 Ok(String),
142 Err(MacroExpansionError),
144}
145impl MacroExpansionResult {
146 #[allow(dead_code)]
148 pub fn is_ok(&self) -> bool {
149 matches!(self, MacroExpansionResult::Ok(_))
150 }
151 #[allow(dead_code)]
153 pub fn unwrap(self) -> String {
154 match self {
155 MacroExpansionResult::Ok(s) => s,
156 MacroExpansionResult::Err(e) => {
157 panic!("macro expansion error: {}", e.message)
158 }
159 }
160 }
161 #[allow(dead_code)]
163 pub fn unwrap_or(self, default: &str) -> String {
164 match self {
165 MacroExpansionResult::Ok(s) => s,
166 MacroExpansionResult::Err(_) => default.to_string(),
167 }
168 }
169}
170#[allow(dead_code)]
172#[allow(missing_docs)]
173pub struct MacroMatcher {
174 pub pattern: Vec<MacroVarExt>,
176}
177impl MacroMatcher {
178 #[allow(dead_code)]
180 #[allow(clippy::should_implement_trait)]
181 pub fn from_str(s: &str) -> Self {
182 MacroMatcher {
183 pattern: s
184 .split_whitespace()
185 .map(|tok| {
186 if let Some(name) = tok.strip_prefix('$') {
187 MacroVarExt::simple(name)
188 } else {
189 MacroVarExt {
190 name: format!("__lit_{}", tok),
191 is_rep: false,
192 }
193 }
194 })
195 .collect(),
196 }
197 }
198 #[allow(dead_code)]
200 pub fn hole_count(&self) -> usize {
201 self.pattern
202 .iter()
203 .filter(|v| !v.name.starts_with("__lit_"))
204 .count()
205 }
206 #[allow(dead_code)]
208 pub fn literal_count(&self) -> usize {
209 self.pattern
210 .iter()
211 .filter(|v| v.name.starts_with("__lit_"))
212 .count()
213 }
214}
215#[allow(dead_code)]
217#[allow(missing_docs)]
218#[derive(Debug, Clone)]
219pub struct MacroExpansionErrorExt2 {
220 pub message: String,
222 pub macro_name: String,
224 pub depth: usize,
226}
227impl MacroExpansionErrorExt2 {
228 #[allow(dead_code)]
230 pub fn new(macro_name: &str, message: &str, depth: usize) -> Self {
231 MacroExpansionErrorExt2 {
232 message: message.to_string(),
233 macro_name: macro_name.to_string(),
234 depth,
235 }
236 }
237 #[allow(dead_code)]
239 pub fn format(&self) -> String {
240 format!(
241 "macro '{}' at depth {}: {}",
242 self.macro_name, self.depth, self.message
243 )
244 }
245}
246#[allow(dead_code)]
248#[allow(missing_docs)]
249#[derive(Debug, Default)]
250pub struct MacroExpansionTraceExt {
251 pub steps: Vec<String>,
253}
254impl MacroExpansionTraceExt {
255 #[allow(dead_code)]
257 pub fn new() -> Self {
258 MacroExpansionTraceExt { steps: Vec::new() }
259 }
260 #[allow(dead_code)]
262 pub fn record(&mut self, step: &str) {
263 self.steps.push(step.to_string());
264 }
265 #[allow(dead_code)]
267 pub fn format(&self) -> String {
268 self.steps
269 .iter()
270 .enumerate()
271 .map(|(i, s)| format!("{}: {}", i, s))
272 .collect::<Vec<_>>()
273 .join("\n")
274 }
275}
276#[allow(dead_code)]
278#[allow(missing_docs)]
279#[derive(Debug, Clone)]
280pub struct MacroExpansionError {
281 pub macro_name: String,
283 pub message: String,
285 pub depth: usize,
287}
288impl MacroExpansionError {
289 #[allow(dead_code)]
291 pub fn new(macro_name: &str, message: &str, depth: usize) -> Self {
292 MacroExpansionError {
293 macro_name: macro_name.to_string(),
294 message: message.to_string(),
295 depth,
296 }
297 }
298 #[allow(dead_code)]
300 pub fn format(&self) -> String {
301 format!(
302 "macro error in '{}' at depth {}: {}",
303 self.macro_name, self.depth, self.message
304 )
305 }
306}
307#[derive(Debug, Clone, PartialEq, Eq)]
309pub enum MacroErrorKind {
310 UnknownMacro,
312 PatternMismatch,
314 HygieneViolation,
316 AmbiguousMatch,
318 ExpansionError,
320}
321#[allow(dead_code)]
323#[allow(missing_docs)]
324pub struct DepthLimitedExpanderExt2 {
325 pub max_depth: usize,
327 pub current_depth: usize,
329}
330impl DepthLimitedExpanderExt2 {
331 #[allow(dead_code)]
333 pub fn new(max_depth: usize) -> Self {
334 DepthLimitedExpanderExt2 {
335 max_depth,
336 current_depth: 0,
337 }
338 }
339 #[allow(dead_code)]
341 pub fn can_expand(&self) -> bool {
342 self.current_depth < self.max_depth
343 }
344 #[allow(dead_code)]
346 pub fn enter(&mut self) -> bool {
347 if self.current_depth >= self.max_depth {
348 return false;
349 }
350 self.current_depth += 1;
351 true
352 }
353 #[allow(dead_code)]
355 pub fn exit(&mut self) {
356 if self.current_depth > 0 {
357 self.current_depth -= 1;
358 }
359 }
360}
361pub struct MacroExpander {
365 macros: HashMap<String, MacroDef>,
367 next_scope: u64,
369 syntax_defs: Vec<SyntaxDef>,
371 pub(super) max_depth: u32,
373}
374impl MacroExpander {
375 pub fn new() -> Self {
377 Self {
378 macros: HashMap::new(),
379 next_scope: 1,
380 syntax_defs: Vec::new(),
381 max_depth: 128,
382 }
383 }
384 pub fn set_max_depth(&mut self, depth: u32) {
386 self.max_depth = depth;
387 }
388 pub fn fresh_scope(&mut self) -> u64 {
390 let id = self.next_scope;
391 self.next_scope += 1;
392 id
393 }
394 pub fn register_macro(&mut self, def: MacroDef) {
396 self.macros.insert(def.name.clone(), def);
397 }
398 pub fn unregister_macro(&mut self, name: &str) -> Option<MacroDef> {
400 self.macros.remove(name)
401 }
402 pub fn has_macro(&self, name: &str) -> bool {
404 self.macros.contains_key(name)
405 }
406 pub fn get_macro(&self, name: &str) -> Option<&MacroDef> {
408 self.macros.get(name)
409 }
410 pub fn macro_count(&self) -> usize {
412 self.macros.len()
413 }
414 pub fn register_syntax(&mut self, def: SyntaxDef) {
416 self.syntax_defs.push(def);
417 }
418 pub fn syntax_defs_for(&self, kind: &SyntaxKind) -> Vec<&SyntaxDef> {
420 self.syntax_defs
421 .iter()
422 .filter(|d| &d.kind == kind)
423 .collect()
424 }
425 #[allow(clippy::result_large_err)]
430 pub fn expand(&mut self, name: &str, input: &[Token]) -> Result<Vec<Token>, MacroError> {
431 self.expand_with_depth(name, input, 0)
432 }
433 #[allow(clippy::result_large_err)]
435 fn expand_with_depth(
436 &mut self,
437 name: &str,
438 input: &[Token],
439 depth: u32,
440 ) -> Result<Vec<Token>, MacroError> {
441 if depth > self.max_depth {
442 return Err(MacroError::new(
443 MacroErrorKind::ExpansionError,
444 format!(
445 "maximum macro expansion depth ({}) exceeded for '{}'",
446 self.max_depth, name
447 ),
448 ));
449 }
450 let def = self.macros.get(name).cloned().ok_or_else(|| {
451 MacroError::new(
452 MacroErrorKind::UnknownMacro,
453 format!("macro '{}' is not defined", name),
454 )
455 })?;
456 let mut matches = Vec::new();
457 for rule in &def.rules {
458 if let Some(bindings) = try_match_rule(rule, input) {
459 matches.push((rule.clone(), bindings));
460 }
461 }
462 match matches.len() {
463 0 => Err(MacroError::new(
464 MacroErrorKind::PatternMismatch,
465 format!(
466 "no rule of macro '{}' matches the input ({} tokens)",
467 name,
468 input.len()
469 ),
470 )),
471 1 => {
472 let (rule, bindings) = matches
473 .into_iter()
474 .next()
475 .expect("matches.len() == 1 per match arm");
476 let binding_slice: Vec<(String, Vec<Token>)> = bindings;
477 Ok(substitute(&rule.template, &binding_slice))
478 }
479 _ => Err(MacroError::new(
480 MacroErrorKind::AmbiguousMatch,
481 format!(
482 "{} rules of macro '{}' match the input",
483 matches.len(),
484 name
485 ),
486 )),
487 }
488 }
489 pub fn macro_names(&self) -> Vec<&str> {
491 let mut names: Vec<&str> = self.macros.keys().map(|s| s.as_str()).collect();
492 names.sort();
493 names
494 }
495}
496#[allow(dead_code)]
498#[allow(missing_docs)]
499#[derive(Debug, Clone)]
500pub enum MacroExpansionResultExt2 {
501 Success(String),
503 Error(MacroExpansionErrorExt2),
505 NoMatch,
507}
508impl MacroExpansionResultExt2 {
509 #[allow(dead_code)]
511 pub fn is_success(&self) -> bool {
512 matches!(self, MacroExpansionResultExt2::Success(_))
513 }
514 #[allow(dead_code)]
516 pub fn as_str(&self) -> Option<&str> {
517 if let MacroExpansionResultExt2::Success(s) = self {
518 Some(s)
519 } else {
520 None
521 }
522 }
523}
524#[allow(dead_code)]
526#[allow(missing_docs)]
527#[derive(Debug, Clone)]
528pub enum MacroTemplateNodeExt {
529 Literal(String),
531 Var(MacroVarExt),
533 Rep {
535 sep: Option<String>,
536 body: Vec<MacroTemplateNodeExt>,
537 },
538 Group(Vec<MacroTemplateNodeExt>),
540}
541#[allow(dead_code)]
543#[allow(missing_docs)]
544#[derive(Debug, Clone)]
545pub struct MacroSignature {
546 pub name: String,
548 pub param_count: usize,
550}
551impl MacroSignature {
552 #[allow(dead_code)]
554 pub fn new(name: &str, param_count: usize) -> Self {
555 MacroSignature {
556 name: name.to_string(),
557 param_count,
558 }
559 }
560 #[allow(dead_code)]
562 pub fn format(&self) -> String {
563 format!("{}/{}", self.name, self.param_count)
564 }
565}
566#[allow(dead_code)]
568#[allow(missing_docs)]
569#[derive(Debug, Clone)]
570pub struct MacroDefinitionExt {
571 pub name: String,
573 pub params: Vec<String>,
575 pub template: String,
577}
578impl MacroDefinitionExt {
579 #[allow(dead_code)]
581 pub fn new(name: &str, params: Vec<&str>, template: &str) -> Self {
582 MacroDefinitionExt {
583 name: name.to_string(),
584 params: params.into_iter().map(|s| s.to_string()).collect(),
585 template: template.to_string(),
586 }
587 }
588 #[allow(dead_code)]
590 pub fn expand(&self, args: &[&str]) -> String {
591 if args.len() != self.params.len() {
592 return format!("(error: wrong arity for {})", self.name);
593 }
594 let mut env = std::collections::HashMap::new();
595 for (p, a) in self.params.iter().zip(args.iter()) {
596 env.insert(p.clone(), a.to_string());
597 }
598 let nodes = parse_simple_template_ext(&self.template);
599 expand_template_ext(&nodes, &env)
600 }
601}
602#[allow(dead_code)]
604#[allow(missing_docs)]
605#[derive(Debug, Clone, Default)]
606pub struct MacroStatsExt2 {
607 pub attempts: usize,
609 pub successes: usize,
611 pub failures: usize,
613 pub max_depth: usize,
615}
616impl MacroStatsExt2 {
617 #[allow(dead_code)]
619 pub fn record_success(&mut self, depth: usize) {
620 self.attempts += 1;
621 self.successes += 1;
622 if depth > self.max_depth {
623 self.max_depth = depth;
624 }
625 }
626 #[allow(dead_code)]
628 pub fn record_failure(&mut self) {
629 self.attempts += 1;
630 self.failures += 1;
631 }
632 #[allow(dead_code)]
634 pub fn success_rate(&self) -> f64 {
635 if self.attempts == 0 {
636 return 1.0;
637 }
638 self.successes as f64 / self.attempts as f64
639 }
640}
641#[derive(Debug, Clone, PartialEq, Eq, Hash)]
643pub enum SyntaxKind {
644 Term,
646 Command,
648 Tactic,
650 Level,
652 Attr,
654}
655#[allow(dead_code)]
657#[allow(missing_docs)]
658#[derive(Debug, Clone, Default)]
659pub struct HygieneContextExt2 {
660 pub counter: u32,
662 pub prefix: String,
664}
665impl HygieneContextExt2 {
666 #[allow(dead_code)]
668 pub fn new(prefix: &str) -> Self {
669 HygieneContextExt2 {
670 counter: 0,
671 prefix: prefix.to_string(),
672 }
673 }
674 #[allow(dead_code)]
676 pub fn fresh(&mut self) -> String {
677 let name = format!("{}{}", self.prefix, self.counter);
678 self.counter += 1;
679 name
680 }
681 #[allow(dead_code)]
683 pub fn generated_count(&self) -> u32 {
684 self.counter
685 }
686}
687#[derive(Debug, Clone, PartialEq)]
689pub enum MacroToken {
690 Literal(TokenKind),
692 Var(String),
694 Repeat(Vec<MacroToken>),
696 Optional(Vec<MacroToken>),
698 Quote(Vec<MacroToken>),
700 Antiquote(String),
702 SpliceArray(String),
704}
705#[derive(Debug, Clone)]
707pub struct MacroRule {
708 pub pattern: Vec<MacroToken>,
710 pub template: Vec<MacroToken>,
712}
713#[derive(Debug, Clone, PartialEq, Eq)]
718pub struct HygieneInfo {
719 pub scope_id: u64,
721 pub def_site: Span,
723}
724impl HygieneInfo {
725 pub fn new(scope_id: u64, def_site: Span) -> Self {
727 Self { scope_id, def_site }
728 }
729}
730#[derive(Debug, Clone)]
732pub struct SyntaxDef {
733 pub name: String,
735 pub kind: SyntaxKind,
737 pub parser: Vec<SyntaxItem>,
739}
740impl SyntaxDef {
741 pub fn new(name: String, kind: SyntaxKind, parser: Vec<SyntaxItem>) -> Self {
743 Self { name, kind, parser }
744 }
745 pub fn item_count(&self) -> usize {
747 self.parser.len()
748 }
749}
750#[allow(dead_code)]
752#[allow(missing_docs)]
753#[derive(Debug, Default)]
754pub struct MacroStats {
755 pub expansions: usize,
757 pub errors: usize,
759 pub max_depth: usize,
761}
762impl MacroStats {
763 #[allow(dead_code)]
765 pub fn new() -> Self {
766 MacroStats::default()
767 }
768 #[allow(dead_code)]
770 pub fn record_success(&mut self, depth: usize) {
771 self.expansions += 1;
772 if depth > self.max_depth {
773 self.max_depth = depth;
774 }
775 }
776 #[allow(dead_code)]
778 pub fn record_error(&mut self) {
779 self.errors += 1;
780 }
781}
782pub struct MacroParser {
784 tokens: Vec<Token>,
786 pub(super) pos: usize,
788}
789impl MacroParser {
790 pub fn new(tokens: Vec<Token>) -> Self {
792 Self { tokens, pos: 0 }
793 }
794 fn current(&self) -> &Token {
796 self.tokens
797 .get(self.pos)
798 .unwrap_or(&self.tokens[self.tokens.len() - 1])
799 }
800 fn is_eof(&self) -> bool {
802 matches!(self.current().kind, TokenKind::Eof)
803 }
804 fn advance(&mut self) -> Token {
806 let tok = self.current().clone();
807 if !self.is_eof() {
808 self.pos += 1;
809 }
810 tok
811 }
812 pub fn parse_rule(&mut self) -> Result<MacroRule, ParseError> {
814 let pattern = self.parse_macro_tokens()?;
815 if !matches!(self.current().kind, TokenKind::Arrow) {
816 return Err(ParseError::unexpected(
817 vec!["=>".to_string()],
818 self.current().kind.clone(),
819 self.current().span.clone(),
820 ));
821 }
822 self.advance();
823 let template = self.parse_macro_tokens()?;
824 Ok(MacroRule { pattern, template })
825 }
826 pub fn parse_rules(&mut self) -> Result<Vec<MacroRule>, ParseError> {
828 let mut rules = Vec::new();
829 rules.push(self.parse_rule()?);
830 while !self.is_eof() && matches!(self.current().kind, TokenKind::Bar) {
831 self.advance();
832 rules.push(self.parse_rule()?);
833 }
834 Ok(rules)
835 }
836 fn parse_macro_tokens(&mut self) -> Result<Vec<MacroToken>, ParseError> {
838 let mut tokens = Vec::new();
839 while !self.is_eof() && !self.is_delimiter() {
840 tokens.push(self.parse_macro_token()?);
841 }
842 Ok(tokens)
843 }
844 pub(super) fn parse_macro_token(&mut self) -> Result<MacroToken, ParseError> {
846 let tok = self.current();
847 match &tok.kind {
848 TokenKind::Ident(name) if name.starts_with("$[") && name.ends_with("]*") => {
849 let inner = name[2..name.len() - 2].to_string();
850 self.advance();
851 Ok(MacroToken::SpliceArray(inner))
852 }
853 TokenKind::Ident(name) if name.starts_with('$') => {
854 let var_name = name[1..].to_string();
855 self.advance();
856 if var_name.is_empty() && matches!(self.current().kind, TokenKind::LParen) {
857 self.advance();
858 let inner = self.parse_group_tokens()?;
859 if matches!(self.current().kind, TokenKind::RParen) {
860 self.advance();
861 }
862 return match &self.current().kind {
863 TokenKind::Star => {
864 self.advance();
865 Ok(MacroToken::Repeat(inner))
866 }
867 TokenKind::Question => {
868 self.advance();
869 Ok(MacroToken::Optional(inner))
870 }
871 _ => Ok(MacroToken::Repeat(inner)),
872 };
873 }
874 if !var_name.is_empty()
875 && !self.is_eof()
876 && matches!(self.current().kind, TokenKind::LBracket)
877 && self.pos + 2 < self.tokens.len()
878 && matches!(self.tokens[self.pos + 1].kind, TokenKind::RBracket)
879 && matches!(self.tokens[self.pos + 2].kind, TokenKind::Star)
880 {
881 self.advance();
882 self.advance();
883 self.advance();
884 return Ok(MacroToken::SpliceArray(var_name));
885 }
886 Ok(MacroToken::Var(var_name))
887 }
888 TokenKind::Ident(name) if name == "`" => {
889 self.advance();
890 if matches!(self.current().kind, TokenKind::LParen) {
891 self.advance();
892 let inner = self.parse_quoted_tokens()?;
893 if matches!(self.current().kind, TokenKind::RParen) {
894 self.advance();
895 }
896 Ok(MacroToken::Quote(inner))
897 } else {
898 Ok(MacroToken::Literal(TokenKind::Ident("`".to_string())))
899 }
900 }
901 TokenKind::Star => {
902 let kind = tok.kind.clone();
903 self.advance();
904 Ok(MacroToken::Literal(kind))
905 }
906 TokenKind::LParen => {
907 let kind = tok.kind.clone();
908 self.advance();
909 Ok(MacroToken::Literal(kind))
910 }
911 _ => {
912 let kind = tok.kind.clone();
913 self.advance();
914 Ok(MacroToken::Literal(kind))
915 }
916 }
917 }
918 fn parse_group_tokens(&mut self) -> Result<Vec<MacroToken>, ParseError> {
922 let mut tokens = Vec::new();
923 let mut depth = 1u32;
924 while !self.is_eof() {
925 match &self.current().kind {
926 TokenKind::LParen => {
927 depth += 1;
928 let kind = self.current().kind.clone();
929 self.advance();
930 tokens.push(MacroToken::Literal(kind));
931 }
932 TokenKind::RParen => {
933 depth -= 1;
934 if depth == 0 {
935 break;
936 }
937 let kind = self.current().kind.clone();
938 self.advance();
939 tokens.push(MacroToken::Literal(kind));
940 }
941 _ => {
942 tokens.push(self.parse_macro_token()?);
943 }
944 }
945 }
946 Ok(tokens)
947 }
948 fn parse_quoted_tokens(&mut self) -> Result<Vec<MacroToken>, ParseError> {
950 let mut tokens = Vec::new();
951 let mut depth = 1u32;
952 while !self.is_eof() {
953 if matches!(self.current().kind, TokenKind::LParen) {
954 depth += 1;
955 } else if matches!(self.current().kind, TokenKind::RParen) {
956 depth -= 1;
957 if depth == 0 {
958 break;
959 }
960 }
961 tokens.push(self.parse_macro_token()?);
962 }
963 Ok(tokens)
964 }
965 fn is_delimiter(&self) -> bool {
967 matches!(
968 self.current().kind,
969 TokenKind::Arrow | TokenKind::Semicolon | TokenKind::RParen | TokenKind::Bar
970 )
971 }
972}
973#[allow(dead_code)]
975#[allow(missing_docs)]
976pub struct DepthLimitedExpander {
977 pub max_depth: usize,
979 pub current_depth: usize,
981}
982impl DepthLimitedExpander {
983 #[allow(dead_code)]
985 pub fn new(max_depth: usize) -> Self {
986 DepthLimitedExpander {
987 max_depth,
988 current_depth: 0,
989 }
990 }
991 #[allow(dead_code)]
993 pub fn try_expand(&mut self) -> bool {
994 if self.current_depth >= self.max_depth {
995 return false;
996 }
997 self.current_depth += 1;
998 true
999 }
1000 #[allow(dead_code)]
1002 pub fn exit(&mut self) {
1003 if self.current_depth > 0 {
1004 self.current_depth -= 1;
1005 }
1006 }
1007}
1008#[allow(dead_code)]
1010#[allow(missing_docs)]
1011#[derive(Debug, Clone)]
1012pub struct HygieneContext {
1013 pub depth: usize,
1015 pub tag: u64,
1017}
1018impl HygieneContext {
1019 #[allow(dead_code)]
1021 pub fn new(tag: u64) -> Self {
1022 HygieneContext { depth: 0, tag }
1023 }
1024 #[allow(dead_code)]
1026 pub fn nested(&self) -> Self {
1027 HygieneContext {
1028 depth: self.depth + 1,
1029 tag: self.tag,
1030 }
1031 }
1032 #[allow(dead_code)]
1034 pub fn hygienic_name(&self, name: &str) -> String {
1035 format!("{}__{}_{}", name, self.tag, self.depth)
1036 }
1037}
1038#[allow(dead_code)]
1040#[allow(missing_docs)]
1041#[derive(Debug, Clone)]
1042pub struct MacroCallSiteExt {
1043 pub macro_name: String,
1045 pub args: Vec<String>,
1047 pub offset: usize,
1049}
1050impl MacroCallSiteExt {
1051 #[allow(dead_code)]
1053 pub fn new(macro_name: &str, args: Vec<&str>, offset: usize) -> Self {
1054 MacroCallSiteExt {
1055 macro_name: macro_name.to_string(),
1056 args: args.into_iter().map(|s| s.to_string()).collect(),
1057 offset,
1058 }
1059 }
1060}
1061#[derive(Debug, Clone)]
1063pub struct MacroError {
1064 pub kind: MacroErrorKind,
1066 pub span: Option<Span>,
1068 pub message: String,
1070}
1071impl MacroError {
1072 pub fn new(kind: MacroErrorKind, message: String) -> Self {
1074 Self {
1075 kind,
1076 span: None,
1077 message,
1078 }
1079 }
1080 pub fn with_span(mut self, span: Span) -> Self {
1082 self.span = Some(span);
1083 self
1084 }
1085}
1086#[allow(dead_code)]
1088#[allow(missing_docs)]
1089pub struct MacroEnvironmentExt {
1090 pub macros: Vec<MacroDefinitionExt>,
1092}
1093impl MacroEnvironmentExt {
1094 #[allow(dead_code)]
1096 pub fn new() -> Self {
1097 MacroEnvironmentExt { macros: Vec::new() }
1098 }
1099 #[allow(dead_code)]
1101 pub fn define(&mut self, def: MacroDefinitionExt) {
1102 self.macros.push(def);
1103 }
1104 #[allow(dead_code)]
1106 pub fn find(&self, name: &str) -> Option<&MacroDefinitionExt> {
1107 self.macros.iter().find(|m| m.name == name)
1108 }
1109 #[allow(dead_code)]
1111 pub fn expand_call(&self, name: &str, args: &[&str]) -> Option<String> {
1112 self.find(name).map(|m| m.expand(args))
1113 }
1114 #[allow(dead_code)]
1116 pub fn len(&self) -> usize {
1117 self.macros.len()
1118 }
1119 #[allow(dead_code)]
1121 pub fn is_empty(&self) -> bool {
1122 self.macros.is_empty()
1123 }
1124}