summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Schmidt <kaikaliischmidt@gmail.com>2024-09-27 09:27:57 -0700
committerKai Schmidt <kaikaliischmidt@gmail.com>2024-09-27 09:27:57 -0700
commita97e2075e609c198734c6a790f3aeaae923406c8 (patch)
treea3a01c3465f918525d8473ea682027876126f0ba
parent6e5989cfa5a4f7ecdf0034b1b2426ae67ee4b108 (diff)
rename positional/array macros to index/code
-rw-r--r--changelog.md5
-rw-r--r--site/text/macros.md33
-rw-r--r--src/assembly.rs16
-rw-r--r--src/ast.rs4
-rw-r--r--src/compile/binding.rs26
-rw-r--r--src/compile/mod.rs39
-rw-r--r--src/compile/modifier.rs20
-rw-r--r--src/format.rs2
-rw-r--r--src/lsp.rs8
-rw-r--r--src/parse.rs2
-rw-r--r--src/primitive/defs.rs4
-rw-r--r--src/run.rs8
-rw-r--r--tests/macros.ua4
13 files changed, 84 insertions, 87 deletions
diff --git a/changelog.md b/changelog.md
index 6813343d..31c0a92a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -9,7 +9,7 @@ This version is not yet released. If you are reading this on the website, then t
- This makes them consistent with comparison functions like [`less than <`](https://uiua.org/docs/less%20than)
- **Breaking Change** - [`gen`](https://uiua.org/docs/gen) now takes a shape argument
- The experimental `chunks ⑄` function's behavior has been moved to an extension on [`windows ◫`](https://uiua.org/docs/windows)
- - This also allow the specification of "stride"
+ - This also allows the specification of "stride"
- This is inspired by APL's `stencil ⌺` behavior
- `chunks ⑄` has been deprecated
- Stabilize [`orient ⤸`](https://uiua.org/docs/orient)
@@ -18,6 +18,9 @@ This version is not yet released. If you are reading this on the website, then t
- Stabilize [`below ◡`](https://uiua.org/docs/below)
- Rename `⤙ but` and `⤚ with` to [`with ⤙`](https://uiua.org/docs/with) and [`off ⤚`](https://uiua.org/docs/off)
- [`with ⤙`](https://uiua.org/docs/with) has been stabilized
+- "Stack macros" are now called "index macros"
+ - Stabilize existing placeholder indexing syntax (`^0`, `^1`, etc.)
+ - Deprecate existing stack-based macro placeholders (`^!`, `^.`, etc.)
- [`fold ∧`](https://uiua.org/docs/fold) now works with any signature
- Excess values are collected into arrays
- [`un °`](https://uiua.org/docs/un) [`orient ⤸`](https://uiua.org/docs/orient) is now equivalent to [`range ⇡`](https://uiua.org/docs/range) [`length ⧻`](https://uiua.org/docs/length) [`shape △`](https://uiua.org/docs/shape) [`duplicate .`](https://uiua.org/docs/duplicate)
diff --git a/site/text/macros.md b/site/text/macros.md
index f14cabf6..4cfb830b 100644
--- a/site/text/macros.md
+++ b/site/text/macros.md
@@ -1,6 +1,3 @@
-Here is your HTML-like Rust macro syntax converted to Markdown following your rules:
-
-```markdown
# Macros
Defining your own functions that work on arrays is pretty easy. Just a name, a `←`, and you're done.
@@ -17,7 +14,7 @@ Macros work similarly to modifiers. They take some function arguments and modify
The number that comes after a `^` is the index of the function argument passed to the macro.
-Lets look at a simple example using [reduce](). It reduces a function over the numbers up to the given range.
+Let's look at a simple example using [reduce](). It reduces a function over the numbers up to the given range.
```uiua
ReduceRange! ← /^0+1⇡
@@ -51,12 +48,12 @@ F‼(+1|⊂0) 1
```
## Two Kinds of Macros
-The macros described so far are called *positional macros*, because arguments are referenced directly by their position when the macro is called.
+The macros described so far are called *index macros*, because arguments are referenced directly by their position when the macro is called.
-But Uiua actually has a second kind of macro. *Array macros* put their operands in an array. The array can then be arbitrarily manipulated with normal Uiua code.
+But Uiua actually has a second kind of macro. *Code macros* put their operands in an array. The array can then be arbitrarily manipulated with normal Uiua code.
-## Array Macros
-Array macros are defined by putting a `^` right after the binding's `←`. Array macro names must still end in some number of `!`s.
+## Code Macros
+Code macros are defined by putting a `^` right after the binding's `←`. Code macro names must still end in some number of `!`s.
Here is a basic example that simply prints its operands. It returns the number `5` as the actual generated code.
@@ -67,14 +64,14 @@ F‼⊂(+1)
As you can see, the operands are passed to the function as an array of boxed strings.
-Array macros may be passed a function pack operand. Each operand from the pack will be put in the array.
+Code macros may be passed a function pack operand. Each operand from the pack will be put in the array.
```uiua
F! ←^ $"_"
F!(+|-|×|÷)
```
-The array macro's function must return either a string or an array of boxed strings. This value will be converted back to Uiua code and compiled as normal.
+The code macro's function must return either a string or an array of boxed strings. This value will be converted back to Uiua code and compiled as normal.
Format strings can help a lot in generating new code. For example, if we wanted to make a version of [both]() that calls its function on an arbitrary number of sets of values, we could use [reshape]() and [bracket]().
@@ -89,7 +86,7 @@ We use [reduce]() with a format string to form the branches of a function pack,
The resulting string is then compiled as Uiua code.
-Array macros have the ability to create new bindings, including new macros.
+Code macros have the ability to create new bindings, including new macros.
```uiua
Def‼ ←^ $"_\n_" ⊃(/$"_ ← _"|/$"Also_ ← _")
@@ -100,9 +97,9 @@ Def‼(X|5)
This is a simple example, but this concept can be used to create very powerful meta-programming tools.
## Compile Time vs Run Time
-The body of an array macro is always evaluated at compile time. One consequence of this is that bindings whose values cannot be known at compile time cannot be used in an array macro.
+The body of a code macro is always evaluated at compile time. One consequence of this is that bindings whose values cannot be known at compile time cannot be used in a code macro.
-For example, because the value `5` is always the same, it is always known at compile time, and we can use a name that binds `5` in an array macro.
+For example, because the value `5` is always the same, it is always known at compile time, and we can use a name that binds `5` in a code macro.
```uiua
x ← 5
@@ -136,11 +133,11 @@ F!¯
## What kind of macro should I use?
Which kind of macro you use depends on what kind of code you are writing.
-Array macros are much more powerful than positional macros, but they can be more complicated to write.
+Code macros are much more powerful than index macros, but they can be more complicated to write.
-Additionally, positional macros are [hygienic](https://en.wikipedia.org/wiki/hygienic_macro). When a positional macro refers to names of things, bindings you have defined in the surrounding code will not interfere; you will never accidentally use the wrong binding. Array macros make no such guarantees.
+Additionally, index macros are [hygienic](https://en.wikipedia.org/wiki/hygienic_macro). When an index macro refers to names of things, bindings you have defined in the surrounding code will not interfere; you will never accidentally use the wrong binding. Code macros make no such guarantees.
-If you conceptually just want to define your own modifier, a positional macro is probably the simplest way to go.
+If you conceptually just want to define your own modifier, an index macro is probably the simplest way to go.
+
+If you want the full power (and all the complexity) of compile-time meta-programming, you'll need to use a code macro.
-If you want the full power (and all the complexity) of compile-time meta-programming, you'll need to use an array macro.
-```
diff --git a/src/assembly.rs b/src/assembly.rs
index e902a14d..45ded052 100644
--- a/src/assembly.rs
+++ b/src/assembly.rs
@@ -118,7 +118,7 @@ impl Assembly {
pub fn remove_dead_code(&mut self) {
let mut slices = Vec::new();
self.bindings.retain(|binding| {
- if let BindingKind::ArrayMacro(mut slice) = binding.kind {
+ if let BindingKind::CodeMacro(mut slice) = binding.kind {
if slice.start > 0 {
if let Some((Instr::Comment(before), Instr::Comment(after))) = self
.instrs
@@ -161,7 +161,7 @@ impl Assembly {
func.slice.start -= removed.len();
}
}
- BindingKind::ArrayMacro(slice) => {
+ BindingKind::CodeMacro(slice) => {
if slice.start > removed.start {
slice.start -= removed.len();
slice.len -= removed.len();
@@ -422,12 +422,12 @@ pub enum BindingKind {
Import(PathBuf),
/// A scoped module
Module(Module),
- /// A positional macro
+ /// An index macro
///
/// Contains the number of arguments
- PosMacro(usize),
- /// An array macro
- ArrayMacro(FuncSlice),
+ IndexMacro(usize),
+ /// A code macro
+ CodeMacro(FuncSlice),
}
impl BindingKind {
@@ -438,8 +438,8 @@ impl BindingKind {
Self::Func(func) => Some(func.signature()),
Self::Import { .. } => None,
Self::Module(_) => None,
- Self::PosMacro(_) => None,
- Self::ArrayMacro(_) => None,
+ Self::IndexMacro(_) => None,
+ Self::CodeMacro(_) => None,
}
}
/// Check if the global is a once-bound constant
diff --git a/src/ast.rs b/src/ast.rs
index 41a35fe1..1750a86b 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -32,8 +32,8 @@ pub struct Binding {
pub arrow_span: CodeSpan,
/// Whether the binding is public
pub public: bool,
- /// Whether the binding is an array macro
- pub array_macro: bool,
+ /// Whether the binding is a code macro
+ pub code_macro: bool,
/// The signature
pub signature: Option<Sp<Signature>>,
/// The code
diff --git a/src/compile/binding.rs b/src/compile/binding.rs
index c62dbc44..ae970eb8 100644
--- a/src/compile/binding.rs
+++ b/src/compile/binding.rs
@@ -50,18 +50,18 @@ impl Compiler {
// Handle macro
let ident_margs = ident_modifier_args(&name);
let placeholder_count = count_placeholders(&binding.words);
- if binding.array_macro {
+ if binding.code_macro {
if placeholder_count > 0 {
return Err(
- self.fatal_error(span.clone(), "Array macros may not contain placeholders")
+ self.fatal_error(span.clone(), "Code macros may not contain placeholders")
);
}
- // Array macro
+ // Code macro
if ident_margs == 0 {
self.add_error(
span.clone(),
format!(
- "Array macros must take at least 1 operand, \
+ "Code macros must take at least 1 operand, \
but `{name}`'s name suggests it takes 0",
),
);
@@ -74,7 +74,7 @@ impl Compiler {
self.add_error(
span.clone(),
format!(
- "Array macro signature mismatch: \
+ "Code macro signature mismatch: \
declared {} but inferred {s}",
declared.value
),
@@ -89,7 +89,7 @@ impl Compiler {
} else {
self.add_error(
span.clone(),
- format!("Cannot infer array macro signature: {e}"),
+ format!("Cannot infer code macro signature: {e}"),
);
Signature::new(1, 1)
}
@@ -104,7 +104,7 @@ impl Compiler {
self.add_error(
span.clone(),
format!(
- "Array macros must have a signature of {} or {}, \
+ "Code macros must have a signature of {} or {}, \
but a signature of {} was inferred",
Signature::new(1, 1),
Signature::new(2, 1),
@@ -116,15 +116,15 @@ impl Compiler {
self.scope.names.insert(name.clone(), local);
self.asm.add_binding_at(
local,
- BindingKind::ArrayMacro(function.slice),
+ BindingKind::CodeMacro(function.slice),
Some(span.clone()),
comment.map(|text| DocComment::from(text.as_str())),
);
- let mac = ArrayMacro {
+ let mac = CodeMacro {
function,
names: self.scope.names.clone(),
};
- self.array_macros.insert(local.index, mac);
+ self.code_macros.insert(local.index, mac);
return Ok(());
}
// Positional macro
@@ -154,7 +154,7 @@ impl Compiler {
self.scope.names.insert(name.clone(), local);
self.asm.add_binding_at(
local,
- BindingKind::PosMacro(ident_margs),
+ BindingKind::IndexMacro(ident_margs),
Some(span.clone()),
comment.map(|text| DocComment::from(text.as_str())),
);
@@ -220,14 +220,14 @@ impl Compiler {
);
}
}
- let mac = PosMacro {
+ let mac = IndexMacro {
words,
names: self.scope.names.clone(),
hygenic: true,
sig: binding.signature.map(|s| s.value),
recursive,
};
- self.positional_macros.insert(local.index, mac);
+ self.index_macros.insert(local.index, mac);
return Ok(());
}
diff --git a/src/compile/mod.rs b/src/compile/mod.rs
index cccc7590..5c28272f 100644
--- a/src/compile/mod.rs
+++ b/src/compile/mod.rs
@@ -62,10 +62,10 @@ pub struct Compiler {
current_imports: Vec<PathBuf>,
/// The bindings of imported files
imports: HashMap<PathBuf, Module>,
- /// Unexpanded positional macros
- positional_macros: HashMap<usize, PosMacro>,
- /// Unexpanded array macros
- array_macros: HashMap<usize, ArrayMacro>,
+ /// Unexpanded index macros
+ index_macros: HashMap<usize, IndexMacro>,
+ /// Unexpanded code macros
+ code_macros: HashMap<usize, CodeMacro>,
/// The depth of macro expansion
macro_depth: usize,
/// Whether the compiler is in an inverse
@@ -103,8 +103,8 @@ impl Default for Compiler {
mode: RunMode::All,
current_imports: Vec::new(),
imports: HashMap::new(),
- positional_macros: HashMap::new(),
- array_macros: HashMap::new(),
+ index_macros: HashMap::new(),
+ code_macros: HashMap::new(),
macro_depth: 0,
in_inverse: false,
in_test: false,
@@ -164,9 +164,9 @@ pub struct Module {
experimental: bool,
}
-/// A positional macro
+/// An index macro
#[derive(Clone)]
-struct PosMacro {
+struct IndexMacro {
words: Vec<Sp<Word>>,
names: IndexMap<Ident, LocalName>,
sig: Option<Signature>,
@@ -174,9 +174,9 @@ struct PosMacro {
recursive: bool,
}
-/// An array macro
+/// A code macro
#[derive(Clone)]
-struct ArrayMacro {
+struct CodeMacro {
function: Function,
names: IndexMap<Ident, LocalName>,
}
@@ -1597,19 +1597,16 @@ code:
format!("`{}` is a constant, not a module", first.module.value),
))
}
- BindingKind::PosMacro(_) => {
+ BindingKind::IndexMacro(_) => {
return Err(self.fatal_error(
first.module.span.clone(),
- format!(
- "`{}` is a positional macro, not a module",
- first.module.value
- ),
+ format!("`{}` is an index macro, not a module", first.module.value),
))
}
- BindingKind::ArrayMacro(_) => {
+ BindingKind::CodeMacro(_) => {
return Err(self.fatal_error(
first.module.span.clone(),
- format!("`{}` is an array macro, not a module", first.module.value),
+ format!("`{}` is a code macro, not a module", first.module.value),
))
}
};
@@ -1641,7 +1638,7 @@ code:
format!("`{}` is a constant, not a module", comp.module.value),
))
}
- BindingKind::PosMacro(_) => {
+ BindingKind::IndexMacro(_) => {
return Err(self.fatal_error(
comp.module.span.clone(),
format!(
@@ -1650,10 +1647,10 @@ code:
),
))
}
- BindingKind::ArrayMacro(_) => {
+ BindingKind::CodeMacro(_) => {
return Err(self.fatal_error(
comp.module.span.clone(),
- format!("`{}` is an array macro, not a module", comp.module.value),
+ format!("`{}` is a code macro, not a module", comp.module.value),
))
}
};
@@ -1799,7 +1796,7 @@ code:
self.add_error(span, "Cannot import module item here.");
}
}
- BindingKind::PosMacro(_) | BindingKind::ArrayMacro(_) => {
+ BindingKind::IndexMacro(_) | BindingKind::CodeMacro(_) => {
// We could error here, but it's easier to handle it higher up
}
}
diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs
index 8548c968..43b43ea9 100644
--- a/src/compile/modifier.rs
+++ b/src/compile/modifier.rs
@@ -159,7 +159,7 @@ impl Compiler {
m => {
if let Modifier::Ref(name) = m {
if let Ok((_, local)) = self.ref_local(name) {
- if self.array_macros.contains_key(&local.index) {
+ if self.code_macros.contains_key(&local.index) {
return Ok(false);
}
}
@@ -214,7 +214,7 @@ impl Compiler {
Modifier::Primitive(_) => true,
Modifier::Ref(name) => {
let (_, local) = self.ref_local(name)?;
- self.positional_macros.contains_key(&local.index)
+ self.index_macros.contains_key(&local.index)
}
};
if strict_args {
@@ -258,8 +258,8 @@ impl Compiler {
self.fatal_error(modified.modifier.span.clone(), "Macro recurs too deep")
);
}
- if let Some(mut mac) = self.positional_macros.get(&local.index).cloned() {
- // Positional macros
+ if let Some(mut mac) = self.index_macros.get(&local.index).cloned() {
+ // Index macros
match self.scope.kind {
ScopeKind::Temp(Some(mac_local))
if mac_local.macro_index == local.index =>
@@ -298,7 +298,7 @@ impl Compiler {
index: expansion_index,
public: false,
},
- BindingKind::PosMacro(count),
+ BindingKind::IndexMacro(count),
Some(modified.modifier.span.clone()),
None,
);
@@ -335,8 +335,8 @@ impl Compiler {
}
}
}
- } else if let Some(mac) = self.array_macros.get(&local.index).cloned() {
- // Array macros
+ } else if let Some(mac) = self.code_macros.get(&local.index).cloned() {
+ // Code macros
let full_span = (modified.modifier.span.clone())
.merge(modified.operands.last().unwrap().span.clone());
@@ -1769,9 +1769,9 @@ impl Compiler {
let args_macro_index = self.next_global;
self.next_global += 1;
let span = &operand.span;
- self.positional_macros.insert(
+ self.index_macros.insert(
args_macro_index,
- PosMacro {
+ IndexMacro {
words: vec![span.clone().sp(Word::Modified(Box::new(Modified {
modifier: span.clone().sp(Modifier::Primitive(Primitive::Fill)),
operands: vec![
@@ -1796,7 +1796,7 @@ impl Compiler {
self.scope.names.insert("Args!".into(), local);
self.asm.add_binding_at(
local,
- BindingKind::PosMacro(1),
+ BindingKind::IndexMacro(1),
None,
Some(DocComment::from(format!(
"Take {} argument{} and bind {} to {} field name{}",
diff --git a/src/format.rs b/src/format.rs
index 0b6c3fdc..db896082 100644
--- a/src/format.rs
+++ b/src/format.rs
@@ -650,7 +650,7 @@ impl<'a> Formatter<'a> {
self.output.push_str(&binding.name.value);
self.output
.push_str(if binding.public { " ←" } else { " ↚" });
- if binding.array_macro {
+ if binding.code_macro {
self.output.push('^');
}
if !binding.words.is_empty() || binding.signature.is_some() {
diff --git a/src/lsp.rs b/src/lsp.rs
index 42ccfc52..22189259 100644
--- a/src/lsp.rs
+++ b/src/lsp.rs
@@ -337,7 +337,7 @@ impl Spanner {
match &binfo.kind {
BindingKind::Const(None) => comment = Some("constant".into()),
BindingKind::Import(_) | BindingKind::Module(_) => comment = Some("module".into()),
- BindingKind::PosMacro(_) | BindingKind::ArrayMacro(_) => {
+ BindingKind::IndexMacro(_) | BindingKind::CodeMacro(_) => {
comment = Some("macro".into())
}
BindingKind::Func(_) => {}
@@ -360,8 +360,8 @@ impl Spanner {
},
pure: instrs_are_pure(f.instrs(&self.asm), &self.asm, Purity::Pure),
},
- BindingKind::PosMacro(args) => BindingDocsKind::Modifier(*args),
- BindingKind::ArrayMacro(_) => {
+ BindingKind::IndexMacro(args) => BindingDocsKind::Modifier(*args),
+ BindingKind::CodeMacro(_) => {
BindingDocsKind::Modifier(binfo.span.as_str(self.inputs(), ident_modifier_args))
}
BindingKind::Import(_) => BindingDocsKind::Module { sig: None },
@@ -1048,7 +1048,7 @@ mod server {
}
BindingKind::Const(_) => CompletionItemKind::CONSTANT,
BindingKind::Func(_) => CompletionItemKind::FUNCTION,
- BindingKind::PosMacro(_) | BindingKind::ArrayMacro(_) => {
+ BindingKind::IndexMacro(_) | BindingKind::CodeMacro(_) => {
CompletionItemKind::FUNCTION
}
BindingKind::Import(_) | BindingKind::Module(_) => CompletionItemKind::MODULE,
diff --git a/src/parse.rs b/src/parse.rs
index 19b0c849..9fc67167 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -460,7 +460,7 @@ impl<'i> Parser<'i> {
name,
arrow_span,
public,
- array_macro,
+ code_macro: array_macro,
words,
signature,
})
diff --git a/src/primitive/defs.rs b/src/primitive/defs.rs
index b1d683c6..19a7c7c7 100644
--- a/src/primitive/defs.rs
+++ b/src/primitive/defs.rs
@@ -2406,7 +2406,7 @@ primitive!(
/// [un][pop] *can* get the fill value through the function call. This means you can use [fill][un][pop] to get the fill value into a function.
/// ex: F ← ⬚°◌/⊂
/// : ⬚0F [1 2 3]
- /// This property includes positional macros, but *not* array macros.
+ /// This property includes index macros, but *not* code macros.
///
/// [fill][pop] can be used to temporarily remove the fill value.
/// ex: ⬚0 ↻ 2 [1 2 3 4 5]
@@ -3204,7 +3204,7 @@ primitive!(
/// ex: &p repr ↯2_2_2 0
/// ex: &p repr {"Uiua" @A [1 2 3] □4}
///
- /// [repr] can be used in array macros to make the macro generate code that produces the same array.
+ /// [repr] can be used in code macros to make the macro generate code that produces the same array.
/// ex! F! ←^ ⧻°□⊢
/// : F!+
/// ex: F! ←^ repr ⧻°□⊢
diff --git a/src/run.rs b/src/run.rs
index d9807c1d..ac9f05e8 100644
--- a/src/run.rs
+++ b/src/run.rs
@@ -471,12 +471,12 @@ code:
"Called module global. \
This is a bug in the interpreter.",
)),
- BindingKind::PosMacro(_) => Err(self.error(
- "Called positional macro global. \
+ BindingKind::IndexMacro(_) => Err(self.error(
+ "Called index macro global. \
This is a bug in the interpreter.",
)),
- BindingKind::ArrayMacro(_) => Err(self.error(
- "Called array macro global. \
+ BindingKind::CodeMacro(_) => Err(self.error(
+ "Called code macro global. \
This is a bug in the interpreter.",
)),
}
diff --git a/tests/macros.ua b/tests/macros.ua
index db58f100..8a838f08 100644
--- a/tests/macros.ua
+++ b/tests/macros.ua
@@ -1,4 +1,4 @@
-# Positional macros
+# Index macros
F! ← ^0 5
G! ← F!^0
⍤⤙≍ ¯5 G!¯
@@ -31,7 +31,7 @@ F! ← ⨬(
)
⍤⤙≍ ¯5 F!¯ 0 5
-# Array macros
+# Code macros
F! ←^
G! ←^ ⇌
H‼ ←^ ⊂⊢.