aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/drivers/lsp_test.js18
-rw-r--r--tests/langerrors/typedef_generic_bare.zc6
-rw-r--r--tests/langerrors/typedef_local_redefine.zc8
-rw-r--r--tests/langerrors/typedef_redefine.zc6
-rw-r--r--tests/langerrors/typedef_scope.zc8
-rw-r--r--tests/langerrors/typedef_string_redefine.zc5
-rw-r--r--tests/langerrors/typedef_tag.zc5
-rw-r--r--tests/langerrors/typedef_unknown.zc5
-rw-r--r--tests/langerrors/typedef_variable_clash.zc8
-rw-r--r--tests/langerrors/typedef_void_variable.zc5
-rw-r--r--tests/programs/typedef.zc89
-rwxr-xr-xtests/test.sh1
-rw-r--r--tests/typeerrors/typedef_mismatch.zc6
-rw-r--r--tests/typeerrors/typedef_pointer.zc7
14 files changed, 177 insertions, 0 deletions
diff --git a/tests/drivers/lsp_test.js b/tests/drivers/lsp_test.js
index 18d8bf7..0f4abe1 100644
--- a/tests/drivers/lsp_test.js
+++ b/tests/drivers/lsp_test.js
@@ -250,5 +250,23 @@ check(hcv && hcv.includes('parameter'), 'hover on a use of a parameter named lik
hcv = hover(scp, 4, at(scp, 4, 'len'));
check(hcv && hcv.includes('the number of items'), 'hover on the built-in still shows its text where no local shadows it', hcv);
+// typedefs: the name shows its declaration, at the declaration, at a use in a declaration, and in a block
+const tdsrc = 'struct node { int v; node* next; };\n// another name for node*\ntypedef node* link;\ntypedef int(int, int) binop;\nlink head(link n) { return n; }\nint use(string s) {\n\ttypedef int cell;\n\tcell c = 1;\n\tbinop f = 0;\n\treturn c;\n}\n';
+hv = hover(tdsrc, 2, at(tdsrc, 2, 'link'));
+check(hv && hv.includes('typedef node* link;') && hv.includes('another name for node*'), 'hover on the name in a typedef shows the typedef and its doc', hv);
+hv = hover(tdsrc, 4, at(tdsrc, 4, 'link'));
+check(hv && hv.includes('typedef node* link;') && hv.includes('a pointer to `node`'), 'hover on a typedef name used as a type shows the typedef and the type', hv);
+hv = hover(tdsrc, 4, at(tdsrc, 4, 'link', 1));
+check(hv && hv.includes('typedef node* link;'), 'hover on a typedef name used as a parameter type shows the typedef', hv);
+hv = hover(tdsrc, 3, at(tdsrc, 3, 'binop'));
+check(hv && hv.includes('typedef int(int, int) binop;'), 'hover on a function type typedef shows the whole typedef', hv);
+hv = hover(tdsrc, 7, at(tdsrc, 7, 'cell'));
+check(hv && hv.includes('typedef int cell;'), 'hover on a typedef made in a block shows the typedef', hv);
+hv = hover(tdsrc, 5, at(tdsrc, 5, 'string'));
+check(hv && hv.includes('char*') && hv.includes('built-in alias'), 'hover on string shows char* and what string is', hv);
+hv = hover(tdsrc, 2, 3);
+check(hv && hv.includes('typedef T name;') && hv.includes('type name = T;'), 'hover on the typedef keyword explains it', hv);
+check(tokens(tdsrc).includes('typedef:keyword'), 'typedef is highlighted as a keyword', tokens(tdsrc));
+
console.log(ok + ' lsp checks passed, ' + bad + ' failed');
process.exit(bad ? 1 : 0);
diff --git a/tests/langerrors/typedef_generic_bare.zc b/tests/langerrors/typedef_generic_bare.zc
new file mode 100644
index 0000000..5f3e906
--- /dev/null
+++ b/tests/langerrors/typedef_generic_bare.zc
@@ -0,0 +1,6 @@
+namespace;
+
+// expect: expected '<', found 'plain'
+struct box<T> { T item; };
+typedef box plain;
+fn main() { return 0; }
diff --git a/tests/langerrors/typedef_local_redefine.zc b/tests/langerrors/typedef_local_redefine.zc
new file mode 100644
index 0000000..e51c32f
--- /dev/null
+++ b/tests/langerrors/typedef_local_redefine.zc
@@ -0,0 +1,8 @@
+namespace;
+
+// expect: cell: already defined
+fn main() {
+ typedef int cell;
+ typedef char* cell;
+ return 0;
+}
diff --git a/tests/langerrors/typedef_redefine.zc b/tests/langerrors/typedef_redefine.zc
new file mode 100644
index 0000000..05085ec
--- /dev/null
+++ b/tests/langerrors/typedef_redefine.zc
@@ -0,0 +1,6 @@
+namespace;
+
+// expect: num: already defined
+typedef int num;
+typedef char* num;
+fn main() { return 0; }
diff --git a/tests/langerrors/typedef_scope.zc b/tests/langerrors/typedef_scope.zc
new file mode 100644
index 0000000..833e30e
--- /dev/null
+++ b/tests/langerrors/typedef_scope.zc
@@ -0,0 +1,8 @@
+namespace;
+
+// expect: expected ';', found 'x'
+fn main() {
+ { typedef int cell; cell a = 1; }
+ cell x = 2;
+ return 0;
+}
diff --git a/tests/langerrors/typedef_string_redefine.zc b/tests/langerrors/typedef_string_redefine.zc
new file mode 100644
index 0000000..226a94e
--- /dev/null
+++ b/tests/langerrors/typedef_string_redefine.zc
@@ -0,0 +1,5 @@
+namespace;
+
+// expect: string: already defined
+typedef int string;
+fn main() { return 0; }
diff --git a/tests/langerrors/typedef_tag.zc b/tests/langerrors/typedef_tag.zc
new file mode 100644
index 0000000..70ab491
--- /dev/null
+++ b/tests/langerrors/typedef_tag.zc
@@ -0,0 +1,5 @@
+namespace;
+
+// expect: a typedef names a type, which has no tag
+typedef char*.u owned;
+fn main() { return 0; }
diff --git a/tests/langerrors/typedef_unknown.zc b/tests/langerrors/typedef_unknown.zc
new file mode 100644
index 0000000..8076e86
--- /dev/null
+++ b/tests/langerrors/typedef_unknown.zc
@@ -0,0 +1,5 @@
+namespace;
+
+// expect: missing_t: isn't a type
+typedef missing_t thing;
+fn main() { return 0; }
diff --git a/tests/langerrors/typedef_variable_clash.zc b/tests/langerrors/typedef_variable_clash.zc
new file mode 100644
index 0000000..2c843f2
--- /dev/null
+++ b/tests/langerrors/typedef_variable_clash.zc
@@ -0,0 +1,8 @@
+namespace;
+
+// expect: count: already defined
+fn main() {
+ int count = 1;
+ typedef int count;
+ return count;
+}
diff --git a/tests/langerrors/typedef_void_variable.zc b/tests/langerrors/typedef_void_variable.zc
new file mode 100644
index 0000000..c5c7ced
--- /dev/null
+++ b/tests/langerrors/typedef_void_variable.zc
@@ -0,0 +1,5 @@
+namespace;
+
+// expect: a variable can't be void
+typedef void nothing;
+fn main() { nothing x; return 0; }
diff --git a/tests/programs/typedef.zc b/tests/programs/typedef.zc
new file mode 100644
index 0000000..307ef75
--- /dev/null
+++ b/tests/programs/typedef.zc
@@ -0,0 +1,89 @@
+namespace;
+include rt;
+typecheck on;
+
+// typedef T name; makes name another way to write T: the same type, so the two mix freely
+struct node { int v; node* next; };
+struct pair<A, B> { A a; B b; };
+
+typedef int count;
+typedef char* label;
+typedef node* link;
+typedef link* links;
+typedef int[4] quad;
+typedef int(int, int) binop;
+typedef pair<int, int> ipair;
+typedef int[?] ints;
+typedef count counter;
+
+struct box { count n; link head; ipair p; };
+
+count twice(count x) { return x + x; }
+count add(int a, int b) { return a + b; }
+count apply(binop f, count a, count b) { return f(a, b); }
+count sum(link n) { count s = 0; while (n) { s += n.v; n = n.next; } return s; }
+label hello() { return "hello"; }
+string greet(string s) { return s; }
+// string is only a type where a type is expected: an untyped parameter can still be called string
+fn twice_name(string) { return string + string; }
+count first_of(links ls) { return ls[0].v; }
+T pick<T>(T x) { typedef T item; item y = x; return y; }
+count scoped() {
+ count total = 0;
+ { typedef int cell; cell c = 3; total += c; }
+ { typedef char* cell; cell c = "ab"; total += rt.len_w(c); }
+ return total;
+}
+count scoped_again() { typedef quad cell; cell c; c[2] = 7; return c[2] + sizeof(cell); }
+
+// a link is a node*: every use below mixes the two
+count same_ptr(node* p, link q) { return p == q; }
+count casts(link p) {
+ word w = p as word;
+ link back = w as link;
+ node* n = (node*)back;
+ return back.v + ((link)n == p);
+}
+count boxed(link p) {
+ box bx; bx.n = 6; bx.head = 0; bx.p.a = 1; bx.p.b = 2;
+ pair<link, count> pl; pl.a = 0; pl.b = 5;
+ return bx.n + p.v + bx.p.a + bx.p.b + pl.b + !bx.head + !pl.a;
+}
+count by_ref(links ls) { return first_of(ls); }
+
+fn main() {
+ link a = rt.new(node), b = rt.new(node);
+ a.v = 3; b.v = 4; a.next = b;
+ rt.put_n(sum(a)); rt.put_c(' ');
+ rt.put_n(same_ptr(a, a)); rt.put_c(' ');
+ rt.put_n(twice(21)); rt.put_c(' ');
+ rt.put_n(apply(add, 2, 3)); rt.put_c(' ');
+ binop op = add;
+ rt.put_n(op(10, 20)); rt.put_c(10);
+
+ quad q; q[3] = 9;
+ rt.put_n(q[3] + sizeof(quad)); rt.put_c(' ');
+ rt.put_n(sizeof(count) + sizeof(link) + sizeof(ipair)); rt.put_c(' ');
+ rt.put_n(boxed(a)); rt.put_c(' ');
+ ints xs = {1, 2, 3};
+ push(xs, 4);
+ rt.put_n(len(xs)); rt.put_c(10);
+
+ rt.put_n(casts(a)); rt.put_c(' ');
+ counter k = (count)3;
+ rt.put_n(k); rt.put_c(' ');
+ links ls = &a;
+ rt.put_n(by_ref(ls)); rt.put_c(' ');
+ rt.put_n(pick<count>(11) + pick(1)); rt.put_c(10);
+
+ rt.put_n(scoped()); rt.put_c(' ');
+ rt.put_n(scoped_again()); rt.put_c(10);
+
+ string s = "hi";
+ label l = s;
+ char* c = l;
+ rt.put_s(s); rt.put_s(l); rt.put_s(c); rt.put_s(hello()); rt.put_s(greet("ok")); rt.put_c(10);
+ rt.put_n(twice_name(4)); rt.put_c(10);
+ rt.free(d*a);
+ return 0;
+}
diff --git a/tests/test.sh b/tests/test.sh
index 46625a6..df6417f 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -106,6 +106,7 @@ run(){ # $1 = vm command, $2 = label
chk "$($vm < tests/programs/meta.zc | tr '\n' '/')" "1024 19/unless ok/rrr/15 42/7/42/7/144/" "$l parse words, quote, eval, load, operator tables"
chk "$($vm < tests/programs/misc.zc | tr '\n' '/')" "45/54321/ok/" "$l compile-time eval, patched mnemonics, unchecked"
chk "$($vm < tests/programs/types.zc | tr '\n' '/')" "12 5 2 15 56 42 7 14 3/rect rect* list<int>* list<T>*.u(int) T(list<T>*) fn(word.d)/a:point@0 b:point@2 tag:int@4 /point 1 1/" "$l types, generics, reflection"
+ chk "$($vm < tests/programs/typedef.zc | tr '\n' '/')" "7 1 42 5 30/13 4 19 4/4 3 3 12/5 11/hihihihellook/8/" "$l typedef, global and local, in every place a type goes, and string"
chk "$($vm < tests/programs/typeok.zc)" "14" "$l a program the typechecker accepts"
chk "$($vm < tests/programs/typeoff.zc)" "6" "$l the typechecker is off by default"
chk "$($vm < tests/programs/enhance.zc)" "100 0 343 3,2 5 -2 0" "$l virtual enhancements"
diff --git a/tests/typeerrors/typedef_mismatch.zc b/tests/typeerrors/typedef_mismatch.zc
new file mode 100644
index 0000000..26453dd
--- /dev/null
+++ b/tests/typeerrors/typedef_mismatch.zc
@@ -0,0 +1,6 @@
+namespace;
+
+// expect: type error: initializer: expected int, got char*
+typecheck on;
+typedef int count;
+fn main() { count c = "text"; return 0; }
diff --git a/tests/typeerrors/typedef_pointer.zc b/tests/typeerrors/typedef_pointer.zc
new file mode 100644
index 0000000..5dbbb17
--- /dev/null
+++ b/tests/typeerrors/typedef_pointer.zc
@@ -0,0 +1,7 @@
+namespace;
+
+// expect: type error: initializer: expected node*, got int*
+typecheck on;
+struct node { int v; };
+typedef node* link;
+fn main() { int n = 0; link p = &n; return 0; }