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

nickg / nvc / 21785130883

07 Feb 2026 06:51PM UTC coverage: 92.618% (-0.004%) from 92.622%
21785130883

push

github

nickg
Work around case where cloned layout may not match

4 of 4 new or added lines in 1 file covered. (100.0%)

287 existing lines in 6 files now uncovered.

76584 of 82688 relevant lines covered (92.62%)

453582.36 hits per line

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

98.1
/src/type.c
1
//
2
//  Copyright (C) 2011-2025  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_CONSTRAINT | 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_INCOMPLETE
61
   (I_IDENT),
62

63
   // T_NONE
64
   (I_IDENT),
65

66
   // T_PROTECTED
67
   (I_IDENT | I_FIELDS),
68

69
   // T_GENERIC
70
   (I_IDENT | I_SUBKIND | I_DESIGNATED | I_INDEXES | I_ELEM),
71

72
   // T_VIEW
73
   (I_IDENT | I_DESIGNATED | I_FIELDS),
74

75
   // T_SIGNATURE
76
   (I_IDENT | I_PARAMS | I_RESULT),
77
};
78

79
static const char *kind_text_map[T_LAST_TYPE_KIND] = {
80
   "T_SUBTYPE",   "T_INTEGER",    "T_REAL",      "T_ENUM",
81
   "T_PHYSICAL",  "T_ARRAY",      "T_RECORD",    "T_FILE",
82
   "T_ACCESS",    "T_INCOMPLETE", "T_NONE",      "T_PROTECTED",
83
   "T_GENERIC",   "T_VIEW",       "T_SIGNATURE",
84
};
85

86
static const change_allowed_t change_allowed[] = {
87
   { -1, -1 }
88
};
89

90
struct _type {
91
   object_t object;
92
};
93

94
struct _tree {
95
   object_t object;
96
};
97

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

107
extern object_arena_t *global_arena;
108

109
static inline tree_t tree_array_nth(item_t *item, unsigned n)
27,917,807✔
110
{
111
   object_t *o = obj_array_nth(item->obj_array, n);
27,917,807✔
112
   return container_of(o, struct _tree, object);
27,917,807✔
113
}
114

115
static inline void tree_array_add(item_t *item, tree_t t)
10,322✔
116
{
117
   obj_array_add(&(item->obj_array), &(t->object));
10,322✔
118
}
10,322✔
119

120
static inline type_t type_array_nth(item_t *item, unsigned n)
3,606,619✔
121
{
122
   object_t *o = obj_array_nth(item->obj_array, n);
3,606,619✔
123
   return container_of(o, struct _type, object);
3,606,619✔
124
}
125

126
static inline void type_array_add(item_t *item, type_t t)
111,243✔
127
{
128
   obj_array_add(&(item->obj_array), &(t->object));
111,243✔
129
}
111,243✔
130

131
type_t type_new(type_kind_t kind)
108,541✔
132
{
133
   object_t *o = object_new(NULL, &type_object, kind);
108,541✔
134
   return container_of(o, struct _type, object);
108,541✔
135
}
136

137
type_kind_t type_kind(type_t t)
10,183,237✔
138
{
139
   assert(t != NULL);
10,183,237✔
140
   return t->object.kind;
10,183,237✔
141
}
142

143
static inline type_t type_base_map(type_t t, hash_t *map)
1,349,409✔
144
{
145
   assert(t->object.kind == T_SUBTYPE);
1,349,409✔
146
   type_t base = type_base(t);
1,349,409✔
147
   if (map != NULL)
1,349,409✔
148
      return hash_get(map, base) ?: base;
5,683✔
149
   else
150
      return base;
151
}
152

153
static inline type_t type_result_or_null(type_t t)
7,335,239✔
154
{
155
   item_t *item = lookup_item(&type_object, t, I_RESULT);
7,335,239✔
156
   if (item->object == NULL)
7,335,239✔
157
      return NULL;
158
   else
159
      return container_of(item->object, struct _type, object);
7,201,486✔
160
}
161

