diff --git a/src/ast.rs b/src/ast.rs index 65c72e638..c6e365c82 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -251,6 +251,15 @@ pub struct Comments { pub semantic: HashMap, } +/// An inline macro +#[derive(Clone, PartialEq)] +pub struct InlineMacro { + /// The function + pub func: Sp, + /// The identifier, which consists of only exclamation marks + pub ident: Sp, +} + /// A word #[derive(Clone)] #[allow(missing_docs)] @@ -284,7 +293,7 @@ pub enum Word { n: usize, }, Subscript(Box), - InlineMacro(Sp, Sp), + InlineMacro(InlineMacro), } impl PartialEq for Word { @@ -405,7 +414,7 @@ impl fmt::Debug for Word { Word::SemanticComment(comment) => write!(f, "{comment}"), Word::OutputComment { i, n, .. } => write!(f, "output_comment({i}/{n})"), Word::Subscript(sub) => sub.fmt(f), - Word::InlineMacro(ident, func) => { + Word::InlineMacro(InlineMacro { ident, func }) => { write!(f, "func_macro({:?}{}))", func.value, ident.value) } } @@ -572,7 +581,7 @@ pub enum Modifier { /// A user-defined modifier Ref(Ref), /// An inline macro - Macro(Sp, Sp), + Macro(InlineMacro), } impl fmt::Debug for Modifier { @@ -580,7 +589,7 @@ impl fmt::Debug for Modifier { match self { Modifier::Primitive(prim) => prim.fmt(f), Modifier::Ref(refer) => write!(f, "ref({refer:?})"), - Modifier::Macro(_, func) => write!(f, "macro({func:?})"), + Modifier::Macro(mac) => write!(f, "macro({:?})", mac.func), } } } @@ -590,7 +599,7 @@ impl fmt::Display for Modifier { match self { Modifier::Primitive(prim) => prim.format().fmt(f), Modifier::Ref(refer) => write!(f, "{refer}"), - Modifier::Macro(ident, _) => match ident_modifier_args(&ident.value) { + Modifier::Macro(mac) => match ident_modifier_args(&mac.ident.value) { 0 | 1 => write!(f, "monadic inline macro"), 2 => write!(f, "dyadic inline macro"), 3 => write!(f, "triadic inline macro"), @@ -607,7 +616,7 @@ impl Modifier { match self { Modifier::Primitive(prim) => prim.modifier_args().unwrap_or(0), Modifier::Ref(r) => r.modifier_args(), - Modifier::Macro(ident, _) => ident_modifier_args(&ident.value), + Modifier::Macro(mac) => ident_modifier_args(&mac.ident.value), } } } diff --git a/src/compile/mod.rs b/src/compile/mod.rs index e17ad6e82..245cee37d 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -1288,7 +1288,7 @@ code: Word::OutputComment { i, n } => Node::SetOutputComment { i, n }, Word::Subscript(sub) => self.subscript(*sub, word.span)?, Word::Comment(_) | Word::Spaces | Word::BreakLine | Word::FlipLine => Node::empty(), - Word::InlineMacro(..) => { + Word::InlineMacro(_) => { self.add_error( word.span.clone(), "Inline macro was not parsed as a modifier.\ diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs index 4f321d1eb..537d225a5 100644 --- a/src/compile/modifier.rs +++ b/src/compile/modifier.rs @@ -357,8 +357,8 @@ impl Compiler { Modifier::Ref(r) => { return self.modifier_ref(r, modified.modifier.span, modified.operands) } - Modifier::Macro(ident, func) => { - return self.inline_macro(func, ident, modified.modifier.span, modified.operands); + Modifier::Macro(mac) => { + return self.inline_macro(mac, modified.modifier.span, modified.operands); } }; @@ -913,8 +913,7 @@ impl Compiler { // Compile an inline macro fn inline_macro( &mut self, - func: Sp, - ident: Sp, + mac: InlineMacro, span: CodeSpan, operands: Vec>, ) -> UiuaResult { @@ -922,15 +921,18 @@ impl Compiler { "Inline macros are experimental. \ To use them, add `# Experimental!` to the top of the file." }); - let mut words: Vec<_> = - flip_unsplit_lines(func.value.lines.into_iter().flat_map(split_words).collect()) - .into_iter() - .flatten() - .collect(); + let mut words: Vec<_> = flip_unsplit_lines( + (mac.func.value.lines.into_iter()) + .flat_map(split_words) + .collect(), + ) + .into_iter() + .flatten() + .collect(); // Track self.code_meta .inline_macros - .insert(func.span, ident_modifier_args(&ident.value)); + .insert(mac.func.span, ident_modifier_args(&mac.ident.value)); // Expand self.expand_index_macro(None, &mut words, operands, span.clone(), true)?; // Compile diff --git a/src/format.rs b/src/format.rs index 9c62c354d..f423ae569 100644 --- a/src/format.rs +++ b/src/format.rs @@ -12,6 +12,7 @@ use std::{ }; use paste::paste; +use InlineMacro; use crate::{ ast::*, @@ -1277,7 +1278,7 @@ impl<'a> Formatter<'a> { } self.push(&word.span, &s); } - Word::InlineMacro(ident, func) => { + Word::InlineMacro(InlineMacro { ident, func }) => { self.func(&func.value, depth); self.push(&ident.span, &ident.value); } @@ -1357,9 +1358,9 @@ impl<'a> Formatter<'a> { match &modifier.value { Modifier::Primitive(prim) => self.push(&modifier.span, &prim.to_string()), Modifier::Ref(r) => self.format_ref(r), - Modifier::Macro(ident, func) => { - self.func(&func.value, depth); - self.push(&ident.span, &ident.value); + Modifier::Macro(mac) => { + self.func(&mac.func.value, depth); + self.push(&mac.ident.span, &mac.ident.value); } } } @@ -1460,7 +1461,7 @@ pub(crate) fn word_is_multiline(word: &Word) -> bool { || (func.lines.iter()) .any(|words| words.iter().any(|word| word_is_multiline(&word.value))) } - Word::InlineMacro(_, func) => { + Word::InlineMacro(InlineMacro { func, .. }) => { func.value.lines.len() > 1 || (func.value.lines.iter()) .any(|words| words.iter().any(|word| word_is_multiline(&word.value))) @@ -1474,9 +1475,9 @@ pub(crate) fn word_is_multiline(word: &Word) -> bool { Word::Modified(m) => { m.operands.iter().any(|word| word_is_multiline(&word.value)) || match &m.modifier.value { - Modifier::Macro(_, func) => { - func.value.lines.len() > 1 - || (func.value.lines.iter()).any(|words| { + Modifier::Macro(mac) => { + mac.func.value.lines.len() > 1 + || (mac.func.value.lines.iter()).any(|words| { words.iter().any(|word| word_is_multiline(&word.value)) }) } diff --git a/src/lsp.rs b/src/lsp.rs index c8eab500d..3252d98b8 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -10,7 +10,7 @@ use std::{ }; use crate::{ - ast::{Func, Item, Modifier, ModuleKind, Ref, RefComponent, Word}, + ast::{Func, InlineMacro, Item, Modifier, ModuleKind, Ref, RefComponent, Word}, ident_modifier_args, is_custom_glyph, lex::{CodeSpan, Sp}, parse::parse, @@ -650,10 +650,10 @@ impl Spanner { spans.push((m.modifier.span.clone()).sp(SpanKind::Primitive(*p, None))) } Modifier::Ref(r) => spans.extend(self.ref_spans(r)), - Modifier::Macro(ident, func) => { - spans.extend(self.func_spans(&func.value, &func.span)); - let ident_span = (ident.span.clone()) - .sp(SpanKind::MacroDelim(ident_modifier_args(&ident.value))); + Modifier::Macro(mac) => { + spans.extend(self.func_spans(&mac.func.value, &mac.func.span)); + let ident_span = (mac.ident.span.clone()) + .sp(SpanKind::MacroDelim(ident_modifier_args(&mac.ident.value))); spans.push(ident_span); } } @@ -688,10 +688,11 @@ impl Spanner { spans.extend(self.ref_spans(r)); spans.push(sub.n.clone().map(|n| SpanKind::Subscript(None, n))); } - Modifier::Macro(ident, func) => { - spans.extend(self.func_spans(&func.value, &func.span)); - let ident_span = (ident.span.clone()) - .sp(SpanKind::MacroDelim(ident_modifier_args(&ident.value))); + Modifier::Macro(mac) => { + spans.extend(self.func_spans(&mac.func.value, &mac.func.span)); + let ident_span = (mac.ident.span.clone()).sp(SpanKind::MacroDelim( + ident_modifier_args(&mac.ident.value), + )); spans.push(ident_span); spans.push(sub.n.clone().map(|n| SpanKind::Subscript(None, n))); } @@ -708,7 +709,7 @@ impl Spanner { spans.push(sub.n.clone().map(|n| SpanKind::Subscript(None, n))); } }, - Word::InlineMacro(ident, func) => { + Word::InlineMacro(InlineMacro { ident, func }) => { let ident_span = (ident.span.clone()) .sp(SpanKind::MacroDelim(ident_modifier_args(&ident.value))); spans.push(ident_span); diff --git a/src/parse.rs b/src/parse.rs index fbfdada14..8e69a63e2 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -945,7 +945,7 @@ impl<'i> Parser<'i> { } (Modifier::Ref(item), term.span) } - Word::InlineMacro(ident, func) => (Modifier::Macro(ident, func), term.span), + Word::InlineMacro(mac) => (Modifier::Macro(mac), term.span), _ => return Some(term), } }; @@ -1258,7 +1258,7 @@ impl<'i> Parser<'i> { { let func = outer_span.clone().sp(func); outer_span = outer_span.merge(ident.span.clone()); - outer_span.sp(Word::InlineMacro(ident, func)) + outer_span.sp(Word::InlineMacro(InlineMacro { ident, func })) } else { self.index = reset; outer_span.sp(Word::Func(func)) diff --git a/todo.md b/todo.md index 5938d2d69..0d11cd6cf 100644 --- a/todo.md +++ b/todo.md @@ -3,7 +3,7 @@ ## 0.14 The next version of Uiua -- Stabilize `sort`, `last`, `backward`, `case` +- Stabilize `last`, `backward`, `case` - Optimize `group`/`partition` reduction replacement - Compile-time code string evaluation - `do` function pack