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

nickg / nvc / 6302411954

25 Sep 2023 04:52PM UTC coverage: 91.068% (+0.02%) from 91.05%
6302411954

push

github

nickg
Additional checking for LCS2016-059

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

48581 of 53346 relevant lines covered (91.07%)

942730.65 hits per line

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

91.72
/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,360✔
119
{
120
   obj_array_add(&(item->obj_array), &(t->object));
45,360✔
121
}
45,360✔
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)
90,903✔
130
{
131
   obj_array_add(&(item->obj_array), &(t->object));
90,903✔
132
}
90,903✔
133

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

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

146
static inline type_t type_base_map(type_t t, hash_t *map)
1,411,060✔
147
{
148
   assert(t->object.kind == T_SUBTYPE);
1,411,060✔
149
   type_t base = type_base(t);
1,411,060✔
150
   if (map != NULL)
1,411,060✔
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,029,200✔
157
{
158
   assert(a != NULL);
29,029,200✔
159
   assert(b != NULL);
29,029,200✔
160

161
   if (a == b)
29,029,200✔
162
      return true;
163

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

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

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

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

182
   if (!strict) {
26,107,300✔
183
      // Subtypes are convertible to the base type
184
      while ((kind_a = a->object.kind) == T_SUBTYPE)
26,498,500✔
185
         a = type_base_map(a, map);
391,322✔
186
      while ((kind_b = b->object.kind) == T_SUBTYPE)
27,126,900✔
187
         b = type_base_map(b, map);
1,019,730✔
188

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

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

195
   if (!(has & I_PARAMS)) {
25,886,300✔
196
      ident_t ai = lookup_item(&type_object, a, I_IDENT)->ident;
21,659,900✔
197
      ident_t bi = lookup_item(&type_object, b, I_IDENT)->ident;
21,659,900✔
198

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

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

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

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

212
   if (kind_a == T_ACCESS)
4,005,300✔
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,005,300✔
216
      return false;
217

218
   if (kind_a == T_FUNC) {
4,005,300✔
219
      if (!_type_eq(type_result(a), type_result(b), strict, map))
3,924,080✔
220
         return false;
221
   }
222

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

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

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

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

241
   return true;
242
}
243

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

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

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

259
ident_t type_ident(type_t t)
226,889✔
260
{
261
   assert(t != NULL);
228,373✔
262

263
   item_t *item = lookup_item(&type_object, t, I_IDENT);
228,373✔
264
   if (item->ident == NULL) {
228,373✔
265
      switch (t->object.kind) {
1,511✔
266
      case T_SUBTYPE:
1,484✔
267
         return type_ident(type_base(t));
1,484✔
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,417✔
282
{
283
   assert(t != NULL);
47,417✔
284
   return (lookup_item(&type_object, t, I_IDENT)->ident != NULL);
47,417✔
285
}
286

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

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

299
tree_t type_dim(type_t t, unsigned n)
651,950✔
300
{
301
   item_t *item = lookup_item(&type_object, t, I_DIMS);
651,950✔
302
   return tree_array_nth(item, n);
651,950✔
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)
9,554,490✔
312
{
313
   item_t *item = lookup_item(&type_object, t, I_BASE);
9,554,490✔
314
   assert(item->object != NULL);
9,554,490✔
315
   return container_of(item->object, struct _type, object);
9,554,490✔
316
}
317

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

324
type_t type_elem(type_t t)
1,116,600✔
325
{
326
   assert(t != NULL);
1,994,480✔
327

328
   if (t->object.kind == T_NONE)
1,994,480✔
329
      return t;
330
   else {
331
      item_t *item = lookup_item(&type_object, t, I_ELEM);
1,994,480✔
332
      if (t->object.kind == T_SUBTYPE && item->object == NULL)
1,994,480✔
333
         return type_elem(type_base(t));
877,879✔
334
      else {
335
         assert(item->object != NULL);
1,116,600✔
336
         return container_of(item->object, struct _type, object);
1,116,600✔
337
      }
338
   }
339
}
340

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

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

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

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

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

367
   switch (t->object.kind) {
3,128,270✔
368
   case T_INTEGER:
766,386✔
369
      return t == std_type(NULL, STD_UNIVERSAL_INTEGER);
766,386✔
370
   case T_REAL:
286,941✔
371
      return t == std_type(NULL, STD_UNIVERSAL_REAL);
286,941✔
372
   default:
373
      return false;
374
   }
375
}
376

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

383
tree_t type_unit(type_t t, unsigned n)
28,426✔
384
{
385
   item_t *item = lookup_item(&type_object, t, I_UNITS);
28,426✔
386
   return tree_array_nth(item, n);
28,426✔
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)
494,272✔
396
{
397
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
494,272✔
398
   return obj_array_count(item->obj_array);
494,272✔
399
}
400

401
tree_t type_enum_literal(type_t t, unsigned n)
31,969,100✔
402
{
403
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
31,969,100✔
404
   return tree_array_nth(item, n);
31,969,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,889✔
415
{
416
   item_t *item = lookup_item(&type_object, t, I_PARAMS);
1,889✔
417
   return obj_array_count(item->obj_array);
1,889✔
418
}
419

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

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

432
unsigned type_fields(type_t t)
58,799✔
433
{
434
   if (t->object.kind == T_SUBTYPE)
64,725✔
435
      return type_fields(type_base(t));
5,926✔
436
   else {
437
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
58,799✔
438
      return obj_array_count(item->obj_array);
58,799✔
439
   }
440
}
441

442
tree_t type_field(type_t t, unsigned n)
195,824✔
443
{
444
   if (t->object.kind == T_SUBTYPE)
210,560✔
445
      return type_field(type_base(t), n);
14,736✔
446
   else {
447
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
195,824✔
448
      return tree_array_nth(item, n);
195,824✔
449
   }
450
}
451

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

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

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

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

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

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

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

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

502
tree_t type_constraint(type_t t, unsigned n)
2,812,540✔
503
{
504
   assert(n == 0);    // TODO: this list is largely redundant now
2,812,540✔
505
   item_t *item = lookup_item(&type_object, t, I_CONSTR);
2,812,540✔
506
   return tree_array_nth(item, n);
2,812,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,148✔
516
{
517
   return lookup_item(&type_object, t, I_RESOLUTION)->object != NULL;
23,148✔
518
}
519

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

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

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

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

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

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

563
   switch (type_kind(t)) {
5,993✔
564
   case T_FUNC:
2,696✔
565
   case T_PROC:
566
      {
567
         static hash_t *cache = NULL;
2,696✔
568
         if (cache == NULL)
2,696✔
569
            cache = hash_new(64);
350✔
570

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

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

583
         return tb_get(tb);
2,696✔
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,295✔
594
         const char *dot1  = strrchr(full1, '.');
3,295✔
595
         const char *tail1 = dot1 ? dot1 + 1 : full1;
3,295✔
596

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

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

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

615
type_kind_t type_base_kind(type_t t)
27,939,500✔
616
{
617
   assert(t != NULL);
33,868,900✔
618
   if (t->object.kind == T_SUBTYPE)
33,868,900✔
619
      return type_base_kind(type_base(t));
5,929,410✔
620
   else
621
      return t->object.kind;
27,939,500✔
622
}
623

624
bool type_is_array(type_t t)
3,451,050✔
625
{
626
   const type_kind_t base = type_base_kind(t);
3,451,050✔
627
   if (base == T_GENERIC)
3,451,050✔
628
      return type_subkind(type_base_recur(t)) == GTYPE_ARRAY;
1,066✔
629
   else
630
      return base == T_ARRAY;
3,449,980✔
631
}
632

633
bool type_is_record(type_t t)
1,885,490✔
634
{
635
   return type_base_kind(t) == T_RECORD;
1,885,490✔
636
}
637

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

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

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

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

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

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

676
tree_t type_constraint_for_field(type_t t, tree_t f)
5,123✔
677
{
678
   if (t->object.kind == T_SUBTYPE) {
5,145✔
679
      const int ncon = type_constraints(t);
4,219✔
680
      if (ncon > 0) {
4,219✔
681
         tree_t c = type_constraint(t, ncon - 1);
4,217✔
682

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

686
         const int nelem = tree_ranges(c);
4,217✔
687
         for (int i = 0; i < nelem; i++) {
6,287✔
688
            tree_t ei = tree_range(c, i);
6,267✔
689
            assert(tree_kind(ei) == T_ELEM_CONSTRAINT);
6,267✔
690

691
            if (tree_has_ref(ei) && tree_ref(ei) == f)
6,267✔
692
               return ei;
4,197✔
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,510,680✔
703
{
704
   assert(t != NULL);
1,510,680✔
705

706
   if (t->object.kind == T_SUBTYPE) {
1,510,680✔
707
      if (type_is_record(t)) {
854,310✔
708
         if (standard() >= STD_08) {
2,481✔
709
            const int nfields = type_fields(t);
2,267✔
710
            for (int i = 0; i < nfields; i++) {
6,358✔
711
               tree_t f = type_field(t, i);
4,096✔
712
               if (type_is_unconstrained(tree_type(f))
4,096✔
713
                   && type_constraint_for_field(t, f) == NULL)
2,798✔
714
                  return true;
715
            }
716
         }
717

718
         return false;
2,476✔
719
      }
720
      else if (type_is_array(t)) {
851,829✔
721
         if (standard() >= STD_08) {
836,071✔
722
            if (type_is_array(t)) {
236,832✔
723
               type_t elem = type_elem(t);
236,832✔
724
               if (type_is_unconstrained(elem))
236,832✔
725
                  return true;
726
            }
727
         }
728

729
         for (; t->object.kind == T_SUBTYPE; t = type_base(t)) {
850,002✔
730
            if (type_constraints(t) > 0) {
835,922✔
731
               tree_t c = type_constraint(t, 0);
822,187✔
732
               if (tree_subkind(c) == C_INDEX)
822,187✔
733
                  return false;
734
            }
735
         }
736

737
         assert(t->object.kind == T_ARRAY);
14,080✔
738
         return true;
739
      }
740
      else
741
         return false;
742
   }
743
   else if (t->object.kind == T_ARRAY)
656,375✔
744
      return true;
745
   else if (t->object.kind == T_GENERIC && type_subkind(t) == GTYPE_ARRAY)
259,578✔
746
      return true;
747
   else if (t->object.kind == T_RECORD && standard() >= STD_08) {
259,577✔
748
      const int nfields = type_fields(t);
3,156✔
749
      for (int i = 0; i < nfields; i++) {
11,360✔
750
         if (type_is_unconstrained(tree_type(type_field(t, i))))
8,890✔
751
            return true;
752
      }
753
      return false;
754
   }
755
   else
756
      return false;
256,421✔
757
}
758

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

764
bool type_is_discrete(type_t t)
25,096✔
765
{
766
   const type_kind_t base = type_base_kind(t);
25,096✔
767
   if (base == T_GENERIC) {
25,096✔
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,081✔
773
}
774

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

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

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

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

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

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

825
bool type_is_representable(type_t t)
12,129✔
826
{
827
   if (type_is_scalar(t))
12,708✔
828
      return true;
829
   else if (standard() < STD_19)
5,623✔
830
      return false;
831
   else if (type_is_record(t)) {
1,028✔
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))
717✔
841
      return type_is_representable(type_elem(t));
579✔
842
   else
843
      return false;
844
}
845

846
type_t type_base_recur(type_t t)
397,652✔
847
{
848
   assert(t != NULL);
397,652✔
849
   while (t->object.kind == T_SUBTYPE)
582,952✔
850
      t = type_base(t);
185,300✔
851
   return t;
397,652✔
852
}
853

854
const char *type_kind_str(type_kind_t t)
×
855
{
856
   assert(t < T_LAST_TYPE_KIND);
×
857
   return kind_text_map[t];
×
858
}
859

860
bool type_known_width(type_t type)
×
861
{
862
   if (!type_is_array(type))
×
863
      return true;
864

865
   if (type_is_unconstrained(type))
×
866
      return false;
867

868
   if (!type_known_width(type_elem(type)))
×
869
      return false;
870

871
   const int ndims = dimension_of(type);
×
872
   for (int i = 0; i < ndims; i++) {
×
873
      int64_t low, high;
×
874
      if (!folded_bounds(range_of(type, i), &low, &high))
×
875
         return false;
×
876
   }
877

878
   return true;
879
}
880

881
unsigned type_width(type_t type)
14,961✔
882
{
883
   if (type_is_array(type)) {
14,961✔
884
      const unsigned elem_w = type_width(type_elem(type));
×
885
      unsigned w = 1;
×
886
      const int ndims = dimension_of(type);
×
887
      for (int i = 0; i < ndims; i++) {
×
888
         int64_t low, high;
×
889
         range_bounds(range_of(type, i), &low, &high);
×
890
         w *= MAX(high - low + 1, 0);
×
891
      }
892
      return w * elem_w;
×
893
   }
894
   else if (type_is_record(type)) {
14,961✔
895
      type_t base = type_base_recur(type);
×
896
      unsigned w = 0;
×
897
      const int nfields = type_fields(base);
×
898
      for (int i = 0; i < nfields; i++)
×
899
         w += type_width(tree_type(type_field(base, i)));
×
900
      return w;
×
901
   }
902
   else
903
      return 1;
904
}
905

906
bool type_is_convertible_map(type_t from, type_t to, hash_t *map)
2,014,950✔
907
{
908
   // LRM 08 section 9.3.6 final paragraph lists rules for implicit
909
   // conversion from universal operands to other integer/real types.
910

911
   type_kind_t fromk = type_base_kind(from);
2,014,950✔
912
   type_kind_t tok   = type_base_kind(to);
2,014,950✔
913

914
   if (fromk == T_NONE)
2,014,950✔
915
      return true;  // Suppress cascading errors
916
   else if (!type_is_universal(from))
2,014,680✔
917
      return false;
918
   else if (type_is_universal(to))
310,822✔
919
      return false;
920
   else if (fromk == T_INTEGER && tok == T_INTEGER)
291,285✔
921
      return true;
922
   else if (fromk == T_REAL && tok == T_REAL)
186,588✔
923
      return true;
924
   else if (tok == T_GENERIC && map != NULL) {
147,629✔
925
      type_t to_map = hash_get(map, to);
54✔
926
      return to_map ? type_is_convertible_map(from, to_map, map) : false;
54✔
927
   }
928
   else if (tok == T_GENERIC) {
147,575✔
929
      // Handle VHDL-2019 anonymous type classes
930
      return (fromk == T_INTEGER && type_subkind(to) == GTYPE_INTEGER)
121✔
931
         || (fromk == T_REAL && type_subkind(to) == GTYPE_FLOATING);
351✔
932
   }
933
   else
934
      return false;
935
}
936

937
bool type_is_convertible(type_t from, type_t to)
1,948,180✔
938
{
939
   return type_is_convertible_map(from, to, NULL);
1,948,180✔
940
}
941

942
bool type_is_composite(type_t t)
372,276✔
943
{
944
   const type_kind_t base = type_base_kind(t);
372,276✔
945
   return base == T_ARRAY || base == T_RECORD;
372,276✔
946
}
947

948
bool type_is_homogeneous(type_t t)
106,109✔
949
{
950
   if (type_is_scalar(t))
149,578✔
951
      return true;
952
   else if (type_is_array(t))
53,429✔
953
      return type_is_homogeneous(type_elem(t));
43,469✔
954
   else
955
      return false;
956
}
957

958
bool type_is_resolved(type_t t)
53✔
959
{
960
   if (t->object.kind == T_SUBTYPE)
53✔
961
      return type_has_resolution(t) || type_is_resolved(type_base(t));
17✔
962
   else
963
      return false;
964
}
965

966
bool type_frozen(type_t t)
77✔
967
{
968
   return arena_frozen(object_arena(&(t->object)));
77✔
969
}
970

971
tree_t type_container(type_t t)
162✔
972
{
973
   object_t *o = arena_root(object_arena(&(t->object)));
162✔
974
   assert(o->tag == OBJECT_TAG_TREE);
162✔
975
   return container_of(o, struct _tree, object);
162✔
976
}
977

978
object_t *type_to_object(type_t t)
×
979
{
980
   return t ? &(t->object) : NULL;
×
981
}
982

983
type_t type_from_object(object_t *obj)
×
984
{
985
   assert(obj->tag == OBJECT_TAG_TYPE);
×
986
   return container_of(obj, struct _type, object);
×
987
}
988

989
int type_bit_width(type_t type)
8,554✔
990
{
991
   switch (type_kind(type)) {
20,235✔
992
   case T_INTEGER:
2,911✔
993
   case T_PHYSICAL:
994
      {
995
         tree_t r = range_of(type, 0);
2,911✔
996
         return bits_for_range(assume_int(tree_left(r)),
2,911✔
997
                               assume_int(tree_right(r)));
998
      }
999

1000
   case T_REAL:
1001
       // All real types are doubles at the moment
1002
       return 64;
1003

1004
   case T_SUBTYPE:
7,322✔
1005
      return type_bit_width(type_base(type));
7,322✔
1006

1007
   case T_ENUM:
5,337✔
1008
      return bits_for_range(0, type_enum_literals(type) - 1);
5,337✔
1009

1010
   case T_ARRAY:
4,359✔
1011
      return type_bit_width(type_elem(type));
4,359✔
1012

1013
   default:
×
1014
      fatal_trace("unhandled type %s in type_bit_width", type_pp(type));
×
1015
   }
1016
}
1017

1018
int type_byte_width(type_t type)
8,554✔
1019
{
1020
   return (type_bit_width(type) + 7) / 8;
8,554✔
1021
}
1022

1023
bool type_is_character_array(type_t t)
613✔
1024
{
1025
   // LRM 93 section 3.1.1 an enumeration type is a character type if at
1026
   // least one of its enumeration literals is a character literal
1027

1028
   if (!type_is_array(t))
613✔
1029
      return false;
1030

1031
   if (dimension_of(t) != 1)
198✔
1032
      return false;
1033

1034
   type_t elem = type_base_recur(type_elem(t));
197✔
1035

1036
   if (!type_is_enum(elem))
197✔
1037
      return false;
1038

1039
   const int nlits = type_enum_literals(elem);
183✔
1040
   for (int i = 0; i < nlits; i++) {
1,049✔
1041
      tree_t lit = type_enum_literal(elem, i);
1,048✔
1042
      if (ident_char(tree_ident(lit), 0) == '\'')
1,048✔
1043
         return true;
1044
   }
1045

1046
   return false;
1047
}
1048

1049
bool type_matches_class(type_t t, gtype_class_t class)
148✔
1050
{
1051
   switch (class) {
148✔
1052
   case GTYPE_PRIVATE:
1053
      return true;
1054
   case GTYPE_SCALAR:
7✔
1055
      return type_is_scalar(t);
7✔
1056
   case GTYPE_DISCRETE:
5✔
1057
      return type_is_discrete(t);
5✔
1058
   case GTYPE_INTEGER:
5✔
1059
      return type_is_integer(t);
5✔
1060
   case GTYPE_FLOATING:
3✔
1061
      return type_is_real(t);
3✔
1062
   case GTYPE_PHYSICAL:
3✔
1063
      return type_is_physical(t);
3✔
1064
   case GTYPE_ACCESS:
5✔
1065
      return type_is_access(t);
5✔
1066
   case GTYPE_ARRAY:
7✔
1067
      return type_is_array(t);
7✔
1068
   case GTYPE_FILE:
5✔
1069
      return type_is_file(t);
5✔
1070
   default:
×
1071
      return false;
×
1072
   }
1073
}
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