GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/operator.c Lines: 220 223 98.7 %
Date: 2020-09-14 00:22:58 Branches: 161 178 90.4 %

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 "emit.h"
10
#include "operator.h"
11
#include "object.h"
12
#include "array.h"
13
14
typedef Type (*f_type)(const Env env, const Exp exp);
15
16
typedef struct M_Operator_{
17
  Type lhs, rhs, ret;
18
  f_instr instr;
19
  Func func;
20
  opck ck;
21
  opem em;
22
  m_uint emit_var;
23
} M_Operator;
24
25
747
ANN void free_op_map(Map map, struct Gwion_ *gwion) {
26
  LOOP_OPTIM
27
37759
  for(m_uint i = map_size(map) + 1; --i;) {
28
36265
    const restrict Vector v = (Vector)map_at(map, (vtype)i - 1);
29
    LOOP_OPTIM
30
203970
    for(m_uint j = vector_size(v) + 1; --j;)
31
131440
      mp_free(gwion->mp, M_Operator, (M_Operator*)vector_at(v, j - 1));
32
36265
    free_vector(gwion->mp, v);
33
  }
34
747
  map_release(map);
35
747
}
36
37
2003
ANN static Type op_parent(const Env env, const Type t) {
38

2003
  if(GET_FLAG(t, template) && GET_FLAG(t, ref)) {
39
50
    const Type type = typedef_base(t);
40
50
    const m_str post = strrchr(type->name, '>') + 1;
41
50
    return nspc_lookup_type1(env->curr, insert_symbol(env->gwion->st, post));
42
  }
43
1953
  return t->e->parent;
44
}
45
46
26751
static m_bool op_match(const restrict Type t, const restrict Type mo) {
47

26751
  if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
48
3897
    return GW_OK;
49
22854
  Type type = t;
50


22854
  while(SAFE_FLAG(type, template) && type->e->def && type->e->def->base.tmpl && type->e->def->base.tmpl->call) type = type->e->parent;
51


22854
  if((type && mo && mo->xid == type->xid) || (!type && !mo))
52
5689
    return GW_OK;
53
17165
  return 0;
54
}
55
56
4700
ANN2(1) static M_Operator* operator_find(const Vector v, const restrict Type lhs, const restrict Type rhs) {
57
26572
  for(m_uint i = vector_size(v) + 1; --i;) {
58
20446
    M_Operator* mo = (M_Operator*)vector_at(v, i - 1);
59
20446
    if(!mo)
60
7
      continue;
61

20439
    if(op_match(lhs, mo->lhs) && op_match(rhs, mo->rhs))
62
3274
      return mo;
63
  }
64
1426
  return NULL;
65
}
66
67
408643
static m_bool op_match2(const restrict Type t, const restrict Type mo) {
68
//  if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
69
//    return GW_OK;
70



408643
  if((t && mo && (t != OP_ANY_TYPE && mo != OP_ANY_TYPE && mo->xid == t->xid)) || (!t && !mo))
71
64199
    return GW_OK;
72
344444
  return 0;
73
}
74
75
95397
ANN2(1) static M_Operator* operator_find2(const Vector v, const restrict Type lhs, const restrict Type rhs) {
76
535227
  for(m_uint i = vector_size(v) + 1; --i;) {
77
344434
    M_Operator* mo = (M_Operator*)vector_at(v, i - 1);
78

344434
    if(op_match2(lhs, mo->lhs) && op_match2(rhs, mo->rhs))
79
1
      return mo;
80
  }
81
95396
  return NULL;
82
}
83
84
24
ANN void operator_suspend(const Nspc n, struct Op_Import *opi) {
85
24
  const Vector v = (Vector)map_get(&n->info->op_map, (vtype)opi->op);
86
59
  for(m_uint i = vector_size(v) + 1; --i;) {
87
35
    M_Operator* mo = (M_Operator*)vector_at(v, i - 1);
88

35
    if(op_match2(opi->lhs, mo->lhs) && op_match2(opi->rhs, mo->rhs)) {
89
24
      opi->data = (uintptr_t)mo;
90
24
      opi->ret = (Type)&VPTR(v, i-1);
91
24
      VPTR(v, i-1) = 0;
92
24
      break;
93
    }
94
  }
95
24
}
96
97
131625
ANN static M_Operator* new_mo(MemPool p, const struct Op_Import* opi) {
98
131625
  M_Operator* mo = mp_calloc(p, M_Operator);
99
131625
  mo->lhs       = opi->lhs;
100
131625
  mo->rhs       = opi->rhs;
101
131625
  mo->ret       = opi->ret;
102
131625
  mo->instr     = (f_instr)opi->data;
103
131625
  if(opi->func) {
104
131625
    mo->ck     = opi->func->ck;
105
131625
    mo->em     = opi->func->em;
106
  }
107
131625
  return mo;
108
}
109
110
struct OpChecker {
111
  const Env env;
112
  const Map map;
113
  const struct Op_Import* opi;
114
  m_bool mut;
115
};
116
117
__attribute__((returns_nonnull))
118
131625
ANN static Vector op_vector(MemPool p, const struct OpChecker *ock) {
119
131625
  const Vector exist = (Vector)map_get(ock->map, (vtype)ock->opi->op);
120
131625
  if(exist)
121
95309
    return exist;
122
36316
  const Vector create = new_vector(p);
123
36316
  map_set(ock->map, (vtype)ock->opi->op, (vtype)create);
124
36316
  return create;
125
}
126
127
158
static m_str type_name(const Type t) {
128

158
  return t ? t == OP_ANY_TYPE ? "any" : t->name : "";
129
}
130
131
130974
ANN static m_bool _op_exist(const struct OpChecker* ock, const Nspc n) {
132
130974
  const Vector v = (Vector)map_get(&n->info->op_map, (vtype)ock->opi->op);
133

130974
  if(!v || !operator_find2(v, ock->opi->lhs, ock->opi->rhs))
134
130973
    return GW_OK;
135
3
  env_err(ock->env, ock->opi->pos, _("operator '%s', for type '%s' and '%s' already imported"),
136
3
        s_name(ock->opi->op), type_name(ock->opi->lhs), type_name(ock->opi->rhs));
137
1
  return GW_ERROR;
138
}
139
140
131898
ANN static m_bool op_exist(const struct OpChecker* ock, const Nspc n) {
141
131898
  return n->info->op_map.ptr ? _op_exist(ock, n) : GW_OK;
142
}
143
144
131626
ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) {
145
131626
  Nspc n = gwion->env->curr;
146
  do {
147
131898
    struct OpChecker ock = { gwion->env, &n->info->op_map, opi, 0 };
148
131898
    CHECK_BB(op_exist(&ock, n))
149
131897
  } while((n = n->parent));
150
131625
  if(!gwion->env->curr->info->op_map.ptr)
151
748
    map_init(&gwion->env->curr->info->op_map);
152
131625
  struct OpChecker ock = { gwion->env, &gwion->env->curr->info->op_map, opi, 0 };
153
131625
  const Vector v = op_vector(gwion->mp, &ock);
154
131625
  const M_Operator* mo = new_mo(gwion->mp, opi);
155
131625
  vector_add(v, (vtype)mo);
156
131625
  return GW_OK;
157
}
158
159
1682
ANN static void set_nspc(struct Op_Import *opi, const Nspc nspc) {
160
1682
  if(opi->op_type == op_implicit) {
161
44
    struct Implicit* imp = (struct Implicit*)opi->data;
162
44
    imp->e->info->nspc = nspc;
163
44
    return;
164
  }
165
1638
  if(opi->op_type == op_array) {
166
28
    Array_Sub array = (Array_Sub)opi->data;
167
28
    array->exp->info->nspc = nspc;
168
28
    return;
169
  }
170
1610
  if(opi->op_type == op_exp) {
171
98
    ((Exp)opi->data)->info->nspc = nspc;
172
98
    return;
173
  }
174
1512
  if(opi->op_type != op_scan)
175
1458
    exp_self((union exp_data*)opi->data)->info->nspc = nspc;
176
}
177
178
2437
ANN static inline void set_nonnull(const Type t, const Exp exp) {
179

2437
  if(t != OP_ANY_TYPE && GET_FLAG(t, nonnull))
180
101
    exp_setnonnull(exp, 1);
181
2437
}
182
183
1846
ANN static void opi_nonnull(const M_Operator *mo, const struct Op_Import *opi) {
184


1846
  switch(opi->op_type) {
185
56
    case op_implicit:
186
    {
187
56
      const struct Implicit *a = (struct Implicit*)opi->data;
188
56
      set_nonnull(mo->lhs, a->e);
189
56
      break;
190
    }
191
98
    case op_exp:
192
    {
193
98
      const Exp a = (Exp)opi->data;
194
98
      set_nonnull(mo->rhs, a); // rhs ???
195
98
      break;
196
    }
197
742
    case op_dot:
198
    {
199
742
      const Exp_Dot *a = (Exp_Dot*)opi->data;
200
742
      set_nonnull(mo->lhs, a->base);
201
742
      break;
202
    }
203
33
    case op_array:
204
    {
205
33
      const Array_Sub a = (Array_Sub)opi->data;
206
33
      set_nonnull(mo->lhs, a->exp);
207
33
      break;
208
    }
209
649
    case op_binary:
210
    {
211
649
      const Exp_Binary *a = (Exp_Binary*)opi->data;
212
649
      set_nonnull(mo->lhs, a->lhs);
213
649
      set_nonnull(mo->rhs, a->rhs);
214
649
      break;
215
    }
216
40
    case op_cast:
217
    {
218
40
      const Exp_Cast *a = (Exp_Cast*)opi->data;
219
40
      set_nonnull(mo->lhs, a->exp);
220
40
      break;
221
    }
222
36
    case op_postfix:
223
    {
224
36
      const Exp_Postfix *a = (Exp_Postfix*)opi->data;
225
36
      set_nonnull(mo->lhs, a->exp);
226
36
      break;
227
    }
228
134
    case op_unary:
229
    {
230
134
      const Exp_Unary *a = (Exp_Unary*)opi->data;
231
134
      set_nonnull(mo->rhs, a->exp);
232
134
      break;
233
    }
234
58
    case op_scan:
235
58
      break;
236
  }
237
1846
}
238
239
2371
ANN static Type op_check_inner(struct OpChecker* ock) {
240
2371
  Type t, r = ock->opi->rhs;
241
  do {
242
    const M_Operator* mo;
243
2989
    const Vector v = (Vector)map_get(ock->map, (vtype)ock->opi->op);
244

2989
    if(v && (mo = operator_find(v, ock->opi->lhs, r))) {
245
1846
      opi_nonnull(mo, ock->opi);
246

1846
      if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data, &ock->mut))))
