Refresh tests 🌊

This commit is contained in:
Laurenz 2021-02-17 21:30:20 +01:00
parent db1659a987
commit 2f4dc99cec
41 changed files with 328 additions and 389 deletions

View File

@ -1,23 +1,23 @@
#[page width: 450pt, height: 300pt, margins: 1cm] #page(width: 450pt, height: 300pt, margins: 1cm)
#[box][ #box[
*Technische Universität Berlin* \ *Technische Universität Berlin* \
*Fakultät II, Institut for Mathematik* \ *Fakultät II, Institut for Mathematik* \
Sekretariat MA \ Sekretariat MA \
Dr. Max Mustermann \ Dr. Max Mustermann \
Ola Nordmann, John Doe Ola Nordmann, John Doe
] ]
#[align right | box][*WiSe 2019/2020* \ Woche 3] #align(right, box[*WiSe 2019/2020* \ Woche 3])
#[v 6mm] #v(6mm)
#[align center][ #align(center)[
==== 3. Übungsblatt Computerorientierte Mathematik II #[v 2mm] ==== 3. Übungsblatt Computerorientierte Mathematik II #v(2mm)
*Abgabe: 03.05.2019* (bis 10:10 Uhr in MA 001) #[v 2mm] *Abgabe: 03.05.2019* (bis 10:10 Uhr in MA 001) #v(2mm)
*Alle Antworten sind zu beweisen.* *Alle Antworten sind zu beweisen.*
] ]
*1. Aufgabe* #[align right][(1 + 1 + 2 Punkte)] *1. Aufgabe* #align(right)[(1 + 1 + 2 Punkte)]
Ein _Binärbaum_ ist ein Wurzelbaum, in dem jeder Knoten 2 Kinder hat. Ein _Binärbaum_ ist ein Wurzelbaum, in dem jeder Knoten 2 Kinder hat.
Die Tiefe eines Knotens _v_ ist die Länge des eindeutigen Weges von der Wurzel Die Tiefe eines Knotens _v_ ist die Länge des eindeutigen Weges von der Wurzel

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -19,13 +19,13 @@
, #003 , #003
,)} ,)}
// Error: 3-3 expected closing paren // Error: 3 expected closing paren
{(} {(}
// Error: 2-3 expected expression, found closing paren // Error: 2-3 expected expression, found closing paren
{)} {)}
// Error: 2:4-2:4 expected comma // Error: 2:4 expected comma
// Error: 1:4-1:6 expected expression, found end of block comment // Error: 1:4-1:6 expected expression, found end of block comment
{(1*/2)} {(1*/2)}
@ -36,7 +36,7 @@
{(,1)} {(,1)}
// Missing expression makes named pair incomplete, making this an empty array. // Missing expression makes named pair incomplete, making this an empty array.
// Error: 5-5 expected expression // Error: 5 expected expression
{(a:)} {(a:)}
// Named pair after this is already identified as an array. // Named pair after this is already identified as an array.

View File

