Skip to content

Commit 1a5489c

Browse files
committed
feat: Allow macros to refer to symbols in scope at the expansion site
Fixes #895
1 parent 8f43cb6 commit 1a5489c

File tree

4 files changed

+25
-16
lines changed

4 files changed

+25
-16
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,17 @@ factorial 10
6060
// * Only the following operators/functions are allowed: multiplication, division, addition, subtraction
6161
// * Division should use floating point or rational arithmetic, etc, to preserve remainders.
6262
// * Brackets are allowed, if using an infix expression evaluator.
63-
// * Forming multiple digit numbers from the supplied digits is disallowed. (So an answer of 12+12 - when given 1, 2, 2, and 1 - is wrong).
64-
// * The order of the digits, when given, does not have to be preserved.
63+
// * Forming multiple digit numbers from the supplied digits is disallowed. (So an answer of 12+12 when given 1, 2, 2, and 1 is wrong).
64+
// * The order of the digits when given does not have to be preserved.
6565
//
6666
//
6767
// ## Notes
6868
//
6969
// The type of expression evaluator used is not mandated. An RPN evaluator is equally acceptable for example.
70-
// The task is not for the program to generate the expression or test whether an expression is even possible.
70+
// The task is not for the program to generate the expression, or test whether an expression is even possible.
7171
7272
73-
// The `import!` macro is used to load and refer to other modules.
73+
// The `import!` macro are used to load and refer to other modules.
7474
// It gets replaced by the value returned by evaluating that module (cached of course, so that
7575
// multiple `import!`s to the same module only evaluates the module once)
7676
let io @ { ? } = import! std.io
@@ -83,7 +83,7 @@ let list @ { List, ? } = import! std.list
8383
let random = import! std.random
8484
let string = import! std.string
8585
86-
// Since imports in gluon return regular values we can load specific parts of a module using pattern matches.
86+
// Since imports in gluon returns regular values we can load specific parts of a module using pattern matches.
8787
let char @ { ? } = import! std.char
8888
8989
let { (<>) } = import! std.semigroup

src/import.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::base::{
2525
ast::{self, expr_to_path, Expr, Literal, SpannedExpr},
2626
filename_to_module, pos,
2727
source::FileId,
28-
symbol::Symbol,
28+
symbol::{Symbol, Symbols},
2929
types::ArcType,
3030
};
3131

@@ -477,9 +477,10 @@ where
477477
}
478478
}
479479

480-
fn expand<'r, 'a: 'r, 'b: 'r, 'ast: 'r>(
480+
fn expand<'r, 'a: 'r, 'b: 'r, 'c: 'r, 'ast: 'r>(
481481
&self,
482482
macros: &'b mut MacroExpander<'a>,
483+
_symbols: &'c mut Symbols,
483484
_arena: &'b mut ast::OwnedArena<'ast, Symbol>,
484485
args: &'b mut [SpannedExpr<'ast, Symbol>],
485486
) -> MacroFuture<'r, 'ast> {

src/lift_io.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ use {
2222
pub(crate) struct LiftIo;
2323

2424
impl Macro for LiftIo {
25-
fn expand<'r, 'a: 'r, 'b: 'r, 'ast: 'r>(
25+
fn expand<'r, 'a: 'r, 'b: 'r, 'c: 'r, 'ast: 'r>(
2626
&self,
2727
env: &'b mut MacroExpander<'a>,
28+
_symbols: &'c mut Symbols,
2829
arena: &'b mut ast::OwnedArena<'ast, Symbol>,
2930
args: &'b mut [SpannedExpr<'ast, Symbol>],
3031
) -> MacroFuture<'r, 'ast> {

vm/src/macros.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,13 @@ pub trait Macro: Trace + DowncastArc + Send + Sync {
245245
None
246246
}
247247

248-
fn expand<'r, 'a: 'r, 'b: 'r, 'ast: 'r>(
248+
/// Creating a symbol in `symbols` will put it in the same scope as the code surrounding the
249+
/// expansion. If you want to create a unique symbol then call `Symbol::from` or create a new
250+
/// `Symbols` table
251+
fn expand<'r, 'a: 'r, 'b: 'r, 'c: 'r, 'ast: 'r>(
249252
&self,
250253
env: &'b mut MacroExpander<'a>,
254+
symbols: &'c mut Symbols,
251255
arena: &'b mut ast::OwnedArena<'ast, Symbol>,
252256
args: &'b mut [SpannedExpr<'ast, Symbol>],
253257
) -> MacroFuture<'r, 'ast>;
@@ -283,13 +287,14 @@ where
283287
(**self).get_capability_impl(thread, arc_self, id)
284288
}
285289

286-
fn expand<'r, 'a: 'r, 'b: 'r, 'ast: 'r>(
290+
fn expand<'r, 'a: 'r, 'b: 'r, 'c: 'r, 'ast: 'r>(
287291
&self,
288292
env: &'b mut MacroExpander<'a>,
293+
symbols: &'c mut Symbols,
289294
arena: &'b mut ast::OwnedArena<'ast, Symbol>,
290295
args: &'b mut [SpannedExpr<'ast, Symbol>],
291296
) -> MacroFuture<'r, 'ast> {
292-
(**self).expand(env, arena, args)
297+
(**self).expand(env, symbols, arena, args)
293298
}
294299
}
295300

@@ -307,13 +312,14 @@ where
307312
(**self).get_capability_impl(thread, arc_self, id)
308313
}
309314

310-
fn expand<'r, 'a: 'r, 'b: 'r, 'ast: 'r>(
315+
fn expand<'r, 'a: 'r, 'b: 'r, 'c: 'r, 'ast: 'r>(
311316
&self,
312317
env: &'b mut MacroExpander<'a>,
318+
symbols: &'c mut Symbols,
313319
arena: &'b mut ast::OwnedArena<'ast, Symbol>,
314320
args: &'b mut [SpannedExpr<'ast, Symbol>],
315321
) -> MacroFuture<'r, 'ast> {
316-
(**self).expand(env, arena, args)
322+
(**self).expand(env, symbols, arena, args)
317323
}
318324
}
319325

@@ -457,19 +463,20 @@ impl<'a> MacroExpander<'a> {
457463
exprs: Vec::new(),
458464
};
459465
visitor.visit_expr(expr);
460-
let MacroVisitor { exprs, .. } = visitor;
461-
self.expand(arena, exprs).await
466+
let MacroVisitor { exprs, symbols, .. } = visitor;
467+
self.expand(symbols, arena, exprs).await
462468
}
463469

464470
async fn expand<'ast>(
465471
&mut self,
472+
symbols: &mut Symbols,
466473
arena: &mut ast::OwnedArena<'ast, Symbol>,
467474
mut exprs: Vec<(&'_ mut SpannedExpr<'ast, Symbol>, Arc<dyn Macro>)>,
468475
) {
469476
let mut futures = Vec::with_capacity(exprs.len());
470477
for (expr, mac) in exprs.drain(..) {
471478
let result = match &mut expr.value {
472-
Expr::App { args, .. } => mac.expand(self, arena, args).await,
479+
Expr::App { args, .. } => mac.expand(self, symbols, arena, args).await,
473480
_ => unreachable!("{:?}", expr),
474481
};
475482
match result {

0 commit comments

Comments
 (0)