-Subproject commit ecdd2a8aabed7f730f7ef06cc32d48a2c431134f
+Subproject commit 4a237db7d547d5b132ffcdb4489ed67126e67e69
-Subproject commit 4287d6bba515c6d9a304341f43a759352778ce68
+Subproject commit 01aa72eaba624e348de046ab573f498861e2103f
Scope type;
Scope func;
Scope trait;
+ MP_Vector *using;
} NspcInfo;
typedef struct NspcOp_ {
#define RET_NSPC(exp) \
++env->scope->depth; \
+ const uint32_t nusing = env->curr->info->using \
+ ? env->curr->info->using->len \
+ : 0; \
nspc_push_value(env->gwion->mp, env->curr); \
const bool ret = exp; \
nspc_pop_value(env->gwion->mp, env->curr); \
+ if(nusing) \
+ env->curr->info->using->len = nusing; \
--env->scope->depth; \
return ret;
#define clean_stmt_retry clean_dummy
#define clean_stmt_spread clean_dummy
+// TODO: check me
+#define clean_stmt_using clean_dummy
+
DECL_STMT_FUNC(clean, void, Clean *)
ANN static void clean_stmt(Clean *a, Stmt* b) {
clean_stmt_func[b->stmt_type](a, &b->d);
#define emit_stmt_while emit_stmt_flow
#define emit_stmt_until emit_stmt_flow
#define emit_stmt_spread dummy_func
+#define emit_stmt_using dummy_func
DECL_STMT_FUNC(emit, bool, Emitter);
const Nspc nspc = (Nspc)vector_at(v, i - 1);
RETURN_TYPE(nspc_lookup_type1(nspc, xid));
}
- return NULL;
+ if(env->curr->info->using) {
+ for(uint32_t i = 0; i < env->curr->info->using->len; i++) {
+ Stmt_Using using = *mp_vector_at(env->curr->info->using, Stmt_Using, i);
+ if(!using->alias.sym) {
+ const Type owner = known_type(env, using->d.td);
+ if(owner) {
+ const Type ret = nspc_lookup_type0(owner->nspc, xid);
+ if(ret) return ret;
+ }
+ } else if(xid == using->alias.sym) {
+ if(!using->d.exp->type)
+ CHECK_B(traverse_exp(env, using->d.exp));
+ if(is_class(env->gwion, using->d.exp->type))
+ return using->d.exp->type->info->base_type;
+ ERR_B(using->alias.loc, "found an alias %s but it's not a type", s_name(using->alias.sym));
+ }
+}}
+ return NULL;
}
#undef RETURN_TYPE
ANN Type find_type(const Env env, Type_Decl *td) {
DECL_O(Type, type, = find_initial(env, td->tag.sym));
while ((td = td->next) && type && type->nspc) {
-// const Nspc nspc = type->nspc;
-// if(!(type = find_in_parent(type, td->tag.sym)))
-//
- //enERR_O(td->tag.loc, _("...(cannot find class '%s' in nspc '%s')"),
-//s_name(td->tag.sym), nspc->name);
-
-
Type_Decl *next = td->next;
td->next = NULL;
-env_push_type(env, type);
+ const uint32_t scope = env->scope->depth;
+ env_push_type(env, type);
type = known_type(env, td);
if(!type)
ERR_O(td->tag.loc, _("...(cannot find class '%s' in nspc '%s')"),
s_name(td->tag.sym), env->class_def->name);
-env_pop(env, 0); // respect scope depth // use env scope
+ env_pop(env, scope);
td->next = next;
}
nspc_free_trait(a, gwion);
if(a->operators) free_operators(a->operators, gwion);
nspc_free_type(a, gwion);
+ if (a->info->using)
+ free_mp_vector(gwion->mp, Stmt_Using, a->info->using);
if (a->class_data && a->class_data_size)
mp_free2(gwion->mp, a->class_data_size, a->class_data);
if (a->vtable.ptr) vector_release(&a->vtable);
return v->type;
}
}
+ if(env->curr->info->using) {
+ for(uint32_t i = 0; i < env->curr->info->using->len; i++) {
+ Stmt_Using using = *mp_vector_at(env->curr->info->using, Stmt_Using, i);
+ if(!using->alias.sym) {
+ // NOTE: we know type is valid and has nspc
+ const Type type = known_type(env, using->d.td);
+ Value value = nspc_lookup_value1(type->nspc, sym);
+ if(value) {
+ Exp *exp = prim_exp(data);
+ exp->exp_type = ae_exp_dot;
+ Type_Decl *td = cpy_type_decl(env->gwion->mp, using->d.td);
+ exp->d.exp_dot.base = new_exp_td(env->gwion->mp, td, exp->loc);
+ exp->d.exp_dot.xid = insert_symbol(value->name);
+ return check_exp(env, exp);
+ }
+ } else if(sym == using->alias.sym) {
+ Exp *exp = prim_exp(data);
+ Exp *base = cpy_exp(env->gwion->mp, using->d.exp);
+ *exp = *base;
+ mp_free2(env->gwion->mp, sizeof(Exp), base);
+ return check_exp(env, exp);
+ }
+ }
+ }
m_str str = NULL;
gw_asprintf(env->gwion->mp, &str, "Invalid variable {R}%s{0}\n", name);
gwlog_error(str, _("not legit at this point."),
return check_stmt(env, stmt->stmt);
}
+ANN static bool check_stmt_using(const Env env, const Stmt_Using stmt) {
+ if(!stmt->alias.sym) {
+ DECL_B(const Type, type, = known_type(env, stmt->d.td));
+ for(m_uint i = 0; i < map_size(&type->nspc->info->value->map); ++i) {
+ const Symbol sym = (Symbol)VKEY(&type->nspc->info->value->map, i);
+ const Value value = nspc_lookup_value1(env->curr, sym);
+ if(value) {
+ char msg[256];
+ sprintf(msg, "{Y}%s{0} is already defined", value->name);
+ gwlog_error(_(msg), "from this `using` statement", env->name, stmt->d.td->tag.loc, 0);
+ declared_here(value);
+ const Value other = nspc_lookup_value1(type->nspc, sym);
+ declared_here(other);
+ return false;
+ }
+ }
+ } else {
+ const Value value = nspc_lookup_value1(env->curr, stmt->alias.sym);
+ if(value) {
+ char msg[256];
+ sprintf(msg, "{Y}%s{0} is already defined", value->name);
+ gwlog_error(_(msg), NULL, env->name, stmt->alias.loc, 0);
+ declared_here(value);
+ return false;
+ }
+ if(!stmt->d.exp->type)
+ CHECK_B(check_exp(env, stmt->d.exp));
+ }
+ mp_vector_add(env->gwion->mp, &env->curr->info->using, Stmt_Using, stmt);
+ return true;
+}
+
#define check_stmt_retry dummy_func
#define check_stmt_spread dummy_func
DECL_STMT_FUNC(check, bool, Env)
ANN bool check_stmt_list(const Env env, Stmt_List l) {
bool ok = true;
+ const uint32_t nusing = env->curr->info->using
+ ? env->curr->info->using->len
+ : 0;
for(m_uint i = 0; i < l->len; i++) {
Stmt* stmt = mp_vector_at(l, Stmt, i);
if(stmt->poison) { ok = false; continue;}
if(!check_stmt(env, stmt))
POISON_NODE(ok, env, stmt);
}
+ if(env->curr->info->using)
+ env->curr->info->using->len = nusing;
return ok;
}
ANN static bool scan0_stmt_list(const Env env, Stmt_List l) {
bool ok = true;
+ const uint32_t nusing = env->curr->info->using
+ ? env->curr->info->using->len
+ : 0;
for(m_uint i = 0; i < l->len; i++) {
Stmt* stmt = mp_vector_at(l, Stmt, i);
if(stmt->poison) { ok = false; continue; }
if(!plugin_ini(env->gwion, stmt->d.stmt_pp.data, stmt->loc))
POISON_NODE(ok, env, stmt);
}
+ } else if(stmt->stmt_type == ae_stmt_using) {
+ if(!env->curr->info->using)
+ env->curr->info->using = new_mp_vector(env->gwion->mp, Stmt_Using, 0);
+ mp_vector_add(env->gwion->mp, &env->curr->info->using, Stmt_Using, &stmt->d.stmt_using);
} /*else if (stmt->stmt_type == ae_stmt_spread) {
if(!spreadable(env)) // TODO: we can prolly get rid of this
ERR_OK_NODE(ok, stmt, stmt->loc, "spread statement outside of variadic environment");
}*/
}
+ if(env->curr->info->using && env->scope->depth)
+ env->curr->info->using->len = nusing;
return ok;
}
ANN static inline bool scan1_stmt_match_case(const restrict Env env,
const Stmt_Match stmt) {
- RET_NSPC(_scan1_stmt_match_case(env, stmt))}
+ RET_NSPC(_scan1_stmt_match_case(env, stmt));
+}
+
+ANN static inline bool scan1_stmt_using(const restrict Env env,
+ const Stmt_Using stmt) {
+ if(stmt->alias.sym)
+ CHECK_B(scan1_exp(env, stmt->d.exp));
+ if(!env->curr->info->using)
+ env->curr->info->using = new_mp_vector(env->gwion->mp, Stmt_Using, 0);
+ mp_vector_add(env->gwion->mp, &env->curr->info->using, Stmt_Using, stmt);
+ return true;
+}
ANN static inline bool
_scan1_stmt_match(const restrict Env env, const Stmt_Match stmt) {
ANN static bool scan1_stmt_list(const Env env, Stmt_List l) {
uint32_t i;
bool ok = true;
+ const uint32_t nusing = env->curr->info->using
+ ? env->curr->info->using->len
+ : 0;
for(i = 0; i < l->len; i++) {
Stmt* stmt = mp_vector_at(l, Stmt, i);
if(stmt->poison) { ok = false; continue;}
}
if(end_flow(stmt)) break;
}
+ if(env->curr->info->using)
+ env->curr->info->using->len = nusing;
if(++i < l->len) dead_code(env, l, i);
return ok;
}
return scan2_stmt(env, stmt->stmt);
}
+ANN static inline bool scan2_stmt_using(const restrict Env env,
+ const Stmt_Using stmt) {
+ if(stmt->alias.sym)
+ CHECK_B(scan2_exp(env, stmt->d.exp));
+ mp_vector_add(env->gwion->mp, &env->curr->info->using, Stmt_Using, stmt);
+ return true;
+}
+
#define scan2_stmt_spread dummy_func
DECL_STMT_FUNC(scan2, bool, Env)
ANN static bool scan2_stmt_list(const Env env, Stmt_List l) {
bool ok = true;
+ const uint32_t nusing = env->curr->info->using
+ ? env->curr->info->using->len
+ : 0;
for(m_uint i = 0; i < l->len; i++) {
Stmt* stmt = mp_vector_at(l, Stmt, i);
if(stmt->poison) { ok = false; continue; }
if(!scan2_stmt(env, stmt))
POISON_NODE(ok, env, stmt);
}
+ if(env->curr->info->using)
+ env->curr->info->using->len = nusing;
return ok;
}
ANN static bool validate_stmt_spread(Validate *a NUSED, Spread_Def b NUSED) {
return true;
}
+
+#define validate_stmt_using dummy_func
+
DECL_STMT_FUNC(validate, bool, Validate*)
ANN static bool validate_stmt(Validate *a, Stmt* b) {
if(b->poison) return false;
return ok;
}
+#define sema_stmt_using dummy_func
+
DECL_STMT_FUNC(sema, bool, Sema*)
ANN static bool sema_stmt(Sema *a, Stmt* b, bool in_list) {
Stmt_List *stmt_list = a->stmt_list;
--- /dev/null
+#! [contains] 12
+class Foo {
+ 12 :=> var static int bar;
+}
+
+12 :=> Foo.bar;
+using bar : Foo.bar;
+
+<<< bar >>>;
+
--- /dev/null
+#! [contains] 12
+class Foo {
+ 12 :=> var static int bar;
+}
+
+12 :=> Foo.bar;
+using Foo;
+
+<<< bar >>>;
+
--- /dev/null
+#! [contains] foo
+class C {
+ class D {
+ <<< "foo" >>>;
+ }
+}
+
+using C;
+#!var D d;
+class E extends D {};
+
+var E e;
--- /dev/null
+#! [contains] already defined
+class C {
+ class D {}
+}
+class D {}
+
+using C : D;
+
+
--- /dev/null
+#! [contains] from this `using` statement
+class C {
+ class D {
+ }
+}
+
+class D {}
+
+using C;
+
+
--- /dev/null
+#! [contains] found an alias
+class C {
+ var static int i;
+}
+
+using i : C.i;
+
+var i j;
--- /dev/null
+#! [contains] not legit
+class C {
+ var static int testUsingScoping;
+}
+
+fun void test() {
+ using C;
+ <<< testUsingScoping >>>;
+}
+
+<<< testUsingScoping >>>;
--- /dev/null
+#! [contains] Foo.Bar ctor
+class Foo {
+ class Bar {
+ <<< "Foo.Bar ctor" >>>;
+ var int i;
+ }
+}
+
+using Bar : Foo.Bar;
+
+var Bar bar;
+
+<<< bar.i >>>;