Gwion coverage report


Directory: src/
File: src/lib/object.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 103 104 99.0%
Functions: 13 13 100.0%
Branches: 34 38 89.5%

Line Branch Exec Source
1 #include "gwion_util.h"
2 #include "gwion_ast.h"
3 #include "gwion_env.h"
4 #include "vm.h"
5 #include "gwion.h"
6 #include "instr.h"
7 #include "object.h"
8 #include "operator.h"
9 #include "import.h"
10 #include "emit.h"
11 #include "traverse.h"
12 #include "parse.h"
13 #include "specialid.h"
14
15 #include "gwi.h"
16 #include "gack.h"
17
18 8831 ANN M_Object new_object(MemPool p, const Type t) {
19 8831 const uint32_t offset = sizeof(struct M_Object_) + t->nspc->offset;
20 8831 const M_Object a = _mp_calloc(p, offset);
21 8831 a->ref = 1;
22 8831 a->type_ref = t;
23 8831 return a;
24 }
25
26 361 ANN M_Object new_string(const struct Gwion_ *gwion, const m_str str) {
27 361 const M_Object o = new_object(gwion->mp, gwion->type[et_string]);
28 361 STRING(o) = mstrdup(gwion->mp, str);
29 361 return o;
30 }
31
32 1 ANN static void user_dtor(const M_Object o, const VM_Shred shred, const Type t) {
33 1 const VM_Shred sh = new_vm_shred(shred->info->mp, t->nspc->dtor);
34 1 vmcode_addref(t->nspc->dtor);
35 1 sh->base = shred->base;
36 1 *(M_Object *)sh->mem = o;
37 1 *(Type *)(sh->mem + SZ_INT) = t;
38 1 vm_add_shred(shred->info->vm, sh);
39 1 ++sh->info->me->ref;
40 1 }
41
42 5192 ANN static inline void release_not_union(const m_bit *data, const VM_Shred shred, const Scope s) {
43 5192 const Map m = &s->map;
44
2/2
✓ Branch 1 taken 64034 times.
✓ Branch 2 taken 5192 times.
69226 for(m_uint i = map_size(m) + 1; --i;) {
45 64034 const Value v = (Value) VVAL(m, i-1);
46
2/2
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 64009 times.
64034 if (vflag(v, vflag_release))
47 25 compound_release(shred, v->type, data + v->from->offset);
48 }
49 5192 }
50
51 10375 ANN static void do_release(const M_Object o,
52 const VM_Shred shred, const Type t) {
53
2/2
✓ Branch 0 taken 5180 times.
✓ Branch 1 taken 5195 times.
10375 if(!t->nspc->offset) {
54 5180 free_object(shred->info->mp, o);
55 5180 return;
56 }
57
2/2
✓ Branch 1 taken 5192 times.
✓ Branch 2 taken 3 times.
5195 if (!tflag(t, tflag_union))
58 5192 release_not_union(o->data, shred, t->nspc->info->value);
59
2/2
✓ Branch 1 taken 5109 times.
✓ Branch 2 taken 86 times.
5195 if (tflag(t, tflag_dtor)) {
60
2/2
✓ Branch 0 taken 5108 times.
✓ Branch 1 taken 1 times.
5109 if (t->nspc->dtor->builtin)
61 5108 ((f_xtor)t->nspc->dtor->native_func)(o, NULL, shred);
62 1 else return user_dtor(o, shred, t);
63 }
64 5194 return do_release(o, shred, t->info->parent);
65 }
66
67 29 ANN void struct_release(const VM_Shred shred, const Type base,
68 const m_bit *ptr) {
69 29 const Vector types = &base->info->tuple->types;
70 29 const Vector offsets = &base->info->tuple->offset;
71
2/2
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 29 times.
79 for (m_uint i = 0; i < vector_size(types); ++i) {
72 50 const Type t = (Type)vector_at(types, i);
73
2/2
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 3 times.
50 if (!tflag(t, tflag_compound)) continue;
74 3 const m_uint offset = vector_at(offsets, i);
75 3 compound_release(shred, t, ptr + offset);
76 }
77 29 }
78
79 1 INSTR(DTOR_EOC) {
80 1 const M_Object o = *(M_Object *)MEM(0);
81 1 const Type t = *(Type *)MEM(SZ_INT);
82 1 do_release(o, shred, t->info->parent);
83 1 shred->info->me->ref = 1;
84 1 vm_shred_exit(shred);
85 1 }
86
87 5180 ANN void __release(const M_Object o, const VM_Shred shred) {
88 5180 do_release(o, shred, o->type_ref);
89 5180 }
90
91 5180 ANN void free_object(MemPool p, const M_Object o) {
92 5180 mp_free2(p, sizeof(struct M_Object_) + o->type_ref->nspc->offset, o);
93 5180 }
94
95 162 static ID_CHECK(opck_this) {
96
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 161 times.
162 if (!env->class_def)
97 1 ERR_O(exp_self(prim)->pos,
98 _("keyword 'this' can be used only inside class definition..."))
99
1/2
✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
161 if(env->func) {
100
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 160 times.
161 if (!vflag(env->func->value_ref, vflag_member))
101 1 ERR_O(exp_self(prim)->pos,
102 _("keyword 'this' cannot be used inside static functions..."))
103
2/2
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 110 times.
160 if (!exp_getuse(exp_self(prim)) &&
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 !strcmp(s_name(env->func->def->base->xid), "@gack"))
105 return get_gack(env->class_def->info->parent); // get_gack ?
106 }
107 160 return env->class_def;
108 }
109
110 120 static ID_EMIT(opem_this) {
111
4/4
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 109 times.
230 if (!exp_getvar(exp_self(prim)) &&
112 110 tflag(exp_self(prim)->type, tflag_struct)) {
113 1 const Instr instr = emit_add_instr(emit, RegPushMemDeref);
114 1 instr->m_val2 = emit->env->class_def->size;
115 1 return GW_OK;
116 }
117 119 const Instr instr = emit_add_instr(emit, RegPushMem);
118 119 instr->m_val = emit->status.this_offset;
119 119 return GW_OK;
120 }
121
122 3 static ID_CHECK(opck_super) {
123 3 const Exp self = exp_self(prim);
124
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
3 if(!env->func || is_ctor(env->func->def))
125 1 ERR_O(self->pos, "can't use 'super' outside of constructor");
126 2 const Type parent = env->class_def->info->parent;
127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 DECL_OO(const Value, v, = find_value(parent, insert_symbol("new")));
128 2 SET_FLAG(env->func, const);
129 2 return v->type;
130 }
131
132 2 static ID_EMIT(opem_super) {
133 2 const Env env = emit->env;
134 2 const Exp self = exp_self(prim);
135
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(!self->is_call)
136 1 ERR_B(self->pos, "can only use 'super' as a function call");
137 1 emit_regpushmem(emit, 0, SZ_INT, false);
138 1 emit_pushimm(emit, (m_uint)exp_self(prim)->type);
139 1 return GW_OK;
140 }
141
142 638 GWION_IMPORT(object) {
143 638 const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, "@Compound");
144 638 gwi_set_global_type(gwi, t_object, et_object);
145 638 set_tflag(t_object, tflag_compound);
146 638 t_object->nspc = new_nspc(gwi->gwion->mp, "Object");
147 638 struct SpecialId_ spid_this = {.ck = opck_this, .em = opem_this, .is_const = 1};
148 638 gwi_specialid(gwi, "this", &spid_this);
149 638 struct SpecialId_ spid_super = {.ck = opck_super, .em = opem_super, .is_const = 1};
150 638 gwi_specialid(gwi, "super", &spid_super);
151 638 return GW_OK;
152 }
153