GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/operator.c Lines: 221 223 99.1 %
Date: 2020-08-07 19:15:19 Branches: 163 178 91.6 %

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
765
ANN void free_op_map(Map map, struct Gwion_ *gwion) {
26
  LOOP_OPTIM
27
38763
  for(m_uint i = map_size(map) + 1; --i;) {
28
37233
    const restrict Vector v = (Vector)map_at(map, (vtype)i - 1);
29
    LOOP_OPTIM
30
207958
    for(m_uint j = vector_size(v) + 1; --j;)
31
133492
      mp_free(gwion->mp, M_Operator, (M_Operator*)vector_at(v, j - 1));
32
37233
    free_vector(gwion->mp, v);
33
  }
34
765
  map_release(map);
35
765
}
36
37
1949
ANN static Type op_parent(const Env env, const Type t) {
38

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

25644
  if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
48
3763
    return GW_OK;
49
21881
  Type type = t;
50


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


21881
  if((type && mo && mo->xid == type->xid) || (!type && !mo))
52
5718
    return GW_OK;
53
16163
  return 0;
54
}
55
56
4626
ANN2(1) static M_Operator* operator_find(const Vector v, const restrict Type lhs, const restrict Type rhs) {
57
25417
  for(m_uint i = vector_size(v) + 1; --i;) {
58
19409
    M_Operator* mo = (M_Operator*)vector_at(v, i - 1);
59
19409
    if(!mo)
60
2
      continue;
61

19407
    if(op_match(lhs, mo->lhs) && op_match(rhs, mo->rhs))
62
3244
      return mo;
63
  }
64
1382
  return NULL;
65
}
66
67
404056
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



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

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

20
    if(op_match2(opi->lhs, mo->lhs) && op_match2(opi->rhs, mo->rhs)) {
89
19
      opi->data = (uintptr_t)mo;
90
19
      opi->ret = (Type)&VPTR(v, i-1);
91
19
      VPTR(v, i-1) = 0;
92
19
      break;
93
    }
94
  }