@ -7,28 +7,28 @@
{1u} {1u}
// Should output `1`. // Should output `1`.
// Error: 3-3 expected semicolon or line break // Error: 3 expected semicolon or line break
{0 1} {0 1}
// Should output `2`. // Should output `2`.
// Error: 2:13-2:13 expected semicolon or line break // Error: 2:12 expected semicolon or line break
// Error: 1:24-1:24 expected semicolon or line break // Error: 1:22 expected semicolon or line break
{#let x = -1 #let y = 3 x + y} {let x = -1 let y = 3 x + y}
// Should output `3`. // Should output `3`.
{ {
// Error: 10-13 expected identifier, found string // Error: 9-12 expected identifier, found string
#for "v" for "v"
// Error: 11-11 expected keyword `#in` // Error: 10 expected keyword `#in`
#for v #let z = 1 + 2 for v let z = 1 + 2
z z
} }
--- ---
// Ref: false // Ref: false
// Error: 3:1-3:1 expected closing brace // Error: 3:1 expected closing brace
{ {
--- ---

View File

@ -3,17 +3,17 @@
--- ---
// Block in template does not create a scope. // Block in template does not create a scope.
{ #let x = 1 } { let x = 1 }
#[test x, 1] #test(x, 1)
--- ---
// Block in expression does create a scope. // Block in expression does create a scope.
#let a = { #let a = {
#let b = 1 let b = 1
b b
} }
#[test a, 1] #test(a, 1)
// Error: 2-3 unknown variable // Error: 2-3 unknown variable
{b} {b}
@ -21,12 +21,12 @@
--- ---
// Multiple nested scopes. // Multiple nested scopes.
{ {
#let a = "a1" let a = "a1"
{ {
#let a = "a2" let a = "a2"
{ {
test(a, "a2") test(a, "a2")
#let a = "a3" let a = "a3"
test(a, "a3") test(a, "a3")
} }
test(a, "a2") test(a, "a2")

View File

@ -7,7 +7,7 @@ All none
{} {}
// Let evaluates to none. // Let evaluates to none.
{ #let v = 0 } { let v = 0 }
// Trailing none evaluates to none. // Trailing none evaluates to none.
{ {
@ -20,19 +20,19 @@ All none
{ "Hello" } { "Hello" }
// Evaluates to trailing expression. // Evaluates to trailing expression.
{ #let x = "Hel"; x + "lo" } { let x = "Hel"; x + "lo" }
// Evaluates to concatenation of for loop bodies. // Evaluates to concatenation of for loop bodies.
{ {
#let parts = ("Hel", "lo") let parts = ("Hel", "lo")
#for s #in parts [{s}] for s in parts [{s}]
} }
--- ---
// Works the same way in code environment. // Works the same way in code environment.
// Ref: false // Ref: false
#[test { #test(3, {
#let x = 1 let x = 1
#let y = 2 let y = 2
x + y x + y
}, 3] })

View File

@ -2,33 +2,33 @@
--- ---
// One argument. // One argument.
#[f bold] #f(bold)
// One argument and trailing comma. // One argument and trailing comma.
#[f 1,] #f(1,)
// One named argument. // One named argument.
#[f a:2] #f(a:2)
// Mixed arguments. // Mixed arguments.
{f(1, a: (3, 4), 2, b: "5")} {f(1, a: (3, 4), 2, b: "5")}
--- ---
// Error: 5-6 expected expression, found colon // Error: 4-5 expected expression, found colon
#[f :] #f(:)
// Error: 8-10 expected expression, found end of block comment // Error: 7-9 expected expression, found end of block comment
#[f a:1*/] #f(a:1*/)
// Error: 6-6 expected comma // Error: 5 expected comma
#[f 1 2] #f(1 2)
// Error: 2:5-2:6 expected identifier // Error: 2:4-2:5 expected identifier
// Error: 1:7-1:7 expected expression // Error: 1:6 expected expression
#[f 1:] #f(1:)
// Error: 5-6 expected identifier // Error: 4-5 expected identifier
#[f 1:2] #f(1:2)
// Error: 4-7 expected identifier // Error: 4-7 expected identifier
{f((x):1)} {f((x):1)}

View File

@ -1,48 +0,0 @@
// Test bracketed function calls.
---
// Whitespace is insignificant.
#[ f ]
// Alternatives for embedding.
#[f f()], #[f #[f]], #[f][#[f]],
// Tight functions.
#[f]#[f]
// Multi-paragraph body.
#[align right][
First
Second
]
---
// Chained once.
#[f | f]
// Chained twice.
#[f|f|f]
// With body.
// Error: 7-8 expected identifier, found integer
#[f | 1 | box][💕]
// With actual functions.
#[box width: 1cm | image "res/rhino.png"]
---
// Error: 8-8 expected identifier
#[f 1 |]
// Error: 4-4 expected identifier
#[ | f true]
// Error: 2:3-2:3 expected identifier
// Error: 1:4-1:4 expected identifier
#[|][Nope]
// Pipe wins over parens.
// Error: 2:6-2:6 expected closing paren
// Error: 1:9-1:10 expected expression, found closing paren
#[f (|f )]

View File

@ -1,36 +1,24 @@
// Test invalid function calls. // Test invalid function calls.
--- ---
// Error: 4-4 expected closing paren // Error: 1-2 unexpected invalid token
{f(} #
---
// Error: 4:1-4:1 expected identifier
// Error: 3:1-3:1 expected closing bracket
#[
---
// Error: 3-3 expected identifier
#[]
// Error: 3-6 expected identifier, found string
#["f"]
// Error: 2:3-2:4 expected identifier, found opening paren
// Error: 1:5-1:6 expected expression, found closing paren
#[(f)]
--- ---
#let x = "string" #let x = "string"
// Error: 3-4 expected function, found string // Error: 2-3 expected function, found string
#[x] #x()
--- ---
// Error: 3:1-3:1 expected closing bracket // Error: 3:1 expected closing bracket
#[f][`a]` #f[`a]`
--- ---
// Error: 3:1-3:1 expected quote // Error: 4 expected closing paren
// Error: 2:1-2:1 expected closing bracket {f(}
#[f "]
---
// Error: 3:1 expected quote
// Error: 2:1 expected closing bracket
#f("]

View File

@ -1,11 +0,0 @@
// Test parenthesized function calls.
// Ref: false
---
// Whitespace insignificant.
#[test type(1), "integer"]
#[test type (1), "integer"]
// From variable.
#let alias = type
#[test alias(alias), "function"]

View File

@ -0,0 +1,14 @@
// Test function calls.
// Ref: false
---
// Whitespace is insignificant.
#test(type(1), "integer")
#test (type (1), "integer")
// From variable.
#let alias = type
#test(alias(alias), "function")
// Returns template.
#test(type(font(12pt)), "template")

View File

@ -11,8 +11,8 @@ C/*
*/D */D
// Works in code. // Works in code.
#[test type /*1*/ (1) // #test(type /*1*/ (1) //
, "integer"] , "integer")
--- ---
// End should not appear without start. // End should not appear without start.

View File

@ -14,7 +14,7 @@
// Identified as dictionary due to initial colon. // Identified as dictionary due to initial colon.
// Error: 4:4-4:5 expected named pair, found expression // Error: 4:4-4:5 expected named pair, found expression
// Error: 3:5-3:5 expected comma // Error: 3:5 expected comma
// Error: 2:12-2:16 expected identifier // Error: 2:12-2:16 expected identifier
// Error: 1:17-1:18 expected expression, found colon // Error: 1:17-1:18 expected expression, found colon
{(:1 b:[], true::)} {(:1 b:[], true::)}

View File

@ -26,5 +26,5 @@
\u{FFFFFF} \u{FFFFFF}
// Unterminated. // Unterminated.
// Error: 6-6 expected closing brace // Error: 6 expected closing brace
\u{41*Bold* \u{41*Bold*

View File

@ -3,15 +3,15 @@
--- ---
// Math operators are left-associative. // Math operators are left-associative.
#[test 10 / 2 / 2 == (10 / 2) / 2, true] #test(10 / 2 / 2 == (10 / 2) / 2, true)
#[test 10 / 2 / 2 == 10 / (2 / 2), false] #test(10 / 2 / 2 == 10 / (2 / 2), false)
#[test 1 / 2 * 3, 1.5] #test(1 / 2 * 3, 1.5)
--- ---
// Assignment is right-associative. // Assignment is right-associative.
{ {
#let x = 1 let x = 1
#let y = 2 let y = 2
x = y = "ok" x = y = "ok"
test(x, none) test(x, none)
test(y, "ok") test(y, "ok")

View File

@ -10,30 +10,30 @@
// Test math operators. // Test math operators.
// Addition. // Addition.
#[test 2 + 4, 6] #test(2 + 4, 6)
#[test "a" + "b", "ab"] #test("a" + "b", "ab")
#[test (1, 2) + (3, 4), (1, 2, 3, 4)] #test((1, 2) + (3, 4), (1, 2, 3, 4))
#[test (a: 1) + (b: 2, c: 3), (a: 1, b: 2, c: 3)] #test((a: 1) + (b: 2, c: 3), (a: 1, b: 2, c: 3))
// Subtraction. // Subtraction.
#[test 1-4, 3*-1] #test(1-4, 3*-1)
#[test 4cm - 2cm, 2cm] #test(4cm - 2cm, 2cm)
#[test 1e+2-1e-2, 99.99] #test(1e+2-1e-2, 99.99)
// Multiplication. // Multiplication.
#[test 2 * 4, 8] #test(2 * 4, 8)
// Division. // Division.
#[test 12pt/.4, 30pt] #test(12pt/.4, 30pt)
#[test 7 / 2, 3.5] #test(7 / 2, 3.5)
// Combination. // Combination.
#[test 3-4 * 5 < -10, true] #test(3-4 * 5 < -10, true)
#[test { #let x; x = 1 + 4*5 >= 21 and { x = "a"; x + "b" == "ab" }; x }, true] #test({ let x; x = 1 + 4*5 >= 21 and { x = "a"; x + "b" == "ab" }; x }, true)
// Mathematical identities. // Mathematical identities.
#let nums = (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt) #let nums = (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt)
#for v #in nums { #for v in nums {
// Test plus and minus. // Test plus and minus.
test(v + v - v, v) test(v + v - v, v)
test(v - v - v, -v) test(v - v - v, -v)
@ -43,12 +43,12 @@
test(v + v, 2 * v) test(v + v, 2 * v)
// Integer addition does not give a float. // Integer addition does not give a float.
#if type(v) != "integer" { if type(v) != "integer" {
test(v + v, 2.0 * v) test(v + v, 2.0 * v)
} }
// Linears cannot be divided by themselves. // Linears cannot be divided by themselves.
#if type(v) != "linear" { if type(v) != "linear" {
test(v / v, 1.0) test(v / v, 1.0)
test(v / v == 1, true) test(v / v == 1, true)
} }
@ -59,12 +59,12 @@
// - multiplied with integers and floats, // - multiplied with integers and floats,
// - divided by floats. // - divided by floats.
#let dims = (10pt, 30%, 50% + 3cm) #let dims = (10pt, 30%, 50% + 3cm)
#for a #in dims { #for a in dims {
#for b #in dims { for b in dims {
test(type(a + b), type(a - b)) test(type(a + b), type(a - b))
} }
#for b #in (7, 3.14) { for b in (7, 3.14) {
test(type(a * b), type(a)) test(type(a * b), type(a))
test(type(b * a), type(a)) test(type(b * a), type(a))
test(type(a / b), type(a)) test(type(a / b), type(a))
@ -75,57 +75,57 @@
// Test boolean operators. // Test boolean operators.
// And. // And.
#[test false and false, false] #test(false and false, false)
#[test false and true, false] #test(false and true, false)
#[test true and false, false] #test(true and false, false)
#[test true and true, true] #test(true and true, true)
// Or. // Or.
#[test false or false, false] #test(false or false, false)
#[test false or true, true] #test(false or true, true)
#[test true or false, true] #test(true or false, true)
#[test true or true, true] #test(true or true, true)
// Short-circuiting. // Short-circuiting.
#[test false and dont-care, false] #test(false and dont-care, false)
#[test true or dont-care, true] #test(true or dont-care, true)
--- ---
// Test equality operators. // Test equality operators.
#[test 1 == "hi", false] #test(1 == "hi", false)
#[test 1 == 1.0, true] #test(1 == 1.0, true)
#[test 30% == 30% + 0cm, true] #test(30% == 30% + 0cm, true)
#[test 1in == 0% + 72pt, true] #test(1in == 0% + 72pt, true)
#[test 30% == 30% + 1cm, false] #test(30% == 30% + 1cm, false)
#[test "ab" == "a" + "b", true] #test("ab" == "a" + "b", true)
#[test () == (1,), false] #test(() == (1,), false)
#[test (1, 2, 3) == (1, 2.0) + (3,), true] #test((1, 2, 3) == (1, 2.0) + (3,), true)
#[test (:) == (a: 1), false] #test((:) == (a: 1), false)
#[test (a: 2 - 1.0, b: 2) == (b: 2, a: 1), true] #test((a: 2 - 1.0, b: 2) == (b: 2, a: 1), true)
#[test [*Hi*] == [*Hi*], true] #test([*Hi*] == [*Hi*], true)
#[test "a" != "a", false] #test("a" != "a", false)
#[test [*] != [_], true] #test([*] != [_], true)
--- ---
// Test comparison operators. // Test comparison operators.
#[test 13 * 3 < 14 * 4, true] #test(13 * 3 < 14 * 4, true)
#[test 5 < 10, true] #test(5 < 10, true)
#[test 5 > 5, false] #test(5 > 5, false)
#[test 5 <= 5, true] #test(5 <= 5, true)
#[test 5 <= 4, false] #test(5 <= 4, false)
#[test 45deg < 1rad, true] #test(45deg < 1rad, true)
--- ---
// Test assignment operators. // Test assignment operators.
#let x = 0 #let x = 0
{ x = 10 } #[test x, 10] { x = 10 } #test(x, 10)
{ x -= 5 } #[test x, 5] { x -= 5 } #test(x, 5)
{ x += 1 } #[test x, 6] { x += 1 } #test(x, 6)
{ x *= x } #[test x, 36] { x *= x } #test(x, 36)
{ x /= 2.0 } #[test x, 18.0] { x /= 2.0 } #test(x, 18.0)
{ x = "some" } #[test x, "some"] { x = "some" } #test(x, "some")
{ x += "thing" } #[test x, "something"] { x += "thing" } #test(x, "something")

View File

@ -4,14 +4,14 @@
--- ---
// Missing expressions. // Missing expressions.
// Error: 3-3 expected expression // Error: 3 expected expression
{-} {-}
// Error: 11-11 expected expression // Error: 10 expected expression
#[test {1+}, 1] #test({1+}, 1)
// Error: 11-11 expected expression // Error: 10 expected expression
#[test {2*}, 2] #test({2*}, 2)
--- ---
// Mismatched types. // Mismatched types.
@ -36,7 +36,7 @@
{(1 + "2", 40% - 1, 2 * true, 3 / 12pt)} {(1 + "2", 40% - 1, 2 * true, 3 / 12pt)}
// Error: 15-23 cannot apply '+=' to integer and string // Error: 15-23 cannot apply '+=' to integer and string
{ #let x = 1; x += "2" } { let x = 1; x += "2" }
--- ---
// Bad left-hand sides of assignment. // Bad left-hand sides of assignment.

View File

@ -3,14 +3,14 @@
--- ---
// Multiplication binds stronger than addition. // Multiplication binds stronger than addition.
#[test 1+2*-3, -5] #test(1+2*-3, -5)
// Subtraction binds stronger than comparison. // Subtraction binds stronger than comparison.
#[test 3 == 5 - 2, true] #test(3 == 5 - 2, true)
// Boolean operations bind stronger than '=='. // Boolean operations bind stronger than '=='.
#[test "a" == "a" and 2 < 3, true] #test("a" == "a" and 2 < 3, true)
#[test not "b" == "b", false] #test(not "b" == "b", false)
// Assignment binds stronger than boolean operations. // Assignment binds stronger than boolean operations.
// Error: 2-7 cannot assign to this expression // Error: 2-7 cannot assign to this expression
@ -18,11 +18,11 @@
--- ---
// Parentheses override precedence. // Parentheses override precedence.
#[test (1), 1] #test((1), 1)
#[test (1+2)*-3, -9] #test((1+2)*-3, -9)
// Error: 15-15 expected closing paren // Error: 15 expected closing paren
#[test {(1 + 1}, 2] #test({(1 + 1}, 2)
--- ---
// Precedence doesn't matter for chained unary operators. // Precedence doesn't matter for chained unary operators.

View File

@ -3,7 +3,7 @@
--- ---
// Test plus and minus. // Test plus and minus.
#for v #in (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt) { #for v in (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt) {
// Test plus. // Test plus.
test(+v, v) test(+v, v)
@ -15,9 +15,9 @@
test(-++ --v, -v) test(-++ --v, -v)
} }
#[test -(4 + 2), 6-12] #test(-(4 + 2), 6-12)
--- ---
// Test not. // Test not.
#[test not true, false] #test(not true, false)
#[test not false, true] #test(not false, true)

View File

@ -7,29 +7,26 @@
// Error: 7-7 expected keyword `#in` // Error: 7-7 expected keyword `#in`
#for v #for v
// Error: 11-11 expected expression // Error: 10-10 expected expression
#for v #in #for v in
// Error: 16-16 expected body // Error: 15-15 expected body
#for v #in iter #for v in iter
--- ---
// Should output `v iter`. // Should output `v in iter`.
// Error: 2:5-2:5 expected identifier // Error: 5 expected identifier
// Error: 2:3-2:6 unexpected keyword `#in`
#for #for
v #in iter {} v in iter {}
// Should output `A thing`. // Should output `A thing`.
// Error: 7-10 expected identifier, found string // Error: 7-10 expected identifier, found string
A#for "v" thing. A#for "v" thing.
// Should output `iter`. // Should output `in iter`.
// Error: 2:6-2:9 expected identifier, found string // Error: 6-9 expected identifier, found string
// Error: 1:10-1:13 unexpected keyword `#in` #for "v" in iter {}
#for "v" #in iter {}
// Should output `+ b iter`. // Should output `+ b in iter`.
// Error: 2:7-2:7 expected keyword `#in` // Error: 7 expected keyword `#in`
// Error: 1:12-1:15 unexpected keyword `#in` #for a + b in iter {}
#for a + b #in iter {}

View File

@ -4,28 +4,29 @@
--- ---
// Array. // Array.
#for x #in () {} #for x in () {}
#let sum = 0 #let sum = 0
#for x #in (1, 2, 3, 4, 5) { #for x in (1, 2, 3, 4, 5) {
sum += x sum += x
} }
#[test sum, 15]
#test(sum, 15)
--- ---
// Dictionary. // Dictionary.
// Ref: true // Ref: true
(\ #for k, v #in (name: "Typst", age: 2) [ (\ #for k, v in (name: "Typst", age: 2) [
#[h 0.5cm] {k}: {v}, \ #h(0.5cm) {k}: {v}, \
]) ])
--- ---
// String. // String.
{ {
#let out = "" let out = ""
#let first = true let first = true
#for c #in "abc" { for c in "abc" {
#if not first { if not first {
out += ", " out += ", "
} }
first = false first = false
@ -36,16 +37,16 @@
--- ---
// Uniterable expression. // Uniterable expression.
// Error: 12-16 cannot loop over boolean // Error: 11-15 cannot loop over boolean
#for v #in true {} #for v in true {}
// Make sure that we don't complain twice. // Make sure that we don't complain twice.
// Error: 12-19 cannot add integer and string // Error: 11-18 cannot add integer and string
#for v #in 1 + "2" {} #for v in 1 + "2" {}
// Error: 14-17 cannot apply '-' to string // Error: 14-17 cannot apply '-' to string
#let error = -"" #let error = -""
#let result = #for v #in (1, 2, 3) { #let result = for v in (1, 2, 3) {
#if v < 2 [Ok] #else {error} if v < 2 [Ok] else {error}
} }
#[test result, error] #test(result, error)

