aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-01-12 13:17:48 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2025-01-12 13:17:48 +0200
commit2d8691cfef92edf31da746668fd2da3c1fa5043c (patch)
tree0da07f8c72a8c842eae1af86eecea11d4fe6549b
parent67af2eead2b9424ba311ef208cd45df839c3efbe (diff)
downloadek-2d8691cfef92edf31da746668fd2da3c1fa5043c.tar.gz
ek-2d8691cfef92edf31da746668fd2da3c1fa5043c.zip
highlight flaws in current unification system
-rw-r--r--TODO15
-rw-r--r--src/actualize.c3
-rw-r--r--src/debug.c9
-rw-r--r--tests/struct_priv_trait_cont/source.mk1
-rw-r--r--tests/struct_priv_trait_cont/struct.ek32
-rw-r--r--tests/struct_priv_trait_cont/struct_priv_trait_cont.ek30
6 files changed, 86 insertions, 4 deletions
diff --git a/TODO b/TODO
index 8a4adb1..997ae13 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,18 @@
++ I wonder if some kind of `-fast-compile` would be possible? By default I
+ iterate over all definitions in a scope, but an idea for a future rewrite
+ could be to start from main() and typecheck on demand, leaving untouched bits
+ of code unchecked. Unsure how much time it would really save, but we could
+ also add some kind of warning like `function never used` by later iterating
+ over the unchecked stuff? In general I don't like how `actualize.c` works atm,
+ at least generics instantiation (in particular the unification is currently
+ annoying as fuck to deal with)
+
++ Currently the codegen is kind of bugged in that struct instances use the
+ functions defined in the scope of the public part of the chain, one 'shortcut'
+ would be to require that 'continue' matches the pub/private of the base
+ struct, so public structs can only be continued publically and private structs
+ privately? See `tests/struct_priv_trait_cont` for an example.
+
+ Build the consteval stuff
OPTIMIZATIONS:
diff --git a/src/actualize.c b/src/actualize.c
index 2cb2f7a..a6155b9 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -2194,6 +2194,9 @@ static int actualize_trait(struct act_state *state, struct scope *scope,
if (exists)
continue;
+ if (analyze_visibility(trait_scope, n))
+ return -1;
+
if (actualize_proc_sign(trait_scope, n))
return -1;
}
diff --git a/src/debug.c b/src/debug.c
index 0908ee5..0e29efc 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -304,13 +304,14 @@ static void _type_str(FILE *fp, struct type *type)
case TYPE_STRUCT: {
struct ast *def = type->d;
- if (struct_id(def)) {
- fprintf(fp, "%s", struct_id(def));
+ struct ast *base = chain_base(def);
+ if (struct_id(base)) {
+ fprintf(fp, "%s", struct_id(base));
}
- if (struct_params(def)) {
+ if (struct_params(base)) {
fprintf(fp, "![");
- _param_str(fp, struct_params(def));
+ _param_str(fp, struct_params(base));
fprintf(fp, "]");
}
break;
diff --git a/tests/struct_priv_trait_cont/source.mk b/tests/struct_priv_trait_cont/source.mk
new file mode 100644
index 0000000..cff75f9
--- /dev/null
+++ b/tests/struct_priv_trait_cont/source.mk
@@ -0,0 +1 @@
+SIMPLE_XFAIL += struct_priv_trait_cont
diff --git a/tests/struct_priv_trait_cont/struct.ek b/tests/struct_priv_trait_cont/struct.ek
new file mode 100644
index 0000000..6c94aaa
--- /dev/null
+++ b/tests/struct_priv_trait_cont/struct.ek
@@ -0,0 +1,32 @@
+pub typedef ptr {};
+pub typedef i27 {};
+
+pub define trait[] {
+ do_something(=> i27);
+}
+
+pub typedef implementer {}
+continue implementer {
+ trait![];
+ do_something(=> i27)
+ {
+ return 0;
+ }
+}
+
+pub typedef struct[trait T] {
+ T a;
+
+ call_something(*struct![T] self)
+ {
+ self*.a.do_something();
+ }
+}
+
+pub some_func()
+{
+ mut p = struct![implementer]{
+ .a = implementer!{}
+ };
+ p.call_something();
+}
diff --git a/tests/struct_priv_trait_cont/struct_priv_trait_cont.ek b/tests/struct_priv_trait_cont/struct_priv_trait_cont.ek
new file mode 100644
index 0000000..cd67050
--- /dev/null
+++ b/tests/struct_priv_trait_cont/struct_priv_trait_cont.ek
@@ -0,0 +1,30 @@
+import "struct.ek"
+
+/* we implement trait here, but there's another private implementation in
+ * `struct.ek`. Intuitively, I would expect that `p` would end up calling
+ * this implementation, since without this continuation the code wouldn't
+ * compile, but the current instanciation/unification system doesn't handle this
+ * correctly, and the `do_something()` in `struct.ek` is the one that gets
+ * called (since that's the trait implementation visible to that section of the
+ * continuation chain).
+ *
+ * On a related note, for whatever reason `do_something()` doesn't get written
+ * by the codegen. Should maybe try and do something about that as well.
+ */
+continue implementer {
+ trait![];
+ do_something(=> i27)
+ {
+ return 1;
+ }
+}
+
+main()
+{
+ mut p = struct![implementer]{
+ .a = implementer!{}
+ };
+ p.call_something();
+
+ some_func();
+}