95
19
}
96
97
133675
ANN static M_Operator* new_mo(MemPool p, const struct Op_Import* opi) {
98
133675
  M_Operator* mo = mp_calloc(p, M_Operator);
99
133675
  mo->lhs       = opi->lhs;
100
133675
  mo->rhs       = opi->rhs;
101
133675
  mo->ret       = opi->ret;
102
133675
  mo->instr     = (f_instr)opi->data;
103
133675
  if(opi->func) {
104
133675
    mo->ck     = opi->func->ck;
105
133675
    mo->em     = opi->func->em;
106
  }
107
133675
  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
133675
ANN static Vector op_vector(MemPool p, const struct OpChecker *ock) {
119
133675
  const Vector exist = (Vector)map_get(ock->map, (vtype)ock->opi->op);
120
133675
  if(exist)
121
96391
    return exist;
122
37284
  const Vector create = new_vector(p);
123
37284
  map_set(ock->map, (vtype)ock->opi->op, (vtype)create);
124
37284
  return create;
125
}
126
127
154
static m_str type_name(const Type t) {
128

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

133001
  if(!v || !operator_find2(v, ock->opi->lhs, ock->opi->rhs))
134
133000
    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
133933
ANN static m_bool op_exist(const struct OpChecker* ock, const Nspc n) {
141
133933
  return n->info->op_map.ptr ? _op_exist(ock, n) : GW_OK;
142
}
143
144
133676
ANN m_bool add_op(const Gwion gwion, const struct Op_Import* opi) {
145
133676
  Nspc n = gwion->env->curr;
146
  do {
147
133933
    struct OpChecker ock = { gwion->env, &n->info->op_map, opi, 0 };
148
133933
    CHECK_BB(op_exist(&ock, n))
149
133932
  } while((n = n->parent));
150
133675
  if(!gwion->env->curr->info->op_map.ptr)
151
766
    map_init(&gwion->env->curr->info->op_map);
152
133675
  struct OpChecker ock = { gwion->env, &gwion->env->curr->info->op_map, opi, 0 };
153
133675
  const Vector v = op_vector(gwion->mp, &ock);
154
133675
  const M_Operator* mo = new_mo(gwion->mp, opi);
155
133675
  vector_add(v, (vtype)mo);
156
133675
  return GW_OK;
157
}
158
159
1657
ANN static void set_nspc(struct Op_Import *opi, const Nspc nspc) {
160
1657
  if(opi->op_type == op_implicit) {
161
39
    struct Implicit* imp = (struct Implicit*)opi->data;
162
39
    imp->e->info->nspc = nspc;
163
39
    return;
164
  }
165
1618
  if(opi->op_type == op_array) {
166
26
    Array_Sub array = (Array_Sub)opi->data;
167
26
    array->exp->info->nspc = nspc;
168
26
    return;
169
  }
170
1592
  if(opi->op_type == op_exp) {
171
93
    ((Exp)opi->data)->info->nspc = nspc;
172
93
    return;
173
  }
174
1499
  if(opi->op_type != op_scan)
175
1432
    exp_self((union exp_data*)opi->data)->info->nspc = nspc;
176
}
177
178
2433
ANN static inline void set_nonnull(const Type t, const Exp exp) {
179

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


1835
  switch(opi->op_type) {
185
49
    case op_implicit:
186
    {
187
49
      const struct Implicit *a = (struct Implicit*)opi->data;
188
49
      set_nonnull(mo->lhs, a->e);
189
49
      break;
190
    }
191
93
    case op_exp:
192
    {
193
93
      const Exp a = (Exp)opi->data;
194
93
      set_nonnull(mo->rhs, a); // rhs ???
195
93
      break;
196
    }
197
717
    case op_dot:
198
    {
199
717
      const Exp_Dot *a = (Exp_Dot*)opi->data;
200
717
      set_nonnull(mo->lhs, a->base);
201
717
      break;
202
    }
203
29
    case op_array:
204
    {
205
29
      const Array_Sub a = (Array_Sub)opi->data;
206
29
      set_nonnull(mo->lhs, a->exp);
207
29
      break;
208
    }
209
668
    case op_binary:
210
    {
211
668
      const Exp_Binary *a = (Exp_Binary*)opi->data;
212
668
      set_nonnull(mo->lhs, a->lhs);
213
668
      set_nonnull(mo->rhs, a->rhs);
214
668
      break;
215
    }
216
35
    case op_cast:
217
    {
218
35
      const Exp_Cast *a = (Exp_Cast*)opi->data;
219
35
      set_nonnull(mo->lhs, a->exp);
220
35
      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
138
    case op_unary:
229
    {
230
138
      const Exp_Unary *a = (Exp_Unary*)opi->data;
231
138
      set_nonnull(mo->rhs, a->exp);
232
138
      break;
233
    }
234
70
    case op_scan:
235
70
      break;
236
  }
237
1835
}
238
239
2344
ANN static Type op_check_inner(struct OpChecker* ock) {
240
2344
  Type t, r = ock->opi->rhs;
241
  do {
242
    const M_Operator* mo;
243
2945
    const Vector v = (Vector)map_get(ock->map, (vtype)ock->opi->op);
244

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

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

1110
  } while(r && (r = op_parent(ock->env, r)));
252
509
  return NULL;
253
}
254
255
1820
ANN Type op_check(const Env env, struct Op_Import* opi) {
256
1820
  Nspc nspc = env->curr;
257
  do {
258
7604
    if(nspc->info->op_map.ptr) {
259
1906
      Type l = opi->lhs;
260
      do {
261
2344
        struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data, .op_type=opi->op_type };
262
2344
        struct OpChecker ock = { env, &nspc->info->op_map, &opi2, 0 };
263
2344
        const Type ret = op_check_inner(&ock);
264
2344
        if(ret) {
265
1772
          if(ret == env->gwion->type[et_null])
266
45
            break;
267
1727
          if(!ock.mut)
268
1657
            set_nspc(&opi2, nspc);
269
1727
          return ret;
270
        }
271

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

93
  if(opi->op == insert_symbol(env->gwion->st, "$") && opi->rhs == opi->lhs)
275
2
    return opi->rhs;
276
91
  if(opi->op != insert_symbol(env->gwion->st, "@implicit"))
277
76
    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
91
  return NULL;
280
}
281
282
19
ANN m_bool operator_set_func(const struct Op_Import* opi) {
283
19
  const Nspc nspc = ((Func)opi->data)->value_ref->from->owner;
284
19
  const Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
285
19
  DECL_OB(M_Operator*, mo, = operator_find(v, opi->lhs, opi->rhs))
286
19
  mo->func = (Func)opi->data;
287
19
  return GW_OK;
288
}
289
290
650
ANN static Instr handle_instr(const Emitter emit, const M_Operator* mo) {
291
650
  if(mo->func) {
292
9
    const Instr push = emit_add_instr(emit, mo->func->code ? RegPushImm : SetFunc);
293
9
    push->m_val = ((m_uint)mo->func->code ?:(m_uint)mo->func);
294
9
    const Instr instr = emit_exp_call1(emit, mo->func);
295
9
    if(mo->func->def->base->xid == insert_symbol(emit->gwion->st, "@conditionnal"))
296
1
      return emit_add_instr(emit, BranchEqInt);
297
8
    if(mo->func->def->base->xid == insert_symbol(emit->gwion->st, "@unconditionnal"))
298
1
      return emit_add_instr(emit, BranchNeqInt);
299
7
    return instr;
300
  }
301
641
  return emit_add_instr(emit, mo->instr);
302
}
303
304
1391
ANN static Nspc get_nspc(const struct Op_Import* opi) {
305
1391
  if(opi->op_type == op_implicit) {
306
34
    struct Implicit* imp = (struct Implicit*)opi->data;
307
34
    return imp->e->info->nspc;
308
  }
309
1357
  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
1332
  if(opi->op_type == op_exp)
314
90
    return ((Exp)opi->data)->info->nspc;
315
1242
  return exp_self((union exp_data*)opi->data)->info->nspc;
316
}
317
318
1391
ANN static inline Nspc ensure_nspc(const struct Op_Import* opi) {
319
1391
  DECL_OO(Nspc, nspc, = get_nspc(opi))
320
2795
  while(!nspc->info->op_map.ptr)
321
15
    nspc = nspc->parent;
322
1390
  return nspc;
323
}
324
325
1391
ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) {
326
1391
  DECL_OO(Nspc, nspc, = ensure_nspc(opi))
327
1390
  Type l = opi->lhs;
328
  do {
329
1509
    Type r = opi->rhs;
330
    do {
331
1831
      const Vector v = (Vector)map_get(&nspc->info->op_map, (vtype)opi->op);
332
1831
      if(!v)
333
        continue;
334
1831
      const M_Operator* mo = operator_find(v, l, r);
335
1831
      if(mo) {
336
1390
        if(mo->em)
337
740
          return mo->em(emit, (void*)opi->data);
338
650
        return handle_instr(emit, mo);
339
      }
340

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

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