162
static bool _type_eq(type_t a, type_t b, bool strict, hash_t *map)
31,816,948✔
163
{
164
   assert(a != NULL);
31,816,948✔
165
   assert(b != NULL);
31,816,948✔
166

167
   if (a == b)
31,816,948✔
168
      return true;
169

170
   type_kind_t kind_a = a->object.kind;
28,478,879✔
171
   type_kind_t kind_b = b->object.kind;
28,478,879✔
172

173
   if (map != NULL) {
28,478,879✔
174
      a = hash_get(map, a) ?: a;
32,559✔
175
      kind_a = a->object.kind;
32,559✔
176

177
      b = hash_get(map, b) ?: b;
32,559✔
178
      kind_b = b->object.kind;
32,559✔
179

180
      if (a == b)
32,559✔
181
         return true;
182
   }
183

184
   if (!strict) {
28,476,365✔
185
      // Subtypes are convertible to the base type
186
      while ((kind_a = a->object.kind) == T_SUBTYPE)
28,867,056✔
187
         a = type_base_map(a, map);
393,329✔
188
      while ((kind_b = b->object.kind) == T_SUBTYPE)
29,429,807✔
189
         b = type_base_map(b, map);
956,080✔
190

191
      if (a == b)
28,473,727✔
192
         return true;
193
   }
194

195
   const imask_t has = has_map[a->object.kind];
28,220,111✔
196

197
   if (!(has & I_PARAMS)) {
28,220,111✔
198
      ident_t ai = lookup_item(&type_object, a, I_IDENT)->ident;
24,553,577✔
199
      ident_t bi = lookup_item(&type_object, b, I_IDENT)->ident;
24,553,577✔
200

201
      if (ai != bi)
24,553,577✔
202
         return false;
203
      else if (ai == NULL && kind_a == T_GENERIC)
1,538✔
204
         return false;   // Anonymous generic types are distinct
205
   }
206

207
   if (kind_a == T_INCOMPLETE || kind_b == T_INCOMPLETE)
3,667,728✔
208
      return true;
209

210
   if (kind_a != kind_b)
3,666,841✔
211
      return false;
212

213
   if (kind_a == T_ARRAY)
3,666,767✔
214
      return _type_eq(type_elem(a), type_elem(b), strict, map);
×
215

216
   if (kind_a == T_ACCESS)
3,666,767✔
217
      return _type_eq(type_designated(a), type_designated(b), strict, map);
×
218

219
   if ((has & I_DIMS) && (type_dims(a) != type_dims(b)))
3,666,767✔
220
      return false;
221

222
   if (kind_a == T_SIGNATURE) {
3,666,767✔
223
      type_t ra = type_result_or_null(a);
3,666,460✔
224
      type_t rb = type_result_or_null(b);
3,666,460✔
225

226
      if (ra != NULL && rb != NULL) {
3,666,460✔
227
         if (!_type_eq(ra, rb, strict, map))
3,599,372✔
228
            return false;
229
      }
230
      else if (ra != NULL || rb != NULL)
67,088✔
231
         return false;
232
   }
233

234
   if (has & I_PARAMS) {
1,621,313✔
235
      item_t *ap = lookup_item(&type_object, a, I_PARAMS);
1,621,006✔
236
      item_t *bp = lookup_item(&type_object, b, I_PARAMS);
1,621,006✔
237

238
      const int acount = obj_array_count(ap->obj_array);
1,621,006✔
239
      const int bcount = obj_array_count(bp->obj_array);
1,621,006✔
240

241
      if (acount != bcount)
1,621,006✔
242
         return false;
243

244
      for (int i = 0; i < acount; i++) {
1,715,751✔
245
         type_t ai = type_array_nth(ap, i);
1,680,603✔
246
         type_t bi = type_array_nth(bp, i);
1,680,603✔
247
         if (ai != bi && !_type_eq(ai, bi, strict, map))
1,680,603✔
248
            return false;
249
      }
250
   }
251

252
   return true;
253
}
254

255
bool type_strict_eq(type_t a, type_t b)
23,125✔
256
{
257
   return _type_eq(a, b, true, NULL);
23,125✔
258
}
259

260
bool type_eq(type_t a, type_t b)
26,246,486✔
261
{
262
   return _type_eq(a, b, false, NULL);
26,246,486✔
263
}
264

265
bool type_eq_map(type_t a, type_t b, hash_t *map)
422,558✔
266
{
267
   return _type_eq(a, b, false, map);
422,558✔
268
}
269

270
ident_t type_ident(type_t t)
361,595✔
271
{
272
   assert(t != NULL);
363,455✔
273

274
   item_t *item = lookup_item(&type_object, t, I_IDENT);
363,455✔
275
   if (item->ident == NULL) {
363,455✔
276
      switch (t->object.kind) {
1,895✔
277
      case T_SUBTYPE:
1,860✔
278
         return type_ident(type_base(t));
1,860✔
279
      case T_NONE:
35✔
280
         return ident_new("none");
35✔
281
      case T_GENERIC:
×
282
         return ident_new("anonymous");
×
283
      default:
×
284
         fatal_trace("type kind %s has no ident",
285
                     type_kind_str(t->object.kind));
286
      }
287
   }
288
   else
289
      return item->ident;
290
}
291

292
bool type_has_ident(type_t t)
115,268✔
293
{
294
   assert(t != NULL);
115,268✔
295
   return (lookup_item(&type_object, t, I_IDENT)->ident != NULL);
115,268✔
296
}
297

298
void type_set_ident(type_t t, ident_t id)
72,535✔
299
{
300
   assert(t != NULL);
72,535✔
301
   lookup_item(&type_object, t, I_IDENT)->ident = id;
72,535✔
302
}
72,535✔
303

304
unsigned type_dims(type_t t)
7,270✔
305
{
306
   item_t *item = lookup_item(&type_object, t, I_DIMS);
7,270✔
307
   return obj_array_count(item->obj_array);
7,270✔
308
}
309

310
tree_t type_dim(type_t t, unsigned n)
969,820✔
311
{
312
   item_t *item = lookup_item(&type_object, t, I_DIMS);
969,820✔
313
   return tree_array_nth(item, n);
969,820✔
314
}
315

316
void type_add_dim(type_t t, tree_t r)
701✔
317
{
318
   tree_array_add(lookup_item(&type_object, t, I_DIMS), r);
701✔
319
   object_write_barrier(&(t->object), &(r->object));
701✔
320
}
701✔
321

