• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nickg / nvc / 6552546749

17 Oct 2023 08:18PM UTC coverage: 91.187% (+0.01%) from 91.176%
6552546749

push

github

nickg
Type conversion between arrays with closely related elements

91 of 91 new or added lines in 5 files covered. (100.0%)

49106 of 53852 relevant lines covered (91.19%)

590583.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.65
/src/type.c
1
//
2
//  Copyright (C) 2011-2022  Nick Gasson
3
//
4
//  This program is free software: you can redistribute it and/or modify
5
//  it under the terms of the GNU General Public License as published by
6
//  the Free Software Foundation, either version 3 of the License, or
7
//  (at your option) any later version.
8
//
9
//  This program is distributed in the hope that it will be useful,
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
//  GNU General Public License for more details.
13
//
14
//  You should have received a copy of the GNU General Public License
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

18
#include "type.h"
19
#include "tree.h"
20
#include "util.h"
21
#include "common.h"
22
#include "object.h"
23
#include "hash.h"
24

25
#include <assert.h>
26
#include <limits.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <ctype.h>
30
#include <float.h>
31

32
static const imask_t has_map[T_LAST_TYPE_KIND] = {
33
   // T_SUBTYPE
34
   (I_IDENT | I_BASE | I_RESOLUTION | I_CONSTR | I_ELEM),
35

36
   // T_INTEGER
37
   (I_IDENT | I_DIMS),
38

39
   // T_REAL
40
   (I_IDENT | I_DIMS),
41

42
   // T_ENUM
43
   (I_IDENT | I_LITERALS | I_DIMS),
44

45
   // T_PHYSICAL
46
   (I_IDENT | I_UNITS | I_DIMS),
47

48
   // T_ARRAY
49
   (I_IDENT | I_INDEXES | I_ELEM),
50

51
   // T_RECORD
52
   (I_IDENT | I_FIELDS),
53

54
   // T_FILE
55
   (I_IDENT | I_DESIGNATED),
56

57
   // T_ACCESS
58
   (I_IDENT | I_DESIGNATED),
59

60
   // T_FUNC
61
   (I_IDENT | I_PARAMS | I_RESULT),
62

63
   // T_INCOMPLETE
64
   (I_IDENT),
65

66
   // T_PROC
67
   (I_IDENT | I_PARAMS),
68

69
   // T_NONE
70
   (I_IDENT),
71

72
   // T_PROTECTED
73
   (I_IDENT | I_FIELDS),
74

75
   // T_GENERIC
76
   (I_IDENT | I_SUBKIND | I_DESIGNATED | I_INDEXES | I_ELEM),
77

78
   // T_VIEW
79
   (I_IDENT | I_DESIGNATED | I_FIELDS),
80
};
81

82
static const char *kind_text_map[T_LAST_TYPE_KIND] = {
83
   "T_SUBTYPE",    "T_INTEGER",   "T_REAL",       "T_ENUM",
84
   "T_PHYSICAL",   "T_ARRAY",     "T_RECORD",     "T_FILE",
85
   "T_ACCESS",     "T_FUNC",      "T_INCOMPLETE", "T_PROC",
86
   "T_NONE",       "T_PROTECTED", "T_GENERIC",    "T_VIEW",
87
};
88

89
static const change_allowed_t change_allowed[] = {
90
   { -1, -1 }
91
};
92

93
struct _type {
94
   object_t object;
95
};
96

97
struct _tree {
98
   object_t object;
99
};
100

101
object_class_t type_object = {
102
   .name           = "type",
103
   .change_allowed = change_allowed,
104
   .has_map        = has_map,
105
   .kind_text_map  = kind_text_map,
106
   .tag            = OBJECT_TAG_TYPE,
107
   .last_kind      = T_LAST_TYPE_KIND
108
};
109

110
extern object_arena_t *global_arena;
111

112
static inline tree_t tree_array_nth(item_t *item, unsigned n)
113
{
114
   object_t *o = obj_array_nth(item->obj_array, n);
115
   return container_of(o, struct _tree, object);
116
}
117

118
static inline void tree_array_add(item_t *item, tree_t t)
45,888✔
119
{
120
   obj_array_add(&(item->obj_array), &(t->object));
45,888✔
121
}
45,888✔
122

123
static inline type_t type_array_nth(item_t *item, unsigned n)
124
{
125
   object_t *o = obj_array_nth(item->obj_array, n);
126
   return container_of(o, struct _type, object);
127
}
128

129
static inline void type_array_add(item_t *item, type_t t)
91,262✔
130
{
131
   obj_array_add(&(item->obj_array), &(t->object));
91,262✔
132
}
91,262✔
133

134
type_t type_new(type_kind_t kind)
89,574✔
135
{
136
   object_t *o = object_new(NULL, &type_object, kind);
89,574✔
137
   return container_of(o, struct _type, object);
89,574✔
138
}
139

140
type_kind_t type_kind(type_t t)
10,002,200✔
141
{
142
   assert(t != NULL);
10,002,200✔
143
   return t->object.kind;
10,002,200✔
144
}
145

146
static inline type_t type_base_map(type_t t, hash_t *map)
1,413,360✔
147
{
148
   assert(t->object.kind == T_SUBTYPE);
1,413,360✔
149
   type_t base = type_base(t);
1,413,360✔
150
   if (map != NULL)
1,413,360✔
151
      return hash_get(map, base) ?: base;
197✔
152
   else
153
      return base;
154
}
155

