GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/lib/ptr.c Lines: 122 128 95.3 %
Date: 2020-10-03 09:50:08 Branches: 39 52 75.0 %

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#include "gwion_util.h"
4
#include "gwion_ast.h"
5
#include "gwion_env.h"
6
#include "vm.h"
7
#include "gwion.h"
8
#include "instr.h"
9
#include "object.h"
10
#include "operator.h"
11
#include "import.h"
12
#include "emit.h"
13
#include "traverse.h"
14
#include "parse.h"
15
#include "gwi.h"
16
17
8
static m_bool ptr_access(const Env env, const Exp e) {
18
8
  const m_str access = exp_access(e);
19
8
  if(!access)
20
6
    return GW_OK;
21
2
  ERR_B(e->pos, _("operand is %s"), access);
22
}
23
24
5
static OP_CHECK(opck_ptr_assign) {
25
5
  const Exp_Binary* bin = (Exp_Binary*)data;
26
5
  CHECK_BO(ptr_access(env, bin->lhs))
27
3
  CHECK_BO(ptr_access(env, bin->rhs))
28
3
  exp_setvar(bin->lhs, 1);
29
3
  Type t = bin->lhs->info->type;
30
  do {
31
//    t = unflag_type(t);
32
7
    Type u = bin->rhs->info->type;
33
    do {
34
//      u = unflag_type(u);
35
22
      const m_str str = get_type_name(env, u, 1);
36

22
      if(str && !strcmp(t->name, str))
37
2
        return bin->lhs->info->type; // use rhs?
38
20
    } while((u = u->e->parent));
39
5
  } while((t = t->e->parent));
40
1
  return env->gwion->type[et_null];
41
}
42
43
2
static INSTR(instr_ptr_assign) {
44
2
  POP_REG(shred, SZ_INT)
45
2
  const M_Object o = *(M_Object*)REG(0);
46
2
  *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT);
47
2
  _release(o, shred);
