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

nickg / nvc / 13356534393

16 Feb 2025 03:48PM UTC coverage: 92.157% (+0.009%) from 92.148%
13356534393

push

github

nickg
Fix wrong FILE_PATH result with relative path. Fixes #1162

12 of 14 new or added lines in 1 file covered. (85.71%)

29 existing lines in 3 files now uncovered.

63895 of 69333 relevant lines covered (92.16%)

511943.01 hits per line

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

96.57
/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_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)
29,582,764✔
110
{
111
   object_t *o = obj_array_nth(item->obj_array, n);
29,582,764✔
112
   return container_of(o, struct _tree, object);
29,582,764✔
113
}
114

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

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

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

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

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

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

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

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

167
   if (a == b)
28,821,498✔
168
      return true;
169

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

173
   if (map != NULL) {
25,718,281✔
174
      assert(standard() >= STD_08);   // Type generics
31,012✔
175

176
      a = hash_get(map, a) ?: a;
31,012✔
177
      kind_a = a->object.kind;
31,012✔
178

179
      b = hash_get(map, b) ?: b;
31,012✔
180
      kind_b = b->object.kind;
31,012✔
181

182
      if (a == b)
31,012✔
183
         return true;
184
   }
185

186
   if (!strict) {
25,715,853✔
187
      // Subtypes are convertible to the base type
188
      while ((kind_a = a->object.kind) == T_SUBTYPE)
26,078,753✔
189
         a = type_base_map(a, map);
365,549✔
190
      while ((kind_b = b->object.kind) == T_SUBTYPE)
26,599,260✔
191
         b = type_base_map(b, map);
886,056✔
192

193
      if (a == b)
25,713,204✔
194
         return true;
195
   }
196

197
   const imask_t has = has_map[a->object.kind];
25,473,791✔
198

199
   if (!(has & I_PARAMS)) {
25,473,791✔
200
      ident_t ai = lookup_item(&type_object, a, I_IDENT)->ident;
22,079,309✔
201
      ident_t bi = lookup_item(&type_object, b, I_IDENT)->ident;
22,079,309✔
202

203
      if (ai != bi)
22,079,309✔
204
         return false;
205
      else if (ai == NULL && kind_a == T_GENERIC)
1,356✔
206
         return false;   // Anonymous generic types are distinct
207
   }
208

209
   if (kind_a == T_INCOMPLETE || kind_b == T_INCOMPLETE)
3,395,671✔
210
      return true;
211

212
   if (kind_a != kind_b)
3,394,784✔
213
      return false;
214

215
   if (kind_a == T_ARRAY)
3,394,715✔
216
      return _type_eq(type_elem(a), type_elem(b), strict, map);
×
217

218
   if (kind_a == T_ACCESS)
3,394,715✔
219
      return _type_eq(type_designated(a), type_designated(b), strict, map);
×
220

221
   if ((has & I_DIMS) && (type_dims(a) != type_dims(b)))
3,394,715✔
222
      return false;
223

224
   if (kind_a == T_SIGNATURE) {
3,394,715✔
225
      type_t ra = type_result_or_null(a);
3,394,413✔
226
      type_t rb = type_result_or_null(b);
3,394,413✔
227

228
      if (ra != NULL && rb != NULL) {
3,394,413✔
229
         if (!_type_eq(ra, rb, strict, map))
3,334,599✔
230
            return false;
231
      }
232
      else if (ra != NULL || rb != NULL)
59,814✔
233
         return false;
234
   }
235

236
   if (has & I_PARAMS) {
1,494,353✔
237
      item_t *ap = lookup_item(&type_object, a, I_PARAMS);
1,494,051✔
238
      item_t *bp = lookup_item(&type_object, b, I_PARAMS);
1,494,051✔
239

240
      const int acount = obj_array_count(ap->obj_array);
1,494,051✔
241
      const int bcount = obj_array_count(bp->obj_array);
1,494,051✔
242

243
      if (acount != bcount)
1,494,051✔
244
         return false;
245

246
      for (int i = 0; i < acount; i++) {
1,583,771✔
247
         type_t ai = type_array_nth(ap, i);
1,550,579✔
248
         type_t bi = type_array_nth(bp, i);
1,550,579✔
249
         if (ai != bi && !_type_eq(ai, bi, strict, map))
1,550,579✔
250
            return false;
251
      }
252
   }