156
static bool _type_eq(type_t a, type_t b, bool strict, hash_t *map)
29,141,900✔
157
{
158
   assert(a != NULL);
29,141,900✔
159
   assert(b != NULL);
29,141,900✔
160

161
   if (a == b)
29,141,900✔
162
      return true;
163

164
   type_kind_t kind_a = a->object.kind;
26,195,500✔
165
   type_kind_t kind_b = b->object.kind;
26,195,500✔
166

167
   if (map != NULL) {
26,195,500✔
168
      if (kind_a == T_GENERIC) {
14,362✔
169
         a = hash_get(map, a) ?: a;
7,231✔
170
         kind_a = a->object.kind;
7,231✔
171
      }
172

173
      if (kind_b == T_GENERIC) {
14,362✔
174
         b = hash_get(map, b) ?: b;
1,653✔
175
         kind_b = b->object.kind;
1,653✔
176
      }
177

178
      if (a == b)
14,362✔
179
         return true;
180
   }
181

182
   if (!strict) {
26,194,600✔
183
      // Subtypes are convertible to the base type
184
      while ((kind_a = a->object.kind) == T_SUBTYPE)
26,586,400✔
185
         a = type_base_map(a, map);
391,875✔
186
      while ((kind_b = b->object.kind) == T_SUBTYPE)
27,216,000✔
187
         b = type_base_map(b, map);
1,021,480✔
188

189
      if (a == b)
26,194,500✔
190
         return true;
191
   }
192

193
   const imask_t has = has_map[a->object.kind];
25,973,200✔
194

195
   if (!(has & I_PARAMS)) {
25,973,200✔
196
      ident_t ai = lookup_item(&type_object, a, I_IDENT)->ident;
21,723,400✔
197
      ident_t bi = lookup_item(&type_object, b, I_IDENT)->ident;
21,723,400✔
198

199
      if (ai != bi)
21,723,400✔
200
         return false;
201
   }
202

203
   if (kind_a == T_INCOMPLETE || kind_b == T_INCOMPLETE)
4,250,460✔
204
      return true;
205

206
   if (kind_a != kind_b)
4,250,050✔
207
      return false;
208

209
   if (kind_a == T_ARRAY)
4,028,680✔
210
      return _type_eq(type_elem(a), type_elem(b), strict, map);
×
211

212
   if (kind_a == T_ACCESS)
4,028,680✔
213
      return _type_eq(type_designated(a), type_designated(b), strict, map);
×
214

215
   if ((has & I_DIMS) && (type_dims(a) != type_dims(b)))
4,028,680✔
216
      return false;
217

218
   if (kind_a == T_FUNC) {
4,028,680✔
219
      if (!_type_eq(type_result(a), type_result(b), strict, map))
3,947,280✔
220
         return false;
221
   }
222

223
   if (has & I_PARAMS) {
1,547,960✔
224
      item_t *ap = lookup_item(&type_object, a, I_PARAMS);
1,547,740✔
225
      item_t *bp = lookup_item(&type_object, b, I_PARAMS);
1,547,740✔
226

227
      const int acount = obj_array_count(ap->obj_array);
1,547,740✔
228
      const int bcount = obj_array_count(bp->obj_array);
1,547,740✔
229

230
      if (acount != bcount)
1,547,740✔
231
         return false;
232

233
      for (int i = 0; i < acount; i++) {
1,601,490✔
234
         type_t ai = type_array_nth(ap, i);
1,574,940✔
235
         type_t bi = type_array_nth(bp, i);
1,574,940✔
236
         if (ai != bi && !_type_eq(ai, bi, strict, map))
1,574,940✔
237
            return false;
238
      }
239
   }
240

241
   return true;
242
}
243

244
bool type_strict_eq(type_t a, type_t b)
12,557✔
245
{
246
   return _type_eq(a, b, true, NULL);
12,557✔
247
}
248

249
bool type_eq(type_t a, type_t b)
23,397,000✔
250
{
251
   return _type_eq(a, b, false, NULL);
23,397,000✔
252
}
253

254
bool type_eq_map(type_t a, type_t b, hash_t *map)
367,931✔
255
{
256
   return _type_eq(a, b, false, map);
367,931✔
257
}
258

259
ident_t type_ident(type_t t)
228,878✔
260
{
261
   assert(t != NULL);
230,390✔
262

263
   item_t *item = lookup_item(&type_object, t, I_IDENT);
230,390✔
264
   if (item->ident == NULL) {
230,390✔
265
      switch (t->object.kind) {
1,539✔
266
      case T_SUBTYPE:
1,512✔
267
         return type_ident(type_base(t));
1,512✔
268
      case T_NONE:
27✔
269
         return ident_new("none");
27✔
270
      case T_GENERIC:
×
271
         return ident_new("anonymous");
×
272
      default:
×
273
         fatal_trace("type kind %s has no ident",
×
274
                     type_kind_str(t->object.kind));
275
      }
276
   }
277
   else
278
      return item->ident;
279
}
280

281
bool type_has_ident(type_t t)
47,690✔
282
{
283
   assert(t != NULL);
47,690✔
284
   return (lookup_item(&type_object, t, I_IDENT)->ident != NULL);
47,690✔
285
}
286

