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

nickg / nvc / 6903463504

17 Nov 2023 11:35AM UTC coverage: 91.168% (+0.006%) from 91.162%
6903463504

push

github

nickg
Improve handling of implicit literal conversions

329 of 343 new or added lines in 7 files covered. (95.92%)

759 existing lines in 8 files now uncovered.

50580 of 55480 relevant lines covered (91.17%)

608081.41 hits per line

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

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

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

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

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

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

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

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

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

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

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

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

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

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

63
   // T_INCOMPLETE
64
   (I_IDENT),
65

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

69
   // T_NONE
70
   (I_IDENT),
71

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

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

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

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

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

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

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

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

110
extern object_arena_t *global_arena;
111

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

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

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

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

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

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

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

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

161
   if (a == b)
29,863,400✔
162
      return true;
163

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

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

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

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

182
   if (!strict) {
26,775,200✔
183
      // Subtypes are convertible to the base type
184
      while ((kind_a = a->object.kind) == T_SUBTYPE)
27,169,100✔
185
         a = type_base_map(a, map);
397,079✔
186
      while ((kind_b = b->object.kind) == T_SUBTYPE)
27,779,100✔
187
         b = type_base_map(b, map);
1,007,100✔
188

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

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

195
   if (!(has & I_PARAMS)) {
26,546,300✔
196
      ident_t ai = lookup_item(&type_object, a, I_IDENT)->ident;
22,192,200✔
197
      ident_t bi = lookup_item(&type_object, b, I_IDENT)->ident;
22,192,200✔
198

199
      if (ai != bi)
22,192,200✔
200
         return false;
201
   }
202

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

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

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

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

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

218
   if (kind_a == T_FUNC) {
4,131,380✔
219
      if (!_type_eq(type_result(a), type_result(b), strict, map))
4,048,490✔
220
         return false;
221
   }
222

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

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

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

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

241
   return true;
242
}
243

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

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

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

259
ident_t type_ident(type_t t)
233,716✔
260
{
261
   assert(t != NULL);
235,228✔
262

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

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

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

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

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

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

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

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

324
type_t type_elem(type_t t)
1,081,970✔
325
{
326
   assert(t != NULL);
1,997,850✔
327

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

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

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

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

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

363
bool type_is_universal(type_t t)
6,771✔
364
{
365
   assert(t != NULL);
6,771✔
366

367
   switch (t->object.kind) {
6,771✔
368
   case T_INTEGER:
3,178✔
369
      return t == std_type(NULL, STD_UNIVERSAL_INTEGER);
3,178✔
370
   case T_REAL:
4✔
371
      return t == std_type(NULL, STD_UNIVERSAL_REAL);
4✔
372
   default:
373
      return false;
374
   }
375
}
376

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

615
type_kind_t type_base_kind(type_t t)
23,826,600✔
616
{
617
   assert(t != NULL);
29,719,000✔
618
   if (t->object.kind == T_SUBTYPE)
29,719,000✔
619
      return type_base_kind(type_base(t));
5,892,400✔
620
   else
621
      return t->object.kind;
23,826,600✔
622
}
623

624
bool type_is_array(type_t t)
3,894,790✔
625
{
626
   const type_kind_t base = type_base_kind(t);
3,894,790✔
627
   if (base == T_GENERIC)
3,894,790✔
628
      return type_subkind(type_base_recur(t)) == GTYPE_ARRAY;
1,142✔
629
   else
630
      return base == T_ARRAY;
3,893,640✔
631
}
632

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

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

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

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

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

666
bool type_is_none(type_t t)
15,965,900✔
667
{
668
   return type_base_kind(t) == T_NONE;
15,965,900✔
669
}
670

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

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

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

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

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

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

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

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

718
         return false;
4,468✔
719
      }
720
      else if (type_is_array(t)) {
941,251✔
721
         if (standard() >= STD_08) {
851,368✔
722
            if (type_is_array(t)) {
247,064✔
723
               type_t elem = type_elem(t);
247,064✔
724
               if (type_is_unconstrained(elem))
247,064✔
725
                  return true;
726
            }
727
         }
728

729
         for (; t->object.kind == T_SUBTYPE; t = type_base(t)) {
865,663✔
730
            if (type_constraints(t) > 0) {
851,219✔
731
               tree_t c = type_constraint(t, 0);
837,120✔
732
               if (tree_subkind(c) == C_INDEX)
837,120✔
733
                  return false;
734
            }
735
         }
736

737
         assert(t->object.kind == T_ARRAY);
14,444✔
738
         return true;
739
      }
740
      else
741
         return false;
742
   }