View File

@ -5,26 +5,26 @@
#let out = () #let out = ()
// Values of array. // Values of array.
#for v #in (1, 2, 3) { #for v in (1, 2, 3) {
out += (v,) out += (v,)
} }
// Values of dictionary. // Values of dictionary.
#for v #in (a: 4, b: 5) { #for v in (a: 4, b: 5) {
out += (v,) out += (v,)
} }
// Keys and values of dictionary. // Keys and values of dictionary.
#for k, v #in (a: 6, b: 7) { #for k, v in (a: 6, b: 7) {
out += (k,) out += (k,)
out += (v,) out += (v,)
} }
#[test out, (1, 2, 3, 4, 5, "a", 6, "b", 7)] #test(out, (1, 2, 3, 4, 5, "a", 6, "b", 7))
--- ---
// Keys and values of array. // Keys and values of array.
// Error: 6-10 mismatched pattern // Error: 6-10 mismatched pattern
#for k, v #in (-1, -2, -3) { #for k, v in (-1, -2, -3) {
dont-care dont-care
} }

View File

@ -3,18 +3,18 @@
--- ---
// Template body yields template. // Template body yields template.
// Should output `234`. // Should output `234`.
#for v #in (1, 2, 3, 4) [#if v >= 2 [{v}]] #for v in (1, 2, 3, 4) [#if v >= 2 [{v}]]
--- ---
// Block body yields template. // Block body yields template.
// Should output `[1st, 2nd, 3rd, 4th, 5th, 6th]`. // Should output `[1st, 2nd, 3rd, 4th, 5th, 6th]`.
{ {
"[" + #for v #in (1, 2, 3, 4, 5, 6) { "[" + for v in (1, 2, 3, 4, 5, 6) {
(#if v > 1 [, ] (if v > 1 [, ]
+ [{v}] + [{v}]
+ #if v == 1 [st] + if v == 1 [st]
+ #if v == 2 [nd] + if v == 2 [nd]
+ #if v == 3 [rd] + if v == 3 [rd]
+ #if v >= 4 [th]) + if v >= 4 [th])
} + "]" } + "]"
} }