287
void type_set_ident(type_t t, ident_t id)
59,855✔
288
{
289
   assert(t != NULL);
59,855✔
290
   lookup_item(&type_object, t, I_IDENT)->ident = id;
59,855✔
291
}
59,855✔
292

293
unsigned type_dims(type_t t)
3,218✔
294
{
295
   item_t *item = lookup_item(&type_object, t, I_DIMS);
3,218✔
296
   return obj_array_count(item->obj_array);
3,218✔
297
}
298

299
tree_t type_dim(type_t t, unsigned n)
625,636✔
300
{
301
   item_t *item = lookup_item(&type_object, t, I_DIMS);
625,636✔
302
   return tree_array_nth(item, n);
625,636✔
303
}
304

305
void type_add_dim(type_t t, tree_t r)
563✔
306
{
307
   tree_array_add(lookup_item(&type_object, t, I_DIMS), r);
563✔
308
   object_write_barrier(&(t->object), &(r->object));
563✔
309
}
563✔
310

311
type_t type_base(type_t t)
10,197,600✔
312
{
313
   item_t *item = lookup_item(&type_object, t, I_BASE);
10,197,600✔
314
   assert(item->object != NULL);
10,197,600✔
315
   return container_of(item->object, struct _type, object);
10,197,600✔
316
}
317

318
void type_set_base(type_t t, type_t b)
38,232✔
319
{
320
   lookup_item(&type_object, t, I_BASE)->object = &(b->object);
38,232✔
321
   object_write_barrier(&(t->object), &(b->object));
38,232✔
322
}
38,232✔
323

324
type_t type_elem(type_t t)
1,170,110✔
325
{
326
   assert(t != NULL);
2,079,800✔
327

328
   if (t->object.kind == T_NONE)
2,079,800✔
329
      return t;
330
   else {
331
      item_t *item = lookup_item(&type_object, t, I_ELEM);
2,079,800✔
332
      if (t->object.kind == T_SUBTYPE && item->object == NULL)
2,079,800✔
333
         return type_elem(type_base(t));
909,690✔
334
      else {
335
         assert(item->object != NULL);
1,170,110✔
336
         return container_of(item->object, struct _type, object);
1,170,110✔
337
      }
338
   }
339
}
340

341
void type_set_elem(type_t t, type_t e)
2,581✔
342
{
343
   lookup_item(&type_object, t, I_ELEM)->object = &(e->object);
2,581✔
344
   object_write_barrier(&(t->object), &(e->object));
2,581✔
345
}
2,581✔
346

347
bool type_has_elem(type_t t)
10,686✔
348
{
349
   return lookup_item(&type_object, t, I_ELEM)->object != NULL;
10,686✔
350
}
351

352
unsigned type_subkind(type_t t)
2,616✔
353
{
354
   item_t *item = lookup_item(&type_object, t, I_SUBKIND);
2,616✔
355
   return item->ival;
2,616✔
356
}
357

358
void type_set_subkind(type_t t, unsigned sub)
134✔
359
{
360
   lookup_item(&type_object, t, I_SUBKIND)->ival = sub;
134✔
361
}
134✔
362

363
bool type_is_universal(type_t t)
3,138,250✔
364
{
365
   assert(t != NULL);
3,138,250✔
366

367
   switch (t->object.kind) {
3,138,250✔
368
   case T_INTEGER:
767,748✔
369
      return t == std_type(NULL, STD_UNIVERSAL_INTEGER);
767,748✔
370
   case T_REAL:
287,280✔
371
      return t == std_type(NULL, STD_UNIVERSAL_REAL);
287,280✔
372
   default:
373
      return false;
374
   }
375
}
376

377
unsigned type_units(type_t t)
3,663✔
378
{
379
   item_t *item = lookup_item(&type_object, t, I_UNITS);
3,663✔
380
   return obj_array_count(item->obj_array);
3,663✔
381
}
382

383
tree_t type_unit(type_t t, unsigned n)
28,690✔
384
{
385
   item_t *item = lookup_item(&type_object, t, I_UNITS);
28,690✔
386
   return tree_array_nth(item, n);
28,690✔
387
}
388

389
void type_add_unit(type_t t, tree_t u)
138✔
390
{
391
   tree_array_add(lookup_item(&type_object, t, I_UNITS), u);
138✔
392
   object_write_barrier(&(t->object), &(u->object));
138✔
393
}
138✔
394

395
unsigned type_enum_literals(type_t t)
501,822✔
396
{
397
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
501,822✔
398
   return obj_array_count(item->obj_array);
501,822✔
399
}
400

401
tree_t type_enum_literal(type_t t, unsigned n)
32,452,100✔
402
{
403
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
32,452,100✔
404
   return tree_array_nth(item, n);
32,452,100✔
405
}
406

407
void type_enum_add_literal(type_t t, tree_t lit)
3,566✔
408
{
409
   assert(tree_kind(lit) == T_ENUM_LIT);
3,566✔
410
   tree_array_add(lookup_item(&type_object, t, I_LITERALS), lit);
3,566✔
411
   object_write_barrier(&(t->object), &(lit->object));
3,566✔
412
}
3,566✔
413

