aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-01-16 00:21:02 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2025-01-16 00:21:02 +0200
commit9ca1d0c763e1c506ae7b43d50db225914b709397 (patch)
treeff80aa07a1b1ee6515926ec5d078bc44866a46aa
parent7eaa051d4dcc3048c46f302997fd2175a983ac0e (diff)
downloadek-9ca1d0c763e1c506ae7b43d50db225914b709397.tar.gz
ek-9ca1d0c763e1c506ae7b43d50db225914b709397.zip
more strict trait checking
-rw-r--r--src/actualize.c28
-rw-r--r--src/compiler.c1
-rw-r--r--src/parser.y6
-rw-r--r--tests/defer_shadow/defer_shadow.ek2
-rw-r--r--tests/generic/generic.ek2
-rw-r--r--tests/generic_defer/generic_defer.ek2
-rw-r--r--tests/ptr/ptr.ek6
-rw-r--r--tests/struct_generic_cont/struct_generic_cont.ek2
-rw-r--r--tests/struct_priv_trait/source.mk1
-rw-r--r--tests/struct_priv_trait/struct.ek8
-rw-r--r--tests/struct_priv_trait/struct_priv_trait.ek5
-rw-r--r--tests/struct_priv_trait_cont/struct.ek4
-rw-r--r--tests/struct_priv_trait_cont/struct_priv_trait_cont.ek2
-rw-r--r--tests/struct_pub_generic_cont/struct.ek2
-rw-r--r--tests/struct_trait_cont/struct_trait_cont.ek4
-rw-r--r--tests/struct_unexported_trait/source.mk1
-rw-r--r--tests/struct_unexported_trait/struct.ek3
-rw-r--r--tests/struct_unexported_trait/struct_unexported_trait.ek5
-rw-r--r--tests/struct_unexported_trait/trait.ek5
-rw-r--r--tests/trait_expand/trait_expand.ek8
-rw-r--r--tests/trait_multiple_expand/source.mk2
-rw-r--r--tests/trait_multiple_expand/trait_multiple_expand.ek14
-rw-r--r--tests/trait_recursive_expand/trait_recursive_expand.ek8
23 files changed, 89 insertions, 32 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 11c8db7..991beed 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -2131,6 +2131,22 @@ static int params_match(struct scope *scope, struct ast *base, struct ast *node)
return 1;
}
+/* slightly hacky but works well enough for now */
+static int trait_exported(struct scope *scope, struct ast *def)
+{
+ assert(file_scope_find_type(scope, def->s) == def);
+
+ while (!scope_flags(scope, SCOPE_FILE) && scope->parent)
+ scope = scope->parent;
+
+ assert(scope && scope_flags(scope, SCOPE_FILE));
+ struct scope *parent = scope->parent;
+ if (!parent)
+ return true;
+
+ return file_scope_find_type(parent, def->s) == def;
+}
+
static int expand_struct_body(struct act_state *state,
struct scope *scope,
struct ast *node,
@@ -2178,6 +2194,17 @@ static int expand_struct_body(struct act_state *state,
if (actualize_type(&type_state, scope, type))
return -1;
+ if (ast_flags(node, AST_FLAG_PUBLIC)) {
+ struct ast *def = type->d;
+ /* traits should only show up during the initial
+ * expansion, but should maybe make sure somehow */
+ if (def->k == AST_TRAIT_DEF && !trait_exported(scope, def)) {
+ semantic_error(struct_scope->fctx, n,
+ "trait used in pub def must also be exported");
+ return -1;
+ }
+ }
+
type_append(&types, type);
struct ast *alias = gen_alias(strdup(id), type, n->loc);
@@ -2187,6 +2214,7 @@ static int expand_struct_body(struct act_state *state,
struct act_state state = {0};
if (actualize(&state, struct_scope, alias))
return -1;
+
}
if (node->k == AST_STRUCT_CONT_DEF
diff --git a/src/compiler.c b/src/compiler.c
index f7e6a14..2041efd 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -160,6 +160,7 @@ static struct scopes scopes;
static void destroy_scopes()
{
+ if (scopes_len(&scopes))
foreach(scopes, n, &scopes) {
free(n->key);
}
diff --git a/src/parser.y b/src/parser.y
index 18de0e1..45cac92 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -683,7 +683,7 @@ opt_types
| { $$ = NULL; }
type_expand
- : APPLY "[" opt_types "]" { $$ = gen_type_expand($1, $3, src_loc(@$)); }
+ : APPLY { $$ = gen_type_expand($1, NULL, src_loc(@$)); }
var_decl
: type ID { $$ = gen_var($2, $1, NULL, src_loc(@$)); }
@@ -810,8 +810,8 @@ opt_type_params
| { $$ = NULL; }
trait
- : "define" ID "[" opt_type_params "]" "{" opt_behaviours "}" {
- $$ = gen_trait($2, $4, $7, src_loc(@$));
+ : "define" ID "{" opt_behaviours "}" {
+ $$ = gen_trait($2, NULL, $4, src_loc(@$));
}
enum_val
diff --git a/tests/defer_shadow/defer_shadow.ek b/tests/defer_shadow/defer_shadow.ek
index 0e890a2..e12df32 100644
--- a/tests/defer_shadow/defer_shadow.ek
+++ b/tests/defer_shadow/defer_shadow.ek
@@ -1,7 +1,7 @@
typedef i9 {}
typedef i27 {}
-define any[] {}
+define any {}
extern _putchar(i9 c);
diff --git a/tests/generic/generic.ek b/tests/generic/generic.ek
index 065477e..d8a3e7c 100644
--- a/tests/generic/generic.ek
+++ b/tests/generic/generic.ek
@@ -1,4 +1,4 @@
-define any[] {}
+define any {}
typedef i27 {}
typedef i9 {}
diff --git a/tests/generic_defer/generic_defer.ek b/tests/generic_defer/generic_defer.ek
index cb11154..cb2ae33 100644
--- a/tests/generic_defer/generic_defer.ek
+++ b/tests/generic_defer/generic_defer.ek
@@ -1,4 +1,4 @@
-define any[] {}
+define any {}
typedef i27 {}
typedef i9 {}
diff --git a/tests/ptr/ptr.ek b/tests/ptr/ptr.ek
index 86f413c..3e74917 100644
--- a/tests/ptr/ptr.ek
+++ b/tests/ptr/ptr.ek
@@ -1,14 +1,14 @@
typedef bool {}
typedef i27 {
- cmp![];
+ cmp!;
eq(i27 a, i27 b => bool) {
return a == b;
}
}
typedef ptr {
- cmp![];
+ cmp!;
eq(ptr a, ptr b => bool) {
return a == b;
}
@@ -16,7 +16,7 @@ typedef ptr {
typedef test[cmp T] {}
-define cmp[] {
+define cmp {
eq(cmp, cmp => bool);
}
diff --git a/tests/struct_generic_cont/struct_generic_cont.ek b/tests/struct_generic_cont/struct_generic_cont.ek
index 34c604b..661b9e6 100644
--- a/tests/struct_generic_cont/struct_generic_cont.ek
+++ b/tests/struct_generic_cont/struct_generic_cont.ek
@@ -1,4 +1,4 @@
-define any[] {}
+define any {}
typedef ptr {}
typedef i27 {}
diff --git a/tests/struct_priv_trait/source.mk b/tests/struct_priv_trait/source.mk
new file mode 100644
index 0000000..45e3623
--- /dev/null
+++ b/tests/struct_priv_trait/source.mk
@@ -0,0 +1 @@
+SIMPLE_XFAIL += struct_priv_trait,'trait used in pub def must also be exported'
diff --git a/tests/struct_priv_trait/struct.ek b/tests/struct_priv_trait/struct.ek
new file mode 100644
index 0000000..5efb96f
--- /dev/null
+++ b/tests/struct_priv_trait/struct.ek
@@ -0,0 +1,8 @@
+pub typedef ptr {};
+pub typedef i27 {};
+
+define trait {
+ do_something(=> i27);
+}
+
+pub typedef struct[trait T] {};
diff --git a/tests/struct_priv_trait/struct_priv_trait.ek b/tests/struct_priv_trait/struct_priv_trait.ek
new file mode 100644
index 0000000..0e3bd9c
--- /dev/null
+++ b/tests/struct_priv_trait/struct_priv_trait.ek
@@ -0,0 +1,5 @@
+import "struct.ek"
+
+main()
+{
+}
diff --git a/tests/struct_priv_trait_cont/struct.ek b/tests/struct_priv_trait_cont/struct.ek
index 6c94aaa..b790dd4 100644
--- a/tests/struct_priv_trait_cont/struct.ek
+++ b/tests/struct_priv_trait_cont/struct.ek
@@ -1,13 +1,13 @@
pub typedef ptr {};
pub typedef i27 {};
-pub define trait[] {
+pub define trait {
do_something(=> i27);
}
pub typedef implementer {}
continue implementer {
- trait![];
+ trait!;
do_something(=> i27)
{
return 0;
diff --git a/tests/struct_priv_trait_cont/struct_priv_trait_cont.ek b/tests/struct_priv_trait_cont/struct_priv_trait_cont.ek
index cd67050..7fb7e12 100644
--- a/tests/struct_priv_trait_cont/struct_priv_trait_cont.ek
+++ b/tests/struct_priv_trait_cont/struct_priv_trait_cont.ek
@@ -12,7 +12,7 @@ import "struct.ek"
* by the codegen. Should maybe try and do something about that as well.
*/
continue implementer {
- trait![];
+ trait!;
do_something(=> i27)
{
return 1;
diff --git a/tests/struct_pub_generic_cont/struct.ek b/tests/struct_pub_generic_cont/struct.ek
index 5abbe38..4689736 100644
--- a/tests/struct_pub_generic_cont/struct.ek
+++ b/tests/struct_pub_generic_cont/struct.ek
@@ -1,4 +1,4 @@
-pub define any[] {}
+pub define any {}
pub typedef i27 {}
pub typedef struct[any T] {}
diff --git a/tests/struct_trait_cont/struct_trait_cont.ek b/tests/struct_trait_cont/struct_trait_cont.ek
index f8e05c5..b4f7a2a 100644
--- a/tests/struct_trait_cont/struct_trait_cont.ek
+++ b/tests/struct_trait_cont/struct_trait_cont.ek
@@ -1,10 +1,10 @@
-define a[] {
+define a {
a();
}
typedef struct {}
continue struct {
- a![];
+ a!;
a(){}
}
diff --git a/tests/struct_unexported_trait/source.mk b/tests/struct_unexported_trait/source.mk
new file mode 100644
index 0000000..fb22304
--- /dev/null
+++ b/tests/struct_unexported_trait/source.mk
@@ -0,0 +1 @@
+SIMPLE_XFAIL += struct_unexported_trait,'trait used in pub def must also be exported'
diff --git a/tests/struct_unexported_trait/struct.ek b/tests/struct_unexported_trait/struct.ek
new file mode 100644
index 0000000..acf01f5
--- /dev/null
+++ b/tests/struct_unexported_trait/struct.ek
@@ -0,0 +1,3 @@
+import "trait.ek"
+
+pub typedef struct[trait T] {};
diff --git a/tests/struct_unexported_trait/struct_unexported_trait.ek b/tests/struct_unexported_trait/struct_unexported_trait.ek
new file mode 100644
index 0000000..0e3bd9c
--- /dev/null
+++ b/tests/struct_unexported_trait/struct_unexported_trait.ek
@@ -0,0 +1,5 @@
+import "struct.ek"
+
+main()
+{
+}
diff --git a/tests/struct_unexported_trait/trait.ek b/tests/struct_unexported_trait/trait.ek
new file mode 100644
index 0000000..8280a53
--- /dev/null
+++ b/tests/struct_unexported_trait/trait.ek
@@ -0,0 +1,5 @@
+pub typedef i27 {};
+
+pub define trait {
+ do_something(=> i27);
+}
diff --git a/tests/trait_expand/trait_expand.ek b/tests/trait_expand/trait_expand.ek
index c5f0f1c..d7aa288 100644
--- a/tests/trait_expand/trait_expand.ek
+++ b/tests/trait_expand/trait_expand.ek
@@ -1,15 +1,15 @@
typedef ptr {}
-define b[] {
- a![];
+define b {
+ a!;
}
-define a[] {
+define a {
a(*a a);
}
typedef c {
- b![];
+ b!;
a(*c) {}
}
diff --git a/tests/trait_multiple_expand/source.mk b/tests/trait_multiple_expand/source.mk
index 6d1bcbb..e6193c7 100644
--- a/tests/trait_multiple_expand/source.mk
+++ b/tests/trait_multiple_expand/source.mk
@@ -1 +1 @@
-SIMPLE_XFAIL += trait_multiple_expand
+SIMPLE_XFAIL += trait_multiple_expand,"reimplementation of trait"
diff --git a/tests/trait_multiple_expand/trait_multiple_expand.ek b/tests/trait_multiple_expand/trait_multiple_expand.ek
index 04e2b82..3444305 100644
--- a/tests/trait_multiple_expand/trait_multiple_expand.ek
+++ b/tests/trait_multiple_expand/trait_multiple_expand.ek
@@ -1,21 +1,21 @@
typedef ptr {}
-define b[] {
- c![];
- a![];
+define b {
+ c!;
+ a!;
}
-define a[] {
- c![];
+define a {
+ c!;
a(*a a);
}
-define c[] {
+define c {
c(*c c);
}
typedef d {
- b![];
+ b!;
c(*d d) {}
}
diff --git a/tests/trait_recursive_expand/trait_recursive_expand.ek b/tests/trait_recursive_expand/trait_recursive_expand.ek
index 53012bf..6b71b23 100644
--- a/tests/trait_recursive_expand/trait_recursive_expand.ek
+++ b/tests/trait_recursive_expand/trait_recursive_expand.ek
@@ -1,8 +1,8 @@
-define b[] {
- a![];
+define b {
+ a!;
}
-define a[] {
- b![];
+define a {
+ b!;
a(*a a);
}