ANN m_bool is_fptr(const struct Gwion_*, const Type t);
ANN m_bool is_class(const struct Gwion_*, const Type t);
ANN m_uint get_depth(const Type type);
+
+__attribute__((returns_nonnull))
+ANN static inline Type get_gack(Type t) {
+ do if(t->e->gack)
+ return t;
+ while((t = t->e->parent));
+ return t; // unreachable
+}
+
typedef enum {
et_void, et_int, et_bool, et_char, et_float,
- et_null, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack,
+ et_null, et_compound, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack,
et_function, et_fptr, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto,
MAX_TYPE
} type_enum;
return GW_OK;
}
-ANN static inline void struct_interp(const Emitter emit, const Exp e) {
- if(GET_FLAG(e->info->type, struct) && !GET_FLAG(e->info->type, builtin)) {
- exp_setvar(e, 1);
- regpush(emit, e->info->type->size - SZ_INT);
- }
-}
-
ANN static void interp_multi(const Emitter emit, const Exp e) {
Var_Decl_List list = e->d.exp_decl.list;
const int emit_var = exp_getvar(e);
regpop(emit, offset);
}
+ANN static void interp_size(const Emitter emit, const Type t) {
+ const m_uint sz = isa(t, emit->gwion->type[et_compound]) < 0 ?
+ t->size : SZ_INT;
+ const Instr instr = regseti(emit, sz);
+ instr->m_val2 = SZ_INT;
+}
+
ANN static m_bool emit_interp(const Emitter emit, const Exp exp) {
regpushi(emit, 0);
Exp e = exp, next = NULL;
do {
next = e->next;
e->next = NULL;
- struct_interp(emit, e);
if(emit_exp(emit, e) < 0) {
e->next = next;
return GW_ERROR;
if(e->exp_type == ae_exp_decl) // why only objects?
interp_multi(emit, e);
regseti(emit, (m_uint)e->info->type);
+ interp_size(emit, e->info->type);
+// regseti(emit, (m_uint)isa(e->info->type, emit->gwion->type[et_object]) > 0);
const m_bool isobj = isa(e->info->type, emit->gwion->type[et_object]) > 0;
- if(isobj && !GET_FLAG(e->info->type, force))
- emit_add_instr(emit, GackType);
+ if(isobj) {
+ if(!GET_FLAG(e->info->type, force))
+ emit_add_instr(emit, GackType);
+ }
const Instr instr = emit_add_instr(emit, Gack);
instr->m_val = emit_code_offset(emit);
} while((e = e->next = next));
CHECK_BB(emit_interp(emit, *exp))
if(!(emit->env->func && emit->env->func->def->base->xid == insert_symbol("@gack")))
emit_add_instr(emit, GackEnd);
+ else {
+ const Instr instr = emit_add_instr(emit, Reg2Mem);
+ instr->m_val = SZ_INT;
+ instr->m_val2 = -SZ_INT;
+ }
return GW_OK;
}
}
ANN static inline int struct_ctor(const Value v) {
- return GET_FLAG(v->type, struct) && v->type->nspc->pre_ctor;
+ return GET_FLAG(v->type, struct);
}
ANN static void emit_struct_decl_finish(const Emitter emit, const Value v) {
- emit_ext_ctor(emit, v->type->nspc->pre_ctor);
const Instr instr = emit_add_instr(emit, Reg2RegDeref);
instr->m_val = -SZ_INT;
instr->m_val2 = v->type->size;
if(isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
CHECK_BB(decl_static(emit, var_decl, 0))
CHECK_BB(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1))
- if(!emit_addr && struct_ctor(v))
- emit_struct_decl_finish(emit, v);
+ if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */) {
+ emit_ext_ctor(emit, v->type->nspc->pre_ctor);
+ if(!emit_addr)
+ emit_struct_decl_finish(emit, v);
+ }
return GW_OK;
}
ANN static Instr emit_struct_decl(const Emitter emit, const Value v, const m_bool emit_addr) {
emit_add_instr(emit, RegPushMem);
-//regpushi(emit, 0);
const Instr instr = emit_add_instr(emit, !emit_addr ? StructMember : StructMemberAddr);
instr->m_val2 = v->from->offset;
if(!emit_addr)
const Instr clean = emit_add_instr(emit, MemSetImm);
clean->m_val = v->from->offset;
}
- if(!emit_addr && GET_FLAG(type, struct)) {
- for(m_uint i = 0; i <= type->size; ++i) {
- const Instr clean = emit_add_instr(emit, MemSetImm);
- clean->m_val = v->from->offset + i;
- }
- }
}
const Instr instr = !(SAFE_FLAG(emit->env->class_def, struct) && !emit->env->scope->depth) ?
emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, exec) : emit_struct_decl(emit, v, emit_addr);
- if((emit_addr || !GET_FLAG(v, member)))
+ if(!GET_FLAG(v, member))
instr->m_val = v->from->offset;
if(is_obj && (is_array || !is_ref)) {
emit_add_instr(emit, Assign);
const Instr push = emit_add_instr(emit, Reg2Reg);
push->m_val = -(missing_depth) * SZ_INT;
}
- } else if(!emit_addr && struct_ctor(v))
- emit_struct_decl_finish(emit, v);
+ } else if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */) {
+ if(GET_FLAG(v, member)) {
+ const Instr instr = emit_add_instr(emit, DotMember4);
+ instr->m_val = v->from->offset;
+ }
+ emit_ext_ctor(emit, v->type->nspc->pre_ctor);
+ if(!emit_addr)
+ emit_struct_decl_finish(emit, v);
+ }
return GW_OK;
}
}
assign->m_val = emit_var;
(void)emit_addref(emit, emit_var);
- } else if(!emit_var && struct_ctor(v))
- emit_struct_decl_finish(emit, v);
+ } else if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */) {
+ emit_ext_ctor(emit, v->type->nspc->pre_ctor);
+ if(!emit_addr)
+ emit_struct_decl_finish(emit, v);
+ }
return GW_OK;
}
const uint ref = GET_FLAG(decl->td, ref) || type_ref(decl->type);
Var_Decl_List list = decl->list;
do {
- const uint r = (list->self->array && list->self->array->exp && ref) ? 0 : (uint)(GET_FLAG(list->self->value, ref) + ref);
+ const uint r = GET_FLAG(list->self->value, ref) + ref;
if(GET_FLAG(decl->td, static))
CHECK_BB(emit_exp_decl_static(emit, list->self, r, var))
else if(!global)
ADD_REF(f->code)
return f->code;
} else if(f->def->base->xid == insert_symbol("@gack")) {
- regpush(emit, SZ_INT);
+ regpop(emit, SZ_INT*2);
+ const Instr instr = emit_add_instr(emit, RegPushMem);
+ instr->m_val = SZ_INT;
f->code = finalyze(emit, FuncReturn);
return emit->env->class_def->e->gack = f->code;
}
emit->env->func = func;
emit_push_scope(emit);
- if(!strcmp(s_name(fdef->base->xid), "@gack") &&
- SAFE_FLAG(func->value_ref->from->owner_class, struct))
- regpop(emit, func->value_ref->from->owner_class->size - SZ_INT);
+ if(!strcmp(s_name(fdef->base->xid), "@gack")) {
+ emit_local(emit, emit->gwion->type[et_int]);
+ const Instr instr = emit_add_instr(emit, MemSetImm);
+ instr->m_val = SZ_INT;
+ }
const m_bool ret = scanx_fdef(emit->env, emit, fdef, (_exp_func)emit_fdef);
emit_pop_scope(emit);
emit->env->func = former;
return ret;
}
-ANN static inline int no_ctor(const Emitter emit, const Class_Def cdef) {
- if(isa(cdef->base.type, emit->gwion->type[et_object]) > 0)
- return 0;
- Ast ast = cdef->body;
- do {
- if(ast->section->section_type == ae_section_stmt) {
- Stmt_List list = ast->section->d.stmt_list;
- do {
- if(list->stmt->stmt_type != ae_stmt_exp ||
- !list->stmt->d.stmt_exp.val || list->stmt->d.stmt_exp.val->exp_type != ae_exp_decl)
- return 0;
- } while((list = list->next));
- }
- } while((ast = ast->next));
- return 1;
-}
-
-ANN static m_bool emit_struct_body2(const Emitter emit, Section *const section) {
- return section->section_type != ae_section_stmt ?
- emit_section(emit, section) : GW_OK;
-}
-
ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
if(tmpl_base(cdef->base.tmpl))
return GW_OK;
SET_FLAG(t, emit);
nspc_allocdata(emit->gwion->mp, t->nspc);
if(cdef->body) {
- if(!no_ctor(emit, cdef)) {
- emit_class_code(emit, t->name);
- CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
- emit_class_finish(emit, t->nspc);
- } else
- CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_struct_body2, emit))
+ emit_class_code(emit, t->name);
+ CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
+ emit_class_finish(emit, t->nspc);
}
return GW_OK;
}
nspc_add_value_front(env->global_nspc, sym, value);
return value;
}
+
+ANN m_bool isres(const Env env, const Symbol xid, const loc_t pos) {
+ if(vector_find(&env->gwion->data->reserved, (vtype)xid) > -1)
+ ERR_B(pos, _("%s is reserved."), s_name(xid));
+ return GW_OK;
+}
ANN static m_bool mk_gack(MemPool p, const Type type, const f_gack d) {
const VM_Code code = new_vm_code(p, NULL, SZ_INT, ae_flag_member | ae_flag_builtin, "@gack");
code->native_func = (m_uint)d;
+ SET_FLAG(code, builtin);
type->e->gack = code;
return GW_OK;
}
static OP_CHECK(opck_array_slice) {
const Exp e = (Exp)data;
exp_setmeta(exp_self(e), 1);
+ exp_setnonnull(e->d.exp_slice.base, 1);
return e->d.exp_slice.base->info->type;
}
INTERP_PRINTF("%.4f", *(m_float*)VALUE);
}
+static GACK(gack_compound) {
+ INTERP_PRINTF("%p", *(void**)VALUE);
+}
#define mk_class_instr(op, arg0, arg1, ...) \
static INSTR(instr_class_##op) { \
POP_REG(shred, SZ_INT); \
struct SpecialId_ spid = { .type=t_now, .exec=RegPushNow, .is_const=1 };
gwi_specialid(gwi, "now", &spid);
+ const Type t_compound = gwi_mk_type(gwi, "@Compound", 0, NULL);
+ GWI_BB(gwi_gack(gwi, t_compound, gack_compound))
+ GWI_BB(gwi_set_global_type(gwi, t_compound, et_compound))
GWI_BB(import_object(gwi))
GWI_BB(import_prim(gwi))
const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
!GET_FLAG(v, static) && !GET_FLAG(v, pure)) {
const TupleForm tf = v->type->e->tuple;
for(m_uint i = 0; i < vector_size(&tf->types); ++i) {
+ const m_bit *data = o->data + v->from->offset;
const Type t = (Type)vector_at(&tf->types, i);
if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
- release(*(M_Object*)(o->data + v->from->offset + vector_at(&tf->offset, i)), shred);
+ release(*(M_Object*)(data + vector_at(&tf->offset, i)), shred);
}
}
}
ERR_O(exp_self(prim)->pos, _("keyword 'this' can be used only inside class definition..."))
if(env->func && !GET_FLAG(env->func, member))
ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions..."))
- if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack") &&
- GET_FLAG(env->class_def, struct))
- ERR_O(exp_self(prim)->pos, _("can't use 'this' in struct @gack"))
if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack"))
- return force_type(env, env->class_def->e->parent);
+ return force_type(env, get_gack(env->class_def->e->parent)); // get_gack ?
return env->class_def;
}
return emit_add_instr(emit, RegPushMem);
}
-static GACK(gack_object) {
- INTERP_PRINTF("%p", *(M_Object*)VALUE);
-}
-
GWION_IMPORT(object) {
- const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
- gwi_add_type(gwi, t_object);
- GWI_BB(gwi_gack(gwi, t_object, gack_object))
- SET_FLAG(t_object, valid); // should be set by gwi_add_type
- gwi->gwion->type[et_object] = t_object;
-// struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 };
+ const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, "@Compound");
+ gwi_set_global_type(gwi, t_object, et_object);
struct SpecialId_ spid = { .ck=opck_this, .em=opem_this, .is_const=1 };
gwi_specialid(gwi, "this", &spid);
return GW_OK;
static OP_CHECK(opck_struct_scan) {
struct TemplateScan *ts = (struct TemplateScan*)data;
- return (isa(ts->t , env->gwion->type[et_object]) > 0 || GET_FLAG(ts->t, struct)) ?
- opck_object_scan(env, ts) : env->gwion->type[et_null];
+ return opck_object_scan(env, ts);
}
static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
ERR_O(exp_self(member)->pos,
_("cannot access member '%s.%s' without object instance..."),
the_base->name, str)
- if(GET_FLAG(value, const) || GET_FLAG(value, enum))
+ if(GET_FLAG(value, const))
exp_setmeta(exp_self(member), 1);
return value->type;
}
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, (m_str)OP_ANY_TYPE, NULL, NULL))
+ GWI_BB(gwi_oper_ini(gwi, "@Compound", NULL, NULL))
GWI_BB(gwi_oper_add(gwi, opck_struct_scan))
GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
gwi_item_ini(gwi, "@null", "null");
return prim_id_non_res(env, data);
}
-ANN static Type check_prim_hack(const Env env, const Exp *data) {
- if(env->func)
- UNSET_FLAG(env->func, pure);
- CHECK_OO((check_exp(env, *data)))
- return env->gwion->type[et_gack];
-}
-
ANN static Type check_prim_typeof(const Env env, const Exp *exp) {
const Exp e = *exp;
DECL_OO(const Type, t, = check_exp(env, e))
ANN static Type check_prim_interp(const Env env, const Exp* exp) {
CHECK_OO(check_exp(env, *exp))
+ Exp e = *exp;
+ do if(GET_FLAG(e->info->type, struct))
+ exp_setvar(e, 1);
+ while((e = e->next));
return env->gwion->type[et_string];
}
-
+ANN static Type check_prim_hack(const Env env, const Exp *data) {
+ if(env->func)
+ UNSET_FLAG(env->func, pure);
+ CHECK_OO(check_prim_interp(env, data))
+ return env->gwion->type[et_gack];
+}
#define describe_prim_xxx(name, type) \
ANN static Type check##_prim_##name(const Env env NUSED, const union prim_data* data NUSED) {\
struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->info->type,
.rhs=bin->rhs->info->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos, .op_type=op_binary };
const Type ret = op_check(env, &opi);
- if(!ret && is_auto)
+ if(!ret && is_auto && exp_self(bin)->exp_type == ae_exp_binary)
bin->rhs->d.exp_decl.list->self->value->type = env->gwion->type[et_auto];
return ret;
}
if(exp->tmpl) {
CHECK_OO(check_exp(env, exp->func))
const Type t = actual_type(env->gwion, unflag_type(exp->func->info->type));
- const Value v = type_value(env->gwion, t);
+ const Value v = type_value(env->gwion, t) ?: t->e->d.func->value_ref;
if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->info->type, func) )
ERR_O(exp_self(exp)->pos, _("template call of non-function value."))
if(!v->d.func_ref || !v->d.func_ref->def->base->tmpl)
ANN static Type get_parent(const Env env, const Class_Def cdef) {
if(GET_FLAG(cdef, struct))
- return NULL;
+ return env->gwion->type[et_compound];
if(!cdef->base.ext)
return env->gwion->type[et_object];
if(tmpl_base(cdef->base.tmpl))
if(parent == (Type)GW_ERROR)
return NULL;
const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), parent);
- if(GET_FLAG(cdef, struct)) {
+ if(GET_FLAG(cdef, struct))
SET_FLAG(t, struct);
- t->e->gack = env->gwion->type[et_object]->e->gack;
- }
t->e->tuple = new_tupleform(env->gwion->mp, parent);
t->e->owner = env->curr;
t->e->owner_class = env->class_def;
}
ANN static m_bool type_recursive(const Env env, const Type_Decl *td, const Type t) {
- if(env->class_def && !env->scope->depth) {
- const m_int idx = vector_find(&env->scope->class_stack, (vtype)t);
- if(!GET_FLAG(td, ref) && (idx > -1 || t == env->class_def))
- ERR_B(td_pos(td), _("%s declared inside %s\n. (make it a ref ?)"),
- t->name, t == env->class_def ? "itself" : env->class_def->name);
+ if(!GET_FLAG(td, ref) && env->class_def && !env->scope->depth &&
+ t == env->class_def) {
+ ERR_B(td_pos(td), _("%s declared inside %s\n. (make it a ref ?)"),
+ t->name, t == env->class_def ? "itself" : env->class_def->name);
}
return GW_OK;
}
ANN static Type void_type(const Env env, Type_Decl* td) {
DECL_OO(const Type, type, = scan1_type(env, td))
- if(isa(type, env->gwion->type[et_object]) > 0 || GET_FLAG(type, struct))
+ if(isa(type, env->gwion->type[et_compound]) > 0)
CHECK_BO(type_recursive(env, td, type))
if(type->size)
return type;
const m_bool base = tmpl_base(f->base->tmpl);
const m_bool tmpl = GET_FLAG(overload, template);
if(isa(overload->type, env->gwion->type[et_function]) < 0 || is_fptr(env->gwion, overload->type)) {
- if(isa(actual_type(env->gwion, overload->type), env->gwion->type[et_function]) < 0)
- ERR_B(f->pos, _("function name '%s' is already used by another value"), overload->name)
-}
+ if(isa(actual_type(env->gwion, overload->type), env->gwion->type[et_function]) < 0)
+ ERR_B(f->pos, _("function name '%s' is already used by another value"), overload->name)
+ }
if((!tmpl && base) || (tmpl && !base && !GET_FLAG(f, template)))
ERR_B(f->pos, _("must overload template function with template"))
return GW_OK;
}
ANN m_bool scan2_fdef(const Env env, const Func_Def f) {
- const Value overload = nspc_lookup_value0(env->curr, f->base->xid);
+ const Value overload = nspc_lookup_value2(env->curr, f->base->xid);
if(overload)
CHECK_BB(scan2_func_def_overload(env, f, overload))
return (!tmpl_base(f->base->tmpl) ? scan2_fdef_std : scan2_fdef_tmpl)(env, f, overload);
+++ /dev/null
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-#include "vm.h"
-#include "traverse.h"
-#include "parse.h"
-
-ANN m_bool isres(const Env env, const Symbol xid, const loc_t pos) {
- if(vector_find(&env->gwion->data->reserved, (vtype)xid) > -1)
- ERR_B(pos, _("%s is reserved."), s_name(xid));
- return GW_OK;
-}
-
-ANN m_uint id_list_len(ID_List l) {
- m_uint len = 0;
- do len += strlen(s_name(l->xid));
- while((l = l->next) && ++len);
- return len + 1;
-}
-
-ANN void type_path(const m_str str, ID_List l) {
- m_str s = str;
- do {
- const m_str name = s_name(l->xid);
- strcpy(s, name);
- s += strlen(name);
- if(l->next)
- strcpy(s++, ".");
- } while((l = l->next));
-}
return ret;
}
-__attribute__((returns_nonnull))
-ANN static inline VM_Code get_gack(Type t) {
- do if(t->e->gack)
- return t->e->gack;
- while((t = t->e->parent));
- return t->e->gack; // unreachable
-}
-
ANN static void prepare_call(const VM_Shred shred, const m_uint offset) {
shred->mem += offset;
*(m_uint*)(shred->mem + SZ_INT) = offset + SZ_INT;
*(m_uint*)(shred->mem + SZ_INT*3) = shred->pc;
*(m_uint*)(shred->mem + SZ_INT*4) = SZ_INT;
shred->mem += SZ_INT*5;
- *(M_Object*)(shred->mem)= *(M_Object*)(shred->reg - SZ_INT);
+ *(M_Object*)(shred->mem) = *(M_Object*)(shred->reg - SZ_INT);
shred->pc = 0;
}
ANN void gack(const VM_Shred shred, const m_uint offset) {
const Type t = *(Type*)shred->reg;
- const VM_Code code = get_gack(t);
+ const VM_Code code = get_gack(t)->e->gack;
if(GET_FLAG(code, builtin)) {
- ((f_gack)code->native_func)(t, (shred->reg - t->size), shred);
- POP_REG(shred, t->size);
+ const m_uint sz = *(m_uint*)(shred->reg + SZ_INT);
+ ((f_gack)code->native_func)(t, (shred->reg - sz), shred);
+ POP_REG(shred, sz);
} else {
prepare_call(shred, offset);
shred->code = code;
- POP_REG(shred, SZ_INT*2);
}
return;
}