743
   else if (t->object.kind == T_ARRAY)
880,143✔
744
      return true;
745
   else if (t->object.kind == T_GENERIC && type_subkind(t) == GTYPE_ARRAY)
471,098✔
746
      return true;
747
   else if (t->object.kind == T_RECORD && standard() >= STD_08) {
471,097✔
748
      const int nfields = type_fields(t);
6,440✔
749
      for (int i = 0; i < nfields; i++) {
21,358✔
750
         if (type_is_unconstrained(tree_type(type_field(t, i))))
16,288✔
751
            return true;
752
      }
753
      return false;
754
   }
755
   else
756
      return false;
464,657✔
757
}
758

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

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

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

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

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

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

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

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

825
bool type_is_representable(type_t t)
13,118✔
826
{
827
   if (type_is_scalar(t))
13,721✔
828
      return true;
829
   else if (standard() < STD_19) {
6,072✔
830
      if (type_is_array(t)) {
5,007✔
831
         type_t elem = type_elem(t);
3,516✔
832
         return type_is_enum(elem) && all_character_literals(elem);
4,277✔
833
      }
834
      else
835
         return false;
836
   }
837
   else if (type_is_record(t)) {
1,065✔
838
      const int nfields = type_fields(t);
318✔
839
      for (int i = 0; i < nfields; i++) {
1,025✔
840
         if (!type_is_representable(tree_type(type_field(t, i))))
730✔
841
            return false;
842
      }
843

844
      return true;
845
   }
846
   else if (type_is_array(t))
747✔
847
      return type_is_representable(type_elem(t));
603✔
848
   else
849
      return false;
850
}
851

852
bool type_const_bounds(type_t t)
743,762✔
853
{
854
   if (type_is_unconstrained(t))
743,762✔
855
      return false;
856
   else if (type_is_record(t)) {
599,277✔
857
      const int nfields = type_fields(t);
18,698✔
858
      for (int i = 0; i < nfields; i++) {
79,093✔
859
         type_t ftype = tree_type(type_field(t, i));
61,676✔
860
         if (!type_const_bounds(ftype))
61,676✔
861
            return false;
862
      }
863

864
      return true;
865
   }
866
   else if (type_is_array(t)) {
580,579✔
867
      const int ndims = dimension_of(t);
329,099✔
868
      for (int i = 0; i < ndims; i++) {
595,211✔
869
         int64_t low, high;
353,156✔
870
         if (!folded_bounds(range_of(t, i), &low, &high))
353,156✔
871
            return false;
87,044✔
872
      }
873

874
      return type_const_bounds(type_elem(t));
242,055✔
875
   }
876
   else
877
      return true;
878
}
879

880
type_t type_base_recur(type_t t)
410,569✔
881
{
882
   assert(t != NULL);
410,569✔
883
   while (t->object.kind == T_SUBTYPE)
594,703✔
884
      t = type_base(t);
184,134✔
885
   return t;
410,569✔
886
}
887

888
type_t type_elem_recur(type_t type)
102,909✔
889
{
890
   while (type_is_array(type))
208,649✔
891
      type = type_elem(type);
105,740✔
892
   return type;
102,909✔
893
}
894

895
const char *type_kind_str(type_kind_t t)
×
896
{
897
   assert(t < T_LAST_TYPE_KIND);
×
898
   return kind_text_map[t];
×
899
}
900

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

926
bool type_is_composite(type_t t)
67,886✔
927
{
928
   const type_kind_t base = type_base_kind(t);
67,886✔
929
   return base == T_ARRAY || base == T_RECORD;
67,886✔
930
}
931

932
bool type_is_homogeneous(type_t t)
111,592✔
933
{
934
   if (type_is_scalar(t))
156,410✔
935
      return true;
936
   else if (type_is_array(t))
55,130✔
937
      return type_is_homogeneous(type_elem(t));
44,818✔
938
   else
939
      return false;
940
}
941