322
type_t type_base(type_t t)
13,347,232✔
323
{
324
   item_t *item = lookup_item(&type_object, t, I_BASE);
13,347,232✔
325
   assert(item->object != NULL);
13,347,232✔
326
   return container_of(item->object, struct _type, object);
13,347,232✔
327
}
328

329
void type_set_base(type_t t, type_t b)
46,213✔
330
{
331
   lookup_item(&type_object, t, I_BASE)->object = &(b->object);
46,213✔
332
   object_write_barrier(&(t->object), &(b->object));
46,213✔
333
}
46,213✔
334

335
type_t type_elem(type_t t)
1,663,732✔
336
{
337
   assert(t != NULL);
3,050,374✔
338

339
   if (t->object.kind == T_NONE)
3,050,374✔
340
      return t;
341
   else {
342
      item_t *item = lookup_item(&type_object, t, I_ELEM);
3,050,374✔
343
      if (t->object.kind == T_SUBTYPE && item->object == NULL)
3,050,374✔
344
         return type_elem(type_base(t));
1,386,642✔
345
      else {
346
         assert(item->object != NULL);
1,663,732✔
347
         return container_of(item->object, struct _type, object);
348
      }
349
   }
350
}
351

352
void type_set_elem(type_t t, type_t e)
6,933✔
353
{
354
   lookup_item(&type_object, t, I_ELEM)->object = &(e->object);
6,933✔
355
   object_write_barrier(&(t->object), &(e->object));
6,933✔
356
}
6,933✔
357

358
bool type_has_elem(type_t t)
13,125✔
359
{
360
   return lookup_item(&type_object, t, I_ELEM)->object != NULL;
13,125✔
361
}
362

363
unsigned type_subkind(type_t t)
7,992✔
364
{
365
   item_t *item = lookup_item(&type_object, t, I_SUBKIND);
7,992✔
366
   return item->ival;
7,992✔
367
}
368

369
void type_set_subkind(type_t t, unsigned sub)
292✔
370
{
371
   lookup_item(&type_object, t, I_SUBKIND)->ival = sub;
292✔
372
}
292✔
373

374
bool type_is_universal(type_t t)
7,324✔
375
{
376
   assert(t != NULL);
7,324✔
377

378
   switch (t->object.kind) {
7,324✔
379
   case T_INTEGER:
3,317✔
380
      return t == std_type(NULL, STD_UNIVERSAL_INTEGER);
3,317✔
381
   case T_REAL:
4✔
382
      return t == std_type(NULL, STD_UNIVERSAL_REAL);
4✔
383
   default:
384
      return false;
385
   }
386
}
387

388
unsigned type_units(type_t t)
4,783✔
389
{
390
   item_t *item = lookup_item(&type_object, t, I_UNITS);
4,783✔
391
   return obj_array_count(item->obj_array);
4,783✔
392
}
393

394
tree_t type_unit(type_t t, unsigned n)
45,638✔
395
{
396
   item_t *item = lookup_item(&type_object, t, I_UNITS);
45,638✔
397
   return tree_array_nth(item, n);
45,638✔
398
}
399

400
void type_add_unit(type_t t, tree_t u)
158✔
401
{
402
   tree_array_add(lookup_item(&type_object, t, I_UNITS), u);
158✔
403
   object_write_barrier(&(t->object), &(u->object));
158✔
404
}
158✔
405

406
unsigned type_enum_literals(type_t t)
734,817✔
407
{
408
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
734,817✔
409
   return obj_array_count(item->obj_array);
734,817✔
410
}
411

412
tree_t type_enum_literal(type_t t, unsigned n)
26,598,333✔
413
{
414
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
26,598,333✔
415
   return tree_array_nth(item, n);
26,598,333✔
416
}
417

418
void type_enum_add_literal(type_t t, tree_t lit)
4,854✔
419
{
420
   assert(tree_kind(lit) == T_ENUM_LIT);
4,854✔
421
   tree_array_add(lookup_item(&type_object, t, I_LITERALS), lit);
4,854✔
422
   object_write_barrier(&(t->object), &(lit->object));
4,854✔
423
}
4,854✔
424

425
unsigned type_params(type_t t)
3,411✔
426
{
427
   item_t *item = lookup_item(&type_object, t, I_PARAMS);
3,411✔
428
   return obj_array_count(item->obj_array);
3,411✔
429
}
430

431
type_t type_param(type_t t, unsigned n)
3,261✔
432
{
433
   item_t *item = lookup_item(&type_object, t, I_PARAMS);
3,261✔
434
   return type_array_nth(item, n);
3,261✔
435
}
436

437
void type_add_param(type_t t, type_t p)
107,844✔
438
{
439
   type_array_add(lookup_item(&type_object, t, I_PARAMS), p);
107,844✔
440
   object_write_barrier(&(t->object), &(p->object));
107,844✔
441
}
107,844✔
442

443
unsigned type_fields(type_t t)
107,806✔
444
{
445
   if (t->object.kind == T_SUBTYPE)
138,859✔
446
      return type_fields(type_base(t));
31,053✔
447
   else {
448
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
107,806✔
449
      return obj_array_count(item->obj_array);
107,806✔
450
   }
451
}
452

