mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Desugar body into last argument 🍩
This commit is contained in:
parent
650c712eab
commit
c8f6b5bd5c
11
src/func.rs
11
src/func.rs
@ -8,9 +8,7 @@ pub mod prelude {
|
|||||||
pub use crate::layout::Command::{self, *};
|
pub use crate::layout::Command::{self, *};
|
||||||
pub use crate::style::*;
|
pub use crate::style::*;
|
||||||
pub use crate::syntax::expr::*;
|
pub use crate::syntax::expr::*;
|
||||||
pub use crate::syntax::parsing::{
|
pub use crate::syntax::parsing::{parse, FuncArgs, FuncCall, ParseState};
|
||||||
parse, FuncArgs, FuncBody, FuncCall, FuncHeader, ParseState,
|
|
||||||
};
|
|
||||||
pub use crate::syntax::span::{Span, SpanVec, Spanned};
|
pub use crate::syntax::span::{Span, SpanVec, Spanned};
|
||||||
pub use crate::syntax::tree::{DynamicNode, SyntaxNode, SyntaxTree};
|
pub use crate::syntax::tree::{DynamicNode, SyntaxNode, SyntaxTree};
|
||||||
pub use crate::syntax::value::*;
|
pub use crate::syntax::value::*;
|
||||||
@ -55,10 +53,3 @@ pub fn drain_args(args: FuncArgs, f: &mut Feedback) {
|
|||||||
error!(@f, arg.span, "unexpected argument");
|
error!(@f, arg.span, "unexpected argument");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate an error if there is function body even though none was expected.
|
|
||||||
pub fn expect_no_body(body: FuncBody, f: &mut Feedback) {
|
|
||||||
if let Some(body) = body {
|
|
||||||
error!(@f, body.span, "unexpected body");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -12,9 +12,9 @@ use super::*;
|
|||||||
/// There may not be two alignment specifications for the same axis.
|
/// There may not be two alignment specifications for the same axis.
|
||||||
pub fn align(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
pub fn align(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
||||||
let mut f = Feedback::new();
|
let mut f = Feedback::new();
|
||||||
let mut args = call.header.args;
|
let mut args = call.args;
|
||||||
let node = AlignNode {
|
let node = AlignNode {
|
||||||
body: call.body.map(|s| s.v),
|
content: args.pos.get::<SyntaxTree>(),
|
||||||
aligns: args.pos.all::<Spanned<SpecAlign>>().collect(),
|
aligns: args.pos.all::<Spanned<SpecAlign>>().collect(),
|
||||||
h: args.key.get::<Spanned<SpecAlign>>("horizontal", &mut f),
|
h: args.key.get::<Spanned<SpecAlign>>("horizontal", &mut f),
|
||||||
v: args.key.get::<Spanned<SpecAlign>>("vertical", &mut f),
|
v: args.key.get::<Spanned<SpecAlign>>("vertical", &mut f),
|
||||||
@ -25,7 +25,7 @@ pub fn align(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct AlignNode {
|
struct AlignNode {
|
||||||
body: Option<SyntaxTree>,
|
content: Option<SyntaxTree>,
|
||||||
aligns: SpanVec<SpecAlign>,
|
aligns: SpanVec<SpecAlign>,
|
||||||
h: Option<Spanned<SpecAlign>>,
|
h: Option<Spanned<SpecAlign>>,
|
||||||
v: Option<Spanned<SpecAlign>>,
|
v: Option<Spanned<SpecAlign>>,
|
||||||
@ -64,9 +64,9 @@ impl Layout for AlignNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pass::new(match &self.body {
|
Pass::new(match &self.content {
|
||||||
Some(body) => {
|
Some(tree) => {
|
||||||
let layouted = layout(body, ctx).await;
|
let layouted = layout(tree, ctx).await;
|
||||||
f.extend(layouted.feedback);
|
f.extend(layouted.feedback);
|
||||||
vec![AddMultiple(layouted.output)]
|
vec![AddMultiple(layouted.output)]
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ use super::*;
|
|||||||
/// - `height`: The height of the box (length of relative to parent's height).
|
/// - `height`: The height of the box (length of relative to parent's height).
|
||||||
pub fn boxed(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
pub fn boxed(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
||||||
let mut f = Feedback::new();
|
let mut f = Feedback::new();
|
||||||
let mut args = call.header.args;
|
let mut args = call.args;
|
||||||
let node = BoxNode {
|
let node = BoxNode {
|
||||||
body: call.body.map(|s| s.v).unwrap_or(SyntaxTree::new()),
|
content: args.pos.get::<SyntaxTree>().unwrap_or(SyntaxTree::new()),
|
||||||
width: args.key.get::<ScaleLength>("width", &mut f),
|
width: args.key.get::<ScaleLength>("width", &mut f),
|
||||||
height: args.key.get::<ScaleLength>("height", &mut f),
|
height: args.key.get::<ScaleLength>("height", &mut f),
|
||||||
};
|
};
|
||||||
@ -20,7 +20,7 @@ pub fn boxed(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct BoxNode {
|
struct BoxNode {
|
||||||
body: SyntaxTree,
|
content: SyntaxTree,
|
||||||
width: Option<ScaleLength>,
|
width: Option<ScaleLength>,
|
||||||
height: Option<ScaleLength>,
|
height: Option<ScaleLength>,
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ impl Layout for BoxNode {
|
|||||||
ctx.spaces[0].expansion.vertical = true;
|
ctx.spaces[0].expansion.vertical = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
layout(&self.body, ctx).await.map(|out| {
|
layout(&self.content, ctx).await.map(|out| {
|
||||||
let layout = out.into_iter().next().unwrap();
|
let layout = out.into_iter().next().unwrap();
|
||||||
vec![Add(layout)]
|
vec![Add(layout)]
|
||||||
})
|
})
|
||||||
|
@ -20,10 +20,10 @@ use super::*;
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn font(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
pub fn font(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
||||||
let mut f = Feedback::new();
|
let mut f = Feedback::new();
|
||||||
let mut args = call.header.args;
|
let mut args = call.args;
|
||||||
|
|
||||||
let node = FontNode {
|
let node = FontNode {
|
||||||
body: call.body.map(|s| s.v),
|
content: args.pos.get::<SyntaxTree>(),
|
||||||
size: args.pos.get::<ScaleLength>(),
|
size: args.pos.get::<ScaleLength>(),
|
||||||
style: args.key.get::<FontStyle>("style", &mut f),
|
style: args.key.get::<FontStyle>("style", &mut f),
|
||||||
weight: args.key.get::<FontWeight>("weight", &mut f),
|
weight: args.key.get::<FontWeight>("weight", &mut f),
|
||||||
@ -53,7 +53,7 @@ pub fn font(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct FontNode {
|
struct FontNode {
|
||||||
body: Option<SyntaxTree>,
|
content: Option<SyntaxTree>,
|
||||||
size: Option<ScaleLength>,
|
size: Option<ScaleLength>,
|
||||||
style: Option<FontStyle>,
|
style: Option<FontStyle>,
|
||||||
weight: Option<FontWeight>,
|
weight: Option<FontWeight>,
|
||||||
@ -91,7 +91,7 @@ impl Layout for FontNode {
|
|||||||
|
|
||||||
text.fallback.flatten();
|
text.fallback.flatten();
|
||||||
|
|
||||||
Pass::okay(match &self.body {
|
Pass::okay(match &self.content {
|
||||||
Some(tree) => vec![
|
Some(tree) => vec![
|
||||||
SetTextStyle(text),
|
SetTextStyle(text),
|
||||||
LayoutSyntaxTree(tree),
|
LayoutSyntaxTree(tree),
|
||||||
|
@ -18,8 +18,7 @@ use super::*;
|
|||||||
/// - `flip`: Flips custom or paper-defined width and height (boolean).
|
/// - `flip`: Flips custom or paper-defined width and height (boolean).
|
||||||
pub fn page(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
pub fn page(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
||||||
let mut f = Feedback::new();
|
let mut f = Feedback::new();
|
||||||
let mut args = call.header.args;
|
let mut args = call.args;
|
||||||
expect_no_body(call.body, &mut f);
|
|
||||||
let node = PageNode {
|
let node = PageNode {
|
||||||
paper: args.pos.get::<Paper>(),
|
paper: args.pos.get::<Paper>(),
|
||||||
width: args.key.get::<Length>("width", &mut f),
|
width: args.key.get::<Length>("width", &mut f),
|
||||||
@ -79,7 +78,7 @@ impl Layout for PageNode {
|
|||||||
/// `pagebreak`: Ends the current page.
|
/// `pagebreak`: Ends the current page.
|
||||||
pub fn pagebreak(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
pub fn pagebreak(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
||||||
let mut f = Feedback::new();
|
let mut f = Feedback::new();
|
||||||
drain_args(call.header.args, &mut f);
|
drain_args(call.args, &mut f);
|
||||||
Pass::node(PageBreakNode, f)
|
Pass::node(PageBreakNode, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,11 @@ pub fn v(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
|||||||
|
|
||||||
fn spacing(call: FuncCall, axis: SpecAxis) -> Pass<SyntaxNode> {
|
fn spacing(call: FuncCall, axis: SpecAxis) -> Pass<SyntaxNode> {
|
||||||
let mut f = Feedback::new();
|
let mut f = Feedback::new();
|
||||||
let mut args = call.header.args;
|
let mut args = call.args;
|
||||||
expect_no_body(call.body, &mut f);
|
|
||||||
let node = SpacingNode {
|
let node = SpacingNode {
|
||||||
spacing: args.pos.expect::<ScaleLength>(&mut f)
|
spacing: args.pos.expect::<ScaleLength>(&mut f)
|
||||||
.map(|s| (axis, s))
|
.map(|s| (axis, s))
|
||||||
.or_missing(call.header.name.span, "spacing", &mut f),
|
.or_missing(call.name.span, "spacing", &mut f),
|
||||||
};
|
};
|
||||||
drain_args(args, &mut f);
|
drain_args(args, &mut f);
|
||||||
Pass::node(node, f)
|
Pass::node(node, f)
|
||||||
|
@ -5,21 +5,22 @@ use super::*;
|
|||||||
/// This is also the fallback function, which is used when a function name
|
/// This is also the fallback function, which is used when a function name
|
||||||
/// cannot be resolved.
|
/// cannot be resolved.
|
||||||
pub fn val(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
pub fn val(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
||||||
|
let mut args = call.args;
|
||||||
let node = ValNode {
|
let node = ValNode {
|
||||||
body: call.body.map(|s| s.v),
|
content: args.pos.get::<SyntaxTree>(),
|
||||||
};
|
};
|
||||||
Pass::node(node, Feedback::new())
|
Pass::node(node, Feedback::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct ValNode {
|
struct ValNode {
|
||||||
body: Option<SyntaxTree>,
|
content: Option<SyntaxTree>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl Layout for ValNode {
|
impl Layout for ValNode {
|
||||||
async fn layout<'a>(&'a self, _: LayoutContext<'_>) -> Pass<Commands<'a>> {
|
async fn layout<'a>(&'a self, _: LayoutContext<'_>) -> Pass<Commands<'a>> {
|
||||||
Pass::okay(match &self.body {
|
Pass::okay(match &self.content {
|
||||||
Some(tree) => vec![LayoutSyntaxTree(tree)],
|
Some(tree) => vec![LayoutSyntaxTree(tree)],
|
||||||
None => vec![],
|
None => vec![],
|
||||||
})
|
})
|
||||||
|
@ -16,21 +16,10 @@ pub type CallParser = dyn Fn(FuncCall, &ParseState) -> Pass<SyntaxNode>;
|
|||||||
/// An invocation of a function.
|
/// An invocation of a function.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct FuncCall {
|
pub struct FuncCall {
|
||||||
pub header: FuncHeader,
|
|
||||||
pub body: FuncBody,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The parsed header of a function (everything in the first set of brackets).
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub struct FuncHeader {
|
|
||||||
pub name: Spanned<Ident>,
|
pub name: Spanned<Ident>,
|
||||||
pub args: FuncArgs,
|
pub args: FuncArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The body of a function as a raw spanned string containing what's inside of
|
|
||||||
/// the brackets.
|
|
||||||
pub type FuncBody = Option<Spanned<SyntaxTree>>;
|
|
||||||
|
|
||||||
/// The positional and keyword arguments passed to a function.
|
/// The positional and keyword arguments passed to a function.
|
||||||
#[derive(Debug, Default, Clone, PartialEq)]
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
pub struct FuncArgs {
|
pub struct FuncArgs {
|
||||||
@ -166,8 +155,8 @@ impl<'s> FuncParser<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse(mut self) -> Pass<SyntaxNode> {
|
fn parse(mut self) -> Pass<SyntaxNode> {
|
||||||
let (parser, header) = if let Some(header) = self.parse_func_header() {
|
let (parser, mut call) = if let Some(call) = self.parse_func_call() {
|
||||||
let name = header.name.v.as_str();
|
let name = call.name.v.as_str();
|
||||||
let (parser, deco) = match self.state.scope.get_parser(name) {
|
let (parser, deco) = match self.state.scope.get_parser(name) {
|
||||||
// The function exists in the scope.
|
// The function exists in the scope.
|
||||||
Some(parser) => (parser, Decoration::ResolvedFunc),
|
Some(parser) => (parser, Decoration::ResolvedFunc),
|
||||||
@ -177,32 +166,34 @@ impl<'s> FuncParser<'s> {
|
|||||||
// the content of the function is not totally dropped (on a best
|
// the content of the function is not totally dropped (on a best
|
||||||
// effort basis).
|
// effort basis).
|
||||||
None => {
|
None => {
|
||||||
error!(@self.feedback, header.name.span, "unknown function");
|
error!(@self.feedback, call.name.span, "unknown function");
|
||||||
let parser = self.state.scope.get_fallback_parser();
|
let parser = self.state.scope.get_fallback_parser();
|
||||||
(parser, Decoration::UnresolvedFunc)
|
(parser, Decoration::UnresolvedFunc)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.feedback.decorations.push(Spanned::new(deco, header.name.span));
|
self.feedback.decorations.push(Spanned::new(deco, call.name.span));
|
||||||
(parser, header)
|
(parser, call)
|
||||||
} else {
|
} else {
|
||||||
// Parse the body with the fallback parser even when the header is
|
// Parse the call with the fallback parser even when the header is
|
||||||
// completely unparsable.
|
// completely unparsable.
|
||||||
let parser = self.state.scope.get_fallback_parser();
|
let parser = self.state.scope.get_fallback_parser();
|
||||||
let header = FuncHeader {
|
let call = FuncCall {
|
||||||
name: Spanned::new(Ident(String::new()), Span::ZERO),
|
name: Spanned::new(Ident(String::new()), Span::ZERO),
|
||||||
args: FuncArgs::new(),
|
args: FuncArgs::new(),
|
||||||
};
|
};
|
||||||
(parser, header)
|
(parser, call)
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = self.body.map(|body| body.map(|src| {
|
if let Some(body) = self.body {
|
||||||
|
let tree = body.map(|src| {
|
||||||
let parsed = parse(src, body.span.start, &self.state);
|
let parsed = parse(src, body.span.start, &self.state);
|
||||||
self.feedback.extend(parsed.feedback);
|
self.feedback.extend(parsed.feedback);
|
||||||
parsed.output
|
Expr::Tree(parsed.output)
|
||||||
}));
|
});
|
||||||
|
|
||||||
let call = FuncCall { header, body };
|
call.args.pos.push(tree);
|
||||||
|
}
|
||||||
|
|
||||||
let parsed = parser(call, self.state);
|
let parsed = parser(call, self.state);
|
||||||
self.feedback.extend(parsed.feedback);
|
self.feedback.extend(parsed.feedback);
|
||||||
@ -210,7 +201,7 @@ impl<'s> FuncParser<'s> {
|
|||||||
Pass::new(parsed.output, self.feedback)
|
Pass::new(parsed.output, self.feedback)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_func_header(&mut self) -> Option<FuncHeader> {
|
fn parse_func_call(&mut self) -> Option<FuncCall> {
|
||||||
let after_bracket = self.pos();
|
let after_bracket = self.pos();
|
||||||
|
|
||||||
self.skip_white();
|
self.skip_white();
|
||||||
@ -229,7 +220,7 @@ impl<'s> FuncParser<'s> {
|
|||||||
None => FuncArgs::new(),
|
None => FuncArgs::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(FuncHeader { name, args })
|
Some(FuncCall { name, args })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_func_args(&mut self) -> FuncArgs {
|
fn parse_func_args(&mut self) -> FuncArgs {
|
||||||
@ -790,13 +781,13 @@ mod tests {
|
|||||||
value: Z($value),
|
value: Z($value),
|
||||||
})));)*)?
|
})));)*)?
|
||||||
)?
|
)?
|
||||||
SyntaxNode::boxed(DebugNode {
|
SyntaxNode::boxed(DebugNode(
|
||||||
header: FuncHeader {
|
FuncCall {
|
||||||
name: span_item!($name).map(|s| Ident(s.to_string())),
|
name: span_item!($name).map(|s| Ident(s.to_string())),
|
||||||
args,
|
args,
|
||||||
},
|
},
|
||||||
body: func!(@body $($($body)*)?),
|
func!(@body $($($body)*)?),
|
||||||
})
|
))
|
||||||
}};
|
}};
|
||||||
(@body [$($body:tt)*]) => { Some(span_vec![$($body)*].0) };
|
(@body [$($body:tt)*]) => { Some(span_vec![$($body)*].0) };
|
||||||
(@body) => { None };
|
(@body) => { None };
|
||||||
|
@ -3,10 +3,10 @@ use std::fmt::Debug;
|
|||||||
use crate::func::prelude::*;
|
use crate::func::prelude::*;
|
||||||
use super::decoration::Decoration;
|
use super::decoration::Decoration;
|
||||||
use super::expr::{Expr, Ident, NamedTuple, Object, Pair, Tuple};
|
use super::expr::{Expr, Ident, NamedTuple, Object, Pair, Tuple};
|
||||||
use super::parsing::{FuncArg, FuncArgs, FuncHeader};
|
use super::parsing::{FuncArg, FuncArgs};
|
||||||
use super::span::Spanned;
|
use super::span::Spanned;
|
||||||
use super::tokens::Token;
|
use super::tokens::Token;
|
||||||
use super::tree::{DynamicNode, SyntaxNode, SyntaxTree};
|
use super::tree::{DynamicNode, SyntaxNode};
|
||||||
|
|
||||||
pub fn check<T>(src: &str, exp: T, found: T, cmp_spans: bool)
|
pub fn check<T>(src: &str, exp: T, found: T, cmp_spans: bool)
|
||||||
where
|
where
|
||||||
@ -58,19 +58,13 @@ macro_rules! span_item {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_func(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
pub fn debug_func(mut call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
|
||||||
let node = DebugNode {
|
let tree = call.args.pos.get::<SyntaxTree>();
|
||||||
header: call.header,
|
Pass::node(DebugNode(call, tree), Feedback::new())
|
||||||
body: call.body.map(|s| s.v),
|
|
||||||
};
|
|
||||||
Pass::node(node, Feedback::new())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct DebugNode {
|
pub struct DebugNode(pub FuncCall, pub Option<SyntaxTree>);
|
||||||
pub header: FuncHeader,
|
|
||||||
pub body: Option<SyntaxTree>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl Layout for DebugNode {
|
impl Layout for DebugNode {
|
||||||
@ -102,12 +96,12 @@ impl SpanlessEq for SyntaxNode {
|
|||||||
|
|
||||||
impl SpanlessEq for DebugNode {
|
impl SpanlessEq for DebugNode {
|
||||||
fn spanless_eq(&self, other: &Self) -> bool {
|
fn spanless_eq(&self, other: &Self) -> bool {
|
||||||
self.header.spanless_eq(&other.header)
|
self.0.spanless_eq(&other.0)
|
||||||
&& self.body.spanless_eq(&other.body)
|
&& self.1.spanless_eq(&other.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpanlessEq for FuncHeader {
|
impl SpanlessEq for FuncCall {
|
||||||
fn spanless_eq(&self, other: &Self) -> bool {
|
fn spanless_eq(&self, other: &Self) -> bool {
|
||||||
self.name.spanless_eq(&other.name)
|
self.name.spanless_eq(&other.name)
|
||||||
&& self.args.spanless_eq(&other.args)
|
&& self.args.spanless_eq(&other.args)
|
||||||
|
@ -8,6 +8,7 @@ use crate::paper::Paper;
|
|||||||
use crate::Feedback;
|
use crate::Feedback;
|
||||||
use super::expr::*;
|
use super::expr::*;
|
||||||
use super::span::Spanned;
|
use super::span::Spanned;
|
||||||
|
use super::tree::SyntaxTree;
|
||||||
|
|
||||||
/// Value types are used to extract values from functions, tuples and
|
/// Value types are used to extract values from functions, tuples and
|
||||||
/// objects. They represent the value part of an argument.
|
/// objects. They represent the value part of an argument.
|
||||||
@ -58,6 +59,7 @@ match_value!(String, "string", Expr::Str(s) => s);
|
|||||||
match_value!(bool, "bool", Expr::Bool(b) => b);
|
match_value!(bool, "bool", Expr::Bool(b) => b);
|
||||||
match_value!(f64, "number", Expr::Number(n) => n);
|
match_value!(f64, "number", Expr::Number(n) => n);
|
||||||
match_value!(Length, "length", Expr::Length(l) => l);
|
match_value!(Length, "length", Expr::Length(l) => l);
|
||||||
|
match_value!(SyntaxTree, "tree", Expr::Tree(t) => t);
|
||||||
match_value!(Tuple, "tuple", Expr::Tuple(t) => t);
|
match_value!(Tuple, "tuple", Expr::Tuple(t) => t);
|
||||||
match_value!(Object, "object", Expr::Object(o) => o);
|
match_value!(Object, "object", Expr::Object(o) => o);
|
||||||
match_value!(ScaleLength, "number or length",
|
match_value!(ScaleLength, "number or length",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user