aboutsummaryrefslogtreecommitdiff
path: root/boot/tests
diff options
context:
space:
mode:
Diffstat (limited to 'boot/tests')
-rw-r--r--boot/tests/lower/c_for_loop.cskt35
-rw-r--r--boot/tests/lower/compound_assigns.cskt31
-rw-r--r--boot/tests/lower/empty_main.cskt23
-rw-r--r--boot/tests/lower/if_else_chain.cskt38
-rw-r--r--boot/tests/lower/range_for_loop.cskt33
-rw-r--r--boot/tests/lower/shadowing_error.cskt29
-rw-r--r--boot/tests/lower/simple_var.cskt26
-rw-r--r--boot/tests/lower/structural_dedup.cskt29
-rw-r--r--boot/tests/lower/type_cycle_error.cskt29
-rw-r--r--boot/tests/lower/type_simple_struct.cskt23
-rw-r--r--boot/tests/lower/type_with_pointer_self.cskt21
-rw-r--r--boot/tests/lower/while_loop.cskt34
-rw-r--r--boot/tests/test.c23
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;