View File

@ -9,7 +9,7 @@
======6 ======6
// Too many hashtags. // Too many hashtags.
// Warning: 1:1-1:8 should not exceed depth 6 // Warning: 1-8 should not exceed depth 6
=======7 =======7
--- ---
@ -21,7 +21,7 @@
} }
// Function call continues heading. // Function call continues heading.
= #[box][ = #box[
A A
] B ] B
@ -35,7 +35,7 @@ B
// Parsed as headings if at start of the context. // Parsed as headings if at start of the context.
/**/ = Ok /**/ = Ok
{[== Ok]} {[== Ok]}
#[box][=== Ok] #box[=== Ok]
// Not at the start of the context. // Not at the start of the context.
No = heading No = heading

View File

@ -30,7 +30,7 @@
#if false [ #if false [
Bad. Bad.
] #else { ] #else {
#let pt = "." let pt = "."
"Ok" + pt "Ok" + pt
} }

View File

@ -1,13 +1,13 @@
// Test invalid if syntax. // Test invalid if syntax.
--- ---
// Error: 4-4 expected expression // Error: 4 expected expression
#if #if
// Error: 5-5 expected expression // Error: 4 expected expression
{#if} {if}
// Error: 6-6 expected body // Error: 6 expected body
#if x #if x
// Error: 1-6 unexpected keyword `#else` // Error: 1-6 unexpected keyword `#else`
@ -15,14 +15,14 @@
--- ---
// Should output `x`. // Should output `x`.
// Error: 4-4 expected expression // Error: 4 expected expression
#if #if
x {} x {}
// Should output `something`. // Should output `something`.
// Error: 6-6 expected body // Error: 6 expected body
#if x something #if x something
// Should output `A thing.` // Should output `A thing.`
// Error: 20-20 expected body // Error: 20 expected body
A#if false {} #else thing A#if false {} #else thing

View File

@ -3,19 +3,19 @@
--- ---
{ {
#let x = 1 let x = 1
#let y = 2 let y = 2
#let z let z
// Returns if branch. // Returns if branch.
z = #if x < y { "ok" } z = if x < y { "ok" }
test(z, "ok") test(z, "ok")
// Returns else branch. // Returns else branch.
z = #if x > y { "bad" } #else { "ok" } z = if x > y { "bad" } else { "ok" }
test(z, "ok") test(z, "ok")
// Missing else evaluates to none. // Missing else evaluates to none.
z = #if x > y { "bad" } z = if x > y { "bad" }
test(z, none) test(z, none)
} }

View File

@ -1,17 +1,17 @@
// Test invalid let binding syntax. // Test invalid let binding syntax.
--- ---
// Error: 5-5 expected identifier // Error: 5 expected identifier
#let #let
// Error: 6-9 expected identifier, found string // Error: 6-9 expected identifier, found string
#let "v" #let "v"
// Should output `1`. // Should output `1`.
// Error: 7-7 expected semicolon or line break // Error: 7 expected semicolon or line break
#let v 1 #let v 1
// Error: 9-9 expected expression // Error: 9 expected expression
#let v = #let v =
--- ---

View File

@ -13,16 +13,16 @@ One
Three Three
// Terminated because expression ends. // Terminated because expression ends.
// Error: 12-12 expected semicolon or line break // Error: 12 expected semicolon or line break
#let v4 = 4 Four #let v4 = 4 Four
// Terminated by semicolon even though we are in a paren group. // Terminated by semicolon even though we are in a paren group.
// Error: 2:19-2:19 expected expression // Error: 2:19 expected expression
// Error: 1:19-1:19 expected closing paren // Error: 1:19 expected closing paren
#let v5 = (1, 2 + ; Five #let v5 = (1, 2 + ; Five
#[test v1, 1] #test(v1, 1)
#[test v2, 2] #test(v2, 2)
#[test v3, 3] #test(v3, 3)
#[test v4, 4] #test(v4, 4)
#[test v5, (1, 2)] #test(v5, (1, 2))

View File

@ -4,8 +4,8 @@
--- ---
// Automatically initialized with none. // Automatically initialized with none.
#let x #let x
#[test x, none] #test(x, none)
// Manually initialized with one. // Manually initialized with one.
#let x = 1 #let x = 1
#[test x, 1] #test(x, 1)

View File

@ -47,5 +47,5 @@ def hi():
--- ---
// Unterminated. // Unterminated.
// Error: 2:1-2:1 expected backtick(s) // Error: 2:1 expected backtick(s)
`endless `endless

View File

@ -3,11 +3,11 @@
--- ---
// Spacing around let. // Spacing around let.
// Error: 6-6 expected identifier // Error: 6 expected identifier
A#let;B \ A#let;B \
A#let x = 1;B #[test x, 1] \ A#let x = 1;B #test(x, 1) \
A #let x = 2;B #[test x, 2] \ A #let x = 2;B #test(x, 2) \
A#let x = 3; B #[test x, 3] \ A#let x = 3; B #test(x, 3) \
--- ---
// Spacing around if-else. // Spacing around if-else.
@ -22,6 +22,6 @@ A#if true [B] #else [] C \
--- ---
// Spacing around for loop. // Spacing around for loop.
A#for _ #in (none,) [B]C \ A#for _ in (none,) [B]C \
A#for _ #in (none,) [B] C \ A#for _ in (none,) [B] C \
A #for _ #in (none,) [B]C \ A #for _ in (none,) [B]C \

View File

@ -8,7 +8,7 @@
Partly str*ength*ened. Partly str*ength*ened.
// Scoped to body. // Scoped to body.
#[box][*Scoped] to body. #box[*Scoped] to body.
// Unterminated is fine. // Unterminated is fine.
*The End *The End

View File

@ -1,20 +1,20 @@
#[page "a7", flip: true] #page("a7", flip: true)
// Box with fixed width, should have text height. // Box with fixed width, should have text height.
#[box width: 2cm, color: #9650D6][A] #box(width: 2cm, color: #9650D6)[A]
Sometimes there is no box. Sometimes there is no box.
// Box with fixed height, should span line. // Box with fixed height, should span line.
#[box height: 2cm, width: 100%, color: #734CED][B] #box(height: 2cm, width: 100%, color: #734CED)[B]
// Empty box with fixed width and height. // Empty box with fixed width and height.
#[box width: 6cm, height: 12pt, color: #CB4CED] #box(width: 6cm, height: 12pt, color: #CB4CED)
// Not visiblem, but creates a gap between the boxes above and below. // Not visiblem, but creates a gap between the boxes above and below.
#[box width: 2in, color: #ff0000] #box(width: 2in, color: #ff0000)
// These are in a row! // These are in a row!
#[box width: 1in, height: 10pt, color: #D6CD67] #box(width: 1in, height: 10pt, color: #D6CD67)
#[box width: 1in, height: 10pt, color: #EDD466] #box(width: 1in, height: 10pt, color: #EDD466)
#[box width: 1in, height: 10pt, color: #E3BE62] #box(width: 1in, height: 10pt, color: #E3BE62)

View File

@ -1,37 +1,37 @@
// Test configuring font properties. // Test configuring font properties.
#[font "PT Sans", 10pt] #font("PT Sans", 10pt)
// Set same font size in three different ways. // Set same font size in three different ways.
#[font 20pt][A] #font(20pt)[A]
#[font 200%][A] #font(200%)[A]
#[font 15pt + 50%][A] #font(15pt + 50%)[A]
// Do nothing. // Do nothing.
#[font][Normal] #font[Normal]
// Set style (is available). // Set style (is available).
#[font style: italic][Italic] #font(style: italic)[Italic]
// Set weight (is available). // Set weight (is available).
#[font weight: bold][Bold] #font(weight: bold)[Bold]
// Set stretch (not available, matching closest). // Set stretch (not available, matching closest).
#[font stretch: ultra-condensed][Condensed] #font(stretch: ultra-condensed)[Condensed]
// Error: 8-13 unexpected argument // Error: 7-12 unexpected argument
#[font false] #font(false)
// Error: 3:15-3:19 expected font style, found font weight // Error: 3:14-3:18 expected font style, found font weight
// Error: 2:29-2:35 expected font weight, found string // Error: 2:28-2:34 expected font weight, found string
// Error: 1:44-1:45 expected font family or array of font families, found integer // Error: 1:43-1:44 expected font family or array of font families, found integer
#[font style: bold, weight: "thin", serif: 0] #font(style: bold, weight: "thin", serif: 0)
// Warning: 16-20 should be between 100 and 900 // Warning: 15-19 should be between 100 and 900
#[font weight: 2700] #font(weight: 2700)
// Error: 8-28 unexpected argument // Error: 7-27 unexpected argument
#[font something: "invalid"] #font(something: "invalid")
--- ---
// Test font fallback and class definitions. // Test font fallback and class definitions.
@ -40,17 +40,17 @@
Emoji: 🏀 Emoji: 🏀
// CMU Serif + Noto Emoji. // CMU Serif + Noto Emoji.
#[font "CMU Serif", "Noto Emoji"][ #font("CMU Serif", "Noto Emoji")[
Emoji: 🏀 Emoji: 🏀
] ]
// Class definitions. // Class definitions.
#[font serif: ("CMU Serif", "Latin Modern Math", "Noto Emoji")] #font(serif: ("CMU Serif", "Latin Modern Math", "Noto Emoji"))
#[font serif][ #font(serif)[
Math: α + β 3 Math: α + β 3
] ]
// Class definition reused. // Class definition reused.
#[font sans-serif: "Noto Emoji"] #font(sans-serif: "Noto Emoji")
#[font sans-serif: ("Archivo", sans-serif)] #font(sans-serif: ("Archivo", sans-serif))
New sans-serif. 🚀 New sans-serif. 🚀