253

254
   return true;
255
}
256

257
bool type_strict_eq(type_t a, type_t b)
21,520✔
258
{
259
   return _type_eq(a, b, true, NULL);
21,520✔
260
}
261

262
bool type_eq(type_t a, type_t b)
23,661,808✔
263
{
264
   return _type_eq(a, b, false, NULL);
23,661,808✔
265
}
266

267
bool type_eq_map(type_t a, type_t b, hash_t *map)
395,555✔
268
{
269
   return _type_eq(a, b, false, map);
395,555✔
270
}
271

272
ident_t type_ident(type_t t)
273,300✔
273
{
274
   assert(t != NULL);
275,477✔
275

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

294
bool type_has_ident(type_t t)
94,579✔
295
{
296
   assert(t != NULL);
94,579✔
297
   return (lookup_item(&type_object, t, I_IDENT)->ident != NULL);
94,579✔
298
}
299

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

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

312
tree_t type_dim(type_t t, unsigned n)
841,183✔
313
{
314
   item_t *item = lookup_item(&type_object, t, I_DIMS);
841,183✔
315
   return tree_array_nth(item, n);
841,183✔
316
}
317

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

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

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

337
type_t type_elem(type_t t)
1,281,753✔
338
{
339
   assert(t != NULL);
2,366,728✔
340

341
   if (t->object.kind == T_NONE)
2,366,728✔
342
      return t;
343
   else {
344
      item_t *item = lookup_item(&type_object, t, I_ELEM);
2,366,728✔
345
      if (t->object.kind == T_SUBTYPE && item->object == NULL)
2,366,728✔
346
         return type_elem(type_base(t));
1,084,975✔
347
      else {
348
         assert(item->object != NULL);
1,281,753✔
349
         return container_of(item->object, struct _type, object);
350
      }
351
   }
352
}
353

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

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

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

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

376
bool type_is_universal(type_t t)
7,278✔
377
{
378
   assert(t != NULL);
7,278✔
379

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

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

396
tree_t type_unit(type_t t, unsigned n)
41,940✔
397
{
398
   item_t *item = lookup_item(&type_object, t, I_UNITS);
41,940✔
399
   return tree_array_nth(item, n);
41,940✔
400
}
401

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

408
unsigned type_enum_literals(type_t t)
402,865✔
409
{
410
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
402,865✔
411
   return obj_array_count(item->obj_array);
402,865✔
412
}
413

414
tree_t type_enum_literal(type_t t, unsigned n)
26,230,433✔
415
{
416
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
26,230,433✔
417
   return tree_array_nth(item, n);
26,230,433✔
418
}
419

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

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

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

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

445
unsigned type_fields(type_t t)
113,601✔
446
{
447
   if (t->object.kind == T_SUBTYPE)
149,730✔
448
      return type_fields(type_base(t));
36,129✔
449
   else {
450
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
113,601✔
451
      return obj_array_count(item->obj_array);
113,601✔
452
   }
453
}
454

455
tree_t type_field(type_t t, unsigned n)
318,492✔
456
{
457
   if (t->object.kind == T_SUBTYPE)
394,142✔
458
      return type_field(type_base(t), n);
75,650✔
459
   else {
460
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
318,492✔
461
      return tree_array_nth(item, n);
318,492✔
462
   }
463
}
464

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

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

478
bool type_has_result(type_t t)
2,880,183✔
479
{
480
   return lookup_item(&type_object, t, I_RESULT)->object != NULL;
2,880,183✔
481
}
482

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

489
unsigned type_indexes(type_t t)
1,192,735✔
490
{
491
   item_t *item = lookup_item(&type_object, t, I_INDEXES);
1,192,735✔
492
   return obj_array_count(item->obj_array);
1,192,735✔
493
}
494

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

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

507
unsigned type_constraints(type_t t)
2,213,172✔
508
{
509
   item_t *item = lookup_item(&type_object, t, I_CONSTR);
2,213,172✔
510
   return obj_array_count(item->obj_array);
2,213,172✔
511
}
512

513
void type_add_constraint(type_t t, tree_t c)
41,849✔
514
{
515
   assert(c->object.kind == T_CONSTRAINT);
41,849✔
516
   tree_array_add(lookup_item(&type_object, t, I_CONSTR), c);
41,849✔
517
   object_write_barrier(&(t->object), &(c->object));
41,849✔
518
}
41,849✔
519

520
tree_t type_constraint(type_t t, unsigned n)
2,150,716✔
521
{
522
   assert(n == 0);    // TODO: this list is largely redundant now
2,150,716✔
523
   item_t *item = lookup_item(&type_object, t, I_CONSTR);
2,150,716✔
524
   return tree_array_nth(item, n);
2,150,716✔
525
}
526

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

533
bool type_has_resolution(type_t t)
31,876✔
534
{
535
   return lookup_item(&type_object, t, I_RESOLUTION)->object != NULL;
31,876✔
536
}
537

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

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

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

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

566
   tb_printf(tb, "[");
1,073✔
567
   const int nparams = type_params(t);
1,073✔
568
   for (int i = 0; i < nparams; i++)
2,506✔
569
      tb_printf(tb, "%s%s", (i == 0 ? "" : ", "),
1,972✔
570
                type_pp(type_param(t, i)));
571
   type_t r = type_result_or_null(t);
1,073✔
572
   if (r != NULL)
1,073✔
573
      tb_printf(tb, "%sreturn %s", nparams > 0 ? " " : "", type_pp(r));
663✔
574
   tb_printf(tb, "]");
1,073✔
575
}
1,073✔
576

577
const char *type_pp2(type_t t, type_t other)
6,594✔
578
{
579
   assert(t != NULL);
6,594✔
580

581
   switch (type_kind(t)) {
6,594✔
582
   case T_SIGNATURE:
2,592✔
583
      {
584
         static hash_t *cache = NULL;
2,592✔
585
         if (cache == NULL)
2,592✔
586
            cache = hash_new(64);
439✔
587

588
         text_buf_t *tb = hash_get(cache, t);
2,592✔
589
         if (tb == NULL) {
2,592✔
590
            tb = tb_new();
1,010✔
591
            hash_put(cache, t, tb);
1,010✔
592

593
            if (type_has_ident(t)) {
1,010✔
594
               tb_istr(tb, type_ident(t));
1,007✔
595
               tb_append(tb, ' ');
1,007✔
596
            }
597
            type_signature(t, tb);
1,010✔
598
         }
599

600
         return tb_get(tb);
2,592✔
601
      }
602

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

608
   default:
609
      {
610
         const char *full1 = istr(type_ident(t));
4,000✔
611
         const char *dot1  = strrchr(full1, '.');
4,000✔
612
         const char *tail1 = dot1 ? dot1 + 1 : full1;
4,000✔
613

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

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

627
const char *type_pp(type_t t)
6,470✔
628
{
629
   return type_pp2(t, NULL);
6,470✔
630
}
631

632
type_kind_t type_base_kind(type_t t)
25,458,286✔
633
{
634
   assert(t != NULL);
32,414,848✔
635
   if (t->object.kind == T_SUBTYPE)
32,414,848✔
636
      return type_base_kind(type_base(t));
6,956,562✔
637
   else
638
      return t->object.kind;
25,458,286✔
639
}
640

641
bool type_is_array(type_t t)
4,313,877✔
642
{
643
   const type_kind_t base = type_base_kind(t);
4,313,877✔
644
   if (base == T_GENERIC)
4,313,877✔
645
      return type_subkind(type_base_recur(t)) == GTYPE_ARRAY;
1,912✔
646
   else
647
      return base == T_ARRAY;
4,311,965✔
648
}
649

650
bool type_is_record(type_t t)
2,397,471✔
651
{
652
   return type_base_kind(t) == T_RECORD;
2,397,471✔
653
}
654

655
bool type_is_protected(type_t t)
143,259✔
656
{
657
   return type_base_kind(t) == T_PROTECTED;
143,259✔
658
}
659

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

669
bool type_is_access(type_t t)
218,066✔
670
{
671
   const type_kind_t base = type_base_kind(t);
218,066✔
672
   if (base == T_GENERIC)
218,066✔
673
      return type_subkind(type_base_recur(t)) == GTYPE_ACCESS;
1,347✔
674
   else
675
      return base == T_ACCESS;
216,719✔
676
}
677

678
bool type_is_incomplete(type_t t)
306,871✔
679
{
680
   return type_base_kind(t) == T_INCOMPLETE;
306,871✔
681
}
682

683
bool type_is_none(type_t t)
15,949,032✔
684
{
685
   return type_base_kind(t) == T_NONE;
15,949,032✔
686
}
687

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

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

704
         const int nparams = type_params(t);
25✔
705
         for (int i = 0; i < nparams; i++) {
49✔
706
            if (type_is_none(type_param(t, i)))
26✔
707
               return true;
708
         }
709

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

719
tree_t type_constraint_for_field(type_t t, tree_t f)
9,912✔
720
{
721
   if (t->object.kind == T_SUBTYPE) {
9,966✔
722
      const int ncon = type_constraints(t);
8,641✔
723
      if (ncon > 0) {
8,641✔
724
         tree_t c = type_constraint(t, ncon - 1);
8,612✔
725

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

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

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

739
      return type_constraint_for_field(type_base(t), f);
54✔
740
   }
741
   else
742
      return NULL;
743
}
744

745
bool type_is_unconstrained(type_t t)
2,129,661✔
746
{
747
   assert(t != NULL);
2,129,661✔
748

749
   if (t->object.kind == T_SUBTYPE) {
2,129,661✔
750
      if (type_is_record(t)) {
1,085,906✔
751
         if (standard() >= STD_08) {
30,807✔
752
            const int nfields = type_fields(t);
29,443✔
753
            for (int i = 0; i < nfields; i++) {
88,297✔
754
               tree_t f = type_field(t, i);
58,875✔
755
               if (!type_is_unconstrained(tree_type(f)))
58,875✔
756
                  continue;
51,803✔
757

758
               tree_t ec = type_constraint_for_field(t, f);
7,072✔
759
               if (ec == NULL || type_is_unconstrained(tree_type(ec)))
7,072✔
760
                  return true;
21✔
761
            }
762
         }
763

764
         return false;
30,786✔
765
      }
766
      else if (type_is_array(t)) {
1,055,099✔
767
         if (standard() >= STD_08) {
928,559✔
768
            if (type_is_array(t)) {
325,402✔
769
               type_t elem = type_elem(t);
325,402✔
770
               if (type_is_unconstrained(elem))
325,402✔
771
                  return true;
772
            }
773
         }
774

775
         for (; t->object.kind == T_SUBTYPE; t = type_base(t)) {
960,491✔
776
            if (type_constraints(t) > 0) {
935,607✔
777
               tree_t c = type_constraint(t, 0);
908,515✔
778
               if (tree_subkind(c) == C_INDEX)
908,515✔
779
                  return false;
780
            }
781
         }
782

783
         assert(t->object.kind == T_ARRAY);
24,884✔
784
         return true;
785
      }
786
      else
787
         return false;
788
   }
789
   else if (t->object.kind == T_ARRAY)
1,043,755✔
790
      return true;
791
   else if (t->object.kind == T_GENERIC && type_subkind(t) == GTYPE_ARRAY)
637,072✔
792
      return true;
793
   else if (t->object.kind == T_RECORD && standard() >= STD_08) {
637,017✔
794
      const int nfields = type_fields(t);
14,709✔
795
      for (int i = 0; i < nfields; i++) {
45,457✔
796
         if (type_is_unconstrained(tree_type(type_field(t, i))))
33,152✔
797
            return true;
798
      }
799
      return false;
800
   }
801
   else
802
      return false;
622,308✔
803
}
804

805
bool type_is_enum(type_t t)
117,104✔
806
{
807
   return type_base_kind(t) == T_ENUM;
117,104✔
808
}
809

810
bool type_is_discrete(type_t t)
23,575✔
811
{
812
   const type_kind_t base = type_base_kind(t);
23,575✔
813
   if (base == T_GENERIC) {
23,575✔
814
      const gtype_class_t class = type_subkind(type_base_recur(t));
37✔
815
      return class == GTYPE_INTEGER || class == GTYPE_DISCRETE;
37✔
816
   }
817
   else
818
      return base == T_INTEGER || base == T_ENUM;
23,538✔
819
}
820

821
bool type_is_numeric(type_t t)
8,182✔
822
{
823
   const type_kind_t base = type_base_kind(t);
8,182✔
824
   if (base == T_GENERIC) {
8,182✔
825
      const gtype_class_t class = type_subkind(type_base_recur(t));
9✔
826
      return class == GTYPE_INTEGER || class == GTYPE_FLOATING;
9✔
827
   }
828
   else
829
      return base == T_INTEGER || base == T_REAL;
8,173✔
830
}
831

832
bool type_is_subprogram(type_t t)
1,036,633✔
833
{
834
   return t->object.kind == T_SIGNATURE;
1,036,633✔
835
}
836

837
bool type_is_physical(type_t t)
510✔
838
{
839
   const type_kind_t base = type_base_kind(t);
510✔
840
   if (base == T_GENERIC)
510✔
841
      return type_subkind(type_base_recur(t)) == GTYPE_PHYSICAL;
1✔
842
   else
843
      return base == T_PHYSICAL;
509✔
844
}
845

846
bool type_is_integer(type_t t)
566,896✔
847
{
848
   const type_kind_t base = type_base_kind(t);
566,896✔
849
   if (base == T_GENERIC)
566,896✔
850
      return type_subkind(type_base_recur(t)) == GTYPE_INTEGER;
28✔
851
   else
852
      return base == T_INTEGER;
566,868✔
853
}
854

855
bool type_is_real(type_t t)
46,555✔
856
{
857
   const type_kind_t base = type_base_kind(t);
46,555✔
858
   if (base == T_GENERIC)
46,555✔
859
      return type_subkind(type_base_recur(t)) == GTYPE_FLOATING;
4✔
860
   else
861
      return base == T_REAL;
46,551✔
862
}
863

864
bool type_is_generic(type_t t)
204,626✔
865
{
866
   return type_base_kind(t) == T_GENERIC;
204,626✔
867
}
868

869
bool type_is_scalar(type_t t)
934,821✔
870
{
871
   const type_kind_t base = type_base_kind(t);
934,821✔
872
   if (base == T_GENERIC) {
934,821✔
873
      const gtype_class_t class = type_subkind(type_base_recur(t));
686✔
874
      return class == GTYPE_SCALAR || class == GTYPE_DISCRETE
686✔
875
         || class == GTYPE_FLOATING || class == GTYPE_INTEGER;
1,332✔
876
   }
877
   else
878
      return base == T_INTEGER || base == T_REAL
934,135✔
879
         || base == T_ENUM || base == T_PHYSICAL || base == T_NONE;
934,135✔
880
}
881

882
bool type_is_representable(type_t t)
14,770✔
883
{
884
   if (type_is_scalar(t))
15,556✔
885
      return true;
886
   else if (standard() < STD_19) {
7,696✔
887
      if (type_is_array(t) && dimension_of(t) == 1) {
6,307✔
888
         type_t elem = type_elem(t);
4,137✔
889
         return type_is_enum(elem) && all_character_literals(elem);
4,959✔
890
      }
891
      else
892
         return false;
2,170✔
893
   }
894
   else if (type_is_record(t)) {
1,389✔
895
      const int nfields = type_fields(t);
424✔
896
      for (int i = 0; i < nfields; i++) {
1,342✔
897
         if (!type_is_representable(tree_type(type_field(t, i))))
953✔
898
            return false;
899
      }
900

901
      return true;
902
   }
903
   else if (type_is_array(t))
965✔
904
      return type_is_representable(type_elem(t));
786✔
905
   else
906
      return false;
907
}
908

909
bool type_const_bounds(type_t t)
902,356✔
910
{
911
   if (type_is_unconstrained(t))
902,356✔
912
      return false;
913
   else if (type_is_record(t)) {
718,984✔
914
      const int nfields = type_fields(t);
25,085✔
915
      for (int i = 0; i < nfields; i++) {
104,092✔
916
         type_t ftype = tree_type(type_field(t, i));
80,862✔
917
         if (!type_const_bounds(ftype))
80,862✔
918
            return false;
919
      }
920

921
      return true;
922
   }
923
   else if (type_is_array(t)) {
693,899✔
924
      const int ndims = dimension_of(t);
381,875✔
925
      for (int i = 0; i < ndims; i++) {
686,294✔
926
         int64_t low, high;
412,909✔
927
         if (!folded_bounds(range_of(t, i), &low, &high))
412,909✔
928
            return false;
108,490✔
929
      }
930

931
      return type_const_bounds(type_elem(t));
273,385✔
932
   }
933
   else if (type_is_integer(t)) {
312,024✔
934
      int64_t low, high;
69,117✔
935
      return folded_bounds(range_of(t, 0), &low, &high);
69,117✔
936
   }
937
   else
938
      return true;
939
}
940

941
type_t type_base_recur(type_t t)
435,393✔
942
{
943
   assert(t != NULL);
435,393✔
944
   while (t->object.kind == T_SUBTYPE)
646,079✔
945
      t = type_base(t);
210,686✔
946
   return t;
435,393✔
947
}
948

949
type_t type_elem_recur(type_t type)
102,702✔
950
{
951
   while (type_is_array(type))
209,047✔
952
      type = type_elem(type);
106,345✔
953
   return type;
102,702✔
954
}
955

956
const char *type_kind_str(type_kind_t t)
×
957
{
UNCOV
958
   assert(t < T_LAST_TYPE_KIND);
×
UNCOV
959
   return kind_text_map[t];
×
960
}
961

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

981
bool type_is_composite(type_t t)
79,217✔
982
{
983
   const type_kind_t base = type_base_kind(t);
79,217✔
984
   return base == T_ARRAY || base == T_RECORD;
79,217✔
985
}
986

987
bool type_is_homogeneous(type_t t)
94,812✔
988
{
989
   if (type_is_scalar(t))
133,859✔
990
      return true;
991
   else if (type_is_array(t))
51,379✔
992
      return type_is_homogeneous(type_elem(t));
39,047✔
993
   else
994
      return false;
995
}
996

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

1005
bool type_frozen(type_t t)
297✔
1006
{
1007
   return arena_frozen(object_arena(&(t->object)));
297✔
1008
}
1009

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

UNCOV
1017
object_t *type_to_object(type_t t)
×
1018
{
1019
   return t ? &(t->object) : NULL;
×
1020
}
1021

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

1028
int type_bit_width(type_t type)
16,639✔
1029
{
1030
   switch (type_kind(type)) {
33,625✔
1031
   case T_INTEGER:
5,133✔
1032
   case T_PHYSICAL:
1033
      {
1034
         tree_t r = range_of(type, 0);
5,133✔
1035
         return bits_for_range(assume_int(tree_left(r)),
5,133✔
1036
                               assume_int(tree_right(r)));
1037
      }
1038

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

1043
   case T_SUBTYPE:
10,924✔
1044
      return type_bit_width(type_base(type));
10,924✔
1045

1046
   case T_ENUM:
10,184✔
1047
      return bits_for_range(0, type_enum_literals(type) - 1);
10,184✔
1048

1049
   case T_ARRAY:
6,062✔
1050
      return type_bit_width(type_elem(type));
6,062✔
1051

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

1057
int type_byte_width(type_t type)
15,806✔
1058
{
1059
   return (type_bit_width(type) + 7) / 8;
15,806✔
1060
}
1061

1062
bool type_is_character_array(type_t t)
28,637✔
1063
{
1064
   // LRM 93 section 3.1.1 an enumeration type is a character type if at
1065
   // least one of its enumeration literals is a character literal
1066

1067
   if (!type_is_array(t))
28,637✔
1068
      return false;
1069

1070
   if (dimension_of(t) != 1)
25,574✔
1071
      return false;
1072

1073
   type_t elem = type_base_recur(type_elem(t));
25,573✔
1074

1075
   if (!type_is_enum(elem))
25,573✔
1076
      return false;
1077

1078
   const int nlits = type_enum_literals(elem);
25,528✔
1079
   for (int i = 0; i < nlits; i++) {
428,086✔
1080
      tree_t lit = type_enum_literal(elem, i);
428,071✔
1081
      if (ident_char(tree_ident(lit), 0) == '\'')
428,071✔
1082
         return true;
1083
   }
1084

1085
   return false;
1086
}
1087

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