diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-02-20 17:53:40 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-02-20 23:34:33 +0100 |
| commit | 05727bfc3a9cfd45a8e2028dfd0806f7a8f88015 (patch) | |
| tree | 6c0b66eb2a9dff224cb39eb6ccb478656a706c04 /tests/typ/expr | |
| parent | 927341d93ae29678095e3b874bd68bfc57d4bc05 (diff) | |
Reorganize tests 🔀
Diffstat (limited to 'tests/typ/expr')
| -rw-r--r-- | tests/typ/expr/array.typ | 43 | ||||
| -rw-r--r-- | tests/typ/expr/assoc.typ | 18 | ||||
| -rw-r--r-- | tests/typ/expr/block-invalid.typ | 37 | ||||
| -rw-r--r-- | tests/typ/expr/block-scoping.typ | 35 | ||||
| -rw-r--r-- | tests/typ/expr/block.typ | 38 | ||||
| -rw-r--r-- | tests/typ/expr/call-invalid.typ | 44 | ||||
| -rw-r--r-- | tests/typ/expr/call.typ | 40 | ||||
| -rw-r--r-- | tests/typ/expr/dict.typ | 20 | ||||
| -rw-r--r-- | tests/typ/expr/ops-invalid.typ | 59 | ||||
| -rw-r--r-- | tests/typ/expr/ops.typ | 150 | ||||
| -rw-r--r-- | tests/typ/expr/prec.typ | 30 |
11 files changed, 514 insertions, 0 deletions
diff --git a/tests/typ/expr/array.typ b/tests/typ/expr/array.typ new file mode 100644 index 00000000..c9383501 --- /dev/null +++ b/tests/typ/expr/array.typ @@ -0,0 +1,43 @@ +// Test arrays. + +--- +// Empty. +{()} + +// Not an array, just a parenthesized expression. +{(1)} + +// One item and trailing comma. +{(-1,)} + +// No trailing comma. +{(true, false)} + +// Multiple lines and items and trailing comma. +{("1" + , #002 + ,)} + +// Error: 3 expected closing paren +{(} + +// Error: 2-3 expected expression, found closing paren +{)} + +// Error: 2:4 expected comma +// Error: 1:4-1:6 expected expression, found end of block comment +{(1*/2)} + +// Error: 6-8 expected expression, found invalid token +{(1, 1u 2)} + +// Error: 3-4 expected expression, found comma +{(,1)} + +// Missing expression makes named pair incomplete, making this an empty array. +// Error: 5 expected expression +{(a:)} + +// Named pair after this is already identified as an array. +// Error: 6-10 expected expression, found named pair +{(1, b: 2)} diff --git a/tests/typ/expr/assoc.typ b/tests/typ/expr/assoc.typ new file mode 100644 index 00000000..19c56951 --- /dev/null +++ b/tests/typ/expr/assoc.typ @@ -0,0 +1,18 @@ +// Test operator associativity. +// Ref: false + +--- +// Math operators are left-associative. +#test(10 / 2 / 2 == (10 / 2) / 2, true) +#test(10 / 2 / 2 == 10 / (2 / 2), false) +#test(1 / 2 * 3, 1.5) + +--- +// Assignment is right-associative. +{ + let x = 1 + let y = 2 + x = y = "ok" + test(x, none) + test(y, "ok") +} diff --git a/tests/typ/expr/block-invalid.typ b/tests/typ/expr/block-invalid.typ new file mode 100644 index 00000000..d98bf06b --- /dev/null +++ b/tests/typ/expr/block-invalid.typ @@ -0,0 +1,37 @@ +// Test invalid code block syntax. + +--- +// Multiple unseparated expressions in one line. + +// Error: 2-4 expected expression, found invalid token +{1u} + +// Should output `1`. +// Error: 3 expected semicolon or line break +{0 1} + +// Should output `2`. +// Error: 2:12 expected semicolon or line break +// Error: 1:22 expected semicolon or line break +{let x = -1 let y = 3 x + y} + +// Should output `3`. +{ + // Error: 9-12 expected identifier, found string + for "v" + + // Error: 10 expected keyword `in` + for v let z = 1 + 2 + + z +} + +--- +// Ref: false +// Error: 3:1 expected closing brace +{ + +--- +// Ref: false +// Error: 1-2 unexpected closing brace +} diff --git a/tests/typ/expr/block-scoping.typ b/tests/typ/expr/block-scoping.typ new file mode 100644 index 00000000..7bb98969 --- /dev/null +++ b/tests/typ/expr/block-scoping.typ @@ -0,0 +1,35 @@ +// Test scoping with blocks. +// Ref: false + +--- +// Block in template does not create a scope. +{ let x = 1 } +#test(x, 1) + +--- +// Block in expression does create a scope. +#let a = { + let b = 1 + b +} + +#test(a, 1) + +// Error: 2-3 unknown variable +{b} + +--- +// Multiple nested scopes. +{ + let a = "a1" + { + let a = "a2" + { + test(a, "a2") + let a = "a3" + test(a, "a3") + } + test(a, "a2") + } + test(a, "a1") +} diff --git a/tests/typ/expr/block.typ b/tests/typ/expr/block.typ new file mode 100644 index 00000000..196e6c14 --- /dev/null +++ b/tests/typ/expr/block.typ @@ -0,0 +1,38 @@ +// Test code blocks. + +--- +All none + +// Nothing evaluates to none. +{} + +// Let evaluates to none. +{ let v = 0 } + +// Trailing none evaluates to none. +{ + type("") + none +} + +--- +// Evaluates to single expression. +{ "Hello" } + +// Evaluates to trailing expression. +{ let x = "Hel"; x + "lo" } + +// Evaluates to concatenation of for loop bodies. +{ + let parts = ("Hel", "lo") + for s in parts [{s}] +} + +--- +// Works the same way in code environment. +// Ref: false +#test(3, { + let x = 1 + let y = 2 + x + y +}) diff --git a/tests/typ/expr/call-invalid.typ b/tests/typ/expr/call-invalid.typ new file mode 100644 index 00000000..0ed5246f --- /dev/null +++ b/tests/typ/expr/call-invalid.typ @@ -0,0 +1,44 @@ +// Test invalid function calls. + +--- +// Error: 1-2 unexpected invalid token +# + +--- +// Error: 7-8 expected expression, found colon +#args(:) + +// Error: 10-12 expected expression, found end of block comment +#args(a:1*/) + +// Error: 8 expected comma +#args(1 2) + +// Error: 2:7-2:8 expected identifier +// Error: 1:9 expected expression +#args(1:) + +// Error: 7-8 expected identifier +#args(1:2) + +// Error: 7-10 expected identifier +{args((x):1)} + +--- +#let x = "string" + +// Error: 1-3 expected function, found string +#x() + +--- +// Error: 3:1 expected closing bracket +#args[`a]` + +--- +// Error: 7 expected closing paren +{args(} + +--- +// Error: 3:1 expected quote +// Error: 2:1 expected closing paren +#args("] diff --git a/tests/typ/expr/call.typ b/tests/typ/expr/call.typ new file mode 100644 index 00000000..213d5554 --- /dev/null +++ b/tests/typ/expr/call.typ @@ -0,0 +1,40 @@ +// Test function calls. + +--- +// One argument. +#args(bold) + +// One argument and trailing comma. +#args(1,) + +// One named argument. +#args(a:2) + +// Mixed arguments. +{args(1, b: "2", 3)} + +--- +// Different forms of template arguments. +// Ref: true + +#let a = "a" + +#args[a] \ +#args(a) \ +#args(a, [b]) \ +#args(a)[b] \ + +// Template can be argument or body depending on whitespace. +#if "template" == type[b] [Sure ] +#if "template" == type [Nope.] #else [thing.] + +// Should output `<function args> (Okay.)`. +#args (Okay.) + +--- +// Call function assigned to variable. +#let alias = type +#test(alias(alias), "function") + +// Library function `font` returns template. +#test(type(font(12pt)), "template") diff --git a/tests/typ/expr/dict.typ b/tests/typ/expr/dict.typ new file mode 100644 index 00000000..655a3299 --- /dev/null +++ b/tests/typ/expr/dict.typ @@ -0,0 +1,20 @@ +// Test dictionaries. + +--- +// Empty +{(:)} + +// Two pairs. +{(a1: 1, a2: 2)} + +--- +// Simple expression after already being identified as a dictionary. +// Error: 9-10 expected named pair, found expression +{(a: 1, b)} + +// Identified as dictionary due to initial colon. +// Error: 4:4-4:5 expected named pair, found expression +// Error: 3:5 expected comma +// Error: 2:12-2:16 expected identifier +// Error: 1:17-1:18 expected expression, found colon +{(:1 b:[], true::)} diff --git a/tests/typ/expr/ops-invalid.typ b/tests/typ/expr/ops-invalid.typ new file mode 100644 index 00000000..f760ae31 --- /dev/null +++ b/tests/typ/expr/ops-invalid.typ @@ -0,0 +1,59 @@ +// Test invalid expressions. +// Ref: false + +--- +// Missing expressions. + +// Error: 3 expected expression +{-} + +// Error: 10 expected expression +#test({1+}, 1) + +// Error: 10 expected expression +#test({2*}, 2) + +--- +// Mismatched types. + +// Error: 2-12 cannot apply '+' to template +{+([] + [])} + +// Error: 2-5 cannot apply '-' to string +{-""} + +// Error: 2-8 cannot apply 'not' to array +{not ()} + +// Error: 1:2-1:12 cannot apply '<=' to relative and relative +{30% <= 40%} + +// Special messages for +, -, * and /. +// Error: 4:03-4:10 cannot add integer and string +// Error: 3:12-3:19 cannot subtract integer from relative +// Error: 2:21-2:29 cannot multiply integer with boolean +// Error: 1:31-1:39 cannot divide integer by length +{(1 + "2", 40% - 1, 2 * true, 3 / 12pt)} + +// Error: 14-22 cannot apply '+=' to integer and string +{ let x = 1; x += "2" } + +--- +// Bad left-hand sides of assignment. + +// Error: 3-6 cannot assign to this expression +{ (x) = "" } + +// Error: 3-8 cannot assign to this expression +{ 1 + 2 += 3 } + +// Error: 3-4 unknown variable +{ z = 1 } + +// Error: 3-6 cannot assign to a constant +{ box = "hi" } + +// Works if we define box beforehand +// (since then it doesn't resolve to the standard library version anymore). +#let box = "" +{ box = "hi" } diff --git a/tests/typ/expr/ops.typ b/tests/typ/expr/ops.typ new file mode 100644 index 00000000..2390b7b4 --- /dev/null +++ b/tests/typ/expr/ops.typ @@ -0,0 +1,150 @@ +// Test binary expressions. +// Ref: false + +--- +// Test template addition. +// Ref: true +{[*Hello ] + [world!*]} + +--- +// Test math operators. + +// Test plus and minus. +#for v in (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt) { + // Test plus. + test(+v, v) + + // Test minus. + test(-v, -1 * v) + test(--v, v) + + // Test combination. + test(-++ --v, -v) +} + +#test(-(4 + 2), 6-12) + +// Addition. +#test(2 + 4, 6) +#test("a" + "b", "ab") +#test((1, 2) + (3, 4), (1, 2, 3, 4)) +#test((a: 1) + (b: 2, c: 3), (a: 1, b: 2, c: 3)) + +// Subtraction. +#test(1-4, 3*-1) +#test(4cm - 2cm, 2cm) +#test(1e+2-1e-2, 99.99) + +// Multiplication. +#test(2 * 4, 8) + +// Division. +#test(12pt/.4, 30pt) +#test(7 / 2, 3.5) + +// Combination. +#test(3-4 * 5 < -10, true) +#test({ let x; x = 1 + 4*5 >= 21 and { x = "a"; x + "b" == "ab" }; x }, true) + +// Mathematical identities. +#let nums = (1, 3.14, 12pt, 45deg, 90%, 13% + 10pt) +#for v in nums { + // Test plus and minus. + test(v + v - v, v) + test(v - v - v, -v) + + // Test plus/minus and multiplication. + test(v - v, 0 * v) + test(v + v, 2 * v) + + // Integer addition does not give a float. + if type(v) != "integer" { + test(v + v, 2.0 * v) + } + + // Linears cannot be divided by themselves. + if type(v) != "linear" { + test(v / v, 1.0) + test(v / v == 1, true) + } +} + +// Make sure length, relative and linear +// - can all be added to / subtracted from each other, +// - multiplied with integers and floats, +// - divided by floats. +#let dims = (10pt, 30%, 50% + 3cm) +#for a in dims { + for b in dims { + test(type(a + b), type(a - b)) + } + + for b in (7, 3.14) { + test(type(a * b), type(a)) + test(type(b * a), type(a)) + test(type(a / b), type(a)) + } +} + +--- +// Test boolean operators. + +// Test not. +#test(not true, false) +#test(not false, true) + +// And. +#test(false and false, false) +#test(false and true, false) +#test(true and false, false) +#test(true and true, true) + +// Or. +#test(false or false, false) +#test(false or true, true) +#test(true or false, true) +#test(true or true, true) + +// Short-circuiting. +#test(false and dont-care, false) +#test(true or dont-care, true) + +--- +// Test equality operators. + +#test(1 == "hi", false) +#test(1 == 1.0, true) +#test(30% == 30% + 0cm, true) +#test(1in == 0% + 72pt, true) +#test(30% == 30% + 1cm, false) +#test("ab" == "a" + "b", true) +#test(() == (1,), false) +#test((1, 2, 3) == (1, 2.0) + (3,), true) +#test((:) == (a: 1), false) +#test((a: 2 - 1.0, b: 2) == (b: 2, a: 1), true) +#test([*Hi*] == [*Hi*], true) + +#test("a" != "a", false) +#test([*] != [_], true) + +--- +// Test comparison operators. + +#test(13 * 3 < 14 * 4, true) +#test(5 < 10, true) +#test(5 > 5, false) +#test(5 <= 5, true) +#test(5 <= 4, false) +#test(45deg < 1rad, true) + +--- +// Test assignment operators. + +#let x = 0 +{ x = 10 } #test(x, 10) +{ x -= 5 } #test(x, 5) +{ x += 1 } #test(x, 6) +{ x *= x } #test(x, 36) +{ x /= 2.0 } #test(x, 18.0) +{ x = "some" } #test(x, "some") +{ x += "thing" } #test(x, "something") diff --git a/tests/typ/expr/prec.typ b/tests/typ/expr/prec.typ new file mode 100644 index 00000000..e64e583c --- /dev/null +++ b/tests/typ/expr/prec.typ @@ -0,0 +1,30 @@ +// Test operator precedence. +// Ref: false + +--- +// Multiplication binds stronger than addition. +#test(1+2*-3, -5) + +// Subtraction binds stronger than comparison. +#test(3 == 5 - 2, true) + +// Boolean operations bind stronger than '=='. +#test("a" == "a" and 2 < 3, true) +#test(not "b" == "b", false) + +// Assignment binds stronger than boolean operations. +// Error: 2-7 cannot assign to this expression +{not x = "a"} + +--- +// Parentheses override precedence. +#test((1), 1) +#test((1+2)*-3, -9) + +// Error: 14 expected closing paren +#test({(1 + 1}, 2) + +--- +// Precedence doesn't matter for chained unary operators. +// Error: 2-11 cannot apply '-' to boolean +{-not true} |
