diff --git a/src/eval/call.rs b/src/eval/call.rs index 186e7630d..a2387a175 100644 --- a/src/eval/call.rs +++ b/src/eval/call.rs @@ -59,13 +59,16 @@ impl Eval for Spanned<&ExprArgs> { /// Evaluated arguments to a function. #[derive(Debug)] pub struct Args { - span: Span, - pos: SpanVec, - named: Vec<(Spanned, Spanned)>, + /// The span of the whole argument list. + pub span: Span, + /// The positional arguments. + pub pos: SpanVec, + /// The named arguments. + pub named: Vec<(Spanned, Spanned)>, } impl Args { - /// Find the first convertible positional argument. + /// Find and remove the first convertible positional argument. pub fn find(&mut self, ctx: &mut EvalContext) -> Option where T: Cast>, @@ -73,8 +76,8 @@ impl Args { self.pos.iter_mut().find_map(move |slot| try_cast(ctx, slot)) } - /// Find the first convertible positional argument, producing an error if - /// no match was found. + /// Find and remove the first convertible positional argument, producing an + /// error if no match was found. pub fn require(&mut self, ctx: &mut EvalContext, what: &str) -> Option where T: Cast>, @@ -86,7 +89,7 @@ impl Args { found } - /// Filter out all convertible positional arguments. + /// Filter out and remove all convertible positional arguments. pub fn filter<'a, T>( &'a mut self, ctx: &'a mut EvalContext, @@ -97,8 +100,8 @@ impl Args { self.pos.iter_mut().filter_map(move |slot| try_cast(ctx, slot)) } - /// Convert the value for the given named argument, producing an error if - /// the conversion fails. + /// Convert and remove the value for the given named argument, producing an + /// error if the conversion fails. pub fn get<'a, T>(&mut self, ctx: &mut EvalContext, name: &str) -> Option where T: Cast>, @@ -108,6 +111,13 @@ impl Args { cast(ctx, value) } + /// Drain all remainings arguments into an array and a dictionary. + pub fn drain(&mut self) -> (ValueArray, ValueDict) { + let array = self.pos.drain(..).map(|s| s.v).collect(); + let dict = self.named.drain(..).map(|(k, v)| (k.v, v.v)).collect(); + (array, dict) + } + /// Produce "unexpected argument" errors for all remaining arguments. pub fn finish(self, ctx: &mut EvalContext) { let a = self.pos.iter().map(|v| v.as_ref()); diff --git a/src/parse/tests.rs b/src/parse/tests.rs index 9460db6b0..2e7a2af36 100644 --- a/src/parse/tests.rs +++ b/src/parse/tests.rs @@ -217,23 +217,6 @@ macro_rules! Let { }; } -#[test] -fn test_parse_comments() { - // In markup. - t!("a// you\nb" Text("a"), Space, Text("b")); - t!("* // \n /*\n\n*/*" Strong, Space, Space, Strong); - - // In code. - t!("[v /*12pt*/]" Call!("v")); - t!("[v //\n]" Call!("v")); - t!("[v 12, /*\n*/ size: 14]" Call!("v", Args![Int(12), "size" => Int(14)])); - - // Error. - t!("a*/b" - nodes: [Text("a"), Text("b")], - errors: [S(1..3, "unexpected end of block comment")]); -} - #[test] fn test_parse_simple_nodes() { // Basics. diff --git a/tests/ref/comments.png b/tests/ref/comments.png new file mode 100644 index 000000000..399d25a17 Binary files /dev/null and b/tests/ref/comments.png differ diff --git a/tests/typ/comments.typ b/tests/typ/comments.typ new file mode 100644 index 000000000..0dfb4b8ef --- /dev/null +++ b/tests/typ/comments.typ @@ -0,0 +1,23 @@ +// Test interaction with words, spacing and expressions. + +A// you +B + +C/* + /* */ +*/D + +[dump /*1*/ a: "b" // +, 1] + +--- +// Test error. +// +// ref: false +// error: 3:7-3:9 unexpected end of block comment + +// No start of block comment. +/* */ */ + +// Unterminated block comment is okay. +/* diff --git a/tests/typeset.rs b/tests/typeset.rs index 554c91497..f3c411519 100644 --- a/tests/typeset.rs +++ b/tests/typeset.rs @@ -15,7 +15,7 @@ use ttf_parser::OutlineBuilder; use typst::diag::{Diag, Feedback, Level, Pass}; use typst::env::{Env, ImageResource, ResourceLoader, SharedEnv}; -use typst::eval::State; +use typst::eval::{Args, EvalContext, State, Value, ValueFunc}; use typst::export::pdf; use typst::font::FontLoader; use typst::geom::{Length, Point, Sides, Size}; @@ -189,6 +189,13 @@ fn test_part(i: usize, src: &str, env: &SharedEnv) -> (bool, Vec) { state.page.size = Size::uniform(Length::pt(120.0)); state.page.margins = Sides::uniform(Some(Length::pt(10.0).into())); + pub fn dump(_: &mut EvalContext, args: &mut Args) -> Value { + let (array, dict) = args.drain(); + Value::Array(vec![Value::Array(array), Value::Dict(dict)]) + } + + Rc::make_mut(&mut state.scope).set("dump", ValueFunc::new("dump", dump)); + let Pass { output: mut frames, feedback: Feedback { mut diags, .. },