48
2
}
49
50
6
static OP_CHECK(opck_ptr_deref) {
51
6
  const Exp_Unary* unary = (Exp_Unary*)data;
52
6
  DECL_ON(const m_str, str, = get_type_name(env, unary->exp->info->type, 1))
53
6
  return exp_self(unary)->info->type = nspc_lookup_type1(env->curr, insert_symbol(str));
54
}
55
56
2
static OP_CHECK(opck_ptr_cast) {
57
2
  const Exp_Cast* cast = (Exp_Cast*)data;
58

2
  if(!cast->td->types || !cast->td->types->td)
59
    ERR_N(exp_self(cast)->pos, "'Ptr' needs types to cast")
60
2
  DECL_ON(const Type, t, = known_type(env, cast->td))
61
2
  const Type _t = get_type(t);
62

2
  if(_t->e->def && !GET_FLAG(_t, check))
63
2
    CHECK_BN(ensure_traverse(env, _t))
64
2
  const Type to = known_type(env, cast->td->types->td);
65
2
  if(isa(cast->exp->info->type, to) > 0)
66
1
    return t;
67
1
  ERR_N(exp_self(cast)->pos, "invalid pointer cast")
68
}
69
70
3
static OP_CHECK(opck_ptr_implicit) {
71
3
  const struct Implicit* imp = (struct Implicit*)data;
72
3
  const Exp e = imp->e;
73
3
  DECL_OO(const m_str, name, = get_type_name(env, imp->t, 1))
74
3
  if(!strcmp(get_type_name(env, imp->t, 1), e->info->type->name)) {
75
3
    const m_str access = exp_access(e);
76
3
    if(access)
77
2
      ERR_N(e->pos, _("can't cast %s value to Ptr"), access);
78
1
    e->info->cast_to = imp->t;
79
1
    exp_setvar(e, 1);
80
1
    const Type t = get_type(imp->t);
81
1
    if(!GET_FLAG(t, check))
82
1
      CHECK_BN(traverse_class_def(env, t->e->def))
83
1
    return imp->t;
84
  }
85
  return NULL;
86
}
87
88
8
static INSTR(instr_ptr_deref) {
89
8
  const M_Object o = *(M_Object*)REG(-SZ_INT);
90
8
  if(!*(m_bit**)o->data)
91
1
    Except(shred, _("EmptyPointerException"));
92
7
  if(instr->m_val2)
93
1
    memcpy(REG(-SZ_INT), o->data, SZ_INT);
94
  else {
95
6
    shred->reg -= SZ_INT - instr->m_val;
96
6
    memcpy(REG(-instr->m_val), *(m_bit**)o->data, instr->m_val);
97
  }
98
}
99
100
2
static INSTR(Cast2Ptr) {
101
2
  const M_Object o = new_object(shred->info->mp, shred, (Type)instr->m_val);
102
2
  *(m_uint**)o->data = *(m_uint**)REG(-SZ_INT);
103
2
  *(M_Object*)REG(-SZ_INT) = o;
104
2
}
105
106
1
static OP_EMIT(opem_ptr_cast) {
107
1
  const Exp_Cast* cast = (Exp_Cast*)data;
108
1
  const Instr instr = emit_add_instr(emit, Cast2Ptr);
109
1
  instr->m_val = (m_uint)exp_self(cast)->info->type;
110
1
  return instr;
111
}
112
113
1
static OP_EMIT(opem_ptr_implicit) {
114
1
  const struct Implicit* imp = (struct Implicit*)data;
115
1
  const Instr instr = emit_add_instr(emit, Cast2Ptr);
116
1
  instr->m_val = (m_uint)imp->t;
117
1
  return instr;
118
}
119
120
5
static OP_EMIT(opem_ptr_deref) {
121
5
  const Exp_Unary* unary = (Exp_Unary*)data;
122
5
  const Instr instr = emit_add_instr(emit, instr_ptr_deref);
123
5
  instr->m_val = exp_self(unary)->info->type->size;
124
5
  instr->m_val2 = exp_getvar(exp_self(unary));
125
5
  return instr;
126
}
127
128
ANN Type scan_class(const Env env, const Type t, const Type_Decl* td);
129
130
1
static DTOR(ptr_object_dtor) {
131
1
  release(*(M_Object*)o->data, shred);
132
1
}
133
134
static DTOR(ptr_struct_dtor) {
135
  const Type t = (Type)vector_front(&o->type_ref->e->tuple->types);
136
  struct_release(shred, t, *(m_bit**)o->data);
137
}
138
139
18
static OP_CHECK(opck_ptr_scan) {
140
18
  struct TemplateScan *ts = (struct TemplateScan*)data;
141
18
  DECL_ON(const Type, t, = (Type)scan_class(env, ts->t, ts->td))
142
17
  const Type base = known_type(env, t->e->def->base.tmpl->call->td);
143

17
  if(isa(base, env->gwion->type[et_compound]) > 0 && !t->nspc->dtor) {
144
4
    t->nspc->dtor = new_vm_code(env->gwion->mp, NULL, SZ_INT, ae_flag_member | ae_flag_builtin, "@PtrDtor");
145
4
    if(!GET_FLAG(t, struct))
146
4
      t->nspc->dtor->native_func = (m_uint)ptr_object_dtor;
147
    else
148
      t->nspc->dtor->native_func = (m_uint)ptr_struct_dtor;
149
4
    SET_FLAG(t, dtor);
150
  }
151
17
  return t;
152
}
153
154
713
GWION_IMPORT(ptr) {
155
713
  const Type _t_ptr = gwi_class_ini(gwi, "@Ptr", NULL);
156
713
  GWI_BB(gwi_class_end(gwi))
157
713
  SET_FLAG(_t_ptr, unary);
158
713
  GWI_BB(gwi_oper_ini(gwi, "@Ptr", NULL, NULL))
159
713
  GWI_BB(gwi_oper_add(gwi, opck_ptr_scan))
160
713
  GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
161
713
  const Type t_ptr = gwi_class_ini(gwi, "Ptr:[A]", "@Ptr");
162
713
  gwi->gwion->type[et_ptr] = t_ptr;
163
713
  GWI_BB(gwi_item_ini(gwi, "@internal", "@val"))
164
713
  GWI_BB(gwi_item_end(gwi, 0, NULL))
165
713
  GWI_BB(gwi_class_end(gwi))
166
713
  SET_FLAG(t_ptr, unary);
167
713
  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "nonnull Ptr", NULL))
168
713
  GWI_BB(gwi_oper_add(gwi, opck_ptr_assign))
169
713
  GWI_BB(gwi_oper_end(gwi, ":=>", instr_ptr_assign))
170
713
  GWI_BB(gwi_oper_add(gwi, opck_ptr_implicit))
171
713
  GWI_BB(gwi_oper_emi(gwi, opem_ptr_implicit))
172
713
  GWI_BB(gwi_oper_end(gwi, "@implicit", Cast2Ptr))
173
713
  GWI_BB(gwi_oper_add(gwi, opck_ptr_cast))
174
713
  GWI_BB(gwi_oper_emi(gwi, opem_ptr_cast))
175
713
  GWI_BB(gwi_oper_end(gwi, "$", Cast2Ptr))
176
713
  GWI_BB(gwi_oper_ini(gwi, NULL, "nonnull Ptr", NULL))
177
713
  GWI_BB(gwi_oper_add(gwi, opck_ptr_deref))
178
713
  GWI_BB(gwi_oper_emi(gwi, opem_ptr_deref))
179
713
  GWI_BB(gwi_oper_end(gwi, "*", instr_ptr_deref))
180
713
  return GW_OK;
181
}