Skip to content

Commit

Permalink
factor inline macros into a struct
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikalii committed Nov 19, 2024
1 parent 925b5d3 commit d55886c
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 38 deletions.
21 changes: 15 additions & 6 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,15 @@ pub struct Comments {
pub semantic: HashMap<SemanticComment, CodeSpan>,
}

/// An inline macro
#[derive(Clone, PartialEq)]
pub struct InlineMacro {
/// The function
pub func: Sp<Func>,
/// The identifier, which consists of only exclamation marks
pub ident: Sp<Ident>,
}

/// A word
#[derive(Clone)]
#[allow(missing_docs)]
Expand Down Expand Up @@ -284,7 +293,7 @@ pub enum Word {
n: usize,
},
Subscript(Box<Subscript>),
InlineMacro(Sp<Ident>, Sp<Func>),
InlineMacro(InlineMacro),
}

impl PartialEq for Word {
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -572,15 +581,15 @@ pub enum Modifier {
/// A user-defined modifier
Ref(Ref),
/// An inline macro
Macro(Sp<Ident>, Sp<Func>),
Macro(InlineMacro),
}

impl fmt::Debug for Modifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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),
}
}
}
Expand All @@ -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"),
Expand All @@ -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),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.\
Expand Down
22 changes: 12 additions & 10 deletions src/compile/modifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};

Expand Down Expand Up @@ -913,24 +913,26 @@ impl Compiler {
// Compile an inline macro
fn inline_macro(
&mut self,
func: Sp<Func>,
ident: Sp<Ident>,
mac: InlineMacro,
span: CodeSpan,
operands: Vec<Sp<Word>>,
) -> UiuaResult<Node> {
self.experimental_error(&span, || {
"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
Expand Down
17 changes: 9 additions & 8 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::{
};

use paste::paste;
use InlineMacro;

use crate::{
ast::*,
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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)))
Expand All @@ -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))
})
}
Expand Down
21 changes: 11 additions & 10 deletions src/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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)));
}
Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
};
Expand Down Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit d55886c

Please sign in to comment.