414
unsigned type_params(type_t t)
1,937✔
415
{
416
   item_t *item = lookup_item(&type_object, t, I_PARAMS);
1,937✔
417
   return obj_array_count(item->obj_array);
1,937✔
418
}
419

420
type_t type_param(type_t t, unsigned n)
4,041✔
421
{
422
   item_t *item = lookup_item(&type_object, t, I_PARAMS);
4,041✔
423
   return type_array_nth(item, n);
4,041✔
424
}
425

426
void type_add_param(type_t t, type_t p)
88,500✔
427
{
428
   type_array_add(lookup_item(&type_object, t, I_PARAMS), p);
88,500✔
429
   object_write_barrier(&(t->object), &(p->object));
88,500✔
430
}
88,500✔
431

432
unsigned type_fields(type_t t)
62,688✔
433
{
434
   if (t->object.kind == T_SUBTYPE)
69,788✔
435
      return type_fields(type_base(t));
7,100✔
436
   else {
437
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
62,688✔
438
      return obj_array_count(item->obj_array);
62,688✔
439
   }
440
}
441

442
tree_t type_field(type_t t, unsigned n)
204,988✔
443
{
444
   if (t->object.kind == T_SUBTYPE)
221,589✔
445
      return type_field(type_base(t), n);
16,601✔
446
   else {
447
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
204,988✔
448
      return tree_array_nth(item, n);
204,988✔
449
   }
450
}
451

452
void type_add_field(type_t t, tree_t p)
3,819✔
453
{
454
   tree_array_add(lookup_item(&type_object, t, I_FIELDS), p);
3,819✔
455
   object_write_barrier(&(t->object), &(p->object));
3,819✔
456
}
3,819✔
457

458
type_t type_result(type_t t)
9,671,560✔
459
{
460
   item_t *item = lookup_item(&type_object, t, I_RESULT);
9,671,560✔
461
   assert(item->object != NULL);
9,671,560✔
462
   return container_of(item->object, struct _type, object);
9,671,560✔
463
}
464

465
void type_set_result(type_t t, type_t r)
42,085✔
466
{
467
   lookup_item(&type_object, t, I_RESULT)->object = &(r->object);
42,085✔
468
   object_write_barrier(&(t->object), &(r->object));
42,085✔
469
}
42,085✔
470

471
unsigned type_indexes(type_t t)
1,110,230✔
472
{
473
   item_t *item = lookup_item(&type_object, t, I_INDEXES);
1,110,230✔
474
   return obj_array_count(item->obj_array);
1,110,230✔
475
}
476

477
void type_add_index(type_t t, type_t sub)
2,762✔
478
{
479
   type_array_add(lookup_item(&type_object, t, I_INDEXES), sub);
2,762✔
480
   object_write_barrier(&(t->object), &(sub->object));
2,762✔
481
}
2,762✔
482

483
type_t type_index(type_t t, unsigned n)
196,312✔
484
{
485
   item_t *item = lookup_item(&type_object, t, I_INDEXES);
196,312✔
486
   return type_array_nth(item, n);
196,312✔
487
}
488

489
unsigned type_constraints(type_t t)
1,912,220✔
490
{
491
   item_t *item = lookup_item(&type_object, t, I_CONSTR);
1,912,220✔
492
   return obj_array_count(item->obj_array);
1,912,220✔
493
}
494

495
void type_add_constraint(type_t t, tree_t c)
37,802✔
496
{
497
   assert(c->object.kind == T_CONSTRAINT);
37,802✔
498
   tree_array_add(lookup_item(&type_object, t, I_CONSTR), c);
37,802✔
499
   object_write_barrier(&(t->object), &(c->object));
37,802✔
500
}
37,802✔
501

502
tree_t type_constraint(type_t t, unsigned n)
2,879,540✔
503
{
504
   assert(n == 0);    // TODO: this list is largely redundant now
2,879,540✔
505
   item_t *item = lookup_item(&type_object, t, I_CONSTR);
2,879,540✔
506
   return tree_array_nth(item, n);
2,879,540✔
507
}
508

509
void type_set_resolution(type_t t, tree_t r)
329✔
510
{
511
   lookup_item(&type_object, t, I_RESOLUTION)->object = &(r->object);
329✔
512
   object_write_barrier(&(t->object), &(r->object));
329✔
513
}
329✔
514

515
bool type_has_resolution(type_t t)
23,263✔
516
{
517
   return lookup_item(&type_object, t, I_RESOLUTION)->object != NULL;
23,263✔
518
}
519

520
tree_t type_resolution(type_t t)
2,304✔
521
{
522
   item_t *item = lookup_item(&type_object, t, I_RESOLUTION);
2,304✔
523
   assert(item->object != NULL);
2,304✔
524
   return container_of(item->object, struct _tree, object);
2,304✔
525
}
526

527
type_t type_designated(type_t t)
9,903✔
528
{
529
   if (t->object.kind == T_SUBTYPE)
9,904✔
530
      return type_designated(type_base(t));
1✔
531
   else {
532
      item_t *item = lookup_item(&type_object, t, I_DESIGNATED);
9,903✔
533
      assert(item->object != NULL);
9,903✔
534
      return container_of(item->object, struct _type, object);
9,903✔
535
   }
536
}
537