453
tree_t type_field(type_t t, unsigned n)
304,016✔
454
{
455
   if (t->object.kind == T_SUBTYPE)
367,652✔
456
      return type_field(type_base(t), n);
63,636✔
457
   else {
458
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
304,016✔
459
      return tree_array_nth(item, n);
304,016✔
460
   }
461
}
462

463
void type_add_field(type_t t, tree_t p)
4,609✔
464
{
465
   tree_array_add(lookup_item(&type_object, t, I_FIELDS), p);
4,609✔
466
   object_write_barrier(&(t->object), &(p->object));
4,609✔
467
}
4,609✔
468

469
type_t type_result(type_t t)
1,917,582✔
470
{
471
   item_t *item = lookup_item(&type_object, t, I_RESULT);
1,917,582✔
472
   assert(item->object != NULL);
1,917,582✔
473
   return container_of(item->object, struct _type, object);
1,917,582✔
474
}
475

476
bool type_has_result(type_t t)
3,086,187✔
477
{
478
   return lookup_item(&type_object, t, I_RESULT)->object != NULL;
3,086,187✔
479
}
480

481
void type_set_result(type_t t, type_t r)
50,828✔
482
{
483
   lookup_item(&type_object, t, I_RESULT)->object = &(r->object);
50,828✔
484
   object_write_barrier(&(t->object), &(r->object));
50,828✔
485
}
50,828✔
486

487
unsigned type_indexes(type_t t)
1,457,519✔
488
{
489
   item_t *item = lookup_item(&type_object, t, I_INDEXES);
1,457,519✔
490
   return obj_array_count(item->obj_array);
1,457,519✔
491
}
492

493
void type_add_index(type_t t, type_t sub)
3,399✔
494
{
495
   type_array_add(lookup_item(&type_object, t, I_INDEXES), sub);
3,399✔
496
   object_write_barrier(&(t->object), &(sub->object));
3,399✔
497
}
3,399✔
498

499
type_t type_index(type_t t, unsigned n)
242,152✔
500
{
501
   item_t *item = lookup_item(&type_object, t, I_INDEXES);
242,152✔
502
   return type_array_nth(item, n);
242,152✔
503
}
504

505
tree_t type_constraint(type_t t)
2,793,242✔
506
{
507
   item_t *item = lookup_item(&type_object, t, I_CONSTRAINT);
2,793,242✔
508
   assert(item->object != NULL);
2,793,242✔
509
   return container_of(item->object, struct _tree, object);
2,793,242✔
510
}
511

512
bool type_has_constraint(type_t t)
2,866,541✔
513
{
514
   item_t *item = lookup_item(&type_object, t, I_CONSTRAINT);
2,866,541✔
515
   return item->object != NULL;
2,866,541✔
516
}
517

518
void type_set_constraint(type_t t, tree_t c)
45,348✔
519
{
520
   assert(c->object.kind == T_CONSTRAINT);
45,348✔
521
   lookup_item(&type_object, t, I_CONSTRAINT)->object = &(c->object);
45,348✔
522
   object_write_barrier(&(t->object), &(c->object));
45,348✔
523
}
45,348✔
524

525
void type_set_resolution(type_t t, tree_t r)
356✔
526
{
527
   lookup_item(&type_object, t, I_RESOLUTION)->object = &(r->object);
356✔
528
   object_write_barrier(&(t->object), &(r->object));
356✔
529
}
356✔
530

531
bool type_has_resolution(type_t t)
58,115✔
532
{
533
   return lookup_item(&type_object, t, I_RESOLUTION)->object != NULL;
58,115✔
534
}
535

536
tree_t type_resolution(type_t t)
10,370✔
537
{
538
   item_t *item = lookup_item(&type_object, t, I_RESOLUTION);
10,370✔
539
   assert(item->object != NULL);
10,370✔
540
   return container_of(item->object, struct _tree, object);
10,370✔
541
}
542

543
type_t type_designated(type_t t)
14,935✔
544
{
545
   if (t->object.kind == T_SUBTYPE)
14,936✔
546
      return type_designated(type_base(t));
1✔
547
   else {
548
      item_t *item = lookup_item(&type_object, t, I_DESIGNATED);
14,935✔
549
      assert(item->object != NULL);
14,935✔
550
      return container_of(item->object, struct _type, object);
14,935✔
551
   }
552
}
553

554
void type_set_designated(type_t t, type_t d)
520✔
555
{
556
   lookup_item(&type_object, t, I_DESIGNATED)->object = &(d->object);
520✔
557
   object_write_barrier(&(t->object), &(d->object));
520✔
558
}
520✔
559

560
void type_signature(type_t t, text_buf_t *tb)
2,293✔
561
{
562
   assert(t->object.kind == T_SIGNATURE);
2,293✔
563

564
   tb_printf(tb, "[");
2,293✔
565
   const int nparams = type_params(t);
2,293✔
566
   for (int i = 0; i < nparams; i++)
3,685✔
567
      tb_printf(tb, "%s%s", (i == 0 ? "" : ", "),
1,902✔
568
                type_pp(type_param(t, i)));
569
   type_t r = type_result_or_null(t);
2,293✔
570
   if (r != NULL)
2,293✔
571
      tb_printf(tb, "%sreturn %s", nparams > 0 ? " " : "", type_pp(r));
3,048✔
572
   tb_printf(tb, "]");
2,293✔
573
}
2,293✔
574