View File

@ -1,22 +1,22 @@
// Ends paragraphs. // Ends paragraphs.
Tightly #[v -5pt] packed Tightly #v(-5pt) packed
// Eating up soft spacing. // Eating up soft spacing.
Inv #[h 0pt] isible Inv #h(0pt) isible
// Multiple spacings in a row. // Multiple spacings in a row.
Add #[h 10pt] #[h 10pt] up Add #h(10pt) #h(10pt) up
// Relative to font size. // Relative to font size.
Relative #[h 100%] spacing Relative #h(100%) spacing
// Missing spacing. // Missing spacing.
// Error: 12-12 missing argument: spacing // Error: 12 missing argument: spacing
Totally #[h] ignored Totally #h() ignored
// Swapped axes. // Swapped axes.
#[page main-dir: rtl, cross-dir: ttb, height: 80pt][ #page(main-dir: rtl, cross-dir: ttb, height: 80pt)[
1 #[h 1cm] 2 1 #h(1cm) 2
3 #[v 1cm] 4 #[v -1cm] 5 3 #v(1cm) 4 #v(-1cm) 5
] ]

View File

@ -1,39 +1,35 @@
// Test loading different image formats. // Test loading different image formats.
// Load an RGBA PNG image. // Load an RGBA PNG image.
#[image "res/rhino.png"] #image("res/rhino.png")
#[pagebreak] #pagebreak()
// Load an RGB JPEG image. // Load an RGB JPEG image.
#[image "res/tiger.jpg"] #image("res/tiger.jpg")
// Error: 9-30 failed to load image // Error: 9-30 failed to load image
#[image "path/does/not/exist"] #image("path/does/not/exist")
// Error: 9-30 failed to load image // Error: 9-30 failed to load image
#[image "typ/image-error.typ"] #image("typ/image-error.typ")
--- ---
// Test configuring the size and fitting behaviour of images. // Test configuring the size and fitting behaviour of images.
// Fit to width of page. // Fit to width of page.
#[image "res/rhino.png"] #image("res/rhino.png")
// Fit to height of page. // Fit to height of page.
#[page height: 40pt][ #page(height: 40pt, image("res/rhino.png"))
#[image "res/rhino.png"]
]
// Set width explicitly. // Set width explicitly.
#[image "res/rhino.png", width: 50pt] #image("res/rhino.png", width: 50pt)
// Set height explicitly. // Set height explicitly.
#[image "res/rhino.png", height: 50pt] #image("res/rhino.png", height: 50pt)
// Set width and height explicitly and force stretching. // Set width and height explicitly and force stretching.
#[image "res/rhino.png", width: 25pt, height: 50pt] #image("res/rhino.png", width: 25pt, height: 50pt)
// Make sure the bounding-box of the image is correct. // Make sure the bounding-box of the image is correct.
#[align bottom, right][ #align(bottom, right, image("res/tiger.jpg", width: 60pt))
#[image "res/tiger.jpg", width: 60pt]
]