538
void type_set_designated(type_t t, type_t d)
440✔
539
{
540
   lookup_item(&type_object, t, I_DESIGNATED)->object = &(d->object);
440✔
541
   object_write_barrier(&(t->object), &(d->object));
440✔
542
}
440✔
543

544
void type_signature(type_t t, text_buf_t *tb)
986✔
545
{
546
   assert(t->object.kind == T_FUNC || t->object.kind == T_PROC);
986✔
547

548
   tb_printf(tb, "[");
986✔
549
   const int nparams = type_params(t);
986✔
550
   for (int i = 0; i < nparams; i++)
2,377✔
551
      tb_printf(tb, "%s%s", (i == 0 ? "" : ", "),
1,919✔
552
                type_pp(type_param(t, i)));
553
   if (t->object.kind == T_FUNC)
986✔
554
      tb_printf(tb, "%sreturn %s", nparams > 0 ? " " : "",
609✔
555
                type_pp(type_result(t)));
556
   tb_printf(tb, "]");
986✔
557
}
986✔
558

559
const char *type_pp2(type_t t, type_t other)
6,076✔
560
{
561
   assert(t != NULL);
6,076✔
562

563
   switch (type_kind(t)) {
6,076✔
564
   case T_FUNC:
2,711✔
565
   case T_PROC:
566
      {
567
         static hash_t *cache = NULL;
2,711✔
568
         if (cache == NULL)
2,711✔
569
            cache = hash_new(64);
356✔
570

571
         text_buf_t *tb = hash_get(cache, t);
2,711✔
572
         if (tb == NULL) {
2,711✔
573
            tb = tb_new();
935✔
574
            hash_put(cache, t, tb);
935✔
575

576
            if (type_has_ident(t)) {
935✔
577
               tb_istr(tb, type_ident(t));
935✔
578
               tb_append(tb, ' ');
935✔
579
            }
580
            type_signature(t, tb);
935✔
581
         }
582

583
         return tb_get(tb);
2,711✔
584
      }
585

586
   case T_GENERIC:
204✔
587
      if (!type_has_ident(t))
204✔
588
         return "(an anonymous type)";
589
      // Fall-through
590

591
   default:
592
      {
593
         const char *full1 = istr(type_ident(t));
3,363✔
594
         const char *dot1  = strrchr(full1, '.');
3,363✔
595
         const char *tail1 = dot1 ? dot1 + 1 : full1;
3,363✔
596

597
         if (other != NULL) {
3,363✔
598
            const char *full2 = istr(type_ident(other));
88✔
599
            const char *dot2  = strrchr(full2, '.');
88✔
600
            const char *tail2 = dot2 ? dot2 + 1 : full2;
88✔
601

602
            return strcmp(tail1, tail2) ? tail1 : full1;
88✔
603
         }
604
         else
605
            return tail1;
606
      }
607
   }
608
}
609

610
const char *type_pp(type_t t)
5,988✔
611
{
612
   return type_pp2(t, NULL);
5,988✔
613
}
614

615
type_kind_t type_base_kind(type_t t)
28,486,100✔
616
{
617
   assert(t != NULL);
34,998,500✔
618
   if (t->object.kind == T_SUBTYPE)
34,998,500✔
619
      return type_base_kind(type_base(t));
6,512,410✔
620
   else
621
      return t->object.kind;
28,486,100✔
622
}
623

624
bool type_is_array(type_t t)
4,148,670✔
625
{
626
   const type_kind_t base = type_base_kind(t);
4,148,670✔
627
   if (base == T_GENERIC)
4,148,670✔
628
      return type_subkind(type_base_recur(t)) == GTYPE_ARRAY;
1,093✔
629
   else
630
      return base == T_ARRAY;
4,147,580✔
631
}
632

633
bool type_is_record(type_t t)
2,081,700✔
634
{
635
   return type_base_kind(t) == T_RECORD;
2,081,700✔
636
}
637

638
bool type_is_protected(type_t t)
118,307✔
639
{
640
   return type_base_kind(t) == T_PROTECTED;
118,307✔
641
}
642

643
bool type_is_file(type_t t)
102,849✔
644
{
645
   const type_kind_t base = type_base_kind(t);
102,849✔
646
   if (base == T_GENERIC)
102,849✔
647
      return type_subkind(type_base_recur(t)) == GTYPE_FILE;
188✔
648
   else
649
      return base == T_FILE;
102,661✔
650
}
651

652
bool type_is_access(type_t t)
197,000✔
653
{
654
   const type_kind_t base = type_base_kind(t);
197,000✔
655
   if (base == T_GENERIC)
197,000✔
656
      return type_subkind(type_base_recur(t)) == GTYPE_ACCESS;
386✔
657
   else
658
      return base == T_ACCESS;
196,614✔
659
}
660

661
bool type_is_incomplete(type_t t)
25,793✔
662
{
663
   return type_base_kind(t) == T_INCOMPLETE;
25,793✔
664
}
665

666
bool type_is_none(type_t t)
16,596,400✔
667
{
668
   return type_base_kind(t) == T_NONE;
16,596,400✔
669
}
670

671
bool type_is_valid(type_t t)
112✔
672
{
673
   return type_base_kind(t) != T_NONE;
112✔
674
}
675