247
1496
        return t;
248
      else
249
350
        return mo->ret;
250
    }
251

1143
  } while(r && (r = op_parent(ock->env, r)));
252
525
  return NULL;
253
}
254
255
1845
ANN Type op_check(const Env env, struct Op_Import* opi) {
256
1845
  Nspc nspc = env->curr;
257
  do {
258
7728
    if(nspc->info->op_map.ptr) {
259
1944
      Type l = opi->lhs;
260
      do {
261
2371
        struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data, .op_type=opi->op_type };
262
2371
        struct OpChecker ock = { env, &nspc->info->op_map, &opi2, 0 };
263
2371
        const Type ret = op_check_inner(&ock);
264
2371
        if(ret) {
265
1800
          if(ret == env->gwion->type[et_null])
266
50
            break;
267
1750
          if(!ock.mut)
268
1682
            set_nspc(&opi2, nspc);
269
1750
          return ret;
270
        }
271

571
      } while(l && (l = op_parent(env, l)));
272
    }
273
5978
  } while((nspc = nspc->parent));
274

95
  if(opi->op == insert_symbol(env->gwion->st, "$") && opi->rhs == opi->lhs)
275
    return opi->rhs;
276
95
  if(opi->op != insert_symbol(env->gwion->st, "@implicit"))
