summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-03-03 18:15:33 +0100
committerLaurenz <laurmaedje@gmail.com>2021-03-03 18:15:33 +0100
commit1cfc3c72b59f96d1cef3f2e6e488b645648c36ab (patch)
tree11bceb52a84d6cc17f0b14d39d5b5b291393b3e9
parentc94a18833f23d2b57de1b87971458fd54b56d088 (diff)
Show name of user-defined functions in representation 🦋
-rw-r--r--src/eval/mod.rs3
-rw-r--r--src/parse/mod.rs29
-rw-r--r--src/syntax/expr.rs8
-rw-r--r--tests/ref/repr.pngbin8695 -> 10420 bytes
-rw-r--r--tests/typ/repr.typ8
5 files changed, 31 insertions, 17 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index f30ee7a7..17620161 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -401,7 +401,8 @@ impl Eval for ExprClosure {
visitor.finish()
};
- Value::Func(ValueFunc::new(None, move |ctx, args| {
+ let name = self.name.as_ref().map(|id| id.to_string());
+ Value::Func(ValueFunc::new(name, move |ctx, args| {
// Don't leak the scopes from the call site. Instead, we use the
// scope of captured variables we collected earlier.
let prev = std::mem::take(&mut ctx.scopes);
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 29801527..afd85193 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -190,13 +190,13 @@ fn primary(p: &mut Parser) -> Option<Expr> {
// Arrow means this is closure's lone parameter.
if p.eat_if(Token::Arrow) {
- return expr(p).map(|body| {
- Expr::Closure(ExprClosure {
- span: ident.span.join(body.span()),
- params: Rc::new(vec![ident]),
- body: Rc::new(body),
- })
- });
+ let body = expr(p)?;
+ return Some(Expr::Closure(ExprClosure {
+ span: ident.span.join(body.span()),
+ name: None,
+ params: Rc::new(vec![ident]),
+ body: Rc::new(body),
+ }));
}
Some(Expr::Ident(ident))
@@ -263,13 +263,13 @@ pub fn parenthesized(p: &mut Parser) -> Option<Expr> {
// Arrow means this is closure's parameter list.
if p.eat_if(Token::Arrow) {
let params = params(p, items);
- return expr(p).map(|body| {
- Expr::Closure(ExprClosure {
- span: span.join(body.span()),
- params: Rc::new(params),
- body: Rc::new(body),
- })
- });
+ let body = expr(p)?;
+ return Some(Expr::Closure(ExprClosure {
+ span: span.join(body.span()),
+ name: None,
+ params: Rc::new(params),
+ body: Rc::new(body),
+ }));
}
// Find out which kind of collection this is.
@@ -509,6 +509,7 @@ fn expr_let(p: &mut Parser) -> Option<Expr> {
let body = init?;
init = Some(Expr::Closure(ExprClosure {
span: binding.span.join(body.span()),
+ name: Some(binding.clone()),
params: Rc::new(params),
body: Rc::new(body),
}));
diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs
index d76ada69..5d10349b 100644
--- a/src/syntax/expr.rs
+++ b/src/syntax/expr.rs
@@ -27,7 +27,7 @@ pub enum Expr {
Binary(ExprBinary),
/// An invocation of a function: `f(x, y)`.
Call(ExprCall),
- /// A closure expression: `(x, y) => { z }`.
+ /// A closure expression: `(x, y) => z`.
Closure(ExprClosure),
/// A let expression: `let x = 1`.
Let(ExprLet),
@@ -414,11 +414,15 @@ impl ExprArg {
}
}
-/// A closure expression: `(x, y) => { z }`.
+/// A closure expression: `(x, y) => z`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprClosure {
/// The source code location.
pub span: Span,
+ /// The name of the closure.
+ ///
+ /// This only exists if you use the function syntax sugar: `let f(x) = y`.
+ pub name: Option<Ident>,
/// The parameter bindings.
pub params: Rc<Vec<Ident>>,
/// The body of the closure.
diff --git a/tests/ref/repr.png b/tests/ref/repr.png
index 2e7755d3..54a1d240 100644
--- a/tests/ref/repr.png
+++ b/tests/ref/repr.png
Binary files differ
diff --git a/tests/typ/repr.typ b/tests/typ/repr.typ
index 666db428..6eead75e 100644
--- a/tests/typ/repr.typ
+++ b/tests/typ/repr.typ
@@ -48,3 +48,11 @@
---
// Templates.
{[*{"H" + "i"} there*]}
+
+---
+// Functions
+#let f(x) = x
+
+{box} \
+{f} \
+{() => none} \