676
tree_t type_constraint_for_field(type_t t, tree_t f)
6,407✔
677
{
678
   if (t->object.kind == T_SUBTYPE) {
6,429✔
679
      const int ncon = type_constraints(t);
5,501✔
680
      if (ncon > 0) {
5,501✔
681
         tree_t c = type_constraint(t, ncon - 1);
5,499✔
682

683
         if (tree_subkind(c) != C_RECORD)
5,499✔
684
            return NULL;
685

686
         const int nelem = tree_ranges(c);
5,499✔
687
         for (int i = 0; i < nelem; i++) {
7,730✔
688
            tree_t ei = tree_range(c, i);
7,710✔
689
            assert(tree_kind(ei) == T_ELEM_CONSTRAINT);
7,710✔
690

691
            if (tree_has_ref(ei) && tree_ref(ei) == f)
7,710✔
692
               return ei;
5,479✔
693
         }
694
      }
695

696
      return type_constraint_for_field(type_base(t), f);
22✔
697
   }
698
   else
699
      return NULL;
700
}
701

702
bool type_is_unconstrained(type_t t)
1,813,770✔
703
{
704
   assert(t != NULL);
1,813,770✔
705

706
   if (t->object.kind == T_SUBTYPE) {
1,813,770✔
707
      if (type_is_record(t)) {
941,025✔
708
         if (standard() >= STD_08) {
4,473✔
709
            const int nfields = type_fields(t);
3,410✔
710
            for (int i = 0; i < nfields; i++) {
9,331✔
711
               tree_t f = type_field(t, i);
5,926✔
712
               if (type_is_unconstrained(tree_type(f))
5,926✔
713
                   && type_constraint_for_field(t, f) == NULL)
4,076✔
714
                  return true;
715
            }
716
         }
717

718
         return false;
4,468✔
719
      }
720
      else if (type_is_array(t)) {
936,552✔
721
         if (standard() >= STD_08) {
847,773✔
722
            if (type_is_array(t)) {
245,218✔
723
               type_t elem = type_elem(t);
245,218✔
724
               if (type_is_unconstrained(elem))
245,218✔
725
                  return true;
726
            }
727
         }
728

729
         for (; t->object.kind == T_SUBTYPE; t = type_base(t)) {
861,852✔
730
            if (type_constraints(t) > 0) {
847,624✔
731
               tree_t c = type_constraint(t, 0);
833,741✔
732
               if (tree_subkind(c) == C_INDEX)
833,741✔
733
                  return false;
734
            }
735
         }
736

737
         assert(t->object.kind == T_ARRAY);
14,228✔
738
         return true;
739
      }
740
      else
741
         return false;
742
   }
743
   else if (t->object.kind == T_ARRAY)
872,741✔
744
      return true;
745
   else if (t->object.kind == T_GENERIC && type_subkind(t) == GTYPE_ARRAY)
468,455✔
746
      return true;
747
   else if (t->object.kind == T_RECORD && standard() >= STD_08) {
468,454✔
748
      const int nfields = type_fields(t);
6,294✔
749
      for (int i = 0; i < nfields; i++) {
20,904✔
750
         if (type_is_unconstrained(tree_type(type_field(t, i))))
15,980✔
751
            return true;
752
      }
753
      return false;
754
   }
755
   else
756
      return false;
462,160✔
757
}
758

759
bool type_is_enum(type_t t)
105,457✔
760
{
761
   return type_base_kind(t) == T_ENUM;
105,457✔
762
}
763

764
bool type_is_discrete(type_t t)
25,239✔
765
{
766
   const type_kind_t base = type_base_kind(t);
25,239✔
767
   if (base == T_GENERIC) {
25,239✔
768
      const gtype_class_t class = type_subkind(type_base_recur(t));
15✔
769
      return class == GTYPE_INTEGER || class == GTYPE_DISCRETE;
15✔
770
   }
771
   else
772
      return base == T_INTEGER || base == T_ENUM;
25,224✔
773
}
774

775
bool type_is_subprogram(type_t t)
1,008,740✔
776
{
777
   return t->object.kind == T_FUNC || t->object.kind == T_PROC;
1,008,740✔
778
}
779

780
bool type_is_physical(type_t t)
176✔
781
{
782
   const type_kind_t base = type_base_kind(t);
176✔
783
   if (base == T_GENERIC)
176✔
784
      return type_subkind(type_base_recur(t)) == GTYPE_PHYSICAL;
1✔
785
   else
786
      return base == T_PHYSICAL;
175✔
787
}
788

789
bool type_is_integer(type_t t)
98,412✔
790
{
791
   const type_kind_t base = type_base_kind(t);
98,412✔
792
   if (base == T_GENERIC)
98,412✔
793
      return type_subkind(type_base_recur(t)) == GTYPE_INTEGER;
2✔
794
   else
795
      return base == T_INTEGER;
98,410✔
796
}
797

798
bool type_is_real(type_t t)
19,425✔
799
{
800
   const type_kind_t base = type_base_kind(t);
19,425✔
801
   if (base == T_GENERIC)
19,425✔
802
      return type_subkind(type_base_recur(t)) == GTYPE_FLOATING;
2✔
803
   else
804
      return base == T_REAL;
19,423✔
805
}
806

807
bool type_is_generic(type_t t)
9,427✔
808
{
809
   return type_base_kind(t) == T_GENERIC;
9,427✔
810
}
811