277
78
    env_err(env, opi->pos, _("%s %s %s: no match found for operator"),
278
    type_name(opi->lhs), s_name(opi->op), type_name(opi->rhs));
279
95
  return NULL;
280
}
281
282
24
ANN m_bool operator_set_func(const struct Op_Import* opi) {
283
24
  const Nspc nspc = ((Func)opi->data)->value_ref->from->owner;
284
24
  const Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
285
24
  DECL_OB(M_Operator*, mo, = operator_find(v, opi->lhs, opi->rhs))
286
24
  mo->func = (Func)opi->data;
287
24
  return GW_OK;
288
}
289
290
619
ANN static Instr handle_instr(const Emitter emit, const M_Operator* mo) {
291
619
  if(mo->func) {
292
14
    const Instr push = emit_add_instr(emit, mo->func->code ? RegPushImm : SetFunc);
293
14
    push->m_val = ((m_uint)mo->func->code ?:(m_uint)mo->func);
294
14
    const Instr instr = emit_exp_call1(emit, mo->func);
295
14
    if(mo->func->def->base->xid == insert_symbol(emit->gwion->st, "@conditionnal"))
296
1
      return emit_add_instr(emit, BranchEqInt);
297
13
    if(mo->func->def->base->xid == insert_symbol(emit->gwion->st, "@unconditionnal"))
298
1
      return emit_add_instr(emit, BranchNeqInt);
299
12
    return instr;
300
  }
301
605
  return emit_add_instr(emit, mo->instr);
302
}
303
304
1404
ANN static Nspc get_nspc(const struct Op_Import* opi) {
305
1404
  if(opi->op_type == op_implicit) {
306
39
    struct Implicit* imp = (struct Implicit*)opi->data;
307
39
    return imp->e->info->nspc;
308
  }
309
1365
  if(opi->op_type == op_array) {
310
25
    struct ArrayAccessInfo *info = (struct ArrayAccessInfo*)opi->data;
311
25
    return info->array.exp->info->nspc;
312
  }
313
1340
  if(opi->op_type == op_exp)
314
94
    return ((Exp)opi->data)->info->nspc;
315
1246
  return exp_self((union exp_data*)opi->data)->info->nspc;
316
}
317
318
1404
ANN static inline Nspc ensure_nspc(const struct Op_Import* opi) {
319
1404
  DECL_OO(Nspc, nspc, = get_nspc(opi))
320
2823
  while(!nspc->info->op_map.ptr)
321
15
    nspc = nspc->parent;
322
1404
  return nspc;
323
}
324
325
1404
ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) {
326
1404
  DECL_OO(Nspc, nspc, = ensure_nspc(opi))
327
1404
  Type l = opi->lhs;
328
  do {
329
1527
    Type r = opi->rhs;
330
    do {
331
1872
      const Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
332
1872
      if(!v)
333
        continue;
334
1872
      const M_Operator* mo = operator_find(v, l, r);
335
1872
      if(mo) {
336
1404
        if(mo->em)
337
785
          return mo->em(emit, (void*)opi->data);
338
619
        return handle_instr(emit, mo);
339
      }
340

468
    } while(r && (r = op_parent(emit->env, r)));
341

123
  } while(l && (l = op_parent(emit->env, l)));
342
  return NULL;
343
}