Type t;
loc_t pos;
};
+
+struct TemplateScan {
+ const Type t;
+ const Type_Decl *td;
+};
+
ANN m_bool add_op(const Gwion gwion, const struct Op_Import*);
ANN Type op_check(const Env, struct Op_Import*);
ANN struct Instr_* op_emit(const Emitter, const struct Op_Import*);
#define xxx_cdef(prefix) \
static inline m_bool prefix##_cdef(const Env env, const Class_Def cdef) { \
return scanx_cdef(env, env, cdef, \
- (_exp_func)prefix##_class_def, (_exp_func)prefix##_union_def); \
+ (_exp_func)prefix##_class_def, (_exp_func)prefix##_union_def); \
}
-xxx_cdef(scan1)
-xxx_cdef(scan2)
-xxx_cdef(check)
+
+#define xxx_cdef_flag(prefix) \
+static inline m_bool prefix##_cdef(const Env env, const Class_Def cdef) { \
+ SET_FLAG(cdef, prefix); \
+ return scanx_cdef(env, env, cdef, \
+ (_exp_func)prefix##_class_def, (_exp_func)prefix##_union_def); \
+}
+xxx_cdef_flag(scan1)
+xxx_cdef_flag(scan2)
+xxx_cdef_flag(check)
xxx_cdef(traverse)
ANN m_bool scanx_fdef(const Env, void *, const Func_Def, const _exp_func);
#ifndef __TEMPLATE
#define __TEMPLATE
ANN m_bool template_push_types(const Env, const Tmpl*);
+ANN Tmpl* mk_tmpl(const Env, const Tmpl*, const Type_List);
#define POP_RET(a) { nspc_pop_type(env->gwion->mp, env->curr); return (a); }
#endif
#include "import.h"
#include "emit.h"
#include "traverse.h"
+#include "template.h"
#include "parse.h"
#include "specialid.h"
INTERP_PRINTF("%p", *(M_Object*)VALUE);
}
+ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td);
+
+static OP_CHECK(opck_object_scan) {
+ struct TemplateScan *ts = (struct TemplateScan*)data;
+ if(ts->td->types)
+ return scan_class(env, ts->t, ts->td);
+ ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name)
+}
+
GWION_IMPORT(object) {
const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
gwi_add_type(gwi, t_object);
GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
GWI_BB(gwi_oper_end(gwi, "!", IntNot))
+ GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_object_scan))
+ GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
gwi_item_ini(gwi, "@null", "null");
gwi_item_end(gwi, 0, NULL);
struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 };
gwi_specialid(gwi, "this", &spid);
return GW_OK;
}
+struct tmpl_info {
+ const Class_Def cdef;
+ Type_List call;
+ struct Vector_ type;
+ struct Vector_ size;
+ uint8_t index;
+};
+
+ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
+ vector_add(&info->type, (vtype)t);
+ const size_t len = strlen(t->name);
+ vector_add(&info->size, len);
+ return len;
+}
+
+ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
+ ID_List base = info->cdef->base.tmpl->list;
+ Type_List call = info->call;
+ size_t size = tmpl_set(info, info->cdef->base.type);
+ do {
+ DECL_OB(const Type, t, = known_type(env, call->td))
+ size += tmpl_set(info, t);
+ } while((call = call->next) && (base = base->next) && ++size);
+ return size + 16 + 3;
+}
+
+ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
+ const Type t = (Type)vector_at(&info->type, info->index);
+ strcpy(str, t->name);
+ return str += vector_at(&info->size, info->index);
+}
+
+ANN static void template_name(struct tmpl_info* info, m_str s) {
+ m_str str = s;
+ str = tmpl_get(info, str);
+ *str++ = '<';
+ *str++ = '~';
+ const m_uint size = vector_size(&info->type);
+ for(info->index = 1; info->index < size; ++info->index) {
+ str = tmpl_get(info, str);
+ if(info->index < size - 1)
+ *str++ = ',';
+ else {
+ *str++ = '~';
+ *str++ = '>';
+ }
+ }
+ *str = '\0';
+}
+
+ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) {
+ struct tmpl_info info = { .cdef=c, .call=call };
+ vector_init(&info.type);
+ vector_init(&info.size);
+ ssize_t sz = template_size(env, &info);
+ char name[sz];
+ if(sz > GW_ERROR)
+ template_name(&info, name);
+ vector_release(&info.type);
+ vector_release(&info.size);
+ return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL;
+}
+
+ANN m_bool template_match(ID_List base, Type_List call) {
+ while((call = call->next) && (base = base->next));
+ return !call ? GW_OK : GW_ERROR;
+}
+
+ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) {
+ DECL_OO(const Symbol, name, = template_id(env, def, call))
+ if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name))
+ return env->class_def->e->def;
+ const Type t = nspc_lookup_type1(env->curr, name);
+ if(t)
+ return t->e->def;
+ const Class_Def c = cpy_class_def(env->gwion->mp, def);
+ c->base.xid = name;
+ SET_FLAG(c, template | ae_flag_ref);
+ return c;
+
+}
+
+extern ANN m_bool scan0_class_def(const Env, const Class_Def);
+extern ANN m_bool scan1_class_def(const Env, const Class_Def);
+extern ANN m_bool traverse_func_def(const Env, const Func_Def);
+extern ANN m_bool traverse_class_def(const Env, const Class_Def);
+
+ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) {
+ a->union_def = new_union_def(env->gwion->mp, a->list,
+ loc_cpy(env->gwion->mp, t->e->def->pos));
+ a->union_def->type_xid = a->base.xid;
+ CHECK_BB(scan0_union_def(env, a->union_def))
+ SET_FLAG(a, scan0);
+ a->base.type = a->union_def->type;
+ a->base.type->e->def = a;
+ return GW_OK;
+}
+
+ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) {
+ if(template_match(t->e->def->base.tmpl->list, td->types) < 0)
+ ERR_O(td->xid->pos, _("invalid template types number"))
+ DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
+ if(a->base.type)
+ return a->base.type;
+ a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types);
+ if(t->e->parent != env->gwion->type[et_union])
+ CHECK_BO(scan0_class_def(env, a))
+ else
+ CHECK_BO(class2udef(env, a, t))
+ SET_FLAG(a->base.type, template);
+ if(GET_FLAG(t, builtin))
+ SET_FLAG(a->base.type, builtin);
+ CHECK_BO(scan1_cdef(env, a))
+ return a->base.type;
+}
return (Instr)GW_OK;
}
+ANN static Type scan_tuple(const Env env, const Type_Decl *td);
+static OP_CHECK(opck_tuple_scan) {
+ struct TemplateScan *ts = (struct TemplateScan*)data;
+ return ts->td->types ? scan_tuple(env, ts->td) : ts->t;
+}
+
GWION_IMPORT(tuple) {
const Type t_tuple = gwi_mk_type(gwi, "Tuple", SZ_INT, "Object");
gwi_add_type(gwi, t_tuple);
GWI_BB(gwi_oper_add(gwi, tuple_ck))
GWI_BB(gwi_oper_emi(gwi, tuple_em))
GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_tuple_scan))
+ GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
GWI_BB(gwi_oper_ini(gwi, "Object", "Tuple", NULL))
GWI_BB(gwi_oper_add(gwi, opck_at_object_tuple))
GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
GWI_BB(gwi_oper_end(gwi, "==", NULL))
return GW_OK;
}
+
+static ANN Type scan_tuple(const Env env, const Type_Decl *td) {
+ struct Vector_ v;
+ vector_init(&v);
+ Type_List tl = td->types;
+ do {
+ const Type t = tl->td->xid->xid != insert_symbol("_") ?
+ known_type(env, tl->td) : (Type)1;
+ if(t)
+ vector_add(&v, (m_uint)t);
+ else {
+ vector_release(&v);
+ return env->gwion->type[et_null];
+ }
+ } while((tl = tl->next));
+ const Type ret = tuple_type(env, &v, td_pos(td));
+ vector_release(&v);
+ return ret;
+}
td.xid = &id;
tl.td = &td0;
td.types = &tl;
+ td0.xid->pos = stmt->exp->pos;
+ td.xid->pos = stmt->exp->pos;
if(depth) {
array.depth = depth;
td.array = &array;
}
ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) {
+printf("here %s\n", nspc->name);
if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@array")) {
Array_Sub array = (Array_Sub)ock->opi->data;
array->exp->nspc = nspc;
((Exp)ock->opi->data)->nspc = nspc;
return;
}
- exp_self((union exp_data*)ock->opi->data)->nspc = nspc;
+// use .mut
+ if(ock->opi->op != insert_symbol(ock->env->gwion->st, "@scan"))
+ exp_self((union exp_data*)ock->opi->data)->nspc = nspc;
}
ANN static Type op_check_inner(struct OpChecker* ock) {
ANN m_bool scan1_union_def_action(const Env env, const Union_Def udef,
const Decl_List l) {
+ if(GET_FLAG(udef, scan1))
+ return GW_OK;
const Exp_Decl decl = l->self->d.exp_decl;
SET_FLAG(decl.td, checked | udef->flag);
const m_bool global = GET_FLAG(udef, global);
#include "vm.h"
#include "parse.h"
#include "gwion.h"
-#include "tuple.h"
+#include "operator.h"
struct tmpl_info {
const Class_Def cdef;
uint8_t index;
};
-ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
- vector_add(&info->type, (vtype)t);
- const size_t len = strlen(t->name);
- vector_add(&info->size, len);
- return len;
-}
-
-ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
- ID_List base = info->cdef->base.tmpl->list;
- Type_List call = info->call;
- size_t size = tmpl_set(info, info->cdef->base.type);
- do {
- DECL_OB(const Type, t, = known_type(env, call->td))
- size += tmpl_set(info, t);
- } while((call = call->next) && (base = base->next) && ++size);
- return size + 16 + 3;
-}
-
-ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
- const Type t = (Type)vector_at(&info->type, info->index);
- strcpy(str, t->name);
- return str += vector_at(&info->size, info->index);
-}
-
-ANN static void template_name(struct tmpl_info* info, m_str s) {
- m_str str = s;
- str = tmpl_get(info, str);
- *str++ = '<';
- *str++ = '~';
- const m_uint size = vector_size(&info->type);
- for(info->index = 1; info->index < size; ++info->index) {
- str = tmpl_get(info, str);
- if(info->index < size - 1)
- *str++ = ',';
- else {
- *str++ = '~';
- *str++ = '>';
- }
- }
- *str = '\0';
-}
-
-ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) {
- struct tmpl_info info = { .cdef=c, .call=call };
- vector_init(&info.type);
- vector_init(&info.size);
- ssize_t sz = template_size(env, &info);
- char name[sz];
- if(sz > GW_ERROR)
- template_name(&info, name);
- vector_release(&info.type);
- vector_release(&info.size);
- return sz > GW_ERROR ? insert_symbol(name) : NULL;
-}
-
-ANN m_bool template_match(ID_List base, Type_List call) {
- while((call = call->next) && (base = base->next));
- return !call ? GW_OK : GW_ERROR;
-}
-
-ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) {
- DECL_OO(const Symbol, name, = template_id(env, def, call))
- if(env->class_def && name == insert_symbol(env->class_def->name))
- return env->class_def->e->def;
- const Type t = nspc_lookup_type1(env->curr, name);
- if(t)
- return t->e->def;
- const Class_Def c = cpy_class_def(env->gwion->mp, def);
- c->base.xid = name;
- SET_FLAG(c, template | ae_flag_ref);
- return c;
-
-}
-
ANN m_bool template_push_types(const Env env, const Tmpl *tmpl) {
ID_List list = tmpl->list;
Type_List call = tmpl->call;
POP_RET(-1);
}
-extern ANN m_bool scan0_class_def(const Env, const Class_Def);
-extern ANN m_bool scan1_class_def(const Env, const Class_Def);
-extern ANN m_bool traverse_func_def(const Env, const Func_Def);
-extern ANN m_bool traverse_class_def(const Env, const Class_Def);
-
-ANN Type scan_tuple(const Env env, const Type_Decl *td) {
- struct Vector_ v;
- vector_init(&v);
- Type_List tl = td->types;
- do {
- const Type t = tl->td->xid->xid != insert_symbol("_") ?
- known_type(env, tl->td) : (Type)1;
- if(t)
- vector_add(&v, (m_uint)t);
- else {
- vector_release(&v);
- return NULL;
- }
- } while((tl = tl->next));
- const Type ret = tuple_type(env, &v, td_pos(td));
- vector_release(&v);
- return ret;
-}
-
ANN Tmpl* mk_tmpl(const Env env, const Tmpl *tm, const Type_List types) {
Tmpl *tmpl = new_tmpl(env->gwion->mp, tm->list, 0);
tmpl->call = cpy_type_list(env->gwion->mp, types);
return tmpl;
}
-ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) {
- a->union_def = new_union_def(env->gwion->mp, a->list,
- loc_cpy(env->gwion->mp, t->e->def->pos));
- a->union_def->type_xid = a->base.xid;
- CHECK_BB(scan0_union_def(env, a->union_def))
- a->base.type = a->union_def->type;
- a->base.type->e->def = a;
- return GW_OK;
-}
-
-ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) {
- if(template_match(t->e->def->base.tmpl->list, td->types) < 0)
- ERR_O(td->xid->pos, _("invalid template types number"))
- DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
- if(a->base.type)
- return a->base.type;
- a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types);
- if(t->e->parent != env->gwion->type[et_union])
- CHECK_BO(scan0_class_def(env, a))
- else
- CHECK_BO(class2udef(env, a, t))
- SET_FLAG(a->base.type, template);
- if(GET_FLAG(t, builtin))
- SET_FLAG(a->base.type, builtin);
- CHECK_BO(scan1_cdef(env, a))
- return a->base.type;
-}
-
-ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) {
+static ANN Type scan_func(const Env env, const Type t, const Type_Decl* td) {
DECL_OO(const m_str, tl_name, = tl2str(env, td->types))
const Symbol sym = func_symbol(env, t->e->owner->name, t->e->d.func->name, tl_name, 0);
free_mstr(env->gwion->mp, tl_name);
return ret;
}
-ANN Type no_types(const Env env, const Type t) {
- if(t != env->gwion->type[et_tuple])
- ERR_O(t->e->def->pos,
- _("you must provide template types for type '%s'"), t->name)
- return t;
-}
-
-ANN Type maybe_func(const Env env, const Type t, const Type_Decl* td) {
+static ANN Type maybe_func(const Env env, const Type t, const Type_Decl* td) {
if(isa(t, env->gwion->type[et_function]) > 0 && t->e->d.func->def->base->tmpl)
return scan_func(env, t, td);
ERR_O(td->xid->pos,
if(GET_FLAG(t, template)) {
if(GET_FLAG(t, ref))
return t;
- if(!td->types)
- return no_types(env, t);
- if(t->e->def)
- return scan_class(env, t, td);
- else
- return scan_tuple(env, td);
- } else if(td->types)
- return maybe_func(env, t, td);
+ struct TemplateScan ts = { .t=t, .td=td };
+ struct Op_Import opi = { .op=insert_symbol("@scan"), .lhs=t, .data=(uintptr_t)&ts, .pos=td_pos(td) };
+ return op_check(env, &opi);
+ } else if(td->types)
+ return maybe_func(env, t, td);
return t;
}
ANN m_bool traverse_union_def(const Env env, const Union_Def def) {
if(!GET_FLAG(def, scan1))
CHECK_BB(scan1_union_def(env, def))
+ if(!GET_FLAG(def, scan2))
CHECK_BB(scan2_union_def(env, def))
+ if(!GET_FLAG(def, check))
+ CHECK_BB(check_union_def(env, def))
return check_union_def(env, def);
}
class <~A~>C {
- operator @dtor void { <<< __func__ >>>; }
+ operator @dtor void () { <<< __func__ >>>; }
}
class <~A~>D extends <~A~>C {
- operator @dtor { <<< __func__ >>>; }
+ operator @dtor void () { <<< __func__ >>>; }
}
class E extends <~int~>D {
- operator @dtor { <<< __func__ >>>; }
+ operator @dtor void () { <<< __func__ >>>; }
}
E e;