812
bool type_is_scalar(type_t t)
815,929✔
813
{
814
   const type_kind_t base = type_base_kind(t);
815,929✔
815
   if (base == T_GENERIC) {
815,929✔
816
      const gtype_class_t class = type_subkind(type_base_recur(t));
133✔
817
      return class == GTYPE_SCALAR || class == GTYPE_DISCRETE
133✔
818
         || class == GTYPE_FLOATING || class == GTYPE_INTEGER;
262✔
819
   }
820
   else
821
      return base == T_INTEGER || base == T_REAL
815,796✔
822
         || base == T_ENUM || base == T_PHYSICAL || base == T_NONE;
815,796✔
823
}
824

825
bool type_is_representable(type_t t)
12,840✔
826
{
827
   if (type_is_scalar(t))
13,443✔
828
      return true;
829
   else if (standard() < STD_19)
5,948✔
830
      return false;
831
   else if (type_is_record(t)) {
1,058✔
832
      const int nfields = type_fields(t);
311✔
833
      for (int i = 0; i < nfields; i++) {
1,004✔
834
         if (!type_is_representable(tree_type(type_field(t, i))))
716✔
835
            return false;
836
      }
837

838
      return true;
839
   }
840
   else if (type_is_array(t))
747✔
841
      return type_is_representable(type_elem(t));
603✔
842
   else
843
      return false;
844
}
845

846
bool type_const_bounds(type_t t)
737,725✔
847
{
848
   if (type_is_unconstrained(t))
737,725✔
849
      return false;
850
   else if (type_is_record(t)) {
595,858✔
851
      const int nfields = type_fields(t);
18,625✔
852
      for (int i = 0; i < nfields; i++) {
78,906✔
853
         type_t ftype = tree_type(type_field(t, i));
61,534✔
854
         if (!type_const_bounds(ftype))
61,534✔
855
            return false;
856
      }
857

858
      return true;
859
   }
860
   else if (type_is_array(t)) {
577,233✔
861
      const int ndims = dimension_of(t);
327,369✔
862
      for (int i = 0; i < ndims; i++) {
591,818✔
863
         int64_t low, high;
351,426✔
864
         if (!folded_bounds(range_of(t, i), &low, &high))
351,426✔
865
            return false;
86,977✔
866
      }
867

868
      return type_const_bounds(type_elem(t));
240,392✔
869
   }
870
   else
871
      return true;
872
}
873

874
type_t type_base_recur(type_t t)
411,821✔
875
{
876
   assert(t != NULL);
411,821✔
877
   while (t->object.kind == T_SUBTYPE)
602,202✔
878
      t = type_base(t);
190,381✔
879
   return t;
411,821✔
880
}
881

882
type_t type_elem_recur(type_t type)
101,689✔
883
{
884
   while (type_is_array(type))
206,164✔
885
      type = type_elem(type);
104,475✔
886
   return type;
101,689✔
887
}
888

889
const char *type_kind_str(type_kind_t t)
×
890
{
891
   assert(t < T_LAST_TYPE_KIND);
×
892
   return kind_text_map[t];
×
893
}
894

895
unsigned type_width(type_t type)
11,888✔
896
{
897
   if (type_is_array(type)) {
11,888✔
898
      const unsigned elem_w = type_width(type_elem(type));
×
899
      unsigned w = 1;
×
900
      const int ndims = dimension_of(type);
×
901
      for (int i = 0; i < ndims; i++) {
×
902
         int64_t low, high;
×
903
         range_bounds(range_of(type, i), &low, &high);
×
904
         w *= MAX(high - low + 1, 0);
×
905
      }
906
      return w * elem_w;
×
907
   }
908
   else if (type_is_record(type)) {
11,888✔
909
      type_t base = type_base_recur(type);
×
910
      unsigned w = 0;
×
911
      const int nfields = type_fields(base);
×
912
      for (int i = 0; i < nfields; i++)
×
913
         w += type_width(tree_type(type_field(base, i)));
×
914
      return w;
×
915
   }
916
   else
917
      return 1;
918
}
919

920
bool type_is_convertible_map(type_t from, type_t to, hash_t *map)
2,021,700✔
921
{
922
   // LRM 08 section 9.3.6 final paragraph lists rules for implicit
923
   // conversion from universal operands to other integer/real types.
924

925
   type_kind_t fromk = type_base_kind(from);
2,021,700✔
926
   type_kind_t tok   = type_base_kind(to);
2,021,700✔
927

928
   if (fromk == T_NONE)
2,021,700✔
929
      return true;  // Suppress cascading errors
930
   else if (!type_is_universal(from))
2,021,430✔
931
      return false;
932
   else if (type_is_universal(to))
311,549✔
933
      return false;
934
   else if (fromk == T_INTEGER && tok == T_INTEGER)
291,925✔
935
      return true;
936
   else if (fromk == T_REAL && tok == T_REAL)
186,803✔
937
      return true;
938
   else if (tok == T_GENERIC && map != NULL) {
147,820✔
939
      type_t to_map = hash_get(map, to);
54✔
940
      return to_map ? type_is_convertible_map(from, to_map, map) : false;
54✔
941
   }
942
   else if (tok == T_GENERIC) {
147,766✔
943
      // Handle VHDL-2019 anonymous type classes
944
      return (fromk == T_INTEGER && type_subkind(to) == GTYPE_INTEGER)
121✔
945
         || (fromk == T_REAL && type_subkind(to) == GTYPE_FLOATING);
351✔
946
   }
947
   else
948
      return false;
949
}
950

