diff options
Diffstat (limited to 'boot/tests')
| -rw-r--r-- | boot/tests/lower/c_for_loop.cskt | 35 | ||||
| -rw-r--r-- | boot/tests/lower/compound_assigns.cskt | 31 | ||||
| -rw-r--r-- | boot/tests/lower/empty_main.cskt | 23 | ||||
| -rw-r--r-- | boot/tests/lower/if_else_chain.cskt | 38 | ||||
| -rw-r--r-- | boot/tests/lower/range_for_loop.cskt | 33 | ||||
| -rw-r--r-- | boot/tests/lower/shadowing_error.cskt | 29 | ||||
| -rw-r--r-- | boot/tests/lower/simple_var.cskt | 26 | ||||
| -rw-r--r-- | boot/tests/lower/structural_dedup.cskt | 29 | ||||
| -rw-r--r-- | boot/tests/lower/type_cycle_error.cskt | 29 | ||||
| -rw-r--r-- | boot/tests/lower/type_simple_struct.cskt | 23 | ||||
| -rw-r--r-- | boot/tests/lower/type_with_pointer_self.cskt | 21 | ||||
| -rw-r--r-- | boot/tests/lower/while_loop.cskt | 34 | ||||
| -rw-r--r-- | boot/tests/test.c | 23 |
13 files changed, 369 insertions, 5 deletions
diff --git a/boot/tests/lower/c_for_loop.cskt b/boot/tests/lower/c_for_loop.cskt new file mode 100644 index 0000000..98d78f0 --- /dev/null +++ b/boot/tests/lower/c_for_loop.cskt @@ -0,0 +1,35 @@ +c-style for loops are turned into the single loop kind, +with the initializer and the iteration step statements synthesized into +statements within the block. + +<<< + +main = fun () { + for i int = 0, i < 10, i++ { + var x int = i + } +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 main main (returns (ref void)) (block + (block + (declaration i (ref int) (initializer (expr 0))) + (loop (condition (expr (binary < (expr (name i)) (expr 10)))) (block + (declaration x (ref int) (initializer (expr (name i)))) + (assign (expr (name i)) (expr (binary + (expr (name i)) (expr 1)))) + )) + ) + ))) + (emission_order 0 1 2 3 4 5 6 7)) diff --git a/boot/tests/lower/compound_assigns.cskt b/boot/tests/lower/compound_assigns.cskt new file mode 100644 index 0000000..214fe59 --- /dev/null +++ b/boot/tests/lower/compound_assigns.cskt @@ -0,0 +1,31 @@ +compound assignment operators are split during lowering. + +<<< + +main = fun () { + var x int = 0 + x += 1 + x *= 2 + x -= 3 +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 main main (returns (ref void)) (block + (declaration x (ref int) (initializer (expr 0))) + (assign (expr (name x)) (expr (binary + (expr (name x)) (expr 1)))) + (assign (expr (name x)) (expr (binary * (expr (name x)) (expr 2)))) + (assign (expr (name x)) (expr (binary - (expr (name x)) (expr 3)))) + ))) + (emission_order 0 1 2 3 4 5 6 7)) diff --git a/boot/tests/lower/empty_main.cskt b/boot/tests/lower/empty_main.cskt new file mode 100644 index 0000000..8e4635f --- /dev/null +++ b/boot/tests/lower/empty_main.cskt @@ -0,0 +1,23 @@ +the simplest possible translation unit. seeds the eight primitive +types and registers a single, empty `main` function. + +<<< + +main = fun () { +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 main main (returns (ref void)) (block))) + (emission_order 0 1 2 3 4 5 6 7)) \ No newline at end of file diff --git a/boot/tests/lower/if_else_chain.cskt b/boot/tests/lower/if_else_chain.cskt new file mode 100644 index 0000000..a8bf358 --- /dev/null +++ b/boot/tests/lower/if_else_chain.cskt @@ -0,0 +1,38 @@ +a three-branch if/else-if/else chain lowers to a single flat +conditional. + +<<< + +classify = fun (n int) int { + if n < 0 { + return -1 + } else if n == 0 { + return 0 + } else { + return 1 + } +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 classify (returns (ref int)) (param n (ref int)) (block + (conditional (when (expr (binary < (expr (name n)) (expr 0)))) (block + (return (expr (unary - (expr 1)))) + ) (when (expr (binary == (expr (name n)) (expr 0)))) (block + (return (expr 0)) + ) (else) (block + (return (expr 1)) + )) + ))) + (emission_order 0 1 2 3 4 5 6 7)) diff --git a/boot/tests/lower/range_for_loop.cskt b/boot/tests/lower/range_for_loop.cskt new file mode 100644 index 0000000..64ffe0b --- /dev/null +++ b/boot/tests/lower/range_for_loop.cskt @@ -0,0 +1,33 @@ +a range for-each is rewritten into a c-style loop. + +<<< + +main = fun () { + for i int = 0..10 { + var x int = i + } +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 main main (returns (ref void)) (block + (block + (declaration i (ref int) (initializer (expr 0))) + (loop (condition (expr (binary < (expr (name i)) (expr 10)))) (block + (declaration x (ref int) (initializer (expr (name i)))) + (assign (expr (name i)) (expr (binary + (expr (name i)) (expr 1)))) + )) + ) + ))) + (emission_order 0 1 2 3 4 5 6 7)) diff --git a/boot/tests/lower/shadowing_error.cskt b/boot/tests/lower/shadowing_error.cskt new file mode 100644 index 0000000..b22dddf --- /dev/null +++ b/boot/tests/lower/shadowing_error.cskt @@ -0,0 +1,29 @@ +declaring two locals with the same name in overlapping scopes is +a hard error. + +<<< + +main = fun () { + var x int = 1 + var x int = 2 +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 main main (returns (ref void)) (block + (declaration x (ref int) (initializer (expr 1))) + ))) + (emission_order 0 1 2 3 4 5 6 7) + (diagnostics + (error "name 'x' shadows an existing binding"))) diff --git a/boot/tests/lower/simple_var.cskt b/boot/tests/lower/simple_var.cskt new file mode 100644 index 0000000..b1b0c92 --- /dev/null +++ b/boot/tests/lower/simple_var.cskt @@ -0,0 +1,26 @@ +a single typed variable declaration with an integer initializer +inside the body of `main`. + +<<< + +main = fun () { + var x int = 5 +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 main main (returns (ref void)) (block + (declaration x (ref int) (initializer (expr 5))) + ))) + (emission_order 0 1 2 3 4 5 6 7)) \ No newline at end of file diff --git a/boot/tests/lower/structural_dedup.cskt b/boot/tests/lower/structural_dedup.cskt new file mode 100644 index 0000000..ee4bcd3 --- /dev/null +++ b/boot/tests/lower/structural_dedup.cskt @@ -0,0 +1,29 @@ +two functions taking the same anonymous tuple type produce just +one synthesized type entry. + +<<< + +f = fun (a (int, int)) int { return 0 } +g = fun (b (int, int)) int { return 0 } + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive) + (type 8 __cat_type_0 synthetic structure (field _0 (ref int)) (field _1 (ref int)) (depends_on 0 0))) + (functions + (function 0 f (returns (ref int)) (param a (ref __cat_type_0)) (block + (return (expr 0)) + )) + (function 1 g (returns (ref int)) (param b (ref __cat_type_0)) (block + (return (expr 0)) + ))) + (emission_order 0 1 2 3 4 5 6 7 8)) diff --git a/boot/tests/lower/type_cycle_error.cskt b/boot/tests/lower/type_cycle_error.cskt new file mode 100644 index 0000000..29b791e --- /dev/null +++ b/boot/tests/lower/type_cycle_error.cskt @@ -0,0 +1,29 @@ +two types referencing each other by value form a cycle that +we cannot resolve. +the diagnostic should point out the correct cycle. + +<<< + +A = type { b B } +B = type { a A } + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive) + (type 8 A structure (field b (ref B)) (depends_on 9)) + (type 9 B structure (field a (ref A)) (depends_on 8))) + (emission_order 0 1 2 3 4 5 6 7) + (diagnostics + (error "type cycle detected: + A (line 1) depends on B + B (line 2) depends on A +hint: break the cycle with a reference (use `&T` instead of `T`). :)"))) diff --git a/boot/tests/lower/type_simple_struct.cskt b/boot/tests/lower/type_simple_struct.cskt new file mode 100644 index 0000000..085d9db --- /dev/null +++ b/boot/tests/lower/type_simple_struct.cskt @@ -0,0 +1,23 @@ +a top-level struct declaration produces a structure type entry +with each field's type interned. +the by-value dependencies are correctly added as dependencies +and contribute to the ordering. + +<<< + +Point = type { x int, y int } + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive) + (type 8 Point structure (field x (ref int)) (field y (ref int)) (depends_on 0 0))) + (emission_order 0 1 2 3 4 5 6 7 8)) diff --git a/boot/tests/lower/type_with_pointer_self.cskt b/boot/tests/lower/type_with_pointer_self.cskt new file mode 100644 index 0000000..6a0b689 --- /dev/null +++ b/boot/tests/lower/type_with_pointer_self.cskt @@ -0,0 +1,21 @@ +a self-referential structure relying on indirection via a reference. +a dependency should not be added as the reference is not by-value. + +<<< + +Node = type { value int, next &Node } + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive) + (type 8 Node structure (field value (ref int)) (field next (ref & Node)) (depends_on 0))) + (emission_order 0 1 2 3 4 5 6 7 8)) diff --git a/boot/tests/lower/while_loop.cskt b/boot/tests/lower/while_loop.cskt new file mode 100644 index 0000000..b191df5 --- /dev/null +++ b/boot/tests/lower/while_loop.cskt @@ -0,0 +1,34 @@ +while loops are 1:1 with the intermediate representation's +single loop kind. +compound assignments desugar into a simple pair of a simple +assignment and binary operation. + +<<< + +main = fun () { + var i int = 0 + while i < 10 { + i++ + } +} + +>>> + +(unit + (types + (type 0 int primitive) + (type 1 uint primitive) + (type 2 bool primitive) + (type 3 string primitive) + (type 4 float primitive) + (type 5 byte primitive) + (type 6 ascii primitive) + (type 7 void primitive)) + (functions + (function 0 main main (returns (ref void)) (block + (declaration i (ref int) (initializer (expr 0))) + (loop (condition (expr (binary < (expr (name i)) (expr 10)))) (block + (assign (expr (name i)) (expr (binary + (expr (name i)) (expr 1)))) + )) + ))) + (emission_order 0 1 2 3 4 5 6 7)) diff --git a/boot/tests/test.c b/boot/tests/test.c index 841df09..051dbc4 100644 --- a/boot/tests/test.c +++ b/boot/tests/test.c @@ -63,9 +63,10 @@ enum Test_Target TARGET_NONE = 0, TARGET_LEX = 1 << 0, TARGET_PARSE = 1 << 1, - TARGET_TRANSPILE = 1 << 2, + TARGET_LOWER = 1 << 2, + TARGET_TRANSPILE = 1 << 3, - TARGET_ALL = TARGET_LEX | TARGET_PARSE | TARGET_TRANSPILE, + TARGET_ALL = TARGET_LEX | TARGET_PARSE | TARGET_LOWER | TARGET_TRANSPILE, }; struct Known_Target @@ -73,9 +74,8 @@ struct Known_Target const ascii* name; enum Test_Target target; } known_targets[] = { - { "lex", TARGET_LEX }, - { "parse", TARGET_PARSE }, - { "transpile", TARGET_TRANSPILE }, + { "lex", TARGET_LEX }, { "parse", TARGET_PARSE }, + { "lower", TARGET_LOWER }, { "transpile", TARGET_TRANSPILE }, { "all", TARGET_ALL }, }; @@ -532,6 +532,15 @@ parse_tests(bool adjust) } struct Result_Summary +lower_tests(bool adjust) +{ + const ascii* base_path = "./boot/tests/lower/"; + const ascii* base_command = "./build/catboot --test-lower"; + + return tests(base_path, base_command, adjust); +} + +struct Result_Summary transpile_tests(bool adjust) { const ascii* base_path = "./boot/tests/transpile/"; @@ -582,6 +591,10 @@ main(int argc, const ascii** argv) summary = parse_tests(adjust); break; + case TARGET_LOWER: + summary = lower_tests(adjust); + break; + case TARGET_TRANSPILE: summary = transpile_tests(adjust); break; |