575
const char *type_pp2(type_t t, type_t other)
13,303✔
576
{
577
   assert(t != NULL);
13,303✔
578

579
   switch (type_kind(t)) {
13,303✔
580
   case T_SIGNATURE:
2,603✔
581
      {
582
         static hash_t *cache = NULL;
2,603✔
583
         if (cache == NULL)
2,603✔
584
            cache = hash_new(64);
488✔
585

586
         text_buf_t *tb = hash_get(cache, t);
2,603✔
587
         if (tb == NULL) {
2,603✔
588
            tb = tb_new();
1,027✔
589
            hash_put(cache, t, tb);
1,027✔
590

591
            if (type_has_ident(t)) {
1,027✔
592
               tb_istr(tb, type_ident(t));
1,024✔
593
               tb_append(tb, ' ');
1,024✔
594
            }
595
            type_signature(t, tb);
1,027✔
596
         }
597

598
         return tb_get(tb);
2,603✔
599
      }
600

601
   case T_GENERIC:
214✔
602
      if (!type_has_ident(t))
214✔
603
         return "(an anonymous type)";
604
      // Fall-through
605

606
   default:
607
      {
608
         const char *full1 = istr(type_ident(t));
10,698✔
609
         const char *dot1  = strrchr(full1, '.');
10,698✔
610
         const char *tail1 = dot1 ? dot1 + 1 : full1;
10,698✔
611

612
         if (other != NULL) {
10,698✔
613
            const char *full2 = istr(type_ident(other));
168✔
614
            const char *dot2  = strrchr(full2, '.');
168✔
615
            const char *tail2 = dot2 ? dot2 + 1 : full2;
168✔
616

617
            return strcmp(tail1, tail2) ? tail1 : full1;
168✔
618
         }
619
         else
620
            return tail1;
621
      }
622
   }
623
}
624

625
const char *type_pp(type_t t)
13,135✔
626
{
627
   return type_pp2(t, NULL);
13,135✔
628
}
629

630
type_kind_t type_base_kind(type_t t)
28,375,841✔
631
{
632
   assert(t != NULL);
36,932,420✔
633
   if (t->object.kind == T_SUBTYPE)
36,932,420✔
634
      return type_base_kind(type_base(t));
8,556,579✔
635
   else
636
      return t->object.kind;
28,375,841✔
637
}
638

639
bool type_is_array(type_t t)
5,532,579✔
640
{
641
   const type_kind_t base = type_base_kind(t);
5,532,579✔
642
   if (base == T_GENERIC)
5,532,579✔
643
      return type_subkind(type_base_recur(t)) == GTYPE_ARRAY;
2,352✔
644
   else
645
      return base == T_ARRAY;
5,530,227✔
646
}
647

648
bool type_is_record(type_t t)
3,274,011✔
649
{
650
   return type_base_kind(t) == T_RECORD;
3,274,011✔
651
}
652

653
bool type_is_protected(type_t t)
179,513✔
654
{
655
   return type_base_kind(t) == T_PROTECTED;
179,513✔
656
}
657

658
bool type_is_file(type_t t)
123,531✔
659
{
660
   const type_kind_t base = type_base_kind(t);
123,531✔
661
   if (base == T_GENERIC)
123,531✔
662
      return type_subkind(type_base_recur(t)) == GTYPE_FILE;
414✔
663
   else
664
      return base == T_FILE;
123,117✔
665
}
666

667
bool type_is_access(type_t t)
242,178✔
668
{
669
   const type_kind_t base = type_base_kind(t);
242,178✔
670
   if (base == T_GENERIC)
242,178✔
671
      return type_subkind(type_base_recur(t)) == GTYPE_ACCESS;
1,438✔
672
   else
673
      return base == T_ACCESS;
240,740✔
674
}
675

676
bool type_is_incomplete(type_t t)
329,322✔
677
{
678
   return type_base_kind(t) == T_INCOMPLETE;
329,322✔
679
}
680

681
bool type_is_none(type_t t)
16,086,591✔
682
{
683
   return type_base_kind(t) == T_NONE;
16,086,591✔
684
}
685

686
bool type_is_valid(type_t t)
255✔
687
{
688
   return type_base_kind(t) != T_NONE;
255✔
689
}
690

691
bool type_has_error(type_t t)
28✔
692
{
693
   switch (t->object.kind) {
28✔
694
   case T_NONE:
695
      return true;
696
   case T_SIGNATURE:
26✔
697
      {
698
         type_t r = type_result_or_null(t);
26✔
699
         if (r != NULL && type_is_none(r))
26✔
700
            return true;
701

702
         const int nparams = type_params(t);
26✔
703
         for (int i = 0; i < nparams; i++) {
52✔
704
            if (type_is_none(type_param(t, i)))
28✔
705
               return true;
706
         }
707

708
         return false;
709
      }
710
   case T_SUBTYPE:
×
711
      return type_is_none(type_base(t));
×
712
   default:
2✔
713
      return false;
2✔
714
   }
715
}
716

