mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Attach parameter list span to function
This commit is contained in:
parent
f2b0c5e08d
commit
5d475ae32e
@ -20,7 +20,12 @@ use crate::World;
|
|||||||
|
|
||||||
/// An evaluatable function.
|
/// An evaluatable function.
|
||||||
#[derive(Clone, Hash)]
|
#[derive(Clone, Hash)]
|
||||||
pub struct Func(Arc<Prehashed<Repr>>, Span);
|
pub struct Func {
|
||||||
|
/// The internal representation.
|
||||||
|
repr: Arc<Prehashed<Repr>>,
|
||||||
|
/// The span with which errors are reported when this function is called.
|
||||||
|
span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
/// The different kinds of function representations.
|
/// The different kinds of function representations.
|
||||||
#[derive(Hash)]
|
#[derive(Hash)]
|
||||||
@ -38,7 +43,7 @@ enum Repr {
|
|||||||
impl Func {
|
impl Func {
|
||||||
/// The name of the function.
|
/// The name of the function.
|
||||||
pub fn name(&self) -> Option<&str> {
|
pub fn name(&self) -> Option<&str> {
|
||||||
match &**self.0 {
|
match &**self.repr {
|
||||||
Repr::Native(native) => Some(native.info.name),
|
Repr::Native(native) => Some(native.info.name),
|
||||||
Repr::Node(node) => Some(node.info.name),
|
Repr::Node(node) => Some(node.info.name),
|
||||||
Repr::Closure(closure) => closure.name.as_deref(),
|
Repr::Closure(closure) => closure.name.as_deref(),
|
||||||
@ -48,7 +53,7 @@ impl Func {
|
|||||||
|
|
||||||
/// Extract details the function.
|
/// Extract details the function.
|
||||||
pub fn info(&self) -> Option<&FuncInfo> {
|
pub fn info(&self) -> Option<&FuncInfo> {
|
||||||
match &**self.0 {
|
match &**self.repr {
|
||||||
Repr::Native(native) => Some(&native.info),
|
Repr::Native(native) => Some(&native.info),
|
||||||
Repr::Node(node) => Some(&node.info),
|
Repr::Node(node) => Some(&node.info),
|
||||||
Repr::With(func, _) => func.info(),
|
Repr::With(func, _) => func.info(),
|
||||||
@ -58,20 +63,20 @@ impl Func {
|
|||||||
|
|
||||||
/// The function's span.
|
/// The function's span.
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
self.1
|
self.span
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attach a span to this function if it doesn't already have one.
|
/// Attach a span to this function if it doesn't already have one.
|
||||||
pub fn spanned(mut self, span: Span) -> Self {
|
pub fn spanned(mut self, span: Span) -> Self {
|
||||||
if self.1.is_detached() {
|
if self.span.is_detached() {
|
||||||
self.1 = span;
|
self.span = span;
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The number of positional arguments this function takes, if known.
|
/// The number of positional arguments this function takes, if known.
|
||||||
pub fn argc(&self) -> Option<usize> {
|
pub fn argc(&self) -> Option<usize> {
|
||||||
match &**self.0 {
|
match &**self.repr {
|
||||||
Repr::Closure(closure) => closure.argc(),
|
Repr::Closure(closure) => closure.argc(),
|
||||||
Repr::With(wrapped, applied) => Some(wrapped.argc()?.saturating_sub(
|
Repr::With(wrapped, applied) => Some(wrapped.argc()?.saturating_sub(
|
||||||
applied.items.iter().filter(|arg| arg.name.is_none()).count(),
|
applied.items.iter().filter(|arg| arg.name.is_none()).count(),
|
||||||
@ -82,7 +87,7 @@ impl Func {
|
|||||||
|
|
||||||
/// Call the function with the given arguments.
|
/// Call the function with the given arguments.
|
||||||
pub fn call_vm(&self, vm: &mut Vm, mut args: Args) -> SourceResult<Value> {
|
pub fn call_vm(&self, vm: &mut Vm, mut args: Args) -> SourceResult<Value> {
|
||||||
match &**self.0 {
|
match &**self.repr {
|
||||||
Repr::Native(native) => {
|
Repr::Native(native) => {
|
||||||
let value = (native.func)(vm, &mut args)?;
|
let value = (native.func)(vm, &mut args)?;
|
||||||
args.finish()?;
|
args.finish()?;
|
||||||
@ -133,8 +138,11 @@ impl Func {
|
|||||||
|
|
||||||
/// Apply the given arguments to the function.
|
/// Apply the given arguments to the function.
|
||||||
pub fn with(self, args: Args) -> Self {
|
pub fn with(self, args: Args) -> Self {
|
||||||
let span = self.1;
|
let span = self.span;
|
||||||
Self(Arc::new(Prehashed::new(Repr::With(self, args))), span)
|
Self {
|
||||||
|
repr: Arc::new(Prehashed::new(Repr::With(self, args))),
|
||||||
|
span,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a selector for this function's node type, filtering by node's
|
/// Create a selector for this function's node type, filtering by node's
|
||||||
@ -147,7 +155,7 @@ impl Func {
|
|||||||
|
|
||||||
/// The node id of this function if it is an element function.
|
/// The node id of this function if it is an element function.
|
||||||
pub fn id(&self) -> Option<NodeId> {
|
pub fn id(&self) -> Option<NodeId> {
|
||||||
match **self.0 {
|
match **self.repr {
|
||||||
Repr::Node(id) => Some(id),
|
Repr::Node(id) => Some(id),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@ -155,7 +163,7 @@ impl Func {
|
|||||||
|
|
||||||
/// Execute the function's set rule and return the resulting style map.
|
/// Execute the function's set rule and return the resulting style map.
|
||||||
pub fn set(&self, mut args: Args) -> SourceResult<StyleMap> {
|
pub fn set(&self, mut args: Args) -> SourceResult<StyleMap> {
|
||||||
Ok(match &**self.0 {
|
Ok(match &**self.repr {
|
||||||
Repr::Node(node) => {
|
Repr::Node(node) => {
|
||||||
let styles = (node.set)(&mut args)?;
|
let styles = (node.set)(&mut args)?;
|
||||||
args.finish()?;
|
args.finish()?;
|
||||||
@ -190,13 +198,16 @@ impl Debug for Func {
|
|||||||
|
|
||||||
impl PartialEq for Func {
|
impl PartialEq for Func {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
hash128(&self.0) == hash128(&other.0)
|
hash128(&self.repr) == hash128(&other.repr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Repr> for Func {
|
impl From<Repr> for Func {
|
||||||
fn from(repr: Repr) -> Self {
|
fn from(repr: Repr) -> Self {
|
||||||
Self(Arc::new(Prehashed::new(repr)), Span::detached())
|
Self {
|
||||||
|
repr: Arc::new(Prehashed::new(repr)),
|
||||||
|
span: Span::detached(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +329,7 @@ impl Closure {
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
mut args: Args,
|
mut args: Args,
|
||||||
) -> SourceResult<Value> {
|
) -> SourceResult<Value> {
|
||||||
let closure = match &**this.0 {
|
let closure = match &**this.repr {
|
||||||
Repr::Closure(closure) => closure,
|
Repr::Closure(closure) => closure,
|
||||||
_ => panic!("`this` must be a closure"),
|
_ => panic!("`this` must be a closure"),
|
||||||
};
|
};
|
||||||
@ -436,7 +447,7 @@ impl<'a> CapturesVisitor<'a> {
|
|||||||
// body is evaluated. Care must be taken so that the default values
|
// body is evaluated. Care must be taken so that the default values
|
||||||
// of named parameters cannot access previous parameter bindings.
|
// of named parameters cannot access previous parameter bindings.
|
||||||
Some(ast::Expr::Closure(expr)) => {
|
Some(ast::Expr::Closure(expr)) => {
|
||||||
for param in expr.params() {
|
for param in expr.params().children() {
|
||||||
if let ast::Param::Named(named) = param {
|
if let ast::Param::Named(named) = param {
|
||||||
self.visit(named.expr().as_untyped());
|
self.visit(named.expr().as_untyped());
|
||||||
}
|
}
|
||||||
@ -447,7 +458,7 @@ impl<'a> CapturesVisitor<'a> {
|
|||||||
self.bind(name);
|
self.bind(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for param in expr.params() {
|
for param in expr.params().children() {
|
||||||
match param {
|
match param {
|
||||||
ast::Param::Pos(ident) => self.bind(ident),
|
ast::Param::Pos(ident) => self.bind(ident),
|
||||||
ast::Param::Named(named) => self.bind(named.name()),
|
ast::Param::Named(named) => self.bind(named.name()),
|
||||||
|
@ -158,7 +158,7 @@ pub fn eval_code_str(
|
|||||||
/// virtual machine is created for each module evaluation and function call.
|
/// virtual machine is created for each module evaluation and function call.
|
||||||
pub struct Vm<'a> {
|
pub struct Vm<'a> {
|
||||||
/// The underlying virtual typesetter.
|
/// The underlying virtual typesetter.
|
||||||
vt: Vt<'a>,
|
pub vt: Vt<'a>,
|
||||||
/// The language items.
|
/// The language items.
|
||||||
items: LangItems,
|
items: LangItems,
|
||||||
/// The route of source ids the VM took to reach its current location.
|
/// The route of source ids the VM took to reach its current location.
|
||||||
@ -1153,7 +1153,7 @@ impl Eval for ast::Closure {
|
|||||||
let mut sink = None;
|
let mut sink = None;
|
||||||
|
|
||||||
// Collect parameters and an optional sink parameter.
|
// Collect parameters and an optional sink parameter.
|
||||||
for param in self.params() {
|
for param in self.params().children() {
|
||||||
match param {
|
match param {
|
||||||
ast::Param::Pos(name) => {
|
ast::Param::Pos(name) => {
|
||||||
params.push((name, None));
|
params.push((name, None));
|
||||||
@ -1180,7 +1180,7 @@ impl Eval for ast::Closure {
|
|||||||
body: self.body(),
|
body: self.body(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Value::Func(Func::from(closure).spanned(self.span())))
|
Ok(Value::Func(Func::from(closure).spanned(self.params().span())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1504,12 +1504,8 @@ impl Closure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The parameter bindings.
|
/// The parameter bindings.
|
||||||
pub fn params(&self) -> impl DoubleEndedIterator<Item = Param> + '_ {
|
pub fn params(&self) -> Params {
|
||||||
self.0
|
self.0.cast_first_match().unwrap_or_default()
|
||||||
.children()
|
|
||||||
.find(|x| x.kind() == SyntaxKind::Params)
|
|
||||||
.map_or([].iter(), |params| params.children())
|
|
||||||
.filter_map(SyntaxNode::cast)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The body of the closure.
|
/// The body of the closure.
|
||||||
@ -1518,6 +1514,18 @@ impl Closure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node! {
|
||||||
|
/// A closure's parameters: `(x, y)`.
|
||||||
|
Params
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Params {
|
||||||
|
/// The parameter bindings.
|
||||||
|
pub fn children(&self) -> impl DoubleEndedIterator<Item = Param> + '_ {
|
||||||
|
self.0.children().filter_map(SyntaxNode::cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A parameter to a closure.
|
/// A parameter to a closure.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum Param {
|
pub enum Param {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user