View File

@ -1,53 +1,53 @@
// Test configuring page sizes and margins. // Test configuring page sizes and margins.
// Set width and height. // Set width and height.
#[page width: 120pt, height: 120pt] #page(width: 120pt, height: 120pt)
#[page width: 40pt][High] #page(width: 40pt)[High]
#[page height: 40pt][Wide] #page(height: 40pt)[Wide]
// Set all margins at once. // Set all margins at once.
#[page margins: 30pt][ #page(margins: 30pt)[
#[align top, left][TL] #align(top, left)[TL]
#[align bottom, right][BR] #align(bottom, right)[BR]
] ]
// Set individual margins. // Set individual margins.
#[page height: 40pt] #page(height: 40pt)
#[page left: 0pt | align left][Left] #page(left: 0pt, align(left)[Left])
#[page right: 0pt | align right][Right] #page(right: 0pt, align(right)[Right])
#[page top: 0pt | align top][Top] #page(top: 0pt, align(top)[Top])
#[page bottom: 0pt | align bottom][Bottom] #page(bottom: 0pt, align(bottom)[Bottom])
// Ensure that specific margins override general margins. // Ensure that specific margins override general margins.
#[page margins: 0pt, left: 20pt][Overriden] #page(margins: 0pt, left: 20pt)[Overriden]
// Error: 8-19 unknown variable // Error: 7-18 unknown variable
#[page nonexistant] #page(nonexistant)
// Error: 18-21 aligned axis // Error: 17-20 aligned axis
#[page main-dir: ltr] #page(main-dir: ltr)
// Flipped predefined paper. // Flipped predefined paper.
#[page "a11", flip: true][Flipped A11] #page("a11", flip: true)[Flipped A11]
// Flipped custom page size. // Flipped custom page size.
#[page width: 40pt, height: 120pt] #page(width: 40pt, height: 120pt)
#[page flip: true] #page(flip: true)
Wide Wide
// Test changing the layouting directions of pages. // Test changing the layouting directions of pages.
#[page height: 50pt, main-dir: btt, cross-dir: rtl] #page(height: 50pt, main-dir: btt, cross-dir: rtl)
Right to left! Right to left!
--- ---
// Test a combination of pages with bodies and normal content. // Test a combination of pages with bodies and normal content.
#[page height: 50pt] #page(height: 50pt)
#[page][First] #page[First]
#[page][Second] #page[Second]
#[pagebreak] #pagebreak()
Fourth Fourth
#[page][] #page[]
Sixth Sixth
#[page][Seventh and last] #page[Seventh and last]