717
tree_t type_constraint_for_field(type_t t, tree_t f)
11,931✔
718
{
719
   if (t->object.kind != T_SUBTYPE)
11,964✔
720
      return NULL;
721
   else if (!type_has_constraint(t))
10,729✔
722
      return NULL;
723

724
   tree_t c = type_constraint(t);
10,500✔
725

726
   if (tree_subkind(c) != C_RECORD)
10,500✔
727
      return NULL;
728

729
   const int nelem = tree_ranges(c);
10,500✔
730
   for (int i = 0; i < nelem; i++) {
14,815✔
731
      tree_t ei = tree_range(c, i);
14,782✔
732
      assert(tree_kind(ei) == T_ELEM_CONSTRAINT);
14,782✔
733

734
      if (tree_has_ref(ei) && tree_ref(ei) == f)
14,782✔
735
         return ei;
10,467✔
736
   }
737

738

739
   return type_constraint_for_field(type_base(t), f);
33✔
740
}
741

742
bool type_is_unconstrained(type_t t)
2,709,306✔
743
{
744
   assert(t != NULL);
2,709,306✔
745

746
   if (t->object.kind == T_SUBTYPE) {
2,709,306✔
747
      if (type_is_record(t)) {
1,367,712✔
748
         if (standard() >= STD_08) {
26,899✔
749
            const int nfields = type_fields(t);
25,484✔
750
            for (int i = 0; i < nfields; i++) {
76,003✔
751
               tree_t f = type_field(t, i);
50,573✔
752
               if (!type_is_unconstrained(tree_type(f)))
50,573✔
753
                  continue;
41,823✔
754

755
               tree_t ec = type_constraint_for_field(t, f);
8,750✔
756
               if (ec == NULL || type_is_unconstrained(tree_type(ec)))
8,750✔
757
                  return true;
54✔
758
            }
759
         }
760

761
         return false;
26,845✔
762
      }
763
      else if (type_is_array(t)) {
1,340,813✔
764
         if (standard() >= STD_08) {
1,122,448✔
765
            if (type_is_array(t)) {
418,183✔
766
               type_t elem = type_elem(t);
418,183✔
767
               if (type_is_unconstrained(elem))
418,183✔
768
                  return true;
769
            }
770
         }
771

772
         for (; t->object.kind == T_SUBTYPE; t = type_base(t)) {
1,156,506✔
773
            if (type_has_constraint(t)) {
1,129,600✔
774
               tree_t c = type_constraint(t);
1,094,221✔
775
               if (tree_subkind(c) == C_INDEX)
1,094,221✔
776
                  return false;
777
            }
778
         }
779

780
         assert(t->object.kind == T_ARRAY);
26,906✔
781
         return true;
782
      }
783
      else
784
         return false;
785
   }
786
   else if (t->object.kind == T_ARRAY)
1,341,594✔
787
      return true;
788
   else if (t->object.kind == T_GENERIC && type_subkind(t) == GTYPE_ARRAY)
915,849✔
789
      return true;
790
   else if (t->object.kind == T_RECORD && standard() >= STD_08) {
915,740✔
791
      const int nfields = type_fields(t);
18,355✔
792
      for (int i = 0; i < nfields; i++) {
61,827✔
793
         if (type_is_unconstrained(tree_type(type_field(t, i))))
46,150✔
794
            return true;
795
      }
796
      return false;
797
   }
798
   else
799
      return false;
897,385✔
800
}
801

802
bool type_is_enum(type_t t)
157,952✔
803
{
804
   return type_base_kind(t) == T_ENUM;
157,952✔
805
}
806

807
bool type_is_discrete(type_t t)
25,411✔
808
{
809
   const type_kind_t base = type_base_kind(t);
25,411✔
810
   if (base == T_GENERIC) {
25,411✔
811
      const gtype_class_t class = type_subkind(type_base_recur(t));
55✔
812
      return class == GTYPE_INTEGER || class == GTYPE_DISCRETE;
55✔
813
   }
814
   else
815
      return base == T_INTEGER || base == T_ENUM;
25,356✔
816
}
817

818
bool type_is_numeric(type_t t)
8,708✔
819
{
820
   const type_kind_t base = type_base_kind(t);
8,708✔
821
   if (base == T_GENERIC) {
8,708✔
822
      const gtype_class_t class = type_subkind(type_base_recur(t));
9✔
823
      return class == GTYPE_INTEGER || class == GTYPE_FLOATING;
9✔
824
   }
825
   else
826
      return base == T_INTEGER || base == T_REAL;
8,699✔
827
}
828

829
bool type_is_subprogram(type_t t)
1,078,177✔
830
{
831
   return t->object.kind == T_SIGNATURE;
1,078,177✔
832
}
833

834
bool type_is_physical(type_t t)
524✔
835
{
836
   const type_kind_t base = type_base_kind(t);
524✔
837
   if (base == T_GENERIC)
524✔
838
      return type_subkind(type_base_recur(t)) == GTYPE_PHYSICAL;
1✔
839
   else
840
      return base == T_PHYSICAL;
523✔
841
}
842