951
bool type_is_convertible(type_t from, type_t to)
1,954,650✔
952
{
953
   return type_is_convertible_map(from, to, NULL);
1,954,650✔
954
}
955

956
bool type_is_composite(type_t t)
67,769✔
957
{
958
   const type_kind_t base = type_base_kind(t);
67,769✔
959
   return base == T_ARRAY || base == T_RECORD;
67,769✔
960
}
961

962
bool type_is_homogeneous(type_t t)
109,890✔
963
{
964
   if (type_is_scalar(t))
154,256✔
965
      return true;
966
   else if (type_is_array(t))
54,586✔
967
      return type_is_homogeneous(type_elem(t));
44,366✔
968
   else
969
      return false;
970
}
971

972
bool type_is_resolved(type_t t)
53✔
973
{
974
   if (t->object.kind == T_SUBTYPE)
53✔
975
      return type_has_resolution(t) || type_is_resolved(type_base(t));
17✔
976
   else
977
      return false;
978
}
979

980
bool type_frozen(type_t t)
97✔
981
{
982
   return arena_frozen(object_arena(&(t->object)));
97✔
983
}
984

985
tree_t type_container(type_t t)
180✔
986
{
987
   object_t *o = arena_root(object_arena(&(t->object)));
180✔
988
   assert(o->tag == OBJECT_TAG_TREE);
180✔
989
   return container_of(o, struct _tree, object);
180✔
990
}
991

992
object_t *type_to_object(type_t t)
×
993
{
994
   return t ? &(t->object) : NULL;
×
995
}
996

997
type_t type_from_object(object_t *obj)
×
998
{
999
   assert(obj->tag == OBJECT_TAG_TYPE);
×
1000
   return container_of(obj, struct _type, object);
×
1001
}
1002

1003
int type_bit_width(type_t type)
8,838✔
1004
{
1005
   switch (type_kind(type)) {
20,598✔
1006
   case T_INTEGER:
3,006✔
1007
   case T_PHYSICAL:
1008
      {
1009
         tree_t r = range_of(type, 0);
3,006✔
1010
         return bits_for_range(assume_int(tree_left(r)),
3,006✔
1011
                               assume_int(tree_right(r)));
1012
      }
1013

1014
   case T_REAL:
1015
       // All real types are doubles at the moment
1016
       return 64;
1017

1018
   case T_SUBTYPE:
7,382✔
1019
      return type_bit_width(type_base(type));
7,382✔
1020

1021
   case T_ENUM:
5,526✔
1022
      return bits_for_range(0, type_enum_literals(type) - 1);
5,526✔
1023

1024
   case T_ARRAY:
4,378✔
1025
      return type_bit_width(type_elem(type));
4,378✔
1026

1027
   default:
×
1028
      fatal_trace("unhandled type %s in type_bit_width", type_pp(type));
×
1029
   }
1030
}
1031

1032
int type_byte_width(type_t type)
8,666✔
1033
{
1034
   return (type_bit_width(type) + 7) / 8;
8,666✔
1035
}
1036

1037
bool type_is_character_array(type_t t)
41,862✔
1038
{
1039
   // LRM 93 section 3.1.1 an enumeration type is a character type if at
1040
   // least one of its enumeration literals is a character literal
1041

1042
   if (!type_is_array(t))
41,862✔
1043
      return false;
1044

1045
   if (dimension_of(t) != 1)
34,781✔
1046
      return false;
1047

1048
   type_t elem = type_base_recur(type_elem(t));
34,780✔
1049

1050
   if (!type_is_enum(elem))
34,780✔
1051
      return false;
1052

1053
   const int nlits = type_enum_literals(elem);
34,429✔
1054
   for (int i = 0; i < nlits; i++) {
485,911✔
1055
      tree_t lit = type_enum_literal(elem, i);
485,802✔
1056
      if (ident_char(tree_ident(lit), 0) == '\'')
485,802✔
1057
         return true;
1058
   }
1059

1060
   return false;
1061
}
1062

1063
bool type_matches_class(type_t t, gtype_class_t class)
151✔
1064
{
1065
   switch (class) {
151✔
1066
   case GTYPE_PRIVATE:
1067
      return true;
1068
   case GTYPE_SCALAR:
7✔
1069
      return type_is_scalar(t);
7✔
1070
   case GTYPE_DISCRETE:
5✔
1071
      return type_is_discrete(t);
5✔
1072
   case GTYPE_INTEGER:
5✔
1073
      return type_is_integer(t);
5✔
1074
   case GTYPE_FLOATING:
3✔
1075
      return type_is_real(t);
3✔
1076
   case GTYPE_PHYSICAL:
3✔
1077
      return type_is_physical(t);
3✔
1078
   case GTYPE_ACCESS:
5✔
1079
      return type_is_access(t);
5✔
1080
   case GTYPE_ARRAY:
7✔
1081
      return type_is_array(t);
7✔
1082
   case GTYPE_FILE:
5✔
1083
      return type_is_file(t);
5✔
1084
   default:
×
1085
      return false;
×
1086
   }
1087
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc