GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/parse/operator.c Lines: 223 226 98.7 %
Date: 2020-10-03 11:19:27 Branches: 162 178 91.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 "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
749
ANN void free_op_map(Map map, struct Gwion_ *gwion) {
26
  LOOP_OPTIM
27
37865
  for(m_uint i = map_size(map) + 1; --i;) {
28
36367
    const restrict Vector v = (Vector)map_at(map, (vtype)i - 1);
29
    LOOP_OPTIM
30
205256
    for(m_uint j = vector_size(v) + 1; --j;)
31
132522
      mp_free(gwion->mp, M_Operator, (M_Operator*)vector_at(v, j - 1));
32
36367
    free_vector(gwion->mp, v);
33
  }
34
749
  map_release(map);
35
749
}
36
37
1983
ANN static Type op_parent(const Env env, const Type t) {
38

1983
  if(GET_FLAG(t, template) && GET_FLAG(t, ref)) {
39
50
    const Type type = typedef_base(t);
40
50
    char name[strlen(type->name) + 1];
41
50
    strcpy(name, type->name);
42
50
    const m_str post = strchr(name, ':');
43
50
    *post = '\0';
44
50
    return nspc_lookup_type1(env->curr, insert_symbol(env->gwion->st, name));
45
  }
46
1933
  return t->e->parent;
47
}
48
49
26793
static m_bool op_match(const restrict Type t, const restrict Type mo) {
50

26793
  if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
51
3873
    return GW_OK;
52
22920
  Type type = t;
53


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


22920
  if((type && mo && mo->xid == type->xid) || (!type && !mo))
55
5705
    return GW_OK;
56
17215
  return 0;
57
}
58
59
4701
ANN2(1) static M_Operator* operator_find(const Vector v, const restrict Type lhs, const restrict Type rhs) {
60
26624
  for(m_uint i = vector_size(v) + 1; --i;) {
61
20490
    M_Operator* mo = (M_Operator*)vector_at(v, i - 1);
62
20490
    if(!mo)
63
7
      continue;
64

20483
    if(op_match(lhs, mo->lhs) && op_match(rhs, mo->rhs))
65
3268
      return mo;
66
  }
67
1433
  return NULL;
68
}
69
70
410502
static m_bool op_match2(const restrict Type t, const restrict Type mo) {
71
//  if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE)
72
//    return GW_OK;
73



410502
  if((t && mo && (t != OP_ANY_TYPE && mo != OP_ANY_TYPE && mo->xid == t->xid)) || (!t && !mo))
74
64379
    return GW_OK;
75
346123
  return 0;
76
}
77
78
96378
ANN2(1) static M_Operator* operator_find2(const Vector v, const restrict Type lhs, const restrict Type rhs) {
79
538868
  for(m_uint i = vector_size(v) + 1; --i;) {
80
346113
    M_Operator* mo = (M_Operator*)vector_at(v, i - 1);
81

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

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

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

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

2428
  if(t != OP_ANY_TYPE && GET_FLAG(t, nonnull))
183
105
    exp_setnonnull(exp, 1);
184
2428
}
185
186
1834
ANN static void opi_nonnull(const M_Operator *mo, const struct Op_Import *opi) {
187


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

2978
    if(v && (mo = operator_find(v, ock->opi->lhs, r))) {
248
1834
      opi_nonnull(mo, ock->opi);
249

1834
      if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data, &ock->mut))))
250
1513
        return t;
251
      else
252
321
        return mo->ret;
253
    }
254

1144
  } while(r && (r = op_parent(ock->env, r)));
255
526
  return NULL;
256
}
257
258
1850
ANN Type op_check(const Env env, struct Op_Import* opi) {
259
1850
  Nspc nspc = env->curr;
260
  do {
261
7746
    if(nspc->info->op_map.ptr) {
262
1949
      Type l = opi->lhs;
263
      do {
264
2360
        struct Op_Import opi2 = { .op=opi->op, .lhs=l, .rhs=opi->rhs, .data=opi->data, .op_type=opi->op_type };
265
2360
        struct OpChecker ock = { env, &nspc->info->op_map, &opi2, 0 };
266
2360
        const Type ret = op_check_inner(&ock);
267
2360
        if(ret) {
268
1817
          if(ret == env->gwion->type[et_null])
269
62
            break;
270
1755
          if(!ock.mut)
271
1687
            set_nspc(&opi2, nspc);
272
1755
          return ret;
273
        }
274

543
      } while(l && (l = op_parent(env, l)));
275
    }
276
5991
  } while((nspc = nspc->parent));
277

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

474
    } while(r && (r = op_parent(emit->env, r)));
344

125
  } while(l && (l = op_parent(emit->env, l)));
345
  return NULL;
346
}