942
bool type_is_resolved(type_t t)
60✔
943
{
944
   if (t->object.kind == T_SUBTYPE)
60✔
945
      return type_has_resolution(t) || type_is_resolved(type_base(t));
17✔
946
   else
947
      return false;
948
}
949

950
bool type_frozen(type_t t)
97✔
951
{
952
   return arena_frozen(object_arena(&(t->object)));
97✔
953
}
954

955
tree_t type_container(type_t t)
180✔
956
{
957
   object_t *o = arena_root(object_arena(&(t->object)));
180✔
958
   assert(o->tag == OBJECT_TAG_TREE);
180✔
959
   return container_of(o, struct _tree, object);
180✔
960
}
961

962
object_t *type_to_object(type_t t)
×
963
{
UNCOV
964
   return t ? &(t->object) : NULL;
×
965
}
966

UNCOV
967
type_t type_from_object(object_t *obj)
×
968
{
UNCOV
969
   assert(obj->tag == OBJECT_TAG_TYPE);
×
UNCOV
970
   return container_of(obj, struct _type, object);
×
971
}
972

973
int type_bit_width(type_t type)
8,988✔
974
{
975
   switch (type_kind(type)) {
20,925✔
976
   case T_INTEGER:
3,026✔
977
   case T_PHYSICAL:
978
      {
979
         tree_t r = range_of(type, 0);
3,026✔
980
         return bits_for_range(assume_int(tree_left(r)),
3,026✔
981
                               assume_int(tree_right(r)));
982
      }
983

984
   case T_REAL:
985
       // All real types are doubles at the moment
986
       return 64;
987

988
   case T_SUBTYPE:
7,521✔
989
      return type_bit_width(type_base(type));
7,521✔
990

991
   case T_ENUM:
5,656✔
992
      return bits_for_range(0, type_enum_literals(type) - 1);
5,656✔
993

994
   case T_ARRAY:
4,416✔
995
      return type_bit_width(type_elem(type));
4,416✔
996

UNCOV
997
   default:
×
UNCOV
998
      fatal_trace("unhandled type %s in type_bit_width", type_pp(type));
×
999
   }
1000
}
1001

1002
int type_byte_width(type_t type)
8,814✔
1003
{
1004
   return (type_bit_width(type) + 7) / 8;
8,814✔
1005
}
1006

1007
bool type_is_character_array(type_t t)
26,950✔
1008
{
1009
   // LRM 93 section 3.1.1 an enumeration type is a character type if at
1010
   // least one of its enumeration literals is a character literal
1011

1012
   if (!type_is_array(t))
26,950✔
1013
      return false;
1014

1015
   if (dimension_of(t) != 1)
24,133✔
1016
      return false;
1017

1018
   type_t elem = type_base_recur(type_elem(t));
24,132✔
1019

1020
   if (!type_is_enum(elem))
24,132✔
1021
      return false;
1022

1023
   const int nlits = type_enum_literals(elem);
24,066✔
1024
   for (int i = 0; i < nlits; i++) {
409,996✔
1025
      tree_t lit = type_enum_literal(elem, i);
409,975✔
1026
      if (ident_char(tree_ident(lit), 0) == '\'')
409,975✔
1027
         return true;
1028
   }
1029

1030
   return false;
1031
}
1032

1033
bool type_matches_class(type_t t, gtype_class_t class)
155✔
1034
{
1035
   switch (class) {
155✔
1036
   case GTYPE_PRIVATE:
1037
      return true;
1038
   case GTYPE_SCALAR:
7✔
1039
      return type_is_scalar(t);
7✔
1040
   case GTYPE_DISCRETE:
5✔
1041
      return type_is_discrete(t);
5✔
1042
   case GTYPE_INTEGER:
5✔
1043
      return type_is_integer(t);
5✔
1044
   case GTYPE_FLOATING:
3✔
1045
      return type_is_real(t);
3✔
1046
   case GTYPE_PHYSICAL:
3✔
1047
      return type_is_physical(t);
3✔
1048
   case GTYPE_ACCESS:
5✔
1049
      return type_is_access(t);
5✔
1050
   case GTYPE_ARRAY:
7✔
1051
      return type_is_array(t);
7✔
1052
   case GTYPE_FILE:
5✔
1053
      return type_is_file(t);
5✔
UNCOV
1054
   default:
×
UNCOV
1055
      return false;
×
1056
   }
1057
}
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