-Subproject commit 318792cdc12f6b9632f89052c2d6cc258031b99c
+Subproject commit c16ad0087304f84595aa4f901f2d71465e391192
-class C
-{
+class C {
typedef void Test();
fun void test1(){};
- Test test0;
+ Test test0;
<<< test1 @=> test0 >>>;
}
fun void test<~A~>(...) {
- vararg.start;
- <<< vararg $ int >>>;
- vararg.end;
+ varloop vararg {
+ <<< vararg $ int >>>;
+ }
}
test<~int~>(1, 2);
test<~float~>(1, 2, 3);
ANN void emit_union_offset(Decl_List, const m_uint);
ANN2(1,2) m_bool emit_instantiate_object(const Emitter, const Type, const Array_Sub, const m_bool);
ANN m_uint emit_code_offset(const Emitter emit);
-ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj);
+//ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj);
ANN Instr emit_exp_spork(const Emitter, const Exp_Unary*);
-ANN m_bool emit_exp(const Emitter, const Exp, const m_bool add_ref);
+ANN m_bool emit_exp(const Emitter, const Exp);
ANN static inline void emit_except(const Emitter emit, const Type t) {
emit_add_instr(emit, !GET_FLAG(t, nonnull) ? GWOP_EXCEPT : SetObj);
}
#ifndef __IMPORT_CLASS
#define __IMPORT_CLASS
ANN2(1,2) Type gwi_class_ini(const Gwi gwi, const m_str, const m_str parent);
-ANN2(1,2) Type gwi_class_spe(const Gwi gwi, const m_str, const m_uint size);
+ANN2(1,2) Type gwi_struct_ini(const Gwi gwi, const m_str, const m_uint size);
ANN2(1) void gwi_class_xtor(const Gwi gwi, const f_xtor ctor, const f_xtor dtor);
ANN m_int gwi_class_end(const Gwi gwi);
ANN void inherit(const Type);
Instr (*em)(Emitter, void*); // oper
m_str lhs;// oper
m_str rhs;// oper
- m_uint emit_var;
} OperCK;
struct array_checker {
ANN2(1) m_int gwi_oper_end(const Gwi gwi, const m_str op, const f_instr f);
ANN m_int gwi_oper_cond(const Gwi, const m_str, const f_instr, const f_instr);
-//! use this with one if the right side operator's to emit_var is set
-ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset);
-
#define _EQUALITY_OPER(sz, sign) \
POP_REG(shred, sz*2 - SZ_INT); \
*(m_uint*)REG(-SZ_INT) = sign \
eRegPushMem2,
eRegPushMem3,
eRegPushMem4,
+ eRegPushMemDeref,
eRegPushNow,
eRegPushBase,
eRegPushBase2,
eRegPushBase4,
eReg2Reg,
eReg2RegAddr,
+ eReg2RegDeref,
+ eStructMember,
+ eStructMemberAddr,
eMemSetImm,
eRegPushMe,
eRegPushMaybe,
eArrayValid,
eObjectInstantiate,
eRegAddRef,
+ eRegAddRefAddr,
eObjectAssign,
eAssign,
eObjectRelease,
#define RegPushMem2 (f_instr)eRegPushMem2
#define RegPushMem3 (f_instr)eRegPushMem3
#define RegPushMem4 (f_instr)eRegPushMem4
+#define RegPushMemDeref (f_instr)eRegPushMemDeref
#define RegPushNow (f_instr)eRegPushNow
#define RegPushBase (f_instr)eRegPushBase
#define RegPushBase2 (f_instr)eRegPushBase2
#define RegPushBase4 (f_instr)eRegPushBase4
#define Reg2Reg (f_instr)eReg2Reg
#define Reg2RegAddr (f_instr)eReg2RegAddr
+#define Reg2RegDeref (f_instr)eReg2RegDeref
+#define StructMember (f_instr)eStructMember
+#define StructMemberAddr (f_instr)eStructMemberAddr
#define MemSetImm (f_instr)eMemSetImm
#define RegPushMe (f_instr)eRegPushMe
#define RegPushMaybe (f_instr)eRegPushMaybe
#define ArrayValid (f_instr)eArrayValid
#define ObjectInstantiate (f_instr)eObjectInstantiate
#define RegAddRef (f_instr)eRegAddRef
+#define RegAddRefAddr (f_instr)eRegAddRefAddr
#define ObjectAssign (f_instr)eObjectAssign
#define Assign (f_instr)eAssign
#define ObjectRelease (f_instr)eObjectRelease
#define DECL_NN(decl, f, exp) decl f exp; { if(f == env->gwion->type[et_null) return env->gwion->type[et_null]; }
#define CHECK_ON(f) { if(!f) return env->gwion->type[et_null]; }
#define CHECK_BN(f) { if(f < 0) return env->gwion->type[et_null]; }
-#define CHECK_NN(f) { if(f == env->gwion->type[et_null] return env->gwion->type[et_null]; }
+#define CHECK_NN(f) { if(f == env->gwion->type[et_null]) return env->gwion->type[et_null]; }
typedef Type (*opck)(const Env, void*, m_bool*);
typedef struct Instr_* (*opem)(const Emitter, void*);
opem em;
};
+enum op_type {
+ op_implicit,
+ op_exp,
+ op_dot,
+ op_array,
+ op_binary,
+ op_cast,
+ op_postfix,
+ op_unary,
+ op_scan
+};
+
struct Op_Import {
Type lhs, rhs, ret;
const struct Op_Func *func;
uintptr_t data;
loc_t pos;
Symbol op;
- m_uint emit_var;
+ enum op_type op_type;
};
struct Implicit {
ANN static inline Type specialid_type(const Env env,
struct SpecialId_ *spid, const Exp_Primary* prim) {
- exp_self(prim)->type = spid->type;
+ exp_self(prim)->info->type = spid->type;
if(spid->is_const)
- exp_self(prim)->meta = ae_meta_value;
+ exp_getmeta(exp_self(prim));
return spid->ck ? spid->ck(env, prim) : spid->type;
}
RegPushMem2
RegPushMem3
RegPushMem4
+RegPushMemDeref
RegPushNow
RegPushBase
RegPushBase2
RegPushBase4
Reg2Reg
Reg2RegAddr
+Reg2RegDeref
+StructMember
+StructMemberAddr
MemSetImm
RegPushMe
RegPushMaybe
ArrayValid
ObjectInstantiate
RegAddRef
+RegAddRefAddr
ObjectAssign
Assign
ObjectRelease
#define ERR_O(a, b, ...) { env_err(emit->env, (a), (b), ## __VA_ARGS__); return NULL; }
typedef struct Local_ {
- m_uint size;
+ Type type;
m_uint offset;
- m_bool is_obj;
} Local;
static inline void emit_pop(const Emitter emit, const m_uint scope) { env_pop(emit->env, scope); }
mp_free(p, Frame, a);
}
-ANN static Local* new_local(MemPool p, const m_uint size, const m_bool is_obj) {
+ANN static Local* new_local(MemPool p, const Type type) {
Local* local = mp_calloc(p, Local);
- local->size = size;
- local->is_obj = is_obj;
+ local->type = type;
return local;
}
-ANN static m_uint frame_local(MemPool p, Frame* frame, const m_uint size, const m_bool is_obj) {
- Local* local = new_local(p, size, is_obj);
+ANN static m_uint frame_local(MemPool p, Frame* frame, const Type t) {
+ Local* local = new_local(p, t);
local->offset = frame->curr_offset;
- frame->curr_offset += size;
+ frame->curr_offset += t->size;
vector_add(&frame->stack, (vtype)local);
return local->offset;
}
vector_add(&frame->stack, (vtype)NULL);
}
-ANN static m_int frame_pop(Frame* frame) {
+ANN static void struct_pop(const Emitter emit, const Type type, const m_uint offset) {
+ for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) {
+ const Type t = (Type)vector_at(&type->e->tuple->types, i);
+ if(isa(t, emit->gwion->type[et_object]) > 0) {
+ const Instr instr = emit_add_instr(emit, ObjectRelease);
+ instr->m_val = offset + vector_at(&type->e->tuple->offset, i);
+ } else if(GET_FLAG(t, struct))
+ struct_pop(emit, t, offset + vector_at(&type->e->tuple->offset, i));
+ }
+}
+
+ANN static m_int frame_pop(const Emitter emit) {
+ Frame *frame = emit->code->frame;
DECL_OB(const Local*, l, = (Local*)vector_pop(&frame->stack))
- frame->curr_offset -= l->size;
- return l->is_obj ? (m_int)l->offset : frame_pop(frame);
+ frame->curr_offset -= l->type->size;
+ if(GET_FLAG(l->type, struct)) {
+ struct_pop(emit, l->type, l->offset);
+ return frame_pop(emit);
+ }
+ return isa(l->type, emit->gwion->type[et_object]) > 0 ? (m_int)l->offset : frame_pop(emit);
}
-ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref);
+ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp);
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop);
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list);
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member);
ANN static void emit_pop_scope(const Emitter emit) {
m_int offset;
- while((offset = frame_pop(emit->code->frame)) > -1) {
+ while((offset = frame_pop(emit)) > -1) {
Instr instr = emit_add_instr(emit, ObjectRelease);
instr->m_val = (m_uint)offset;
}
return emit->code->frame->curr_offset;
}
-ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj) {
- return frame_local(emit->gwion->mp, emit->code->frame, size, is_obj);
+ANN m_uint emit_local(const Emitter emit, const Type t) {
+ return frame_local(emit->gwion->mp, emit->code->frame, t);
}
ANN static inline void maybe_ctor(const Emitter emit, const Type type) {
ANN2(1) static m_bool extend_indices(const Emitter emit, Exp e, const m_uint depth) {
if(e)
- CHECK_BB(emit_exp(emit, e, 0))
+ CHECK_BB(emit_exp(emit, e))
m_uint count = 0;
while(e) {
++count;
ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
ANN static m_bool emit_symbol_owned(const Emitter emit, const Symbol *data) {
const Exp dot = symbol_owned_exp(emit->gwion, data);
- dot->nspc = prim_exp(data)->nspc;
+ dot->info->nspc = prim_exp(data)->info->nspc;
const m_bool ret = emit_exp_dot(emit, &dot->d.exp_dot);
free_exp(emit->gwion->mp, dot);
return ret;
const Value v = prim_self(data)->value;
if(GET_FLAG(v, union)) {
const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, prim_exp(data)->emit_var, dotstatic);
+ const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), dotstatic);
instr->m_val = (m_uint)v->d.ptr;
} else {
const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, prim_exp(data)->emit_var, regpushimm);
- if(!exp_self(data)->emit_var && size == SZ_INT) {
+ const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), regpushimm);
+ if(!exp_getvar(prim_exp(data)) && size == SZ_INT) {
if(isa(v->type, emit->gwion->type[et_object]) > 0) {
instr->opcode = eRegPushImm;
instr->m_val = (m_uint)v->d.ptr;
if(GET_FLAG(v, builtin) || GET_FLAG(v, union) || GET_FLAG(v, enum))
return emit_symbol_builtin(emit, data);
const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, prim_exp(data)->emit_var, !GET_FLAG(v, global) ? regpushmem : regpushbase);
+ const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), !GET_FLAG(v, global) ? regpushmem : regpushbase);
instr->m_val = v->from->offset;
if(isa(v->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, v->type))
- instr->m_val = prim_exp(data)->type->e->d.func->value_ref->from->offset;
+ instr->m_val = prim_exp(data)->info->type->e->d.func->value_ref->from->offset;
return GW_OK;
}
+
ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) {
return _emit_symbol(emit, &prim->d.var);
}
ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) {
Exp e = (*data)->exp;
- CHECK_BB(emit_exp(emit, e, 0))
+ CHECK_BB(emit_exp(emit, e))
m_uint count = 0;
do ++count;
while((e = e->next));
return GW_OK;
}
-ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e, const m_bool addref);
+ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e);
ANN static m_bool emit_range(const Emitter emit, Range *range) {
if(range->start)
- CHECK_OB(emit_exp_pop_next(emit, range->start, 0))
+ CHECK_OB(emit_exp_pop_next(emit, range->start))
else
regpushi(emit, 0);
if(range->end)
- CHECK_OB(emit_exp_pop_next(emit, range->end, 0))
+ CHECK_OB(emit_exp_pop_next(emit, range->end))
else
regpushi(emit, -1);
return GW_OK;
CHECK_BB(emit_range(emit, range))
const Exp e = range->start ?: range->end;
const Symbol sym = insert_symbol("@range");
- struct Op_Import opi = { .op=sym, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)prim_exp(data) };
+ struct Op_Import opi = { .op=sym, .rhs=e->info->type,
+ .pos=e->pos, .data=(uintptr_t)prim_exp(data), .op_type=op_exp };
CHECK_OB(op_emit(emit, &opi))
emit_add_instr(emit, GcAdd);
return GW_OK;
info->array.type = info->array.type->e->parent;
return emit_array_access(emit, info);
}
- struct Op_Import opi = { .op=insert_symbol("@array"), .lhs=info->array.exp->type, .rhs=info->array.type, .data=(uintptr_t)info };
+ // look mum no pos
+ struct Op_Import opi = { .op=insert_symbol("@array"), .lhs=info->array.exp->info->type, .rhs=info->array.type,
+ .data=(uintptr_t)info, .op_type=op_array };
return op_emit(emit, &opi) != (Instr)GW_ERROR ? GW_OK : GW_ERROR;
}
ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) {
- CHECK_BB(emit_exp(emit, array->base, 0))
+ CHECK_BB(emit_exp(emit, array->base))
const Exp e = exp_self(array);
- struct ArrayAccessInfo info = { *array->array, e->type, e->emit_var };
+ struct ArrayAccessInfo info = { *array->array, e->info->type, exp_getvar(e) };
return emit_array_access(emit, &info);
}
ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice* range) {
- CHECK_BB(emit_exp(emit, range->base, 0))
+ CHECK_BB(emit_exp(emit, range->base))
CHECK_BB(emit_range(emit, range->range))
const Symbol sym = insert_symbol("@slice");
const Exp e = range->range->start ?: range->range->end;
- struct Op_Import opi = { .op=sym, .lhs=range->base->type, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)exp_self(range) };
+ struct Op_Import opi = { .op=sym, .lhs=range->base->info->type, .rhs=e->info->type,
+ .pos=e->pos, .data=(uintptr_t)exp_self(range), .op_type=op_exp };
CHECK_OB(op_emit(emit, &opi))
return GW_OK;
}
-ANN static void emit_vec_addr(const Emitter emit, const m_uint sz) {
- regpop(emit, sz - SZ_INT);
- const Instr cpy = emit_add_instr(emit, Reg2RegAddr);
- cpy->m_val = -SZ_INT;
-}
-
ANN static m_bool emit_prim_id(const Emitter emit, const Symbol *data) {
struct SpecialId_ * spid = specialid_get(emit->gwion, *data);
if(spid)
return GW_OK;
}
+ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) {
+ const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr;
+ const Instr instr = emit_add_instr(emit, exec);
+ instr->m_val = -SZ_INT;
+ return instr;
+}
+
ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) {
char c[strlen(*str) + 1];
if(strlen(*str)) {
if(!v->d.ptr)
v->d.ptr = (m_uint*)new_string2(emit->gwion, NULL, s_name(sym));
regpushi(emit, (m_uint)v->d.ptr);
- emit_add_instr(emit, RegAddRef);
+ emit_addref(emit, 0);
return GW_OK;
}
#define emit_prim_nil (void*)dummy_func
+ANN static inline void struct_interp(const Emitter emit, const Exp e) {
+ if(GET_FLAG(e->info->type, struct)) {
+ exp_setvar(e, 1);
+ regpush(emit, e->info->type->size - 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;
- if(emit_exp(emit, e, 0) < 0) {
+ struct_interp(emit, e);
+ if(emit_exp(emit, e) < 0) {
e->next = next;
return GW_ERROR;
}
- regseti(emit, (m_uint)e->type);
- if(isa(e->type, emit->gwion->type[et_object]) > 0 && !GET_FLAG(e->type, force))
+ regseti(emit, (m_uint)e->info->type);
+ if(isa(e->info->type, emit->gwion->type[et_object]) > 0 && !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);
CHECK_BB(emit_instantiate_object(emit, v->type, var_decl->array, is_ref))
CHECK_BB(emit_dot_static_data(emit, v, 1))
emit_add_instr(emit, Assign);
- emit_add_instr(emit, RegAddRef);
+ (void)emit_addref(emit, 0);
regpop(emit, SZ_INT);
emit->code = code;
return GW_OK;
}
+ANN static inline int struct_ctor(const Value v) {
+ return GET_FLAG(v->type, struct) && v->type->nspc->pre_ctor;
+}
+
+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;
+ regpush(emit, v->type->size - SZ_INT);
+}
+
ANN static m_bool emit_exp_decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref, const uint emit_addr) {
- const Value value = var_decl->value;
- if(isa(value->type, emit->gwion->type[et_object]) > 0 && !is_ref)
+ const Value v = var_decl->value;
+ if(isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
CHECK_BB(decl_static(emit, var_decl, 0))
- return emit_dot_static_data(emit, value, emit_addr);
+ 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);
+ 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);
+ const Instr instr = emit_add_instr(emit, !emit_addr ? StructMember : StructMemberAddr);
+ instr->m_val2 = v->from->offset;
+ if(!emit_addr)
+ regpush(emit, v->type->size - SZ_INT);
+ return instr; // m_val set after but ignored
}
ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl,
CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
f_instr *exec = (f_instr*)allocmember;
if(!GET_FLAG(v, member)) {
- v->from->offset = emit_local(emit, v->type->size, is_obj);
+ v->from->offset = emit_local(emit, type);
exec = (f_instr*)(allocword);
- if(GET_FLAG(var_decl->value, ref)) {
+ if(GET_FLAG(var_decl->value, ref)) { // ref or emit_var ?
const Instr clean = emit_add_instr(emit, MemSetImm);
clean->m_val = v->from->offset;
}
}
- const Instr instr = emit_kind(emit, v->type->size, emit_addr, exec);
- if(emit_addr || !GET_FLAG(v, member))
+ 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)))
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);
return GW_OK;
}
-ANN static m_bool emit_exp_decl_global(const Emitter emit, const Var_Decl var_decl,
+ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl,
const uint is_ref, const uint emit_var) {
const Value v = var_decl->value;
const Type type = v->type;
emit_var : 1;
if(is_obj && (is_array || !is_ref))
CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
- const Instr instr = emit_kind(emit, v->type->size, emit_addr, dotstatic);
+// const Instr instr = emit_kind(emit, v->type->size, emit_addr, dotstatic);
+ const Instr instr = emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, dotstatic);
v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size);
SET_FLAG(v, union);
instr->m_val = (m_uint)v->d.ptr;
instr->m_val2 = v->type->size;
if(is_obj && (is_array || !is_ref)) {
const Instr assign = emit_add_instr(emit, Assign);
+ const size_t missing_depth = type->array_depth - (array ? array->depth : 0);
+ if(missing_depth && !GET_FLAG(decl->td, force)) {
+ const Instr push = emit_add_instr(emit, Reg2Reg);
+ push->m_val = -(missing_depth) * SZ_INT;
+ }
assign->m_val = emit_var;
- const Instr instr = emit_add_instr(emit, RegAddRef);
- instr->m_val = emit_var;
- }
+ (void)emit_addref(emit, emit_var);
+ } else if(!emit_var && struct_ctor(v))
+ emit_struct_decl_finish(emit, v);
return GW_OK;
}
ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
const m_bool global = GET_FLAG(decl->td, global);
- const uint var = exp_self(decl)->emit_var;
+ const uint var = exp_getvar(exp_self(decl));
const uint ref = GET_FLAG(decl->td, ref) || type_ref(decl->type);
Var_Decl_List list = decl->list;
do {
else if(!global)
CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, r, var))
else
- CHECK_BB(emit_exp_decl_global(emit, list->self, r, var))
+ CHECK_BB(emit_exp_decl_global(emit, decl, list->self, r, var))
if(GET_FLAG(list->self->value->type, nonnull))
emit_add_instr(emit, GWOP_EXCEPT);
} while((list = list->next));
m_uint size = 0;
while(e) {
if(!l) {
- size += e->type->size;
- vector_add(kinds, (vtype)e->type); // ->size
+ size += e->info->type->size;
+ vector_add(kinds, (vtype)e->info->type); // ->size
} else
l = l->next;
e = e->next;
}
}
+ANN static inline m_uint exp_size(Exp e);
+ANN static inline m_uint exp_totalsize(Exp e) {
+ m_uint size = 0;
+ do size += exp_size(e);
+ while((e = e->next));
+ return size;
+}
+ANN static /*inline */void emit_exp_addref(const Emitter emit, Exp, const m_int size);
+
ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) {
- if(exp_call->args)
- CHECK_BB(emit_exp(emit, exp_call->args, 1))
+ if(exp_call->args) {
+ CHECK_BB(emit_exp(emit, exp_call->args))
+ emit_exp_addref(emit, exp_call->args, -exp_totalsize(exp_call->args));
+ }
if(GET_FLAG(exp_call->m_func->def, variadic))
emit_func_arg_vararg(emit, exp_call);
return GW_OK;
ANN static m_bool prepare_call(const Emitter emit, const Exp_Call* exp_call) {
CHECK_BB(emit_func_args(emit, exp_call))
- return emit_exp(emit, exp_call->func, 0);
+ return emit_exp(emit, exp_call->func);
}
ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
- if(exp_call->m_func) {
- CHECK_BB(prepare_call(emit, exp_call))
- return emit_exp_call1(emit, exp_call->m_func) ? GW_OK : GW_ERROR;
+ CHECK_BB(prepare_call(emit, exp_call))
+ if(exp_call->m_func)
+ CHECK_OB(emit_exp_call1(emit, exp_call->m_func))
+ else {
+ struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp_call->func->info->type->e->d.base_type,
+ .data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos, .op_type=op_exp };
+ CHECK_OB(op_emit(emit, &opi))
}
- if(exp_call->args)
- CHECK_BB(emit_exp(emit, exp_call->args, 1))
- struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp_call->func->type->e->d.base_type, .data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos };
- CHECK_OB(op_emit(emit, &opi))
const Exp e = exp_self(exp_call);
- if(e->emit_var)
- emit_vec_addr(emit, e->type->size);
+ if(exp_getvar(e)) {
+ regpop(emit, exp_self(exp_call)->info->type->size - SZ_INT);
+ const Instr instr = emit_add_instr(emit, Reg2RegAddr);
+ instr->m_val = -SZ_INT;
+ instr->m_val2 = -SZ_INT;
+ }
return GW_OK;
}
ANN static m_uint pop_exp_size(Exp e) {
m_uint size = 0;
- do {
+ do { // account for emit_var ?
size += (e->exp_type == ae_exp_decl ?
- get_decl_size(e->d.exp_decl.list) : e->type->size);
+ get_decl_size(e->d.exp_decl.list) : e->info->type->size);
} while((e = e->next));
return size;
}
regpop(emit, size);
}
-ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e, const m_bool addref) {
- CHECK_BB(emit_exp(emit, e, addref))
+ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e) {
+ CHECK_BB(emit_exp(emit, e))
if(e->next)
pop_exp(emit, e->next);
return GW_OK;
ANN static m_bool emit_exp_binary(const Emitter emit, const Exp_Binary* bin) {
const Exp lhs = bin->lhs;
const Exp rhs = bin->rhs;
- struct Op_Import opi = { .op=bin->op, .lhs=lhs->type, .rhs=rhs->type, .pos=exp_self(bin)->pos, .data = (uintptr_t)bin };
- CHECK_BB(emit_exp_pop_next(emit, lhs, 1))
- CHECK_BB(emit_exp_pop_next(emit, rhs, 1))
+ struct Op_Import opi = { .op=bin->op, .lhs=lhs->info->type, .rhs=rhs->info->type,
+ .pos=exp_self(bin)->pos, .data=(uintptr_t)bin, .op_type=op_binary };
+ CHECK_BB(emit_exp_pop_next(emit, lhs))
+ CHECK_BB(emit_exp_pop_next(emit, rhs))
+ const m_int size = exp_totalsize(rhs);
+ emit_exp_addref(emit, lhs, -exp_totalsize(lhs) - size);
+ emit_exp_addref(emit, rhs, -size);
return op_emit_bool(emit, &opi);
}
ANN static m_bool emit_exp_cast(const Emitter emit, const Exp_Cast* cast) {
- struct Op_Import opi = { .op=insert_symbol("$"), .lhs=cast->exp->type, .rhs=exp_self(cast)->type, .data=(uintptr_t)cast};
- CHECK_BB(emit_exp(emit, cast->exp, 0))
+ // no pos ?
+ struct Op_Import opi = { .op=insert_symbol("$"), .lhs=cast->exp->info->type, .rhs=exp_self(cast)->info->type,
+ .data=(uintptr_t)cast, .op_type=op_cast};
+ CHECK_BB(emit_exp(emit, cast->exp))
(void)op_emit(emit, &opi);
return GW_OK;
}
ANN static m_bool emit_exp_post(const Emitter emit, const Exp_Postfix* post) {
- struct Op_Import opi = { .op=post->op, .lhs=post->exp->type, .data=(uintptr_t)post };
- CHECK_BB(emit_exp(emit, post->exp, 1))
+ // no pos ?
+ struct Op_Import opi = { .op=post->op, .lhs=post->exp->info->type,
+ .data=(uintptr_t)post, .op_type=op_postfix };
+ CHECK_BB(emit_exp(emit, post->exp))
+ emit_exp_addref(emit, post->exp, -exp_totalsize(post->exp));
return op_emit_bool(emit, &opi);
}
emit_except(emit, t);
if(f->def->base->tmpl)
tmpl_prelude(emit, f);
-
}
const Instr instr = emit_add_instr(emit, SetCode);
instr->m_val2 = 1;
static m_bool me_cmp(MemoizeEmitter *me, const Arg_List arg) {
const Emitter emit = me->emit;
const Symbol sym = insert_symbol("==");
- struct Exp_ exp = { .nspc=me->fdef->base->func->value_ref->from->owner };
- struct Op_Import opi = { .op=sym, .lhs=arg->type, .rhs=arg->type, .pos=me->fdef->pos, .data=(uintptr_t)&exp.d };
+ struct ExpInfo_ info = { .nspc=me->fdef->base->func->value_ref->from->owner };
+ struct Exp_ exp = { .info=&info };
+ struct Op_Import opi = { .op=sym, .lhs=arg->type, .rhs=arg->type,
+ .pos=me->fdef->pos, .data=(uintptr_t)&exp.d, .op_type=op_binary };
CHECK_BB(op_emit_bool(emit, &opi))
const Instr instr = emit_add_instr(emit, BranchEqInt);
vector_add(&me->branch, (vtype)instr);
spork->m_val2 = -SZ_INT;
}
-static inline void stack_alloc(const Emitter emit) {
- emit_local(emit, SZ_INT, 0);
+static inline void stack_alloc(const Emitter emit) { // maybe vararg could use t_vararg instead
+ emit_local(emit, emit->gwion->type[et_int]); // hiding the fact it is an object
emit->code->stack_depth += SZ_INT;
}
}
struct Sporker {
- const m_bool is_spork;
const Stmt code;
const Exp exp;
VM_Code vm_code;
const m_bool emit_var;
+ const m_bool is_spork;
};
ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
CHECK_BO(scoped_stmt(emit, sp->code, 0))
} else {
CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call))
+// emit_exp_addref(emit, &sp->exp->d.exp_call, -exp_totalsize(&sp->exp->d.exp_call);
push_spork_code(emit, sp->is_spork ? SPORK_FUNC_PREFIX : FORK_CODE_PREFIX, sp->exp->pos);
CHECK_BO(call_spork_func(emit, &sp->exp->d.exp_call))
}
ANN Instr emit_exp_spork(const Emitter emit, const Exp_Unary* unary) {
struct Sporker sporker = {
- .is_spork=(unary->op == insert_symbol("spork")),
.exp=unary->exp,
.code=unary->code,
- .emit_var=exp_self(unary)->emit_var
+ .is_spork=(unary->op == insert_symbol("spork")),
+ .emit_var=exp_getvar(exp_self(unary))
};
CHECK_OO((sporker.vm_code = spork_prepare(emit, &sporker)))
const Instr ini = spork_ini(emit, &sporker);
}
ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) {
- struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary };
+// no pos ?
+ struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary, .op_type=op_unary };
if(unary->op != insert_symbol("spork") && unary->op != insert_symbol("fork") && unary->exp) {
- CHECK_BB(emit_exp_pop_next(emit, unary->exp, 1))
- opi.rhs = unary->exp->type;
+ CHECK_BB(emit_exp_pop_next(emit, unary->exp))
+const Exp next = unary->exp->next;
+ emit_exp_addref(emit, unary->exp, -exp_size(unary->exp));
+unary->exp->next = next;
+ opi.rhs = unary->exp->info->type;
}
return op_emit_bool(emit, &opi);
}
ANN static m_bool emit_implicit_cast(const Emitter emit,
const restrict Exp from, const restrict Type to) {
const struct Implicit imp = { from, to, from->pos };
- struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=from->type, .rhs=to, .data=(m_uint)&imp };
+ // no pos
+ struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=from->info->type, .rhs=to,
+ .data=(m_uint)&imp, .op_type=op_implicit };
return op_emit_bool(emit, &opi);
}
ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) {
- CHECK_BO(emit_exp_pop_next(emit, e, 1))
+ CHECK_BO(emit_exp_pop_next(emit, e))
+const Exp next = e->next;
+ emit_exp_addref(emit, e, -exp_size(e));
+e->next = next;
struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
- .rhs=e->type, .pos=e->pos, .data=(uintptr_t)e};
+ .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
const Instr instr = op_emit(emit, &opi);
assert(instr != (Instr)GW_OK);
return instr;
ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) {
const Instr op = emit_flow(emit, exp_if->cond);
- CHECK_BB(emit_exp(emit, exp_if->if_exp ?: exp_if->cond, 0))
+ CHECK_BB(emit_exp(emit, exp_if->if_exp ?: exp_if->cond))
const Instr op2 = emit_add_instr(emit, Goto);
op->m_val = emit_code_size(emit);
- const m_bool ret = emit_exp(emit, exp_if->else_exp, 0);
+ const m_bool ret = emit_exp(emit, exp_if->else_exp);
op2->m_val = emit_code_size(emit);
return ret;
}
ANN static m_bool emit_lambda(const Emitter emit, const Exp_Lambda * lambda) {
CHECK_BB(emit_func_def(emit, lambda->def))
- if(GET_FLAG(lambda->def, member) && !exp_self(lambda)->emit_var)
+ if(GET_FLAG(lambda->def, member) && !exp_getvar(exp_self(lambda)))
emit_add_instr(emit, RegPushMem);
regpushi(emit, (m_uint)lambda->def->base->func->code);
return GW_OK;
}
ANN static m_bool emit_exp_typeof(const Emitter emit, const Exp_Typeof *exp) {
- if(!exp->exp->type->array_depth)
- regpushi(emit, (m_uint)(actual_type(emit->gwion, exp->exp->type)));
+ if(!exp->exp->info->type->array_depth)
+ regpushi(emit, (m_uint)(actual_type(emit->gwion, exp->exp->info->type)));
else
- regpushi(emit, (m_uint)exp->exp->type);
+ regpushi(emit, (m_uint)exp->exp->info->type);
return GW_OK;
}
DECL_EXP_FUNC(emit, m_bool, Emitter)
-ANN2(1) /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) {
+
+ANN static void struct_addref(const Emitter emit, const Type type,
+ const m_int size, const m_bool offset, const m_bool emit_var) {
+ for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) {
+ const Type t = (Type)vector_at(&type->e->tuple->types, i);
+ if(isa(t, emit->gwion->type[et_object]) > 0) {
+ const Instr instr = emit_addref(emit, emit_var);
+ instr->m_val = size;
+ instr->m_val2 = vector_at(&type->e->tuple->offset, i);
+ } else if(GET_FLAG(t, struct))
+ struct_addref(emit, t, size, offset + vector_at(&type->e->tuple->offset, i), emit_var);
+ }
+}
+
+ANN static inline m_uint exp_size(const Exp e) {
+ if(exp_getvar(e))
+ return SZ_INT;
+ const Type type = e->info->cast_to ?: e->info->type;
+ return type->size;
+}
+
+ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) {
do {
- CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
- if(ref && isa(exp->type, emit->gwion->type[et_object]) > 0) {
- const Instr instr = emit_add_instr(emit, RegAddRef);
- instr->m_val = exp->emit_var;
- }
- if(exp->cast_to)
- CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to))
+ if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 &&
+ (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) {
+ const Instr instr = emit_addref(emit, exp_getvar(exp));
+ instr->m_val = size;
+ } else if(GET_FLAG(exp->info->type, struct)) // check cast_to ?
+ struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp));
+ size += exp_size(exp);
+ } while((exp = exp->next));
+}
+
+ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) {
+ Exp exp = e;
+ do {
+ CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
+ if(exp_getnonnull(exp))
+ emit_except(emit, exp->info->type);
+ if(exp->info->cast_to)
+ CHECK_BB(emit_implicit_cast(emit, exp, exp->info->cast_to))
} while((exp = exp->next));
return GW_OK;
}
ANN static m_bool optimize_taill_call(const Emitter emit, const Exp_Call* e) {
if(e->args) {
- CHECK_BB(emit_exp(emit, e->args, 0))
+ CHECK_BB(emit_exp(emit, e->args))
regpop(emit, e->m_func->def->stack_depth);
emit_args(emit, e->m_func);
}
if(stmt->val) {
if(stmt->val->exp_type == ae_exp_call && emit->env->func == stmt->val->d.exp_call.m_func)
return optimize_taill_call(emit, &stmt->val->d.exp_call);
- CHECK_BB(emit_exp_pop_next(emit, stmt->val, 0))
- if(isa(stmt->val->type, emit->gwion->type[et_object]) > 0)
- emit_add_instr(emit, RegAddRef);
+ CHECK_BB(emit_exp_pop_next(emit, stmt->val))
+ if(isa(stmt->val->info->type, emit->gwion->type[et_object]) > 0)
+ (void)emit_addref(emit, 0);
}
vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto));
return GW_OK;
ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) {
regpushi(emit, status);
- CHECK_BB(emit_exp(emit, stmt->exp, 0))
+ CHECK_BB(emit_exp(emit, stmt->exp))
emit_add_instr(emit, SetObj);
const Instr member = emit_add_instr(emit, DotMember4);
member->m_val = SZ_INT;
ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) {
CHECK_BB(variadic_state(emit, stmt, 1))
- CHECK_BB(emit_exp(emit, stmt->exp, 0))
+ CHECK_BB(emit_exp(emit, stmt->exp))
const Instr instr = emit_add_instr(emit, BranchEqInt);
const m_uint pc = emit_code_size(emit);
emit_stmt(emit, stmt->body, 1);
- CHECK_BB(emit_exp(emit, stmt->exp, 0))
+ CHECK_BB(emit_exp(emit, stmt->exp))
emit_vararg_end(emit, pc);
instr->m_val = emit_code_size(emit);
CHECK_BB(variadic_state(emit, stmt, 0))
CHECK_BB(scoped_stmt(emit, stmt->body, 1))
const m_uint action_index = emit_code_size(emit);
if(stmt->c3) {
- CHECK_BB(emit_exp(emit, stmt->c3, 0))
+ CHECK_BB(emit_exp(emit, stmt->c3))
pop_exp(emit, stmt->c3);
}
const Instr _goto = emit_add_instr(emit, Goto);
ANN static Instr emit_stmt_autoptr_init(const Emitter emit, const Type type) {
const Instr new_obj = emit_add_instr(emit, ObjectInstantiate);
new_obj->m_val2 = (m_uint)type;
- emit_add_instr(emit, RegAddRef);
+ (void)emit_addref(emit, 0);
regpop(emit, SZ_INT);
return emit_add_instr(emit, Reg2Mem);
}
// scope push problem
ANN static m_bool emit_stmt_auto(const Emitter emit, const Stmt_Auto stmt) {
- CHECK_BB(emit_exp(emit, stmt->exp, 0))
+ CHECK_BB(emit_exp(emit, stmt->exp))
const Instr s1 = emit_add_instr(emit, MemSetImm);
emit_push_stack(emit);
Instr cpy = stmt->is_ptr ? emit_stmt_autoptr_init(emit, stmt->v->type) : NULL;
const m_uint ini_pc = emit_code_size(emit);
- emit_except(emit, stmt->exp->type);
+ emit_except(emit, stmt->exp->info->type);
const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop);
const Instr end = emit_add_instr(emit, BranchEqInt);
- const m_uint offset = emit_local(emit, SZ_INT + stmt->v->type->size, 0);
+// (void)emit_addref(emit, 0);
+ emit_local(emit, stmt->exp->info->type);
+ const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
stmt->v->from->offset = offset + SZ_INT;
CHECK_BB(emit_stmt(emit, stmt->body, 1))
const m_uint end_pc = emit_code_size(emit);
// scope push problem
ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
emit_push_stack(emit);
- CHECK_BB(emit_exp_pop_next(emit, stmt->cond, 0))
+ CHECK_BB(emit_exp_pop_next(emit, stmt->cond))
const m_uint index = emit_code_size(emit);
const Instr cpy = emit_add_instr(emit, Reg2RegAddr);
cpy->m_val2 = -SZ_INT;
const Value v = (Value)vector_at(&edef->values, i);
if(!emit->env->class_def) {
ALLOC_PTR(emit->gwion->mp, addr, m_uint, i);
- v->from->offset = emit_local(emit, SZ_INT, 0);
+ v->from->offset = emit_local(emit, emit->gwion->type[et_int]);
v->d.ptr = addr;
} else
*(m_bit*)(emit->env->class_def->nspc->info->class_data + v->from->offset) = i;
}
ANN static m_bool emit_stmt_exp(const Emitter emit, const struct Stmt_Exp_* exp) {
- return exp->val ? emit_exp(emit, exp->val, 0) : 1;
+ return exp->val ? emit_exp(emit, exp->val) : 1;
}
ANN static m_bool emit_case_head(const Emitter emit, const Exp base,
const Exp e, const Symbol op, const Vector v) {
- CHECK_BB(emit_exp(emit, base, 1))
+ CHECK_BB(emit_exp(emit, base))
const Exp next = e->next;
- e->next = NULL;
- const m_bool ret = emit_exp(emit, e, 1);
- e->next = next;
+// e->next = NULL;
+ const m_bool ret = emit_exp_pop_next(emit, e);
+ const m_int size = -exp_size(e);
+ emit_exp_addref(emit, base, -exp_totalsize(base) - size);
+ emit_exp_addref(emit, e, -size);
+// e->next = next;
CHECK_BB(ret)
const Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
- struct Exp_ ebin = { .d={.exp_binary=bin}, .nspc=e->nspc};
- struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type, .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos };
+ struct ExpInfo_ info = { .nspc=e->info->nspc };
+ struct Exp_ ebin = { .d={.exp_binary=bin}, .info=&info };
+ struct Op_Import opi = { .op=op, .lhs=base->info->type, .rhs=e->info->type,
+ .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
CHECK_BB(op_emit_bool(emit, &opi))
const Instr instr = emit_add_instr(emit, BranchEqInt);
vector_add(v, (vtype)instr);
ANN static m_bool case_value(const Emitter emit, const Exp base, const Exp e) {
const Value v = e->d.prim.value;
- v->from->offset = emit_local(emit, base->type->size, isa(base->type, emit->gwion->type[et_object]) > 0);
- CHECK_BB(emit_exp(emit, base, 1))
- regpop(emit, base->type->size);
+ v->from->offset = emit_local(emit, base->info->type);
+ CHECK_BB(emit_exp(emit, base))
+ emit_exp_addref(emit, base, -exp_totalsize(base));
+ regpop(emit, base->info->type->size);
const Instr instr = emit_add_instr(emit, Reg2Mem4);
instr->m_val = v->from->offset;
- instr->m_val2 = base->type->size;
+ instr->m_val2 = base->info->type->size;
return GW_OK;
}
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
CHECK_BB(ensure_emit(emit, member->t_base))
struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
- .rhs=exp_self(member)->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
+ .rhs=exp_self(member)->info->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos, .op_type=op_dot };
return op_emit_bool(emit, &opi);
}
ANN static void emit_func_def_args(const Emitter emit, Arg_List a) {
do {
- const Value value = a->var_decl->value;
- const m_uint size = value->type->size;
- const m_bool obj = isa(value->type, emit->gwion->type[et_object]) > 0;
- emit->code->stack_depth += size;
- value->from->offset = emit_local(emit, size, obj);
+ const Type type = a->var_decl->value->type;
+ emit->code->stack_depth += type->size;
+ a->var_decl->value->from->offset = emit_local(emit, type);
} while((a = a->next));
}
if(SAFE_FLAG(emit->env->class_def, builtin) && GET_FLAG(emit->env->class_def, template))
return GW_OK;
if(!emit->env->class_def && !GET_FLAG(fdef, global) && !fdef->base->tmpl && !emit->env->scope->depth)
- func->value_ref->from->offset = emit_local(emit, SZ_INT, 0);
+ func->value_ref->from->offset = emit_local(emit, emit->gwion->type[et_int]);
emit_func_def_init(emit, func);
if(GET_FLAG(func, member))
stack_alloc_this(emit);
+
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);
const m_bool ret = scanx_fdef(emit->env, emit, fdef, (_exp_func)emit_fdef);
emit_pop_scope(emit);
emit->env->func = former;
+
if(ret > 0)
emit_fdef_finish(emit, fdef);
return ret;
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;
-if(GET_FLAG(cdef->base.type, emit))return GW_OK;
+ if(GET_FLAG(cdef->base.type, emit))
+ return GW_OK;
const Type type = cdef->base.type;
const Nspc nspc = type->nspc;
- if(cdef->base.ext && cdef->base.type->e->parent->e->def && !GET_FLAG(cdef->base.type->e->parent, emit))
+ if(cdef->base.ext && type->e->parent->e->def && !GET_FLAG(type->e->parent, emit))
CHECK_BB(cdef_parent(emit, cdef))
SET_FLAG(type, emit);
nspc_allocdata(emit->gwion->mp, nspc);
- emit_class_code(emit, type->name);
- if(cdef->body)
- CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
- emit_class_finish(emit, nspc);
+ if(cdef->body) {
+ if(!no_ctor(emit, cdef)) {
+ emit_class_code(emit, type->name);
+ CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit))
+ emit_class_finish(emit, nspc);
+ } else
+ CHECK_BB(scanx_body(emit->env, cdef, (_exp_func)emit_struct_body2, emit))
+ }
SET_FLAG(type, emit);
return GW_OK;
}
#include "object.h"
#include "gwion.h"
#include "operator.h"
+#include "tuple.h"
ANN void nspc_commit(const Nspc nspc) {
scope_commit(nspc->info->value);
}
}
+ANN2(1,3) static inline void nspc_release_struct(const Nspc a, Value value, Gwion gwion) {
+ if(!SAFE_FLAG(value, pure) && ((SAFE_FLAG(value, static) && a->info->class_data) ||
+ (SAFE_FLAG(value, builtin) && value->d.ptr))) {
+ const m_bit *ptr = (value && value->d.ptr) ? (m_bit*)value->d.ptr:
+ (m_bit*)(a->info->class_data + value->from->offset);
+ for(m_uint i = 0; i < vector_size(&value->type->e->tuple->types); ++i) {
+ const Type t = (Type)vector_at(&value->type->e->tuple->types, i);
+ if(isa(t, gwion->type[et_object]) > 0)
+ release(*(M_Object*)(ptr + vector_at(&value->type->e->tuple->offset, i)), gwion->vm->cleaner_shred);
+ else if(GET_FLAG(t, struct))
+ nspc_release_struct(t->nspc, NULL, gwion);
+ }
+ }
+}
+
ANN static void free_nspc_value(const Nspc a, Gwion gwion) {
struct scope_iter iter = { a->info->value, 0, 0 };
Value v;
while(scope_iter(&iter, &v) > 0) {
if(isa(v->type, gwion->type[et_object]) > 0)
nspc_release_object(a, v, gwion);
+ else if(GET_FLAG(v->type, struct))
+ nspc_release_struct(a, v, gwion);
REM_REF(v, gwion);
}
free_scope(gwion->mp, a->info->value);
type->name = name;
type->e = mp_calloc(p, TypeInfo);
type->e->parent = parent;
- if(parent) {
+ if(parent)
type->size = parent->size;
- type->e->tuple = new_tupleform(p);
- }
type->ref = new_refcount(p, free_type);
return type;
}
ANN void env_err(const Env env, const loc_t pos, const m_str fmt, ...) {
if(env->context && env->context->error)
return;
+#ifndef __AFL_HAVE_MANUAL_CONTROL
env_header(env);
loc_header(pos, env->name);
va_list arg;
va_end(arg);
fprintf(stderr, "\n");
loc_err(pos, env->name);
+#endif
if(env->context)
env->context->error = 1;
}
#include "mpool.h"
#include "specialid.h"
#include "template.h"
+#include "tuple.h"
ANN static m_bool mk_xtor(MemPool p, const Type type, const m_uint d, const ae_flag e) {
VM_Code* code = e == ae_flag_ctor ? &type->nspc->pre_ctor : &type->nspc->dtor;
ANN2(1,2) static void import_class_ini(const Env env, const Type t) {
t->nspc = new_nspc(env->gwion->mp, t->name);
t->nspc->parent = env->curr;
+ if(isa(t, env->gwion->type[et_object]) > 0)
inherit(t);
t->e->owner = env->curr;
SET_FLAG(t, checked);
t->e->def = new_class_def(gwi->gwion->mp, 0, ck.sym, td, NULL, loc(gwi));
t->e->def->base.tmpl = tmpl;
t->e->def->base.type = t;
+ t->e->tuple = new_tupleform(gwi->gwion->mp);
t->e->parent = p;
if(td->array)
SET_FLAG(t, typedef);
return type_finish(gwi, t);
}
-ANN Type gwi_class_spe(const Gwi gwi, const m_str name, const m_uint size) {
+ANN Type gwi_struct_ini(const Gwi gwi, const m_str name, const m_uint size) {
CHECK_OO(str2sym(gwi, name))
const Type t = new_type(gwi->gwion->mp, ++gwi->gwion->env->scope->type_xid, name, NULL);
t->size = size;
gwi_type_flag(t);
+ SET_FLAG(t, struct);
return type_finish(gwi, t);
}
ret = get_type(gwi, op->ret);
const struct Op_Func opfunc = { .ck=op->ck, .em=op->em };
const struct Op_Import opi = { .lhs=lhs, .rhs=rhs, .ret=ret,
- .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=op->sym, .emit_var=op->emit_var };
+ .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=op->sym };
return add_op(gwi->gwion, &opi);
}
return GW_OK;
}
-ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset) {
- gwi->oper->emit_var = offset;
- return GW_OK;
-}
-
ANN m_int gwi_oper_emi(const Gwi gwi, const opem em) {
gwi->oper->em = em;
return GW_OK;
#define ARRAY_OPCK \
const Exp_Binary* bin = (Exp_Binary*)data; \
- const Type l = get_array_type(bin->lhs->type); \
- const Type r = get_array_type(bin->rhs->type); \
+ const Type l = get_array_type(bin->lhs->info->type); \
+ const Type r = get_array_type(bin->rhs->info->type); \
if(isa(l, r) < 0) \
ERR_N(exp_self(bin)->pos, _("array types do not match."))
ARRAY_OPCK
if(opck_const_rhs(env, data, mut) == env->gwion->type[et_null])
return env->gwion->type[et_null];
- if(bin->lhs->type->array_depth != bin->rhs->type->array_depth)
+ if(bin->lhs->info->type->array_depth != bin->rhs->info->type->array_depth)
ERR_N(exp_self(bin)->pos, _("array depths do not match."))
if(bin->rhs->exp_type == ae_exp_decl) {
if(bin->rhs->d.exp_decl.list->self->array &&
bin->rhs->d.exp_decl.list->self->array->exp)
ERR_N(exp_self(bin)->pos, _("do not provide array for 'xxx @=> declaration'."))
}
- bin->rhs->emit_var = 1;
- return bin->rhs->type;
+ exp_setvar(bin->rhs, 1);
+ return bin->rhs->info->type;
}
static OP_CHECK(opck_array_shift) {
ARRAY_OPCK
- if(bin->lhs->type->array_depth != bin->rhs->type->array_depth + 1)
+ if(bin->lhs->info->type->array_depth != bin->rhs->info->type->array_depth + 1)
ERR_N(exp_self(bin)->pos, "array depths do not match for '<<'.");
- return bin->lhs->type;
+ return bin->lhs->info->type;
}
static OP_EMIT(opem_array_shift) {
const Exp_Binary* bin = (Exp_Binary*)data;
- const Type type = bin->rhs->type;
+ const Type type = bin->rhs->info->type;
const Instr pop = emit_add_instr(emit, RegPop);
pop->m_val = type->size;
return emit_add_instr(emit, ArrayAppend);
// check me. use common ancestor maybe
static OP_CHECK(opck_array_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
- Type l = cast->exp->type;
- Type r = exp_self(cast)->type;
+ Type l = cast->exp->info->type;
+ Type r = exp_self(cast)->info->type;
while(!l->e->d.base_type)
l = l->e->parent;
while(!r->e->d.base_type)
r = r->e->parent;
- if(get_depth(cast->exp->type) == get_depth(exp_self(cast)->type) && isa(l->e->d.base_type, r->e->d.base_type) > 0)
+ if(get_depth(cast->exp->info->type) == get_depth(exp_self(cast)->info->type) && isa(l->e->d.base_type, r->e->d.base_type) > 0)
return l;
return env->gwion->type[et_null];
}
static OP_CHECK(opck_array_slice) {
const Exp e = (Exp)data;
- return e->d.exp_slice.base->type;
+ return e->d.exp_slice.base->info->type;
}
static inline m_bool bounds(const M_Vector v, const m_int i) {
ANN static inline m_bool array_do(const Emitter emit, const Array_Sub array, const m_bool is_var) {
emit_add_instr(emit, GcAdd);
- CHECK_BB(emit_exp(emit, array->exp, 0))
+ CHECK_BB(emit_exp(emit, array->exp))
array_loop(emit, array->depth);
array_finish(emit, array->depth, array->type->size, is_var);
return GW_OK;
GWI_BB(gwi_oper_emi(gwi, opem_basic_cast))
GWI_BB(gwi_oper_end(gwi, "$", NULL))
GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", "int", "int"))
+// GWI_BB(gwi_oper_ini(gwi, "@Array", "int", "int"))
GWI_BB(gwi_oper_add(gwi, opck_array_slice))
GWI_BB(gwi_oper_emi(gwi, opem_array_slice))
- GWI_BB(gwi_oper_var(gwi, SZ_INT*2))
GWI_BB(gwi_oper_end(gwi, "@slice", NULL))
GWI_BB(gwi_oper_ini(gwi, "int", (m_str)OP_ANY_TYPE, NULL))
GWI_BB(gwi_oper_add(gwi, opck_not_array))
GWI_BB(gwi_func_end(gwi, event_broadcast, ae_flag_none))
GWI_BB(gwi_class_end(gwi))
GWI_BB(gwi_oper_ini(gwi, "nonnull Event", "@now", "int"))
- GWI_BB(gwi_oper_var(gwi, -SZ_FLOAT))
_CHECK_OP("=>", eventwait, EventWait)
return GW_OK;
}
static OP_EMIT(opem_func_assign) {
Exp_Binary* bin = (Exp_Binary*)data;
- if(bin->rhs->type->e->d.func->def->base->tmpl)
- fptr_instr(emit, bin->lhs->type->e->d.func, 2);
+ if(bin->rhs->info->type->e->d.func->def->base->tmpl)
+ fptr_instr(emit, bin->lhs->info->type->e->d.func, 2);
const Instr instr = emit_add_instr(emit, int_r_assign);
- if(!is_fptr(emit->gwion, bin->lhs->type) && GET_FLAG(bin->rhs->type->e->d.func, member)) {
+ if(!is_fptr(emit->gwion, bin->lhs->info->type) && GET_FLAG(bin->rhs->info->type->e->d.func, member)) {
+//exit(3);
const Instr pop = emit_add_instr(emit, LambdaAssign);
pop->m_val = SZ_INT;
}
env_pop(env, scope);
if(ret < 0)
return GW_ERROR;
- exp_self(l)->type = l->def->base->func->value_ref->type;
+ exp_self(l)->info->type = l->def->base->func->value_ref->type;
return GW_OK;
}
}
ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) {
- if(isa(info->exp->type, env->gwion->type[et_lambda]) < 0) {
- m_bool nonnull = GET_FLAG(info->exp->type, nonnull);
+ if(isa(info->exp->info->type, env->gwion->type[et_lambda]) < 0) {
+ m_bool nonnull = GET_FLAG(info->exp->info->type, nonnull);
CHECK_BB(fptr_check(env, info))
DECL_OB(const Type, t, = fptr_type(env, info))
- info->exp->type = !nonnull ? t : type_nonnull(env, t);
+ info->exp->info->type = !nonnull ? t : type_nonnull(env, t);
return GW_OK;
}
return fptr_lambda(env, info);
static OP_CHECK(opck_fptr_at) {
Exp_Binary* bin = (Exp_Binary*)data;
- if(bin->rhs->type->e->d.func->def->base->tmpl &&
- bin->rhs->type->e->d.func->def->base->tmpl->call) {
- struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->parent->e->d.func,
+ if(bin->rhs->info->type->e->d.func->def->base->tmpl &&
+ bin->rhs->info->type->e->d.func->def->base->tmpl->call) {
+ struct FptrInfo info = { bin->lhs->info->type->e->d.func, bin->rhs->info->type->e->parent->e->d.func,
bin->lhs, exp_self(bin)->pos };
CHECK_BO(fptr_do(env, &info))
- bin->rhs->emit_var = 1;
- return bin->rhs->type;
+ exp_setvar(bin->rhs, 1);
+ return bin->rhs->info->type;
}
- struct FptrInfo info = { bin->lhs->type->e->d.func, bin->rhs->type->e->d.func,
+ struct FptrInfo info = { bin->lhs->info->type->e->d.func, bin->rhs->info->type->e->d.func,
bin->lhs, exp_self(bin)->pos };
CHECK_BO(fptr_do(env, &info))
- bin->rhs->emit_var = 1;
- return bin->rhs->type;
+ exp_setvar(bin->rhs, 1);
+ return bin->rhs->info->type;
}
static OP_CHECK(opck_fptr_cast) {
Exp_Cast* cast = (Exp_Cast*)data;
- const Type t = exp_self(cast)->type;
- struct FptrInfo info = { cast->exp->type->e->d.func, t->e->d.func,
+ const Type t = exp_self(cast)->info->type;
+ struct FptrInfo info = { cast->exp->info->type->e->d.func, t->e->d.func,
cast->exp, exp_self(cast)->pos };
CHECK_BO(fptr_do(env, &info))
- cast->func = cast->exp->type->e->d.func;
+ cast->func = cast->exp->info->type->e->d.func;
return t;
}
static OP_EMIT(opem_fptr_cast) {
CHECK_OO(opem_basic_cast(emit, data))
Exp_Cast* cast = (Exp_Cast*)data;
- if(exp_self(cast)->type->e->d.func->def->base->tmpl)
- fptr_instr(emit, cast->exp->type->e->d.func, 1);
- if(GET_FLAG(cast->exp->type->e->d.func, member) &&
- !(GET_FLAG(cast->exp->type, nonnull) || GET_FLAG(exp_self(cast)->type, nonnull)))
+ if(exp_self(cast)->info->type->e->d.func->def->base->tmpl)
+ fptr_instr(emit, cast->exp->info->type->e->d.func, 1);
+ if(GET_FLAG(cast->exp->info->type->e->d.func, member) &&
+ !(GET_FLAG(cast->exp->info->type, nonnull) || GET_FLAG(exp_self(cast)->info->type, nonnull)))
member_fptr(emit);
return (Instr)GW_OK;
}
static OP_CHECK(opck_fptr_impl) {
struct Implicit *impl = (struct Implicit*)data;
- struct FptrInfo info = { impl->e->type->e->d.func, impl->t->e->d.func,
+ struct FptrInfo info = { impl->e->info->type->e->d.func, impl->t->e->d.func,
impl->e, impl->e->pos };
CHECK_BO(fptr_do(env, &info))
- return ((Exp)impl->e)->cast_to = impl->t;
+ return ((Exp)impl->e)->info->cast_to = impl->t;
}
static OP_EMIT(opem_fptr_impl) {
struct Implicit *impl = (struct Implicit*)data;
if(GET_FLAG(impl->t->e->d.func, member) &&
- !(GET_FLAG(impl->e->type, nonnull) || GET_FLAG(impl->t, nonnull)))
+ !(GET_FLAG(impl->e->info->type, nonnull) || GET_FLAG(impl->t, nonnull)))
member_fptr(emit);
if(impl->t->e->d.func->def->base->tmpl)
- fptr_instr(emit, ((Exp)impl->e)->type->e->d.func, 1);
+ fptr_instr(emit, ((Exp)impl->e)->info->type->e->d.func, 1);
return (Instr)GW_OK;
}
return NULL; // unreachable
}
-ANN static void prepare_call(const VM_Shred shred, m_uint offset) {
+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;
- *(VM_Code*)(shred->mem+ SZ_INT*2) = shred->code;
- *(m_uint*)(shred->mem+ SZ_INT*3) = shred->pc;
- *(m_uint*)(shred->mem+ SZ_INT*4) = SZ_INT;
+ *(m_uint*)(shred->mem + SZ_INT) = offset + SZ_INT;
+ *(VM_Code*)(shred->mem + SZ_INT*2) = shred->code;
+ *(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);
shred->pc = 0;
}
return;
}
+
static OP_CHECK(opck_usrugen) {
Exp_Binary *bin = (Exp_Binary*)data;
- const Arg_List arg = bin->lhs->type->e->d.func->def->base->args;
+ const Arg_List arg = bin->lhs->info->type->e->d.func->def->base->args;
if(!arg || arg->next)
ERR_N(exp_self(bin)->pos, _("Tick function take one and only one argument"))
if(isa(arg->type, env->gwion->type[et_float]) < 0)
ERR_N(exp_self(bin)->pos, _("Tick functions argument must be of type float"))
- if(isa(bin->lhs->type->e->d.func->def->base->ret_type, env->gwion->type[et_float]) < 0)
+ if(isa(bin->lhs->info->type->e->d.func->def->base->ret_type, env->gwion->type[et_float]) < 0)
ERR_N(exp_self(bin)->pos, _("Tick function must return float"))
- if(bin->lhs->type->e->d.func->value_ref->from->owner_class)
- CHECK_BN(isa(bin->lhs->type->e->d.func->value_ref->from->owner_class,
- bin->rhs->type))
- return bin->rhs->type;
+ if(bin->lhs->info->type->e->d.func->value_ref->from->owner_class)
+ CHECK_BN(isa(bin->lhs->info->type->e->d.func->value_ref->from->owner_class,
+ bin->rhs->info->type))
+ return bin->rhs->info->type;
}
static INSTR(UURet) {
static OP_EMIT(opem_usrugen) {
Exp_Binary *bin = (Exp_Binary*)data;
const Instr instr = emit_add_instr(emit, UsrUGenTick);
- instr->m_val = !!bin->lhs->type->e->d.func->value_ref->from->owner_class;
+ instr->m_val = !!bin->lhs->info->type->e->d.func->value_ref->from->owner_class;
return instr;
}
#include "gwi.h"
#include "gack.h"
+#include "tuple.h"
#undef insert_symbol
ANN void exception(const VM_Shred shred, const m_str c) {
if(!GET_FLAG(v, static) && !GET_FLAG(v, pure) &&
isa(v->type, shred->info->vm->gwion->type[et_object]) > 0)
release(*(M_Object*)(o->data + v->from->offset), shred);
+else if(GET_FLAG(v->type, struct) &&
+ !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 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);
+}
+
+//exit(77);
+
+}
}
if(GET_FLAG(t, dtor) && t->nspc->dtor) {
if(GET_FLAG(t->nspc->dtor, builtin))
mp_free(p, M_Object, o);
}
-static ID_CHECK(check_this) {
+static ID_CHECK(opck_this) {
if(!env->class_def)
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..."))
+ 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"))
return env->class_def;
}
+static ID_EMIT(opem_this) {
+ if(!exp_getvar(exp_self(prim)) && GET_FLAG(exp_self(prim)->info->type, struct)) {
+ const Instr instr = emit_add_instr(emit, RegPushMemDeref);
+ instr->m_val2 = emit->env->class_def->size;
+ return (Instr)GW_OK;
+ }
+ return emit_add_instr(emit, RegPushMem);
+}
+
static GACK(gack_object) {
INTERP_PRINTF("%p", *(M_Object*)VALUE);
}
GWI_BB(gwi_gack(gwi, t_object, gack_object))
SET_FLAG(t_object, checked); // 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 };
+// struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 };
+ struct SpecialId_ spid = { .ck=opck_this, .em=opem_this, .is_const=1 };
gwi_specialid(gwi, "this", &spid);
return GW_OK;
}
#undef insert_symbol
#define describe_logical(name, op) \
-static INSTR(name##Object) {\
+static INSTR(name##Object) { \
POP_REG(shred, SZ_INT); \
const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
const M_Object rhs = *(M_Object*)REG(0); \
static OP_CHECK(at_object) {
const Exp_Binary* bin = (Exp_Binary*)data;
- const Type l = bin->lhs->type;
- const Type r = bin->rhs->type;
+ const Type l = bin->lhs->info->type;
+ const Type r = bin->rhs->info->type;
if(opck_rassign(env, data, mut) == env->gwion->type[et_null])
return env->gwion->type[et_null];
if(check_nonnull(env, l, r, "assign", exp_self(bin)->pos) == env->gwion->type[et_null])
SET_FLAG(bin->rhs->d.exp_decl.td, ref);
SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref);
}
- bin->rhs->emit_var = 1;
+ exp_setvar(bin->rhs, 1);
return r;
}
static OP_EMIT(opem_at_object) {
const Exp_Binary* bin = (Exp_Binary*)data;
- const Type l = bin->lhs->type;
- const Type r = bin->rhs->type;
+ const Type l = bin->lhs->info->type;
+ const Type r = bin->rhs->info->type;
if(nonnull_check(l, r)) {
const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
instr->m_val = SZ_INT;
static OP_CHECK(opck_object_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
- const Type l = cast->exp->type;
- const Type r = exp_self(cast)->type;
+ const Type l = cast->exp->info->type;
+ const Type r = exp_self(cast)->info->type;
if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null])
return env->gwion->type[et_null];
return get_force_type(env, r);
static OP_EMIT(opem_object_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
- const Type l = cast->exp->type;
- const Type r = exp_self(cast)->type;
+ const Type l = cast->exp->info->type;
+ const Type r = exp_self(cast)->info->type;
if(nonnull_check(l, r))
emit_add_instr(emit, GWOP_EXCEPT);
return (Instr)GW_OK;
static OP_CHECK(opck_implicit_null2obj) {
const struct Implicit* imp = (struct Implicit*)data;
- const Type l = imp->e->type;
+ const Type l = imp->e->info->type;
const Type r = imp->t;
if(check_nonnull(env, l, r, "implicitly cast", imp->e->pos) == env->gwion->type[et_null])
return env->gwion->type[et_null];
- imp->e->cast_to = r;
+ imp->e->info->cast_to = r;
return imp->t;
}
static OP_EMIT(opem_implicit_null2obj) {
const struct Implicit* imp = (struct Implicit*)data;
- const Type l = imp->e->type;
+ const Type l = imp->e->info->type;
const Type r = imp->t;
if(nonnull_check(l, r))
emit_add_instr(emit, GWOP_EXCEPT);
static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 };
ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
- const Func f = exp_self(member)->type->e->d.func;
- if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
+ const Func f = exp_self(member)->info->type->e->d.func;
+ if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->info->type, force)) {
const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
func_i->m_val = (m_uint)f->code;
return;
if(f->def->base->tmpl)
emit_add_instr(emit, DotTmplVal);
else {
+ if(GET_FLAG(member->t_base, struct)) {
+ if(!GET_FLAG(f->def, static)) {
+ exp_setvar(member->base, 1);
+ emit_exp(emit, member->base);
+ }
+ const Instr instr = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
+ instr->m_val = (m_uint)f->code;
+ return;
+ }
const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
instr->m_val = f->vt_index;
}
instr->m_val2 = size;
}
+ANN static inline void emit_struct_addr(const Emitter emit, const Value v) {
+ const Instr set = emit_add_instr(emit, StructMemberAddr);
+ set->m_val = v->from->owner_class->size - v->type->size;
+ set->m_val2 = v->from->offset;
+}
+
+ANN static inline void emit_struct_var(const Emitter emit, const Value v) {
+ for(m_uint i = 0; i < v->type->size; i += SZ_INT) {
+ const Instr set = emit_add_instr(emit, Reg2Reg);
+ set->m_val = -v->type->size + i;
+ set->m_val2 = -v->type->size + v->from->offset + i;
+ }
+}
+
+ANN static inline void emit_struct_data(const Emitter emit, const Value v, const uint emit_addr) {
+ if(emit_addr) {
+ emit_struct_addr(emit, v);
+ return;
+ }
+ const Instr push = emit_add_instr(emit, RegPush);
+ push->m_val = v->type->size - v->from->owner_class->size;
+ if(v->from->offset)
+ emit_struct_var(emit, v);
+// const Instr push = emit_add_instr(emit, RegPush);
+// push->m_val = v->type->size - SZ_INT;
+}
+
ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
OP_CHECK(opck_object_dot) {
const Exp_Dot *member = (Exp_Dot*)data;
ERR_O(exp_self(member)->pos,
_("can't access private '%s' outside of class..."), value->name)
else if(GET_FLAG(value, protect))
- exp_self(member)->meta = ae_meta_protect;
+ exp_setprot(exp_self(member), 1);
}
if(base_static && GET_FLAG(value, member))
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))
- exp_self(member)->meta = ae_meta_value;
+ exp_setmeta(exp_self(member), 1);
return value->type;
}
OP_EMIT(opem_object_dot) {
const Exp_Dot *member = (Exp_Dot*)data;
- const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
+ const Type t_base = actual_type(emit->gwion, member->t_base);
+ const Value value = find_value(t_base, member->xid);
if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
- (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
- !is_fptr(emit->gwion, exp_self(member)->type)))) {
- CHECK_BO(emit_exp(emit, member->base, 0))
- emit_except(emit, member->t_base);
+ (isa(exp_self(member)->info->type, emit->gwion->type[et_function]) > 0 &&
+ !is_fptr(emit->gwion, exp_self(member)->info->type)))) {
+ if(!GET_FLAG(t_base, struct))
+ CHECK_BO(emit_exp(emit, member->base))
+ if(isa(member->t_base, emit->env->gwion->type[et_object]) > 0)
+ emit_except(emit, member->t_base);
}
- if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
+ if(isa(exp_self(member)->info->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->info->type))
emit_member_func(emit, member);
- else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var);
+ else if(GET_FLAG(value, member)) {
+ if(!GET_FLAG(t_base, struct))
+ emit_member(emit, value, exp_getvar(exp_self(member)));
+ else {
+ exp_setvar(member->base, exp_getvar(exp_self(member)));
+ CHECK_BO(emit_exp(emit, member->base))
+ emit_struct_data(emit, value, exp_getvar(exp_self(member)));
+ }
+ }
+ else if(GET_FLAG(value, static))
+ emit_dot_static_import_data(emit, value, exp_getvar(exp_self(member)));
return (Instr)GW_OK;
}
const Value v = prim_self(data)->value;
const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data)));
const Exp dot = new_exp_dot(gwion->mp, base, *data);
- dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v);
- dot->type = prim_exp(data)->type;
- dot->emit_var = prim_exp(data)->emit_var;
+ dot->d.exp_dot.t_base = dot->d.exp_dot.base->info->type = dot_type(gwion->st, v);
+ dot->info->type = prim_exp(data)->info->type;
+ exp_setvar(dot, exp_getvar(prim_exp(data)));
return dot;
}
#include "operator.h"
#include "import.h"
-static inline m_str access(ae_Exp_Meta meta) {
- return meta == ae_meta_value ? "non-mutable" : "protected";
+static inline m_str get_access(const Exp e) {
+ if(exp_getmeta(e))
+ return "non-mutable";
+ return !exp_getprot(e) ? NULL : "protected";
}
OP_CHECK(opck_basic_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
- return isa(cast->exp->type, exp_self(cast)->type) > 0 ?
- exp_self(cast)->type : env->gwion->type[et_null];
+ return isa(cast->exp->info->type, exp_self(cast)->info->type) > 0 ?
+ exp_self(cast)->info->type : env->gwion->type[et_null];
}
OP_CHECK(opck_usr_implicit) {
struct Implicit* imp = (struct Implicit*)data;
- imp->e->cast_to = imp->t;
+ imp->e->info->cast_to = imp->t;
return imp->t;
}
OP_CHECK(opck_const_rhs) {
const Exp_Binary* bin = (Exp_Binary*)data;
- if(bin->rhs->meta != ae_meta_var)
+ const m_str access = get_access(bin->rhs);
+ if(access)
ERR_N(bin->rhs->pos, _("cannot assign '%s' on types '%s' and '%s'.\n"
" ... (reason: --- right-side operand is %s.)"),
- s_name(bin->op), bin->lhs->type->name, bin->rhs->type->name,
- access(bin->rhs->meta))
- return bin->rhs->type;
+ s_name(bin->op), bin->lhs->info->type->name, bin->rhs->info->type->name,
+ access)
+ return bin->rhs->info->type;
}
OP_CHECK(opck_rhs_emit_var) {
const Exp_Binary* bin = (Exp_Binary*)data;
- bin->rhs->emit_var = 1;
- return bin->rhs->type;
+ exp_setvar(bin->rhs, 1);
+ return bin->rhs->info->type;
}
OP_CHECK(opck_rassign) {
const Exp_Binary* bin = (Exp_Binary*)data;
if(opck_const_rhs(env, data, mut) == env->gwion->type[et_null])
return env->gwion->type[et_null];
- bin->rhs->emit_var = 1;
- return bin->rhs->type;
+ exp_setvar(bin->rhs, 1);
+ return bin->rhs->info->type;
}
OP_CHECK(opck_unary_meta) {
const Exp_Unary* unary = (Exp_Unary*)data;
- exp_self(unary)->meta = ae_meta_value;
- return unary->exp->type;
+ exp_setmeta(exp_self(unary), 1);
+ return unary->exp->info->type;
}
OP_CHECK(opck_unary_meta2) {
const Exp_Unary* unary = (Exp_Unary*)data;
- exp_self(unary)->meta = ae_meta_value;
+ exp_setmeta(exp_self(unary), 1);
return env->gwion->type[et_bool];
}
OP_CHECK(opck_unary) {
const Exp_Unary* unary = (Exp_Unary*)data;
- if(unary->exp->meta != ae_meta_var)
+ const m_str access = get_access(unary->exp);
+ if(access)
ERR_N(unary->exp->pos,
_("unary operator '%s' cannot be used on %s data-types."),
- s_name(unary->op), access(unary->exp->meta))
- unary->exp->emit_var = 1;
- exp_self(unary)->meta = ae_meta_value;
- return unary->exp->type;
+ s_name(unary->op), access);
+ exp_setvar(unary->exp, 1);
+ return unary->exp->info->type;
}
OP_CHECK(opck_post) {
const Exp_Postfix* post = (Exp_Postfix*)data;
- if(post->exp->meta != ae_meta_var)
+ const m_str access = get_access(post->exp);
+ if(access)
ERR_N(post->exp->pos, _("post operator '%s' cannot be used on %s data-type."),
- s_name(post->op), access(post->exp->meta))
- post->exp->emit_var = 1;
- exp_self(post)->meta = ae_meta_value;
- return post->exp->type;
+ s_name(post->op), access)
+ exp_setvar(post->exp, 1);
+ return post->exp->info->type;
}
OP_CHECK(opck_new) {
OP_EMIT(opem_new) {
const Exp_Unary* unary = (Exp_Unary*)data;
- CHECK_BO(emit_instantiate_object(emit, exp_self(unary)->type,
+ CHECK_BO(emit_instantiate_object(emit, exp_self(unary)->info->type,
unary->td->array, GET_FLAG(unary->td, ref)))
return emit_add_instr(emit, GcAdd);
}
const Exp exp = (Exp)data;
const Range *range = exp->d.prim.d.range;
const Exp e = range->start ?: range->end;
- return array_type(env, e->type, 1);
+ return array_type(env, e->info->type, 1);
}
static OP_EMIT(opem_int_range) {
const Exp exp = (Exp)data;
const Instr instr = emit_add_instr(emit, IntRange);
- instr->m_val = (m_uint)exp->type;
+ instr->m_val = (m_uint)exp->info->type;
return instr;
}
static GWION_IMPORT(int_unary) {
GWI_BB(gwi_oper_ini(gwi, NULL, "int", "int"))
- GWI_BB(gwi_oper_add(gwi, opck_unary_meta))
- GWI_BB(gwi_oper_end(gwi, "-", int_negate))
+ GWI_BB(gwi_oper_add(gwi, opck_unary_meta))
+ GWI_BB(gwi_oper_end(gwi, "-", int_negate))
CHECK_OP("++", unary, pre_inc)
CHECK_OP("--", unary, pre_dec)
GWI_BB(gwi_oper_end(gwi, "~", int_cmp))
GWI_BB(gwi_oper_ini(gwi, NULL, "int", NULL))
- GWI_BB(gwi_oper_add(gwi, opck_int_range))
- GWI_BB(gwi_oper_emi(gwi, opem_int_range))
- GWI_BB(gwi_oper_end(gwi, "@range", NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_int_range))
+ GWI_BB(gwi_oper_emi(gwi, opem_int_range))
+ GWI_BB(gwi_oper_end(gwi, "@range", NULL))
GWI_BB(gwi_oper_ini(gwi, "int", NULL, "int"))
CHECK_OP("++", post, post_inc)
GWI_BB(gwi_oper_add(gwi, opck_post))
static OP_CHECK(opck_implicit_i2f) {
struct Implicit* imp = (struct Implicit*)data;
- return imp->e->cast_to = env->gwion->type[et_float];
+ return imp->e->info->cast_to = env->gwion->type[et_float];
}
#define CHECK_FF(op, check, func) _CHECK_OP(op, check, float_##func)
static OP_CHECK(opck_ptr_assign) {
const Exp_Binary* bin = (Exp_Binary*)data;
- if(bin->lhs->meta != ae_meta_var)
- ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
- bin->lhs->emit_var = 1;
- Type t = bin->lhs->type;
+ const m_str access = exp_access(exp_self(bin));
+ if(access)
+ ERR_N(exp_self(bin)->pos, _("left side operand is %s"), access);
+ exp_setvar(bin->lhs, 1);
+ Type t = bin->lhs->info->type;
do {
- Type u = bin->rhs->type;
+ Type u = bin->rhs->info->type;
do {
const m_str str = get_type_name(env, u->name, 1);
if(str && !strcmp(t->name, str))
- return bin->lhs->type;
+ return bin->lhs->info->type;
} while((u = u->e->parent));
} while((t = t->e->parent));
return env->gwion->type[et_null];
static OP_CHECK(opck_ptr_deref) {
const Exp_Unary* unary = (Exp_Unary*)data;
- DECL_ON(const m_str, str, = get_type_name(env, unary->exp->type->name, 1))
- return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(str));
+ DECL_ON(const m_str, str, = get_type_name(env, unary->exp->info->type->name, 1))
+ return exp_self(unary)->info->type = nspc_lookup_type1(env->curr, insert_symbol(str));
}
static OP_CHECK(opck_ptr_cast) {
if(!GET_FLAG(t, check))
CHECK_BN(traverse_class_def(env, t->e->def))
const Type to = known_type(env, cast->td->types->td);
- if(isa(cast->exp->type, to) > 0)
+ if(isa(cast->exp->info->type, to) > 0)
return t;
ERR_N(exp_self(cast)->pos, "invalid pointer cast")
}
static OP_CHECK(opck_ptr_implicit) {
const struct Implicit* imp = (struct Implicit*)data;
const Exp e = imp->e;
- if(!strcmp(get_type_name(env, imp->t->name, 1), e->type->name)) {
- if(e->meta == ae_meta_value)
- ERR_N(e->pos, _("can't cast constant to Ptr"));
- e->cast_to = imp->t;
- e->emit_var = 1;
+ if(!strcmp(get_type_name(env, imp->t->name, 1), e->info->type->name)) {
+ const m_str access = exp_access(e);
+ if(access)
+ ERR_N(e->pos, _("can't cast %s value to Ptr"), access);
+ e->info->cast_to = imp->t;
+ exp_setvar(e, 1);
if(!GET_FLAG(imp->t, check))
CHECK_BN(traverse_class_def(env, imp->t->e->def))
return imp->t;
static OP_EMIT(opem_ptr_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
const Instr instr = emit_add_instr(emit, Cast2Ptr);
- instr->m_val = (m_uint)exp_self(cast)->type;
+ instr->m_val = (m_uint)exp_self(cast)->info->type;
return instr;
}
static OP_EMIT(opem_ptr_deref) {
const Exp_Unary* unary = (Exp_Unary*)data;
const Instr instr = emit_add_instr(emit, instr_ptr_deref);
- instr->m_val = exp_self(unary)->type->size;
- instr->m_val2 = exp_self(unary)->emit_var;
+ instr->m_val = exp_self(unary)->info->type->size;
+ instr->m_val2 = exp_getvar(exp_self(unary));
return instr;
}
}
#define describe_string_logical(name, action) \
-static INSTR(String_##name) {\
+static INSTR(String_##name) { \
POP_REG(shred, SZ_INT); \
const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
const M_Object rhs = *(M_Object*)REG(0); \
static OP_CHECK(opck_chuck_ugen) {
const Exp_Binary* bin = (Exp_Binary*)data;
- return bin->rhs->type;
+ return bin->rhs->info->type;
}
GWION_IMPORT(ugen) {
static OP_EMIT(opem_vararg_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
const Instr instr = emit_add_instr(emit, VarargCast);
- instr->m_val = (m_uint)exp_self(cast)->type;
+ instr->m_val = (m_uint)exp_self(cast)->info->type;
const Instr push = emit_add_instr(emit, RegPush);
- push->m_val = exp_self(cast)->type->size - SZ_INT;
+ push->m_val = exp_self(cast)->info->type->size - SZ_INT;
return instr;
}
static ID_CHECK(idck_vararg) {
if(env->func && GET_FLAG(env->func->def, variadic))
- return type_nonnull(env, exp_self(prim)->type);
+ return type_nonnull(env, exp_self(prim)->info->type);
ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
}
#ifdef __AFL_HAVE_MANUAL_CONTROL
ANN static void gwion_reset(const Gwion gwion) {
- release_ctx(gwion->env->scope, gwion);
pop_global(gwion);
push_global(gwion, "[user]");
}
-#define BUFSIZE 1024
+//#define BUFSIZE 1024
+#define BUFSIZE 256
static void afl_run(const Gwion gwion) {
char buf[BUFSIZE];
ANN static m_bool check_internal(const Env env, const Symbol sym,
const Exp e, const Type t) {
struct Implicit imp = { .e=e, .t=t, .pos=e->pos };
- struct Op_Import opi = { .op=sym, .lhs=e->type,
- .rhs=t, .data=(uintptr_t)&imp, .pos=e->pos };
+ struct Op_Import opi = { .op=sym, .lhs=e->info->type,
+ .rhs=t, .data=(uintptr_t)&imp, .pos=e->pos, .op_type=op_implicit };
CHECK_OB(op_check(env, &opi))
assert(e->nspc);
return GW_OK;
}
ANN m_bool check_implicit(const Env env, const Exp e, const Type t) {
- if(e->type == t)
+ if(e->info->type == t)
return GW_OK;
const Symbol sym = insert_symbol("@implicit");
return check_internal(env, sym, e, t);
CHECK_BO(scan1_exp(env, td->exp))
CHECK_BO(scan2_exp(env, td->exp))
CHECK_OO(check_exp(env, td->exp))
- const Type t = actual_type(env->gwion, td->exp->type);
+ const Type t = actual_type(env->gwion, td->exp->info->type);
assert(t);
if(GET_FLAG(t, template) && !GET_FLAG(t, ref))
ERR_O(td_pos(td), _("type '%s' needs template types"), t->name)
if(env->class_def) {
if(GET_FLAG(td, member)) {
decl_member(env, v);
- if(isa(env->class_def, env->gwion->type[et_object]) > 0)
+ if(env->class_def->e->tuple)
tuple_info(env, td, var);
} else if(GET_FLAG(td, static))
- decl_static(env, v);
+ decl_static(env, v);
} else if(GET_FLAG(td, global) || (env->func && GET_FLAG(env->func->def, global)))
SET_FLAG(v, abstract);
return GW_OK;
ANN static inline void set_cast(const Env env, Type type, const Exp e) {
- e->cast_to = type;
- e->nspc = env->curr;
+ e->info->cast_to = type;
+ e->info->nspc = env->curr;
}
ANN static m_bool prim_array_inner(const Env env, Type type, const Exp e) {
- const Type common = find_common_anc(e->type, type);
+ const Type common = find_common_anc(e->info->type, type);
if(common)
return GW_OK;
if(check_implicit(env, e, type) < 0)
}
ANN static inline Type prim_array_match(const Env env, Exp e) {
- const Type type = e->type;
+ const Type type = e->info->type;
do CHECK_BO(prim_array_inner(env, type, e))
while((e = e->next));
return array_type(env, type->array_depth ? array_base(type) : type, type->array_depth + 1);
if(range->end)
CHECK_OB(check_exp(env, range->end))
if(range->start && range->end) {
- if(isa(range->end->type, range->start->type) < 0)
+ if(isa(range->end->info->type, range->start->info->type) < 0)
ERR_B(range->start->pos, _("range types do not match"))
}
return GW_OK;
CHECK_BO(check_range(env, range))
const Exp e = range->start ?: range->end;
const Symbol sym = insert_symbol("@range");
- struct Op_Import opi = { .op=sym, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)prim_exp(data) };
+ struct Op_Import opi = { .op=sym, .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)prim_exp(data), .op_type=op_exp };
return op_check(env, &opi);
}
ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
ANN static Type check_dot(const Env env, const Exp_Dot *member) {
- struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
+ struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member,
+ .pos=exp_self(member)->pos, .op_type=op_dot };
return op_check(env, &opi);
}
SET_FLAG(v, used);
prim_self(data)->value = v;
if(GET_FLAG(v, const))
- prim_exp(data)->meta = ae_meta_value;
+ exp_setmeta(prim_exp(data), 1);
if(v->from->owner_class) {
const Exp exp = symbol_owned_exp(env->gwion, data);
const Type ret = check_dot(env, &exp->d.exp_dot);
- prim_exp(data)->nspc = exp->nspc;
+ prim_exp(data)->info->nspc = exp->info->nspc;
free_exp(env->gwion->mp, exp);
CHECK_OO(ret);
}
DECL_PRIM_FUNC(check, Type, Env);
ANN static Type check_prim(const Env env, Exp_Primary *prim) {
- return exp_self(prim)->type = check_prim_func[prim->prim_type](env, &prim->d);
+ return exp_self(prim)->info->type = check_prim_func[prim->prim_type](env, &prim->d);
}
ANN Type check_array_access(const Env env, const Array_Sub array) {
const Symbol sym = insert_symbol("@array");
- struct Op_Import opi = { .op=sym, .lhs=array->exp->type, .rhs=array->type, .pos=array->exp->pos, .data=(uintptr_t)array };
+ struct Op_Import opi = { .op=sym, .lhs=array->exp->info->type, .rhs=array->type,
+ .pos=array->exp->pos, .data=(uintptr_t)array, .op_type=op_array };
return op_check(env, &opi);
}
CHECK_BO(check_range(env, range->range))
const Symbol sym = insert_symbol("@slice");
const Exp e = range->range->start ?: range->range->end;
- struct Op_Import opi = { .op=sym, .lhs=range->base->type, .rhs=e->type, .pos=e->pos, .data=(uintptr_t)exp_self(range) };
+ struct Op_Import opi = { .op=sym, .lhs=range->base->info->type, .rhs=e->info->type,
+ .pos=e->pos, .data=(uintptr_t)exp_self(range), .op_type=op_exp };
return op_check(env, &opi);
}
ANN static m_bool func_match_inner(const Env env, const Exp e, const Type t,
const m_bool implicit, const m_bool specific) {
- const m_bool match = (specific ? e->type == t : isa(e->type, t) > 0) &&
- e->type->array_depth == t->array_depth &&
- array_base(e->type) == array_base(t);
+ const m_bool match = (specific ? e->info->type == t : isa(e->info->type, t) > 0) &&
+ e->info->type->array_depth == t->array_depth &&
+ array_base(e->info->type) == array_base(t);
if(!match) {
- if(e->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
+ if(e->info->type == env->gwion->type[et_lambda] && is_fptr(env->gwion, t)) {
const Type owner = nspc_lookup_type1(t->e->owner->parent,
insert_symbol(t->e->owner->name));
const m_bool ret = check_lambda(env, owner, &e->d.exp_lambda, t->e->d.func->def);
-// e->emit_var = 1;
+// exp_setvar(e, 1);
return ret;
}
if(implicit)
ANN2(1, 2) static Func find_func_match(const Env env, const Func up, const Exp exp) {
Func func;
- const Exp args = (exp && isa(exp->type, env->gwion->type[et_void]) < 0) ? exp : NULL;
+ const Exp args = (exp && isa(exp->info->type, env->gwion->type[et_void]) < 0) ? exp : NULL;
if((func = find_func_match_actual(env, up, args, 0, 1)) ||
(func = find_func_match_actual(env, up, args, 1, 1)) ||
(func = find_func_match_actual(env, up, args, 0, 0)) ||
if(exists)
m_func = exists->e->d.func;
else {
- Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->type->e->d.func->def;
+ Func_Def base = v->d.func_ref ? v->d.func_ref->def : exp->func->info->type->e->d.func->def;
Func_Base *fbase = cpy_func_base(env->gwion->mp, base->base);
fbase->xid = sym;
fbase->tmpl->base = 0;
ANN static void print_current_args(Exp e) {
gw_err(_("and not\n "));
- do gw_err(" \033[32m%s\033[0m", e->type->name);
+ do gw_err(" \033[32m%s\033[0m", e->info->type->name);
while((e = next_arg_Exp(e)));
gw_err("\n");
}
const Func f = find_template_match(env, v, func);
if(f) {
Tmpl* tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call);
- tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->type->e->d.func->def->base->tmpl->list;
+ tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->info->type->e->d.func->def->base->tmpl->list;
((Exp_Call*)func)->tmpl = tmpl;
return ((Exp_Call*)func)->m_func = f;
}
char path[id_list_len(arg->td->xid)];
type_path(path, arg->td->xid);
if(!strcmp(s_name(list->xid), path)) {
- tl[args_number] = mk_type_list(env, template_arg->type, fdef->pos);
+ tl[args_number] = mk_type_list(env, template_arg->info->type, fdef->pos);
if(args_number)
tl[args_number - 1]->next = tl[args_number];
++args_number;
}
ANN static Type check_exp_call_template(const Env env, Exp_Call *exp) {
- const Type t = exp->func->type;
+ const Type t = exp->func->info->type;
DECL_OO(const Value, value, = nspc_lookup_value1(t->e->owner, insert_symbol(t->name)))
const Func_Def fdef = value->d.func_ref ? value->d.func_ref->def : t->e->d.func->def;
Tmpl *tm = fdef->base->tmpl;
Arg_List arg = l->def->base->args;
Exp e = exp->args;
while(arg && e) {
- arg->type = e->type;
+ arg->type = e->info->type;
arg = arg->next;
e = e->next;
}
ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
CHECK_OO(check_exp(env, exp->func))
- if(isa(exp->func->type, env->gwion->type[et_function]) < 0) {
+ if(isa(exp->func->info->type, env->gwion->type[et_function]) < 0) {
// use func flag?
- if(isa(exp->func->type, env->gwion->type[et_class]) < 0)
+ if(isa(exp->func->info->type, env->gwion->type[et_class]) < 0)
ERR_O(exp->func->pos, _("function call using a non-function value"))
// if(exp->args)
// CHECK_OO(check_exp(env, exp->args))
- struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp->func->type->e->d.base_type, .data=(uintptr_t)exp, .pos=exp_self(exp)->pos };
+ struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp->func->info->type->e->d.base_type,
+ .data=(uintptr_t)exp, .pos=exp_self(exp)->pos, .op_type=op_exp };
const Type t = op_check(env, &opi);
- exp_self(exp)->nspc = t ? t->e->owner : NULL;
+ exp_self(exp)->info->nspc = t ? t->e->owner : NULL;
return t;
}
- if(exp->func->type == env->gwion->type[et_lambda])
+ if(exp->func->info->type == env->gwion->type[et_lambda])
return check_lambda_call(env, exp);
- if(GET_FLAG(exp->func->type->e->d.func, ref)) {
- const Value value = exp->func->type->e->d.func->value_ref;
+ if(GET_FLAG(exp->func->info->type->e->d.func, ref)) {
+ const Value value = exp->func->info->type->e->d.func->value_ref;
if(value->from->owner_class && !GET_FLAG(value->from->owner_class, check))
CHECK_BO(traverse_class_def(env, value->from->owner_class->e->def))
}
if(exp->args)
CHECK_OO(check_exp(env, exp->args))
- if(GET_FLAG(exp->func->type, func))
+ if(GET_FLAG(exp->func->info->type, func))
return check_exp_call_template(env, (Exp_Call*)exp);
- const Func func = find_func_match(env, exp->func->type->e->d.func, exp->args);
+ const Func func = find_func_match(env, exp->func->info->type->e->d.func, exp->args);
if((exp_self(exp)->d.exp_call.m_func = func)) {
- exp->func->type = func->value_ref->type;
+ exp->func->info->type = func->value_ref->type;
return func->def->base->ret_type;
}
- function_alternative(env, exp->func->type, exp->args, exp_self(exp)->pos);
+ function_alternative(env, exp->func->info->type, exp->args, exp_self(exp)->pos);
return NULL;
}
CHECK_OO(check_exp(env, bin->lhs))
const m_bool is_auto = bin->rhs->exp_type == ae_exp_decl && bin->rhs->d.exp_decl.type == env->gwion->type[et_auto];
if(is_auto)
- bin->rhs->type = bin->rhs->d.exp_decl.type = bin->lhs->type;
+ bin->rhs->info->type = bin->rhs->d.exp_decl.type = bin->lhs->info->type;
CHECK_OO(check_exp(env, bin->rhs))
- struct Op_Import opi = { .op=bin->op, .lhs=bin->lhs->type,
- .rhs=bin->rhs->type, .data=(uintptr_t)bin, .pos=exp_self(bin)->pos };
+ 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)
bin->rhs->d.exp_decl.list->self->value->type = env->gwion->type[et_auto];
ANN static Type check_exp_cast(const Env env, const Exp_Cast* cast) {
DECL_OO(const Type, t, = check_exp(env, cast->exp))
- CHECK_OO((exp_self(cast)->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
- struct Op_Import opi = { .op=insert_symbol("$"), .lhs=t, .rhs=exp_self(cast)->type, .data=(uintptr_t)cast, .pos=exp_self(cast)->pos };
+ CHECK_OO((exp_self(cast)->info->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
+ struct Op_Import opi = { .op=insert_symbol("$"), .lhs=t, .rhs=exp_self(cast)->info->type,
+ .data=(uintptr_t)cast, .pos=exp_self(cast)->pos, .op_type=op_cast };
return op_check(env, &opi);
}
ANN static Type check_exp_post(const Env env, const Exp_Postfix* post) {
- struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp), .data=(uintptr_t)post, .pos=exp_self(post)->pos };
+ struct Op_Import opi = { .op=post->op, .lhs=check_exp(env, post->exp),
+ .data=(uintptr_t)post, .pos=exp_self(post)->pos, .op_type=op_postfix };
CHECK_OO(opi.lhs)
const Type t = op_check(env, &opi);
if(t && isa(t, env->gwion->type[et_object]) < 0)
- exp_self(post)->meta = ae_meta_value;
+ exp_setmeta(exp_self(post), 1);
return t;
}
ANN static Type check_exp_call(const Env env, Exp_Call* exp) {
if(exp->tmpl) {
CHECK_OO(check_exp(env, exp->func))
- const Type t = actual_type(env->gwion, !GET_FLAG(exp->func->type, nonnull) ?
- exp->func->type : exp->func->type->e->parent);
+ const Type t = actual_type(env->gwion, !GET_FLAG(exp->func->info->type, nonnull) ?
+ exp->func->info->type : exp->func->info->type->e->parent);
const Value v = nspc_lookup_value1(t->e->owner, insert_symbol(t->name));
- if(!GET_FLAG(v, func) && !GET_FLAG(exp->func->type, func) )
+ 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)
ERR_O(exp_self(exp)->pos, _("template call of non-template function."))
ANN static Type check_exp_unary(const Env env, const Exp_Unary* unary) {
struct Op_Import opi = { .op=unary->op, .rhs=unary->exp ? check_exp(env, unary->exp) : NULL,
- .data=(uintptr_t)unary, .pos=exp_self(unary)->pos };
+ .data=(uintptr_t)unary, .pos=exp_self(unary)->pos, .op_type=op_unary };
if(unary->exp && !opi.rhs)
return NULL;
return op_check(env, &opi);
ANN static Type _flow(const Env env, const Exp e, const m_bool b) {
DECL_OO(const Type, type, = check_exp(env, e))
struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
- .rhs=type, .pos=e->pos, .data=(uintptr_t)e };
+ .rhs=type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
return op_check(env, &opi);
}
#define check_flow(emit,b) _flow(emit, b, 1)
ANN Type check_exp(const Env env, const Exp exp) {
Exp curr = exp;
do {
- CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d)))
- if(env->func && isa(curr->type, env->gwion->type[et_lambda]) < 0 && isa(curr->type, env->gwion->type[et_function]) > 0 &&
- !GET_FLAG(curr->type->e->d.func, pure))
+ CHECK_OO((curr->info->type = check_exp_func[curr->exp_type](env, &curr->d)))
+ if(env->func && isa(curr->info->type, env->gwion->type[et_lambda]) < 0 && isa(curr->info->type, env->gwion->type[et_function]) > 0 &&
+ !GET_FLAG(curr->info->type->e->d.func, pure))
UNSET_FLAG(env->func, pure);
} while((curr = curr->next));
- return exp->type;
+ return exp->info->type;
}
ANN m_bool check_enum_def(const Env env, const Enum_Def edef) {
ANN static m_bool check_stmt_varloop(const Env env, const Stmt_VarLoop stmt) {
CHECK_OB(check_exp(env, stmt->exp))
- if(isa(stmt->exp->type, env->gwion->type[et_vararg]) < 0)
+ if(isa(stmt->exp->info->type, env->gwion->type[et_vararg]) < 0)
ERR_B(stmt->exp->pos, "varloop expression type must be '%s', not '%s'",
- env->gwion->type[et_vararg]->name, stmt->exp->type->name)
+ env->gwion->type[et_vararg]->name, stmt->exp->info->type->name)
return check_stmt(env, stmt->body);
}
const m_uint depth = t->array_depth - 1;
if(!ptr || isa(t, env->gwion->type[et_array]) < 0)
ERR_B(stmt_self(stmt)->pos, _("type '%s' is not array.\n"
- " This is not allowed in auto loop"), stmt->exp->type->name)
+ " This is not allowed in auto loop"), stmt->exp->info->type->name)
if(stmt->is_ptr) {
struct ID_List_ id0, id;
struct Type_List_ tl;
Var_Decl_List list = l->self->d.exp_decl.list;
do SET_FLAG(list->self->value, pure);
while((list = list->next));
- if(l->self->type->size > udef->s)
- udef->s = l->self->type->size;
+ if(l->self->info->type->size > udef->s)
+ udef->s = l->self->info->type->size;
} while((l = l->next));
return GW_OK;
}
ANN static Value match_value(const Env env, const Exp_Primary* prim, const m_uint i) {
const Symbol sym = prim->d.var;
const Value v = new_value(env->gwion->mp,
- ((Exp)VKEY(&env->scope->match->map, i))->type, s_name(sym));
+ ((Exp)VKEY(&env->scope->match->map, i))->info->type, s_name(sym));
SET_FLAG(v, checked);
nspc_add_value(env->curr, sym, v);
VVAL(&env->scope->match->map, i) = (vtype)v;
const Exp base = (Exp)VKEY(&env->scope->match->map, i);
CHECK_OB(check_exp(env, e))
Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
- struct Exp_ ebin = { .d={.exp_binary=bin}, .nspc=env->curr};
- struct Op_Import opi = { .op=op, .lhs=base->type, .rhs=e->type, .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos };
+ struct ExpInfo_ info = { .nspc=env->curr };
+ struct Exp_ ebin = { .d={.exp_binary=bin}, .info=&info };
+ struct Op_Import opi = { .op=op, .lhs=base->info->type, .rhs=e->info->type,
+ .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
CHECK_OB(op_check(env, &opi))
- e->nspc= ebin.nspc;
+ e->info->nspc= info.nspc;
return GW_OK;
}
}
SET_FLAG(type, check);
if(cdef->base.ext)
CHECK_BB(cdef_parent(env, cdef))
- assert(type->e->parent);
- inherit(type);
+ assert(type->e->parent || GET_FLAG(cdef, struct));
+ if(!GET_FLAG(cdef, struct))
+ inherit(type);
if(cdef->body)
CHECK_BB(env_body(env, cdef, check_section))
SET_FLAG(type, checked);
mo->ck = opi->func->ck;
mo->em = opi->func->em;
}
- mo->emit_var = opi->emit_var;
return mo;
}
return GW_OK;
}
-ANN static void set_nspc(struct OpChecker* ock, const Nspc nspc) {
- if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@array")) {
- Array_Sub array = (Array_Sub)ock->opi->data;
- array->exp->nspc = nspc;
+ANN static void set_nspc(struct Op_Import *opi, const Nspc nspc) {
+ if(opi->op_type == op_implicit) {
+ struct Implicit* imp = (struct Implicit*)opi->data;
+ imp->e->info->nspc = nspc;
return;
-
}
- if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@implicit")) {
- struct Implicit* imp = (struct Implicit*)ock->opi->data;
- imp->e->nspc = nspc;
+ if(opi->op_type == op_array) {
+ Array_Sub array = (Array_Sub)opi->data;
+ array->exp->info->nspc = nspc;
return;
}
- if(ock->opi->op == insert_symbol(ock->env->gwion->st, "@slice") ||
- ock->opi->op == insert_symbol(ock->env->gwion->st, "@range") ||
- ock->opi->op == insert_symbol(ock->env->gwion->st, "@conditionnal") ||
- ock->opi->op == insert_symbol(ock->env->gwion->st, "@unconditionnal")) {
- ((Exp)ock->opi->data)->nspc = nspc;
+ if(opi->op_type == op_exp) {
+ ((Exp)opi->data)->info->nspc = nspc;
return;
}
-// use .mut
- if(ock->opi->op != insert_symbol(ock->env->gwion->st, "@scan"))
- exp_self((union exp_data*)ock->opi->data)->nspc = nspc;
+ if(opi->op_type != op_scan)
+ exp_self((union exp_data*)opi->data)->info->nspc = nspc;
+}
+
+ANN static void set_nonnull(const Type t, const Exp exp) {
+ if(t != OP_ANY_TYPE && GET_FLAG(t, nonnull))
+ exp_setnonnull(exp, 1);
+}
+
+ANN static void opi_nonnull(const M_Operator *mo, const struct Op_Import *opi) {
+ switch(opi->op_type) {
+ case op_implicit:
+ {
+ const struct Implicit *a = (struct Implicit*)opi->data;
+ set_nonnull(mo->lhs, a->e);
+ break;
+ }
+ case op_exp:
+ {
+ const Exp a = (Exp)opi->data;
+ set_nonnull(mo->rhs, a); // rhs ???
+ break;
+ }
+ case op_dot:
+ {
+ const Exp_Dot *a = (Exp_Dot*)opi->data;
+ set_nonnull(mo->lhs, a->base);
+ break;
+ }
+ case op_array:
+ {
+ const Array_Sub a = (Array_Sub)opi->data;
+ set_nonnull(mo->lhs, a->exp);
+ break;
+ }
+ case op_binary:
+ {
+ const Exp_Binary *a = (Exp_Binary*)opi->data;
+ set_nonnull(mo->lhs, a->lhs);
+ set_nonnull(mo->rhs, a->rhs);
+ break;
+ }
+ case op_cast:
+ {
+ const Exp_Cast *a = (Exp_Cast*)opi->data;
+ set_nonnull(mo->lhs, a->exp);
+ break;
+ }
+ case op_postfix:
+ {
+ const Exp_Postfix *a = (Exp_Postfix*)opi->data;
+ set_nonnull(mo->lhs, a->exp);
+ break;
+ }
+ case op_unary:
+ {
+ const Exp_Unary *a = (Exp_Unary*)opi->data;
+ set_nonnull(mo->rhs, a->exp);
+ break;
+ }
+ case op_scan:
+ break;
+ }
}
ANN static Type op_check_inner(struct OpChecker* ock) {
const M_Operator* mo;
const Vector v = (Vector)map_get(ock->map, (vtype)ock->opi->op);
if(v && (mo = operator_find(v, ock->opi->lhs, r))) {
+ opi_nonnull(mo, ock->opi);
if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data, &ock->mut))))
return t;
else
if(nspc->info->op_map.ptr) {
Type l = opi->lhs;
do {
- struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data };
+ struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data, .op_type=opi->op_type };
struct OpChecker ock = { env, &nspc->info->op_map, &opi2, 0 };
const Type ret = op_check_inner(&ock);
if(ret) {
if(ret == env->gwion->type[et_null])
break;
if(!ock.mut)
- set_nspc(&ock, nspc);
+ set_nspc(&opi2, nspc);
return ret;
}
} while(l && (l = op_parent(env, l)));
return emit_add_instr(emit, mo->instr);
}
-ANN static Nspc get_nspc(SymTable *st, const struct Op_Import* opi) {
- if(opi->op == insert_symbol(st, "@array")) {
- struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)opi->data;
- return info->array.exp->nspc;
- }
- if(opi->op == insert_symbol(st, "@implicit")) {
+ANN static Nspc get_nspc(const struct Op_Import* opi) {
+ if(opi->op_type == op_implicit) {
struct Implicit* imp = (struct Implicit*)opi->data;
- return imp->e->nspc;
+ return imp->e->info->nspc;
}
- if(opi->op == insert_symbol(st, "@range") ||
- opi->op == insert_symbol(st, "@slice") ||
- opi->op == insert_symbol(st, "@conditionnal") ||
- opi->op == insert_symbol(st, "@unconditionnal"))
- return ((Exp)opi->data)->nspc;
- return exp_self((union exp_data*)opi->data)->nspc;
+ if(opi->op_type == op_array) {
+ struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)opi->data;
+ return info->array.exp->info->nspc;
+ }
+ if(opi->op_type == op_exp)
+ return ((Exp)opi->data)->info->nspc;
+ return exp_self((union exp_data*)opi->data)->info->nspc;
}
-ANN static inline Nspc ensure_nspc(SymTable *st, const struct Op_Import* opi) {
- DECL_OO(Nspc, nspc, = get_nspc(st, opi))
+ANN static inline Nspc ensure_nspc(const struct Op_Import* opi) {
+ DECL_OO(Nspc, nspc, = get_nspc(opi))
while(!nspc->info->op_map.ptr)
nspc = nspc->parent;
return nspc;
}
-ANN2(1) void op_emit_nonnull(const Emitter emit, const Type mo, const Type opi, const m_uint offset) {
- if(!mo || mo == OP_ANY_TYPE)
- return;
- if(GET_FLAG(mo, nonnull) && !GET_FLAG(opi, nonnull)) {
- const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
- instr->m_val = offset;
- }
-}
-
ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) {
- DECL_OO(Nspc, nspc, = ensure_nspc(emit->gwion->st, opi))
+ DECL_OO(Nspc, nspc, = ensure_nspc(opi))
Type l = opi->lhs;
do {
Type r = opi->rhs;
do {
const Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
- if(!v)continue;
+ if(!v)
+ continue;
const M_Operator* mo = operator_find(v, l, r);
if(mo) {
- const m_uint sz = opi->rhs ? opi->rhs->size : 0;
- op_emit_nonnull(emit, mo->lhs, opi->lhs, mo->emit_var ?: sz);
- op_emit_nonnull(emit, mo->rhs, opi->rhs, 0);
if(mo->em)
return mo->em(emit, (void*)opi->data);
return handle_instr(emit, mo);
#include "instr.h"
#include "operator.h"
#include "import.h"
+#include "tuple.h"
static inline void add_type(const Env env, const Nspc nspc, const Type t) {
nspc_add_type_front(nspc, insert_symbol(t->name), t);
}
static OP_CHECK(opck_implicit_similar) {
- const Exp_Binary *bin = (Exp_Binary*)data;
- return bin->rhs->type;
+ const struct Implicit *imp = (struct Implicit*)data;
+ return imp->e->info->type;
}
static OP_CHECK(opck_cast_similar) {
const Exp_Cast *cast = (Exp_Cast*)data;
- return exp_self(cast)->type;
+ return exp_self(cast)->info->type;
}
ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) {
ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) {
CHECK_BO(scan0_defined(env, cdef->base.xid, cdef->pos))
- const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), env->gwion->type[et_object]);
+ const Type parent = !GET_FLAG(cdef, struct) ? env->gwion->type[et_object] : NULL;
+ const Type t = scan0_type(env, ++env->scope->type_xid, s_name(cdef->base.xid), parent);
+ 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);
t->e->owner = env->curr;
t->nspc = new_nspc(env->gwion->mp, t->name);
t->nspc->parent = env->curr;
ANN static Type void_type(const Env env, const Type_Decl* td) {
DECL_OO(const Type, type, = known_type(env, td))
const Type t = get_type(type);
- if(isa(t, env->gwion->type[et_object]) > 0)
+ if(isa(t, env->gwion->type[et_object]) > 0 || GET_FLAG(t, struct))
CHECK_BO(type_recursive(env, td, t))
if(type->size)
return type;
if(env->class_def)
type_contains(env->class_def, t);
const Value v = var->value = former ?: new_value(env->gwion->mp, t, s_name(var->xid));
+ if(SAFE_FLAG(env->class_def, struct) && !GET_FLAG(decl->td, static)) {
+ v->from->offset = env->class_def->size;
+ env->class_def->size += t->size;
+ }
nspc_add_value(env->curr, var->xid, v);
v->flag = decl->td->flag;
v->type = t;
((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
CHECK_OB(decl->type)
if(GET_FLAG(decl->type, const))
- exp_self(decl)->meta = ae_meta_value;
+ exp_setmeta(exp_self(decl), 1);
// SET_FLAG(decl->td, const);
const m_bool global = GET_FLAG(decl->td, global);
if(global && decl->type->e->owner != env->global_nspc)
ANN static m_bool scan1_exp_post(const Env env, const Exp_Postfix* post) {
CHECK_BB(scan1_exp(env, post->exp))
- if(post->exp->meta == ae_meta_var)
+ const m_str access = exp_access(post->exp);
+ if(access)
return GW_OK;
ERR_B(post->exp->pos, _("post operator '%s' cannot be used"
- " on non-mutable data-type..."), s_name(post->op));
+ " on %S data-type..."), s_name(post->op), access);
}
ANN static m_bool scan1_exp_call(const Env env, const Exp_Call* exp_call) {
#include "object.h"
#include "instr.h"
#include "import.h"
-#include "tuple.h"
ANN static m_bool scan2_stmt(const Env, const Stmt);
ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
ANN static Type func_type(const Env env, const Func func) {
const Type t = type_copy(env->gwion->mp, env->gwion->type[func->def->base->td ? et_function : et_lambda]);
t->xid = ++env->scope->type_xid;
-// = type_copy(env->gwion->mp, env->gwion->type[func->def->base->td ? et_function : et_lambda]);
t->e->parent = env->gwion->type[func->def->base->td ? et_function : et_lambda];
t->name = func->name;
t->e->owner = env->curr;
if(GET_FLAG(func, member))
t->size += SZ_INT;
t->e->d.func = func;
- if(t->e->tuple)
- free_tupleform(env->gwion->mp, t->e->tuple);
- t->e->tuple = NULL;
+// t->e->tuple = NULL;
return t;
}
ANN2(1,2) static Value func_value(const Env env, const Func f,
if(GET_FLAG(t, ref))
return t;
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) };
+ struct Op_Import opi = { .op=insert_symbol("@scan"), .lhs=t, .data=(uintptr_t)&ts, .pos=td_pos(td), .op_type=op_scan };
return op_check(env, &opi);
} else if(td->types)
return maybe_func(env, t, td);
static const void* dispatch[] = {
&®setimm,
&®pushimm, &®pushfloat, &®pushother, &®pushaddr,
- &®pushmem, &®pushmemfloat, &®pushmemother, &®pushmemaddr,
+ &®pushmem, &®pushmemfloat, &®pushmemother, &®pushmemaddr, &®pushmemderef,
&&pushnow,
&&baseint, &&basefloat, &&baseother, &&baseaddr,
- &®toreg, &®toregaddr,
+ &®toreg, &®toregaddr, &®toregderef,
+ &&structmember, &&structmemberaddr,
&&memsetimm,
&®pushme, &®pushmaybe,
&&funcreturn,
&&sporkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&forkend, &&sporkend,
&&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat,
&&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
- &&newobj, &&addref, &&objassign, &&assign, &&remref,
+ &&newobj, &&addref, &&addrefaddr, &&objassign, &&assign, &&remref,
&&setobj, &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr,
&&staticint, &&staticfloat, &&staticother,
&&dotfunc, &&dotstaticfunc, &&pushstaticcode,
*(m_bit**)reg = &*(m_bit*)(mem + (m_int)VAL);
reg += SZ_INT;
DISPATCH()
+regpushmemderef:
+ memcpy(reg, *(m_uint**)(mem+(m_int)VAL), VAL2);
+ reg += VAL2;
+ DISPATCH()
pushnow:
*(m_float*)reg = vm->bbq->pos;
reg += SZ_FLOAT;
reg += VAL2;
DISPATCH();
baseaddr:
- *(m_bit**)reg = (shred->base + VAL);
+ *(m_uint**)reg = &*(m_uint*)(shred->base + (m_int)VAL);
reg += SZ_INT;
DISPATCH();
regtoreg:
regtoregaddr:
*(m_uint**)(reg + (m_int)VAL) = &*(m_uint*)(reg + (m_int)VAL2);
DISPATCH()
+regtoregderef:
+ memcpy(*(m_bit**)(reg - SZ_INT), *(m_bit**)(reg + (m_int)VAL), VAL2);
+ DISPATCH()
+structmember:
+ *(m_bit**)(reg-SZ_INT) = *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL2);
+ DISPATCH()
+structmemberaddr:
+ *(m_bit**)(reg-SZ_INT) = &*(*(m_bit**)(reg-SZ_INT) + (m_int)VAL2);
+ DISPATCH()
memsetimm:
*(m_uint*)(mem+VAL) = VAL2;
DISPATCH();
reg += VAL;
DISPATCH();
regtomem:
- *(m_uint*)(mem+VAL) = *(m_uint*)(reg+VAL2);
+ *(m_uint*)(mem+VAL) = *(m_uint*)(reg+(m_int)VAL2);
DISPATCH()
regtomemother:
memcpy(mem+VAL, reg, VAL2);
reg += SZ_INT;
DISPATCH()
addref:
- if((a.obj = VAL ? **(M_Object**)(reg-SZ_INT) :
- *(M_Object*)(reg-SZ_INT)))
+ a.obj = *((M_Object*)(reg+(m_int)VAL) + (m_int)VAL2);
+ goto addrefcommon;
+addrefaddr:
+ a.obj = *(*(M_Object**)(reg+(m_int)VAL) + (m_int)VAL2);
+addrefcommon:
+ if(a.obj)
++a.obj->ref;
DISPATCH()
objassign:
}
assign:
reg -= SZ_INT;
- a.obj = *(M_Object*)(reg-SZ_INT);
- **(M_Object**)reg = a.obj;
+// a.obj = *(M_Object*)(reg-SZ_INT);
+// **(M_Object**)reg = a.obj;
+// a.obj =
+ **(M_Object**)reg = *(M_Object*)(reg-SZ_INT);
DISPATCH()
remref:
release(*(M_Object*)(mem + VAL), shred);
-#! [contains] can't cast constant to Ptr
+#! [contains] can't cast non-mutable value to Ptr
fun void test(<~int~>Ptr i) { <<< *i>>>; }
1 => test;
+++ /dev/null
-#include "gwion_util.h"
-#include "gwion_ast.h"
-#include "gwion_env.h"
-#include "vm.h"
-#include "object.h"
-#include "instr.h"
-#include "gwion.h"
-#include "operator.h"
-#include "import.h"
-
-static OP_CHECK(opck_ptrext_assign) {
- const Exp_Binary* bin = (Exp_Binary*)data;
- if(bin->rhs->meta != ae_meta_var)
- ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
- bin->rhs->emit_var = 1;
- Type t = bin->rhs->type;
- do {
- Type u = bin->lhs->type;
- do {
- const m_str str = get_type_name(env, u->name, 1);
- if(str && !strcmp(t->name, str))
- return bin->lhs->type;
- } while((u = u->e->parent));
- } while((t = t->e->parent));
- return env->gwion->type[et_null];
-}
-
-static INSTR(instr_ptrext_assign) {
- POP_REG(shred, SZ_INT)
- const M_Object o = *(M_Object*)REG(-SZ_INT);
- *(m_float**)o->data = *(m_float**)REG(0);
-}
-
-GWION_IMPORT(typedef_test) {
- GWI_OB(gwi_class_ini(gwi, "PtrExt", "Ptr<~float~>"))
- GWI_BB(gwi_class_end(gwi))
- GWI_BB(gwi_oper_ini(gwi, "nonnull PtrExt", "float", NULL))
- GWI_BB(gwi_oper_var(gwi, SZ_INT))
- GWI_BB(gwi_oper_add(gwi, opck_ptrext_assign))
- GWI_BB(gwi_oper_end(gwi, "<=:", instr_ptrext_assign))
- return GW_OK;
-}
+++ /dev/null
-1234.5 => float f;
-PtrExt ref ptr;
-<<< ptr >>>;
-ptr <=: f;
-<<< f >>>;
--- /dev/null
+op_already_imported.gw
#!/bin/bash
-# [test] #75
+# [test] #74
n=0
[ "$1" ] && n="$1"
--- /dev/null
+class C {
+ fun int test(int i) {
+ 13 => int j;
+ return j;
+ }
+}
+C c;
+12 => c.test => int ret;
+
+<<< 1394 >>>;
+<<<ret>>>;
--- /dev/null
+struct S {
+ 13 => int i;
+ operator @gack void() { <<< "test", i >>>; }
+ <<< this >>>;
+}
+S s;
+<<< s >>>;
--- /dev/null
+struct global GlobalStruct {
+ int i;
+ float f;
+ string s;
+}
+
+struct global GlobalStructWithCtor {
+ int i;
+ float f;
+ string s;
+}
+
+global GlobalStruct s;
+GlobalStructWithCtor sctor;
--- /dev/null
+GlobalStruct s;
--- /dev/null
+class C {
+ struct S {
+ string s;
+ float a;
+ 11 => int i;
+ 13 => float f;
+ }
+ S s;
+ <<< "after ctor" >>>;
+}
+C c;
+<<< c.s.i >>>;
+
--- /dev/null
+struct S {
+ 4 => int i;
+ 12 => int j;
+ fun int test() { <<< "test", i >>>; }
+ test();
+}
+S s;
+s.test();
--- /dev/null
+struct S {
+ float f;
+ fun void test() { <<< __func__, f >>>; }
+}
+
+S s;
+12.3 => s.f;
+s.test();
--- /dev/null
+struct S {
+ int i;
+ float f;
+}
+
+fun S test() {
+ S s;
+ 12 => s.i;
+ 12 => s.f;
+ return s;
+}
+
+<<< test().i >>>;
+<<< test().f >>>;
--- /dev/null
+class C {
+ struct S {
+ 12 => int i;
+ "testing::" => string s;
+ 13 => float f;
+ <<< __func__ >>>;
+ }
+ static S s;
+}
+C c;
--- /dev/null
+struct S {
+ int i;
+ int j;
+ 12 => static int si;
+ fun static void test() { <<< __func__, si >>>; }
+ test();
+}
+S s;
+s.test();
--- /dev/null
+struct S {
+ int i;
+}
+S s;
+<<< s.i >>>;
+<<< 12 => s.i >>>;
+<<< s.i >>>;
-Subproject commit 360d8733bbf2a1358ee4b82444711235388d4b81
+Subproject commit ca4eea2ca7862dcf66c3e230d2cd09142b84ebf7