843
bool type_is_integer(type_t t)
801,617✔
844
{
845
   const type_kind_t base = type_base_kind(t);
801,617✔
846
   if (base == T_GENERIC)
801,617✔
847
      return type_subkind(type_base_recur(t)) == GTYPE_INTEGER;
43✔
848
   else
849
      return base == T_INTEGER;
801,574✔
850
}
851

852
bool type_is_real(type_t t)
53,596✔
853
{
854
   const type_kind_t base = type_base_kind(t);
53,596✔
855
   if (base == T_GENERIC)
53,596✔
856
      return type_subkind(type_base_recur(t)) == GTYPE_FLOATING;
4✔
857
   else
858
      return base == T_REAL;
53,592✔
859
}
860

861
bool type_is_generic(type_t t)
219,891✔
862
{
863
   return type_base_kind(t) == T_GENERIC;
219,891✔
864
}
865

866
bool type_is_scalar(type_t t)
1,214,049✔
867
{
868
   const type_kind_t base = type_base_kind(t);
1,214,049✔
869
   if (base == T_GENERIC) {
1,214,049✔
870
      const gtype_class_t class = type_subkind(type_base_recur(t));
941✔
871
      return class == GTYPE_SCALAR || class == GTYPE_DISCRETE
941✔
872
         || class == GTYPE_FLOATING || class == GTYPE_INTEGER;
1,797✔
873
   }
874
   else
875
      return base == T_INTEGER || base == T_REAL
1,213,108✔
876
         || base == T_ENUM || base == T_PHYSICAL || base == T_NONE;
1,213,108✔
877
}
878

879
bool type_is_representable(type_t t)
83,073✔
880
{
881
   if (type_is_scalar(t))
85,789✔
882
      return true;
883
   else if (standard() < STD_19) {
32,188✔
884
      if (type_is_array(t) && dimension_of(t) == 1) {
26,754✔
885
         type_t elem = type_elem(t);
21,961✔
886
         return type_is_enum(elem) && all_character_literals(elem);
27,902✔
887
      }
888
      else
889
         return false;
4,793✔
890
   }
891
   else if (type_is_record(t)) {
5,434✔
892
      const int nfields = type_fields(t);
1,074✔
893
      for (int i = 0; i < nfields; i++) {
3,183✔
894
         if (!type_is_representable(tree_type(type_field(t, i))))
2,548✔
895
            return false;
896
      }
897

898
      return true;
899
   }
900
   else if (type_is_array(t))
4,360✔
901
      return type_is_representable(type_elem(t));
2,716✔
902
   else
903
      return false;
904
}
905

906
bool type_const_bounds(type_t t)
1,232,819✔
907
{
908
   if (type_is_unconstrained(t))
1,232,819✔
909
      return false;
910
   else if (type_is_record(t)) {
1,062,713✔
911
      const int nfields = type_fields(t);
25,761✔
912
      for (int i = 0; i < nfields; i++) {
109,485✔
913
         type_t ftype = tree_type(type_field(t, i));
86,755✔
914
         if (!type_const_bounds(ftype))
86,755✔
915
            return false;
916
      }
917

918
      return true;
919
   }
920
   else if (type_is_array(t)) {
1,036,952✔
921
      const int ndims = dimension_of(t);
518,589✔
922
      for (int i = 0; i < ndims; i++) {
1,023,672✔
923
         int64_t low, high;
612,957✔
924
         if (!folded_bounds(range_of(t, i), &low, &high))
612,957✔
925
            return false;
107,874✔
926
      }
927

928
      return type_const_bounds(type_elem(t));
410,715✔
929
   }
930
   else if (type_is_integer(t)) {
518,363✔
931
      int64_t low, high;
88,285✔
932
      return folded_bounds(range_of(t, 0), &low, &high);
88,285✔
933
   }
934
   else
935
      return true;
936
}
937

938
type_t type_base_recur(type_t t)
573,658✔
939
{
940
   assert(t != NULL);
573,658✔
941
   while (t->object.kind == T_SUBTYPE)
819,640✔
942
      t = type_base(t);
245,982✔
943
   return t;
573,658✔
944
}
945

946
type_t type_elem_recur(type_t type)
144,676✔
947
{
948
   while (type_is_array(type))
292,473✔
949
      type = type_elem(type);
147,797✔
950
   return type;
144,676✔
951
}
952

953
void type_copy_mark(type_t t, object_copy_ctx_t *ctx)
762✔
954
{
955
   object_copy_mark_root(&(t->object), ctx);
762✔
956
}
762✔
957

958
const char *type_kind_str(type_kind_t t)
5,492✔
959
{
960
   assert(t < T_LAST_TYPE_KIND);
5,492✔
961
   return kind_text_map[t];
5,492✔
962
}
963

964
unsigned type_width(type_t type)
695✔
965
{
966
   if (type_is_array(type)) {
695✔
967
      const unsigned elem_w = type_width(type_elem(type));
226✔
968
      unsigned w = 1;
226✔
969
      const int ndims = dimension_of(type);
226✔
970
      for (int i = 0; i < ndims; i++) {
458✔
971
         int64_t low, high;
232✔
972
         range_bounds(range_of(type, i), &low, &high);
232✔
973
         w *= MAX(high - low + 1, 0);
232✔
974
      }
975
      return w * elem_w;
226✔
976
   }
977
   else {
978
      type_is_scalar(type);
469✔
979
      return 1;
469✔
980
   }
981
}
982

