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

nickg / nvc / 13577502570

27 Feb 2025 09:17AM UTC coverage: 92.149% (-0.003%) from 92.152%
13577502570

push

github

nickg
Remove open constraint type

10 of 10 new or added lines in 2 files covered. (100.0%)

273 existing lines in 4 files now uncovered.

64366 of 69850 relevant lines covered (92.15%)

505145.57 hits per line

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

96.56
/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,413,781✔
110
{
111
   object_t *o = obj_array_nth(item->obj_array, n);
27,413,781✔
112
   return container_of(o, struct _tree, object);
27,413,781✔
113
}
114

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

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

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

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

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

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

153
static inline type_t type_result_or_null(type_t t)
6,791,836✔
154
{
155
   item_t *item = lookup_item(&type_object, t, I_RESULT);
6,791,836✔
156
   if (item->object == NULL)
6,791,836✔
157
      return NULL;
158
   else
159
      return container_of(item->object, struct _type, object);
6,672,397✔
160
}
161

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

167
   if (a == b)
28,839,178✔
168
      return true;
169

170
   type_kind_t kind_a = a->object.kind;
25,732,310✔
171
   type_kind_t kind_b = b->object.kind;
25,732,310✔
172

173
   if (map != NULL) {
25,732,310✔
174
      a = hash_get(map, a) ?: a;
31,021✔
175
      kind_a = a->object.kind;
31,021✔
176

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

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

184
   if (!strict) {
25,729,882✔
185
      // Subtypes are convertible to the base type
186
      while ((kind_a = a->object.kind) == T_SUBTYPE)
26,092,894✔
187
         a = type_base_map(a, map);
365,661✔
188
      while ((kind_b = b->object.kind) == T_SUBTYPE)
26,613,696✔
189
         b = type_base_map(b, map);
886,463✔
190

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

195
   const imask_t has = has_map[a->object.kind];
25,487,626✔
196

197
   if (!(has & I_PARAMS)) {
25,487,626✔
198
      ident_t ai = lookup_item(&type_object, a, I_IDENT)->ident;
22,092,192✔
199
      ident_t bi = lookup_item(&type_object, b, I_IDENT)->ident;
22,092,192✔
200

201
      if (ai != bi)
22,092,192✔
202
         return false;
203
      else if (ai == NULL && kind_a == T_GENERIC)
1,356✔
204
         return false;   // Anonymous generic types are distinct
205
   }
206

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

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

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

216
   if (kind_a == T_ACCESS)
3,395,667✔
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,395,667✔
220
      return false;
221

222
   if (kind_a == T_SIGNATURE) {
3,395,667✔
223
      type_t ra = type_result_or_null(a);
3,395,365✔
224
      type_t rb = type_result_or_null(b);
3,395,365✔
225

226
      if (ra != NULL && rb != NULL) {
3,395,365✔
227
         if (!_type_eq(ra, rb, strict, map))
3,335,547✔
228
            return false;
229
      }
230
      else if (ra != NULL || rb != NULL)
59,818✔
231
         return false;
232
   }
233

234
   if (has & I_PARAMS) {
1,495,301✔
235
      item_t *ap = lookup_item(&type_object, a, I_PARAMS);
1,494,999✔
236
      item_t *bp = lookup_item(&type_object, b, I_PARAMS);
1,494,999✔
237

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

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

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

252
   return true;
253
}
254

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

260
bool type_eq(type_t a, type_t b)
23,676,951✔
261
{
262
   return _type_eq(a, b, false, NULL);
23,676,951✔
263
}
264

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

270
ident_t type_ident(type_t t)
274,527✔
271
{
272
   assert(t != NULL);
276,768✔
273

274
   item_t *item = lookup_item(&type_object, t, I_IDENT);
276,768✔
275
   if (item->ident == NULL) {
276,768✔
276
      switch (t->object.kind) {
2,276✔
277
      case T_SUBTYPE:
2,241✔
278
         return type_ident(type_base(t));
2,241✔
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)
96,286✔
293
{
294
   assert(t != NULL);
96,286✔
295
   return (lookup_item(&type_object, t, I_IDENT)->ident != NULL);
96,286✔
296
}
297

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

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

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

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

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

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

335
type_t type_elem(type_t t)
1,287,529✔
336
{
337
   assert(t != NULL);
2,377,287✔
338

339
   if (t->object.kind == T_NONE)
2,377,287✔
340
      return t;
341
   else {
342
      item_t *item = lookup_item(&type_object, t, I_ELEM);
2,377,287✔
343
      if (t->object.kind == T_SUBTYPE && item->object == NULL)
2,377,287✔
344
         return type_elem(type_base(t));
1,089,758✔
345
      else {
346
         assert(item->object != NULL);
1,287,529✔
347
         return container_of(item->object, struct _type, object);
348
      }
349
   }
350
}
351

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

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

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

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

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

378
   switch (t->object.kind) {
7,308✔
379
   case T_INTEGER:
3,309✔
380
      return t == std_type(NULL, STD_UNIVERSAL_INTEGER);
3,309✔
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,460✔
389
{
390
   item_t *item = lookup_item(&type_object, t, I_UNITS);
4,460✔
391
   return obj_array_count(item->obj_array);
4,460✔
392
}
393

394
tree_t type_unit(type_t t, unsigned n)
42,256✔
395
{
396
   item_t *item = lookup_item(&type_object, t, I_UNITS);
42,256✔
397
   return tree_array_nth(item, n);
42,256✔
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)
407,730✔
407
{
408
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
407,730✔
409
   return obj_array_count(item->obj_array);
407,730✔
410
}
411

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

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

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

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

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

443
unsigned type_fields(type_t t)
104,902✔
444
{
445
   if (t->object.kind == T_SUBTYPE)
139,739✔
446
      return type_fields(type_base(t));
34,837✔
447
   else {
448
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
104,902✔
449
      return obj_array_count(item->obj_array);
104,902✔
450
   }
451
}
452

453
tree_t type_field(type_t t, unsigned n)
289,178✔
454
{
455
   if (t->object.kind == T_SUBTYPE)
360,929✔
456
      return type_field(type_base(t), n);
71,751✔
457
   else {
458
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
289,178✔
459
      return tree_array_nth(item, n);
289,178✔
460
   }
461
}
462

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

579
   switch (type_kind(t)) {
6,661✔
580
   case T_SIGNATURE:
2,612✔
581
      {
582
         static hash_t *cache = NULL;
2,612✔
583
         if (cache == NULL)
2,612✔
584
            cache = hash_new(64);
445✔
585

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

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

598
         return tb_get(tb);
2,612✔
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));
4,047✔
609
         const char *dot1  = strrchr(full1, '.');
4,047✔
610
         const char *tail1 = dot1 ? dot1 + 1 : full1;
4,047✔
611

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

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

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

630
type_kind_t type_base_kind(type_t t)
25,461,555✔
631
{
632
   assert(t != NULL);
32,417,328✔
633
   if (t->object.kind == T_SUBTYPE)
32,417,328✔
634
      return type_base_kind(type_base(t));
6,955,773✔
635
   else
636
      return t->object.kind;
25,461,555✔
637
}
638

639
bool type_is_array(type_t t)
4,322,499✔
640
{
641
   const type_kind_t base = type_base_kind(t);
4,322,499✔
642
   if (base == T_GENERIC)
4,322,499✔
643
      return type_subkind(type_base_recur(t)) == GTYPE_ARRAY;
1,912✔
644
   else
645
      return base == T_ARRAY;
4,320,587✔
646
}
647

648
bool type_is_record(type_t t)
2,404,004✔
649
{
650
   return type_base_kind(t) == T_RECORD;
2,404,004✔
651
}
652

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

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

667
bool type_is_access(type_t t)
218,546✔
668
{
669
   const type_kind_t base = type_base_kind(t);
218,546✔
670
   if (base == T_GENERIC)
218,546✔
671
      return type_subkind(type_base_recur(t)) == GTYPE_ACCESS;
1,347✔
672
   else
673
      return base == T_ACCESS;
217,199✔
674
}
675

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

681
bool type_is_none(type_t t)
15,947,735✔
682
{
683
   return type_base_kind(t) == T_NONE;
15,947,735✔
684
}
685

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

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

702
         const int nparams = type_params(t);
25✔
703
         for (int i = 0; i < nparams; i++) {
49✔
704
            if (type_is_none(type_param(t, i)))
26✔
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)
9,929✔
718
{
719
   if (t->object.kind != T_SUBTYPE)
9,957✔
720
      return NULL;
721
   else if (!type_has_constraint(t))
8,649✔
722
      return NULL;
723

724
   tree_t c = type_constraint(t);
8,620✔
725

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

729
   const int nelem = tree_ranges(c);
8,620✔
730
   for (int i = 0; i < nelem; i++) {
12,683✔
731
      tree_t ei = tree_range(c, i);
12,655✔
732
      assert(tree_kind(ei) == T_ELEM_CONSTRAINT);
12,655✔
733

734
      if (tree_has_ref(ei) && tree_ref(ei) == f)
12,655✔
735
         return ei;
8,592✔
736
   }
737

738

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

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

746
   if (t->object.kind == T_SUBTYPE) {
2,133,127✔
747
      if (type_is_record(t)) {
1,086,388✔
748
         if (standard() >= STD_08) {
30,780✔
749
            const int nfields = type_fields(t);
29,416✔
750
            for (int i = 0; i < nfields; i++) {
88,221✔
751
               tree_t f = type_field(t, i);
58,832✔
752
               if (!type_is_unconstrained(tree_type(f)))
58,832✔
753
                  continue;
51,776✔
754

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

761
         return false;
30,753✔
762
      }
763
      else if (type_is_array(t)) {
1,055,608✔
764
         if (standard() >= STD_08) {
928,688✔
765
            if (type_is_array(t)) {
326,763✔
766
               type_t elem = type_elem(t);
326,763✔
767
               if (type_is_unconstrained(elem))
326,763✔
768
                  return true;
769
            }
770
         }
771

772
         for (; t->object.kind == T_SUBTYPE; t = type_base(t)) {
960,472✔
773
            if (type_has_constraint(t)) {
935,751✔
774
               tree_t c = type_constraint(t);
902,935✔
775
               if (tree_subkind(c) == C_INDEX)
902,935✔
776
                  return false;
777
            }
778
         }
779

780
         assert(t->object.kind == T_ARRAY);
24,721✔
781
         return true;
782
      }
783
      else
784
         return false;
785
   }
786
   else if (t->object.kind == T_ARRAY)
1,046,739✔
787
      return true;
788
   else if (t->object.kind == T_GENERIC && type_subkind(t) == GTYPE_ARRAY)
640,589✔
789
      return true;
790
   else if (t->object.kind == T_RECORD && standard() >= STD_08) {
640,534✔
791
      const int nfields = type_fields(t);
14,708✔
792
      for (int i = 0; i < nfields; i++) {
45,392✔
793
         if (type_is_unconstrained(tree_type(type_field(t, i))))
33,108✔
794
            return true;
795
      }
796
      return false;
797
   }
798
   else
799
      return false;
625,826✔
800
}
801

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

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

818
bool type_is_numeric(type_t t)
8,192✔
819
{
820
   const type_kind_t base = type_base_kind(t);
8,192✔
821
   if (base == T_GENERIC) {
8,192✔
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,183✔
827
}
828

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

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

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

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

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

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

879
bool type_is_representable(type_t t)
14,990✔
880
{
881
   if (type_is_scalar(t))
15,776✔
882
      return true;
883
   else if (standard() < STD_19) {
7,822✔
884
      if (type_is_array(t) && dimension_of(t) == 1) {
6,433✔
885
         type_t elem = type_elem(t);
4,230✔
886
         return type_is_enum(elem) && all_character_literals(elem);
5,078✔
887
      }
888
      else
889
         return false;
2,203✔
890
   }
891
   else if (type_is_record(t)) {
1,389✔
892
      const int nfields = type_fields(t);
424✔
893
      for (int i = 0; i < nfields; i++) {
1,342✔
894
         if (!type_is_representable(tree_type(type_field(t, i))))
953✔
895
            return false;
896
      }
897

898
      return true;
899
   }
900
   else if (type_is_array(t))
965✔
901
      return type_is_representable(type_elem(t));
786✔
902
   else
903
      return false;
904
}
905

906
bool type_const_bounds(type_t t)
905,987✔
907
{
908
   if (type_is_unconstrained(t))
905,987✔
909
      return false;
910
   else if (type_is_record(t)) {
722,564✔
911
      const int nfields = type_fields(t);
25,202✔
912
      for (int i = 0; i < nfields; i++) {
104,347✔
913
         type_t ftype = tree_type(type_field(t, i));
81,006✔
914
         if (!type_const_bounds(ftype))
81,006✔
915
            return false;
916
      }
917

918
      return true;
919
   }
920
   else if (type_is_array(t)) {
697,362✔
921
      const int ndims = dimension_of(t);
383,666✔
922
      for (int i = 0; i < ndims; i++) {
690,082✔
923
         int64_t low, high;
415,243✔
924
         if (!folded_bounds(range_of(t, i), &low, &high))
415,243✔
925
            return false;
108,827✔
926
      }
927

928
      return type_const_bounds(type_elem(t));
274,839✔
929
   }
930
   else if (type_is_integer(t)) {
313,696✔
931
      int64_t low, high;
69,133✔
932
      return folded_bounds(range_of(t, 0), &low, &high);
69,133✔
933
   }
934
   else
935
      return true;
936
}
937

938
type_t type_base_recur(type_t t)
436,595✔
939
{
940
   assert(t != NULL);
436,595✔
941
   while (t->object.kind == T_SUBTYPE)
647,651✔
942
      t = type_base(t);
211,056✔
943
   return t;
436,595✔
944
}
945

946
type_t type_elem_recur(type_t type)
103,224✔
947
{
948
   while (type_is_array(type))
210,112✔
949
      type = type_elem(type);
106,888✔
950
   return type;
103,224✔
951
}
952

UNCOV
953
const char *type_kind_str(type_kind_t t)
×
954
{
UNCOV
955
   assert(t < T_LAST_TYPE_KIND);
×
956
   return kind_text_map[t];
×
957
}
958

959
unsigned type_width(type_t type)
369✔
960
{
961
   if (type_is_array(type)) {
369✔
962
      const unsigned elem_w = type_width(type_elem(type));
75✔
963
      unsigned w = 1;
75✔
964
      const int ndims = dimension_of(type);
75✔
965
      for (int i = 0; i < ndims; i++) {
150✔
966
         int64_t low, high;
75✔
967
         range_bounds(range_of(type, i), &low, &high);
75✔
968
         w *= MAX(high - low + 1, 0);
75✔
969
      }
970
      return w * elem_w;
75✔
971
   }
972
   else {
973
      type_is_scalar(type);
294✔
974
      return 1;
294✔
975
   }
976
}
977

978
bool type_is_composite(type_t t)
81,324✔
979
{
980
   const type_kind_t base = type_base_kind(t);
81,324✔
981
   return base == T_ARRAY || base == T_RECORD;
81,324✔
982
}
983

984
bool type_is_homogeneous(type_t t)
96,002✔
985
{
986
   if (type_is_scalar(t))
135,481✔
987
      return true;
988
   else if (type_is_array(t))
52,044✔
989
      return type_is_homogeneous(type_elem(t));
39,479✔
990
   else
991
      return false;
992
}
993

994
bool type_is_resolved(type_t t)
83✔
995
{
996
   if (t->object.kind == T_SUBTYPE)
83✔
997
      return type_has_resolution(t) || type_is_resolved(type_base(t));
27✔
998
   else
999
      return false;
1000
}
1001

1002
bool type_frozen(type_t t)
315✔
1003
{
1004
   return arena_frozen(object_arena(&(t->object)));
315✔
1005
}
1006

1007
tree_t type_container(type_t t)
78✔
1008
{
1009
   object_t *o = arena_root(object_arena(&(t->object)));
78✔
1010
   assert(o->tag == OBJECT_TAG_TREE);
78✔
1011
   return container_of(o, struct _tree, object);
78✔
1012
}
1013

UNCOV
1014
object_t *type_to_object(type_t t)
×
1015
{
UNCOV
1016
   return t ? &(t->object) : NULL;
×
1017
}
1018

UNCOV
1019
type_t type_from_object(object_t *obj)
×
1020
{
UNCOV
1021
   assert(obj->tag == OBJECT_TAG_TYPE);
×
1022
   return container_of(obj, struct _type, object);
×
1023
}
1024

1025
int type_bit_width(type_t type)
16,754✔
1026
{
1027
   switch (type_kind(type)) {
33,828✔
1028
   case T_INTEGER:
5,166✔
1029
   case T_PHYSICAL:
1030
      {
1031
         tree_t r = range_of(type, 0);
5,166✔
1032
         return bits_for_range(assume_int(tree_left(r)),
5,166✔
1033
                               assume_int(tree_right(r)));
1034
      }
1035

1036
   case T_REAL:
1037
       // All real types are doubles at the moment
1038
       return 64;
1039

1040
   case T_SUBTYPE:
10,972✔
1041
      return type_bit_width(type_base(type));
10,972✔
1042

1043
   case T_ENUM:
10,260✔
1044
      return bits_for_range(0, type_enum_literals(type) - 1);
10,260✔
1045

1046
   case T_ARRAY:
6,102✔
1047
      return type_bit_width(type_elem(type));
6,102✔
1048

UNCOV
1049
   default:
×
1050
      fatal_trace("unhandled type %s in type_bit_width", type_pp(type));
1051
   }
1052
}
1053

1054
int type_byte_width(type_t type)
15,909✔
1055
{
1056
   return (type_bit_width(type) + 7) / 8;
15,909✔
1057
}
1058

1059
bool type_is_character_array(type_t t)
28,704✔
1060
{
1061
   // LRM 93 section 3.1.1 an enumeration type is a character type if at
1062
   // least one of its enumeration literals is a character literal
1063

1064
   if (!type_is_array(t))
28,704✔
1065
      return false;
1066

1067
   if (dimension_of(t) != 1)
25,653✔
1068
      return false;
1069

1070
   type_t elem = type_base_recur(type_elem(t));
25,652✔
1071

1072
   if (!type_is_enum(elem))
25,652✔
1073
      return false;
1074

1075
   const int nlits = type_enum_literals(elem);
25,607✔
1076
   for (int i = 0; i < nlits; i++) {
428,965✔
1077
      tree_t lit = type_enum_literal(elem, i);
428,950✔
1078
      if (ident_char(tree_ident(lit), 0) == '\'')
428,950✔
1079
         return true;
1080
   }
1081

1082
   return false;
1083
}
1084

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