]> Nishi Git Mirror - gwion.git/commitdiff
:art: Add scoped enums
authorJérémie Astor <fennecdjay@gmail.com>
Fri, 30 Jul 2021 07:45:08 +0000 (09:45 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Fri, 30 Jul 2021 07:45:08 +0000 (09:45 +0200)
ast
src/emit/emit.c
src/parse/check.c
src/parse/scan1.c
tests/enum/class_scoped.gw [new file with mode: 0644]
tests/enum/scoped.gw [new file with mode: 0644]

diff --git a/ast b/ast
index 2505a7e746b8a63731c11310593d3d7aaddce714..d1d23609b24dc2f754c2808bd23f13100edcc001 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 2505a7e746b8a63731c11310593d3d7aaddce714
+Subproject commit d1d23609b24dc2f754c2808bd23f13100edcc001
index c84c5b3ca0e27bededc9ce893b949a8ac1b667be..f8d95deef33ccc41c341b7f6383f65df499e616b 100644 (file)
@@ -2213,12 +2213,12 @@ ANN static m_bool emit_enum_def(const Emitter emit, const Enum_Def edef) {
   LOOP_OPTIM
   for (m_uint i = 0; i < vector_size(&edef->values); ++i) {
     const Value v = (Value)vector_at(&edef->values, i);
-    if (!emit->env->class_def) {
+    if(edef->is_scoped || emit->env->class_def)
+      *(m_uint *)(v->from->owner->info->class_data + v->from->offset) = i;
+    else {
       v->from->offset = emit_local(emit, emit->gwion->type[et_int]);
       v->d.num        = i;
-    } else
-      *(m_uint *)(emit->env->class_def->nspc->info->class_data +
-                 v->from->offset) = i;
+    }
   }
   set_tflag(edef->t, tflag_emit);
   return GW_OK;
index dc5098638b72c4ce04966463bde7e7200821bb11..0e2fff4c86febe2856c023cba11cc53c57899ed7 100644 (file)
@@ -1095,11 +1095,18 @@ ANN Type check_exp(const Env env, const Exp exp) {
 }
 
 ANN m_bool check_enum_def(const Env env, const Enum_Def edef) {
-  if (env->class_def) {
+  const bool is_scoped = edef->is_scoped;
+  const m_uint scope = is_scoped ?
+    env_push_type(env, edef->t) : 0;
+  if (is_scoped || env->class_def) {
     ID_List list = edef->list;
     do decl_static(env, nspc_lookup_value0(env->curr, list->xid));
     while ((list = list->next));
   }
+  if (is_scoped) {
+    env_pop(env, scope);
+    nspc_allocdata(env->gwion->mp, edef->t->nspc);
+  }
   return GW_OK;
 }
 
index c7f4155487bcec08b1adbdd7b109fa784836e308..c52241916ab0070b11ea871d89e91921cc8ccd04 100644 (file)
@@ -366,11 +366,20 @@ ANN static inline m_bool scan1_stmt_exp(const Env env, const Stmt_Exp stmt) {
 }
 
 ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) {
+  const m_bool is_scoped = edef->is_scoped;
+  if(is_scoped)
+    edef->t->nspc = new_nspc(env->gwion->mp, edef->t->name);
+  const Nspc nspc = is_scoped ?
+    edef->t->nspc : edef->t->info->value->from->owner;
+  const m_uint scope = is_scoped ?
+    env_push_type(env, edef->t) : 0;
   ID_List list = edef->list;
   do {
-    CHECK_BB(already_defined(env, list->xid, edef->pos));
-    if (nspc_lookup_value1(edef->t->info->value->from->owner, list->xid))
-      ERR_B(edef->pos, "'%s' already defined", s_name(list->xid));
+    if(!is_scoped) {
+      CHECK_BB(already_defined(env, list->xid, edef->pos));
+      if (nspc_lookup_value1(nspc, list->xid))
+        ERR_B(edef->pos, "'%s' already defined", s_name(list->xid));
+    }
     const Value v = new_value(env->gwion->mp, edef->t, s_name(list->xid));
     valuefrom(env, v->from, edef->pos);
     if (env->class_def) {
@@ -381,9 +390,11 @@ ANN m_bool scan1_enum_def(const Env env, const Enum_Def edef) {
       set_vflag(v, vflag_builtin);
     SET_FLAG(v, const);
     set_vflag(v, vflag_valid);
-    nspc_add_value(edef->t->info->value->from->owner, list->xid, v);
+    nspc_add_value(nspc, list->xid, v);
     vector_add(&edef->values, (vtype)v);
   } while ((list = list->next));
+  if(is_scoped)
+    env_pop(env, scope);
   return GW_OK;
 }
 
diff --git a/tests/enum/class_scoped.gw b/tests/enum/class_scoped.gw
new file mode 100644 (file)
index 0000000..d0b7d19
--- /dev/null
@@ -0,0 +1,7 @@
+class C {
+  enum MyEnum@ {
+    zero, one
+  }
+}
+
+<<< C.MyEnum.one >>>;
diff --git a/tests/enum/scoped.gw b/tests/enum/scoped.gw
new file mode 100644 (file)
index 0000000..4b4fcf7
--- /dev/null
@@ -0,0 +1,6 @@
+#! [contains] 1
+enum MyEnum@ {
+  zero, one
+}
+
+<<< MyEnum.one >>>;