983
bool type_is_composite(type_t t)
86,104✔
984
{
985
   const type_kind_t base = type_base_kind(t);
86,104✔
986
   return base == T_ARRAY || base == T_RECORD;
86,104✔
987
}
988

989
bool type_is_homogeneous(type_t t)
155,658✔
990
{
991
   if (type_is_scalar(t))
216,389✔
992
      return true;
993
   else if (type_is_array(t))
76,223✔
994
      return type_is_homogeneous(type_elem(t));
60,731✔
995
   else
996
      return false;
997
}
998

999
bool type_is_resolved(type_t t)
102✔
1000
{
1001
   if (t->object.kind == T_SUBTYPE)
102✔
1002
      return type_has_resolution(t) || type_is_resolved(type_base(t));
27✔
1003
   else
1004
      return false;
1005
}
1006

1007
bool type_frozen(type_t t)
327✔
1008
{
1009
   return arena_frozen(object_arena(&(t->object)));
327✔
1010
}
1011

1012
tree_t type_container(type_t t)
192✔
1013
{
1014
   object_t *o = arena_root(object_arena(&(t->object)));
192✔
1015
   assert(o->tag == OBJECT_TAG_TREE);
192✔
1016
   return container_of(o, struct _tree, object);
192✔
1017
}
1018

1019
object_t *type_to_object(type_t t)
5,228✔
1020
{
1021
   return t ? &(t->object) : NULL;
5,228✔
1022
}
1023

1024
type_t type_from_object(object_t *obj)
1,493✔
1025
{
1026
   assert(obj->tag == OBJECT_TAG_TYPE);
1,493✔
1027
   return container_of(obj, struct _type, object);
1,493✔
1028
}
1029

1030
int type_bit_width(type_t type)
17,555✔
1031
{
1032
   switch (type_kind(type)) {
35,368✔
1033
   case T_INTEGER:
5,254✔
1034
   case T_PHYSICAL:
1035
      {
1036
         tree_t r = range_of(type, 0);
5,254✔
1037
         return bits_for_range(assume_int(tree_left(r)),
5,254✔
1038
                               assume_int(tree_right(r)));
1039
      }
1040

1041
   case T_REAL:
1042
       // All real types are doubles at the moment
1043
       return 64;
1044

1045
   case T_SUBTYPE:
11,403✔
1046
      return type_bit_width(type_base(type));
11,403✔
1047

1048
   case T_ENUM:
10,911✔
1049
      return bits_for_range(0, type_enum_literals(type) - 1);
10,911✔
1050

1051
   case T_ARRAY:
6,410✔
1052
      return type_bit_width(type_elem(type));
6,410✔
1053

UNCOV
1054
   default:
×
1055
      fatal_trace("unhandled type %s in type_bit_width", type_pp(type));
1056
   }
1057
}
1058

1059
int type_byte_width(type_t type)
16,428✔
1060
{
1061
   return (type_bit_width(type) + 7) / 8;
16,428✔
1062
}
1063

1064
bool type_is_character_array(type_t t)
29,428✔
1065
{
1066
   // LRM 93 section 3.1.1 an enumeration type is a character type if at
1067
   // least one of its enumeration literals is a character literal
1068

1069
   if (!type_is_array(t))
29,428✔
1070
      return false;
1071

1072
   if (dimension_of(t) != 1)
26,256✔
1073
      return false;
1074

1075
   type_t elem = type_base_recur(type_elem(t));
26,255✔
1076

1077
   if (!type_is_enum(elem))
26,255✔
1078
      return false;
1079

1080
   const int nlits = type_enum_literals(elem);
26,214✔
1081
   for (int i = 0; i < nlits; i++) {
442,978✔
1082
      tree_t lit = type_enum_literal(elem, i);
442,964✔
1083
      if (ident_char(tree_ident(lit), 0) == '\'')
442,964✔
1084
         return true;
1085
   }
1086

1087
   return false;
1088
}
1089

1090
bool type_matches_class(type_t t, gtype_class_t class)
399✔
1091
{
1092
   switch (class) {
399✔
1093
   case GTYPE_PRIVATE:
1094
      return true;
1095
   case GTYPE_SCALAR:
7✔
1096
      return type_is_scalar(t);
7✔
1097
   case GTYPE_DISCRETE:
52✔
1098
      return type_is_discrete(t);
52✔
1099
   case GTYPE_INTEGER:
14✔
1100
      return type_is_integer(t);
14✔
1101
   case GTYPE_FLOATING:
3✔
1102
      return type_is_real(t);
3✔
1103
   case GTYPE_PHYSICAL:
3✔
1104
      return type_is_physical(t);
3✔
1105
   case GTYPE_ACCESS:
5✔
1106
      return type_is_access(t);
5✔
1107
   case GTYPE_ARRAY:
53✔
1108
      return type_is_array(t);
53✔
1109
   case GTYPE_FILE:
6✔
1110
      return type_is_file(t);
6✔
UNCOV
1111
   default:
×
UNCOV
1112
      return false;
×
1113
   }
1114
}
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