View File

@ -1,3 +1,3 @@
First of two First of two
#[pagebreak] #pagebreak()
#[page height: 40pt] #page(height: 40pt)

View File

@ -1,17 +1,17 @@
// Check the output. // Check the output.
#[rgb 0.0, 0.3, 0.7] #rgb(0.0, 0.3, 0.7)
// Alpha channel. // Alpha channel.
#[rgb 1.0, 0.0, 0.0, 0.5] #rgb(1.0, 0.0, 0.0, 0.5)
// Warning: 2:7-2:10 should be between 0.0 and 1.0 // Warning: 2:6-2:9 should be between 0.0 and 1.0
// Warning: 1:12-1:16 should be between 0.0 and 1.0 // Warning: 1:11-1:15 should be between 0.0 and 1.0
#[rgb -30, 15.5, 0.5] #rgb(-30, 15.5, 0.5)
// Error: 7-11 missing argument: blue component // Error: 6-10 missing argument: blue component
#[rgb 0, 1] #rgb(0, 1)
// Error: 3:6-3:6 missing argument: red component // Error: 3:6-3:6 missing argument: red component
// Error: 2:6-2:6 missing argument: green component // Error: 2:6-2:6 missing argument: green component
// Error: 1:6-1:6 missing argument: blue component // Error: 1:6-1:6 missing argument: blue component
#[rgb] #rgb()

View File

@ -296,7 +296,9 @@ fn parse_metadata(src: &str, map: &LineMap) -> (Option<bool>, DiagSet) {
}; };
let mut s = Scanner::new(rest); let mut s = Scanner::new(rest);
let (start, _, end) = (pos(&mut s), s.eat_assert('-'), pos(&mut s)); let start = pos(&mut s);
let end = if s.eat_if('-') { pos(&mut s) } else { start };
diags.insert(Diag::new(start .. end, level, s.rest().trim())); diags.insert(Diag::new(start .. end, level, s.rest().trim()));
} }