ndtypes 0.2.0dev5 → 0.2.0dev6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +12 -0
  3. data/Rakefile +8 -0
  4. data/ext/ruby_ndtypes/GPATH +0 -0
  5. data/ext/ruby_ndtypes/GRTAGS +0 -0
  6. data/ext/ruby_ndtypes/GTAGS +0 -0
  7. data/ext/ruby_ndtypes/extconf.rb +1 -1
  8. data/ext/ruby_ndtypes/include/ndtypes.h +231 -122
  9. data/ext/ruby_ndtypes/include/ruby_ndtypes.h +1 -1
  10. data/ext/ruby_ndtypes/lib/libndtypes.a +0 -0
  11. data/ext/ruby_ndtypes/lib/libndtypes.so.0.2.0dev3 +0 -0
  12. data/ext/ruby_ndtypes/ndtypes/Makefile +87 -0
  13. data/ext/ruby_ndtypes/ndtypes/config.h +68 -0
  14. data/ext/ruby_ndtypes/ndtypes/config.log +477 -0
  15. data/ext/ruby_ndtypes/ndtypes/config.status +1027 -0
  16. data/ext/ruby_ndtypes/ndtypes/doc/_static/style.css +7 -0
  17. data/ext/ruby_ndtypes/ndtypes/doc/_templates/layout.html +2 -0
  18. data/ext/ruby_ndtypes/ndtypes/doc/conf.py +40 -4
  19. data/ext/ruby_ndtypes/ndtypes/doc/images/xndlogo.png +0 -0
  20. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/types.rst +1 -1
  21. data/ext/ruby_ndtypes/ndtypes/doc/requirements.txt +2 -0
  22. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile +287 -0
  23. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.in +20 -4
  24. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.vc +22 -3
  25. data/ext/ruby_ndtypes/ndtypes/libndtypes/alloc.c +1 -1
  26. data/ext/ruby_ndtypes/ndtypes/libndtypes/alloc.o +0 -0
  27. data/ext/ruby_ndtypes/ndtypes/libndtypes/attr.o +0 -0
  28. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/Makefile +73 -0
  29. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.c +246 -229
  30. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.h +15 -11
  31. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.o +0 -0
  32. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.y +38 -28
  33. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.c +91 -91
  34. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.h +1 -1
  35. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.l +4 -3
  36. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.o +0 -0
  37. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/export.c +8 -7
  38. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/export.o +0 -0
  39. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/import.c +2 -2
  40. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/import.o +0 -0
  41. data/ext/ruby_ndtypes/ndtypes/libndtypes/context.o +0 -0
  42. data/ext/ruby_ndtypes/ndtypes/libndtypes/copy.c +263 -182
  43. data/ext/ruby_ndtypes/ndtypes/libndtypes/copy.o +0 -0
  44. data/ext/ruby_ndtypes/ndtypes/libndtypes/encodings.o +0 -0
  45. data/ext/ruby_ndtypes/ndtypes/libndtypes/equal.c +67 -7
  46. data/ext/ruby_ndtypes/ndtypes/libndtypes/equal.o +0 -0
  47. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.c +1112 -1000
  48. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.h +69 -58
  49. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.o +0 -0
  50. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.y +150 -99
  51. data/ext/ruby_ndtypes/ndtypes/libndtypes/io.c +185 -15
  52. data/ext/ruby_ndtypes/ndtypes/libndtypes/io.o +0 -0
  53. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.c +301 -276
  54. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.h +1 -1
  55. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.l +9 -4
  56. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.o +0 -0
  57. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.a +0 -0
  58. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so +1 -0
  59. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so.0 +1 -0
  60. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so.0.2.0dev3 +0 -0
  61. data/ext/ruby_ndtypes/ndtypes/libndtypes/match.c +729 -228
  62. data/ext/ruby_ndtypes/ndtypes/libndtypes/match.o +0 -0
  63. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.c +768 -403
  64. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.h +1002 -0
  65. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.h.in +231 -122
  66. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.o +0 -0
  67. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.c +176 -84
  68. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.h +26 -14
  69. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.o +0 -0
  70. data/ext/ruby_ndtypes/ndtypes/libndtypes/parser.c +57 -35
  71. data/ext/ruby_ndtypes/ndtypes/libndtypes/parser.o +0 -0
  72. data/ext/ruby_ndtypes/ndtypes/libndtypes/primitive.c +420 -0
  73. data/ext/ruby_ndtypes/ndtypes/libndtypes/primitive.o +0 -0
  74. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.c +8 -8
  75. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.h +1 -1
  76. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.o +0 -0
  77. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/Makefile +48 -0
  78. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/deserialize.c +200 -116
  79. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/deserialize.o +0 -0
  80. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/serialize.c +46 -4
  81. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/serialize.o +0 -0
  82. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.c +58 -27
  83. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.h +1 -1
  84. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.o +0 -0
  85. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.c +3 -5
  86. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.h +12 -4
  87. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.o +0 -0
  88. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile +55 -0
  89. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.in +8 -8
  90. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.vc +5 -5
  91. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/runtest.c +274 -172
  92. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test.h +24 -4
  93. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_array.c +2 -2
  94. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_buffer.c +14 -14
  95. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_match.c +32 -30
  96. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse.c +37 -0
  97. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_error.c +36 -0
  98. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_roundtrip.c +16 -0
  99. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_record.c +5 -5
  100. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_typecheck.c +706 -253
  101. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_unify.c +132 -0
  102. data/ext/ruby_ndtypes/ndtypes/libndtypes/unify.c +703 -0
  103. data/ext/ruby_ndtypes/ndtypes/libndtypes/unify.o +0 -0
  104. data/ext/ruby_ndtypes/ndtypes/libndtypes/util.c +335 -127
  105. data/ext/ruby_ndtypes/ndtypes/libndtypes/util.o +0 -0
  106. data/ext/ruby_ndtypes/ndtypes/libndtypes/values.c +2 -2
  107. data/ext/ruby_ndtypes/ndtypes/libndtypes/values.o +0 -0
  108. data/ext/ruby_ndtypes/ndtypes/python/ndt_randtype.py +88 -71
  109. data/ext/ruby_ndtypes/ndtypes/python/ndt_support.py +0 -1
  110. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/__init__.py +10 -13
  111. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/_ndtypes.c +395 -314
  112. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.a +0 -0
  113. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so +1 -0
  114. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so.0 +1 -0
  115. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so.0.2.0dev3 +0 -0
  116. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/ndtypes.h +1002 -0
  117. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/pyndtypes.h +15 -33
  118. data/ext/ruby_ndtypes/ndtypes/python/test_ndtypes.py +340 -132
  119. data/ext/ruby_ndtypes/ndtypes/setup.py +11 -2
  120. data/ext/ruby_ndtypes/ruby_ndtypes.c +364 -241
  121. data/ext/ruby_ndtypes/ruby_ndtypes.h +1 -1
  122. data/ext/ruby_ndtypes/ruby_ndtypes_internal.h +0 -1
  123. data/lib/ndtypes.rb +11 -0
  124. data/lib/ndtypes/version.rb +2 -2
  125. data/lib/ruby_ndtypes.so +0 -0
  126. data/ndtypes.gemspec +3 -0
  127. data/spec/ndtypes_spec.rb +6 -0
  128. metadata +98 -4
  129. data/ext/ruby_ndtypes/gc_guard.c +0 -36
  130. data/ext/ruby_ndtypes/gc_guard.h +0 -12
@@ -31,6 +31,10 @@
31
31
  */
32
32
 
33
33
 
34
+ #ifdef _MSC_VER
35
+ #include <windows.h>
36
+ #endif
37
+
34
38
  #include <stdlib.h>
35
39
  #include <string.h>
36
40
  #include <stdint.h>
@@ -54,6 +58,12 @@ max(uint16_t x, uint16_t y)
54
58
  return x >= y ? x : y;
55
59
  }
56
60
 
61
+ static inline int64_t
62
+ max_i64(int64_t x, int64_t y)
63
+ {
64
+ return x >= y ? x : y;
65
+ }
66
+
57
67
  static inline int
58
68
  ispower2(uint16_t n)
59
69
  {
@@ -79,11 +89,29 @@ round_up(int64_t offset, uint16_t align, bool *overflow)
79
89
  static uint32_t
80
90
  ndt_subtree_flags(const ndt_t *type)
81
91
  {
82
- if (type && type->flags & (NDT_OPTION|NDT_SUBTREE_OPTION)) {
83
- return NDT_SUBTREE_OPTION;
92
+ uint32_t flags = 0U;
93
+
94
+ if (type == NULL) {
95
+ return flags;
84
96
  }
85
97
 
86
- return 0;
98
+ if (type->flags & (NDT_OPTION|NDT_SUBTREE_OPTION)) {
99
+ flags |= NDT_SUBTREE_OPTION;
100
+ }
101
+
102
+ if (type->flags & NDT_POINTER) {
103
+ flags |= NDT_POINTER;
104
+ }
105
+
106
+ if (type->flags & NDT_REF) {
107
+ flags |= NDT_REF;
108
+ }
109
+
110
+ if (type->flags & NDT_CHAR) {
111
+ flags |= NDT_CHAR;
112
+ }
113
+
114
+ return flags;
87
115
  }
88
116
 
89
117
  /* Determine general subtree and ellipsis flags. */
@@ -109,7 +137,7 @@ ndt_itemsize(const ndt_t *t)
109
137
  switch (t->tag) {
110
138
  case FixedDim:
111
139
  return t->Concrete.FixedDim.itemsize;
112
- case VarDim:
140
+ case VarDim: case VarDimElem:
113
141
  return t->Concrete.VarDim.itemsize;
114
142
  default:
115
143
  return t->datasize;
@@ -121,6 +149,38 @@ ndt_itemsize(const ndt_t *t)
121
149
  /* Predicates */
122
150
  /*****************************************************************************/
123
151
 
152
+ bool
153
+ ndt_is_static(const ndt_t *t)
154
+ {
155
+ switch (t->tag) {
156
+ case String:
157
+ case Bool:
158
+ case SignedKind: case Int8: case Int16: case Int32: case Int64:
159
+ case UnsignedKind: case Uint8: case Uint16: case Uint32: case Uint64:
160
+ case FloatKind: case BFloat16: case Float16: case Float32: case Float64:
161
+ case ComplexKind: case BComplex32: case Complex32: case Complex64: case Complex128:
162
+ return true;
163
+ default:
164
+ return false;
165
+ }
166
+ }
167
+
168
+ bool
169
+ ndt_is_static_tag(enum ndt tag)
170
+ {
171
+ switch (tag) {
172
+ case String:
173
+ case Bool:
174
+ case SignedKind: case Int8: case Int16: case Int32: case Int64:
175
+ case UnsignedKind: case Uint8: case Uint16: case Uint32: case Uint64:
176
+ case FloatKind: case BFloat16: case Float16: case Float32: case Float64:
177
+ case ComplexKind: case BComplex32: case Complex32: case Complex64: case Complex128:
178
+ return true;
179
+ default:
180
+ return false;
181
+ }
182
+ }
183
+
124
184
  /* Type field access */
125
185
  int
126
186
  ndt_is_abstract(const ndt_t *t)
@@ -147,6 +207,18 @@ ndt_subtree_is_optional(const ndt_t *t)
147
207
  return t->flags & NDT_SUBTREE_OPTION;
148
208
  }
149
209
 
210
+ int
211
+ ndt_is_pointer_free(const ndt_t *t)
212
+ {
213
+ return !(t->flags & NDT_POINTER);
214
+ }
215
+
216
+ int
217
+ ndt_is_ref_free(const ndt_t *t)
218
+ {
219
+ return !(t->flags & NDT_REF);
220
+ }
221
+
150
222
  /* Array predicates */
151
223
  int
152
224
  ndt_is_ndarray(const ndt_t *t)
@@ -222,6 +294,44 @@ ndt_is_f_contiguous(const ndt_t *t)
222
294
  return 1;
223
295
  }
224
296
 
297
+ static int
298
+ _is_var_contiguous(const ndt_t *t, int32_t nitems)
299
+ {
300
+ if (t->ndim == 0) {
301
+ return 1;
302
+ }
303
+
304
+ switch (t->tag) {
305
+ case VarDim: {
306
+ const int32_t noffsets = t->Concrete.VarDim.offsets->n;
307
+ const int32_t *offsets = t->Concrete.VarDim.offsets->v;
308
+
309
+ if (noffsets != nitems+1) {
310
+ return 0;
311
+ }
312
+
313
+ if (t->Concrete.VarDim.nslices != 0 ||
314
+ t->Concrete.VarDim.slices != NULL) {
315
+ return 0;
316
+ }
317
+
318
+ return _is_var_contiguous(t->VarDim.type, offsets[noffsets-1]);
319
+ }
320
+ default:
321
+ return 0;
322
+ }
323
+ }
324
+
325
+ int
326
+ ndt_is_var_contiguous(const ndt_t *t)
327
+ {
328
+ if (ndt_is_abstract(t)) {
329
+ return 0;
330
+ }
331
+
332
+ return _is_var_contiguous(t, 1);
333
+ }
334
+
225
335
  int
226
336
  ndt_really_fortran(const ndt_t *t)
227
337
  {
@@ -236,8 +346,8 @@ ndt_is_scalar(const ndt_t *t)
236
346
  case Bool:
237
347
  case Int8: case Int16: case Int32: case Int64:
238
348
  case Uint8: case Uint16: case Uint32: case Uint64:
239
- case Float16: case Float32: case Float64:
240
- case Complex32: case Complex64: case Complex128:
349
+ case BFloat16: case Float16: case Float32: case Float64:
350
+ case BComplex32: case Complex32: case Complex64: case Complex128:
241
351
  case FixedString: case FixedBytes:
242
352
  case String: case Bytes:
243
353
  case Char:
@@ -274,7 +384,7 @@ int
274
384
  ndt_is_float(const ndt_t *t)
275
385
  {
276
386
  switch (t->tag) {
277
- case Float16: case Float32: case Float64:
387
+ case BFloat16: case Float16: case Float32: case Float64:
278
388
  return 1;
279
389
  default:
280
390
  return 0;
@@ -285,7 +395,7 @@ int
285
395
  ndt_is_complex(const ndt_t *t)
286
396
  {
287
397
  switch (t->tag) {
288
- case Complex32: case Complex64: case Complex128:
398
+ case BComplex32: case Complex32: case Complex64: case Complex128:
289
399
  return 1;
290
400
  default:
291
401
  return 0;
@@ -304,8 +414,8 @@ ndt_is_little_endian(const ndt_t *t)
304
414
  switch (t->tag) {
305
415
  case Int8: case Int16: case Int32: case Int64:
306
416
  case Uint8: case Uint16: case Uint32: case Uint64:
307
- case Float16: case Float32: case Float64:
308
- case Complex32: case Complex64: case Complex128:
417
+ case BFloat16: case Float16: case Float32: case Float64:
418
+ case BComplex32: case Complex32: case Complex64: case Complex128:
309
419
  if (t->flags & NDT_LITTLE_ENDIAN) {
310
420
  return 1;
311
421
  }
@@ -324,8 +434,8 @@ ndt_is_big_endian(const ndt_t *t)
324
434
  switch (t->tag) {
325
435
  case Int16: case Int32: case Int64:
326
436
  case Uint16: case Uint32: case Uint64:
327
- case Float16: case Float32: case Float64:
328
- case Complex32: case Complex64: case Complex128:
437
+ case BFloat16: case Float16: case Float32: case Float64:
438
+ case BComplex32: case Complex32: case Complex64: case Complex128:
329
439
  if (t->flags & NDT_BIG_ENDIAN) {
330
440
  return 1;
331
441
  }
@@ -449,7 +559,7 @@ get_align(uint16_opt_t align, uint16_t default_align, ndt_context_t *ctx)
449
559
  * 'name' is NULL for a tuple field.
450
560
  */
451
561
  ndt_field_t *
452
- ndt_field(char *name, ndt_t *type, uint16_opt_t align, uint16_opt_t pack,
562
+ ndt_field(char *name, const ndt_t *type, uint16_opt_t align, uint16_opt_t pack,
453
563
  uint16_opt_t pad, ndt_context_t *ctx)
454
564
  {
455
565
  ndt_field_t *field;
@@ -462,7 +572,6 @@ ndt_field(char *name, ndt_t *type, uint16_opt_t align, uint16_opt_t pack,
462
572
  min_align = min_field_align(type, align, pack, ctx);
463
573
  if (min_align == UINT16_MAX) {
464
574
  ndt_free(name);
465
- ndt_del(type);
466
575
  return NULL;
467
576
  }
468
577
 
@@ -470,10 +579,11 @@ ndt_field(char *name, ndt_t *type, uint16_opt_t align, uint16_opt_t pack,
470
579
  field = ndt_alloc_size(sizeof *field);
471
580
  if (field == NULL) {
472
581
  ndt_free(name);
473
- ndt_del(type);
474
582
  return ndt_memory_error(ctx);
475
583
  }
476
584
  field->name = name;
585
+
586
+ ndt_incref(type);
477
587
  field->type = type;
478
588
 
479
589
  /* concrete access */
@@ -493,7 +603,7 @@ ndt_field_del(ndt_field_t *field)
493
603
  {
494
604
  if (field) {
495
605
  ndt_free(field->name);
496
- ndt_del(field->type);
606
+ ndt_decref(field->type);
497
607
  ndt_free(field);
498
608
  }
499
609
  }
@@ -509,14 +619,14 @@ ndt_field_array_del(ndt_field_t *fields, int64_t shape)
509
619
 
510
620
  for (i = 0; i < shape; i++) {
511
621
  ndt_free(fields[i].name);
512
- ndt_del(fields[i].type);
622
+ ndt_decref(fields[i].type);
513
623
  }
514
624
 
515
625
  ndt_free(fields);
516
626
  }
517
627
 
518
628
  void
519
- ndt_type_array_clear(ndt_t **types, int64_t shape)
629
+ ndt_type_array_clear(const ndt_t **types, int64_t shape)
520
630
  {
521
631
  int64_t i;
522
632
 
@@ -525,15 +635,15 @@ ndt_type_array_clear(ndt_t **types, int64_t shape)
525
635
  }
526
636
 
527
637
  for (i = 0; i < shape; i++) {
528
- ndt_del(types[i]);
638
+ ndt_decref(types[i]);
529
639
  }
530
640
  }
531
641
 
532
642
  void
533
- ndt_type_array_del(ndt_t **types, int64_t shape)
643
+ ndt_type_array_del(const ndt_t **types, int64_t shape)
534
644
  {
535
645
  ndt_type_array_clear(types, shape);
536
- ndt_free(types);
646
+ ndt_free((void *)types);
537
647
  }
538
648
 
539
649
 
@@ -542,35 +652,29 @@ ndt_type_array_del(ndt_t **types, int64_t shape)
542
652
  /*****************************************************************************/
543
653
 
544
654
  /*
545
- * Add a typedef name -> type to the symbol table. Steals the 'type'
546
- * reference.
655
+ * Add a typedef name -> type to the symbol table.
547
656
  */
548
657
  int
549
- ndt_typedef(const char *name, ndt_t *type, const ndt_methods_t *m, ndt_context_t *ctx)
658
+ ndt_typedef(const char *name, const ndt_t *type, const ndt_methods_t *m, ndt_context_t *ctx)
550
659
  {
551
- if (ndt_typedef_add(name, type, m, ctx) < 0) {
552
- return -1;
553
- }
554
-
555
- return 0;
660
+ return ndt_typedef_add(name, type, m, ctx);
556
661
  }
557
662
 
558
663
  int
559
664
  ndt_typedef_from_string(const char *name, const char *type, const ndt_methods_t *m,
560
665
  ndt_context_t *ctx)
561
666
  {
562
- ndt_t *t;
667
+ const ndt_t *t;
668
+ int ret;
563
669
 
564
670
  t = ndt_from_string(type, ctx);
565
671
  if (t == NULL) {
566
672
  return -1;
567
673
  }
568
674
 
569
- if (ndt_typedef_add(name, t, m, ctx) < 0) {
570
- return -1;
571
- }
572
-
573
- return 0;
675
+ ret = ndt_typedef_add(name, t, m, ctx);
676
+ ndt_decref(t);
677
+ return ret;
574
678
  }
575
679
 
576
680
 
@@ -578,7 +682,7 @@ ndt_typedef_from_string(const char *name, const char *type, const ndt_methods_t
578
682
  /* Type invariants */
579
683
  /******************************************************************************/
580
684
 
581
- /* Invariants for all types except for var and ellipsis dimensions. */
685
+ /* Invariants for all types except for dimensions. */
582
686
  static int
583
687
  check_type_invariants(const ndt_t *type, ndt_context_t *ctx)
584
688
  {
@@ -588,9 +692,29 @@ check_type_invariants(const ndt_t *type, ndt_context_t *ctx)
588
692
  return 0;
589
693
  }
590
694
 
591
- if (type->tag == VarDim) {
695
+ if (type->ndim >= NDT_MAX_DIM) {
696
+ ndt_err_format(ctx, NDT_TypeError, "ndim > %d", NDT_MAX_DIM);
697
+ return 0;
698
+ }
699
+
700
+ return 1;
701
+ }
702
+
703
+ /* Invariants for fixed dimensions. */
704
+ static int
705
+ check_fixed_invariants(const ndt_t *type, ndt_context_t *ctx)
706
+ {
707
+ if (type->tag == Module) {
592
708
  ndt_err_format(ctx, NDT_TypeError,
593
- "nested or non-uniform var dimensions are not supported");
709
+ "nested module types are not supported");
710
+ return 0;
711
+ }
712
+
713
+ if (type->tag == VarDim || type->tag == VarDimElem ||
714
+ type->tag == Array) {
715
+ ndt_err_format(ctx, NDT_TypeError,
716
+ "fixed dimensions cannot contain var dimensions "
717
+ "or flexible arrays");
594
718
  return 0;
595
719
  }
596
720
 
@@ -612,13 +736,16 @@ check_abstract_var_invariants(const ndt_t *type, ndt_context_t *ctx)
612
736
  return 0;
613
737
  }
614
738
 
615
- if (type->tag == FixedDim || type->tag == SymbolicDim) {
739
+ if (type->tag == FixedDim || type->tag == SymbolicDim ||
740
+ type->tag == Array) {
616
741
  ndt_err_format(ctx, NDT_TypeError,
617
- "mixed fixed and var dim are not supported");
742
+ "var dimensions cannot contain fixed dimensions or "
743
+ "flexible arrays");
618
744
  return 0;
619
745
  }
620
746
 
621
- if (type->tag == VarDim && ndt_is_concrete(type)) {
747
+ if ((type->tag == VarDim && ndt_is_concrete(type)) ||
748
+ type->tag == VarDimElem) {
622
749
  ndt_err_format(ctx, NDT_TypeError,
623
750
  "mixing abstract and concrete var dimensions is not allowed");
624
751
  return 0;
@@ -634,7 +761,7 @@ check_abstract_var_invariants(const ndt_t *type, ndt_context_t *ctx)
634
761
 
635
762
  /* Invariants for concrete var dimensions. */
636
763
  static int
637
- check_var_invariants(enum ndt_offsets flag, const ndt_t *type, ndt_context_t *ctx)
764
+ check_var_invariants(const ndt_t *type, ndt_context_t *ctx)
638
765
  {
639
766
  if (type->tag == Module) {
640
767
  ndt_err_format(ctx, NDT_TypeError,
@@ -642,23 +769,20 @@ check_var_invariants(enum ndt_offsets flag, const ndt_t *type, ndt_context_t *ct
642
769
  return 0;
643
770
  }
644
771
 
645
- if (type->tag == FixedDim || type->tag == SymbolicDim) {
772
+ if (type->tag == FixedDim || type->tag == SymbolicDim ||
773
+ type->tag == Array) {
646
774
  ndt_err_format(ctx, NDT_TypeError,
647
- "mixed fixed and var dim are not supported");
775
+ "var dimensions cannot contain fixed dimensions or "
776
+ "flexible arrays");
648
777
  return 0;
649
778
  }
650
779
 
651
- if (type->tag == VarDim) {
780
+ if (type->tag == VarDim || type->tag == VarDimElem) {
652
781
  if (ndt_is_abstract(type)) {
653
782
  ndt_err_format(ctx, NDT_TypeError,
654
783
  "mixing abstract and concrete var dimensions is not allowed");
655
784
  return 0;
656
785
  }
657
- if (flag != type->Concrete.VarDim.flag) {
658
- ndt_err_format(ctx, NDT_TypeError,
659
- "mixing internal and external offsets is not allowed");
660
- return 0;
661
- }
662
786
  }
663
787
 
664
788
  if (type->ndim >= NDT_MAX_DIM) {
@@ -669,6 +793,32 @@ check_var_invariants(enum ndt_offsets flag, const ndt_t *type, ndt_context_t *ct
669
793
  return 1;
670
794
  }
671
795
 
796
+ /* Invariants for array dimensions. */
797
+ static int
798
+ check_array_invariants(const ndt_t *type, ndt_context_t *ctx)
799
+ {
800
+ if (type->tag == Module) {
801
+ ndt_err_format(ctx, NDT_TypeError,
802
+ "nested module types are not supported");
803
+ return 0;
804
+ }
805
+
806
+ if (type->tag == FixedDim || type->tag == SymbolicDim ||
807
+ type->tag == VarDim || type->tag == VarDimElem) {
808
+ ndt_err_format(ctx, NDT_TypeError,
809
+ "cannot mix fixed or var dimensions with flexible arrays");
810
+ return 0;
811
+ }
812
+
813
+ if (!ndt_is_ref_free(type)) {
814
+ ndt_err_format(ctx, NDT_TypeError,
815
+ "flexible array elements cannot be contain references");
816
+ return 0;
817
+ }
818
+
819
+ return 1;
820
+ }
821
+
672
822
  /* Invariants for ellipsis dimensions. */
673
823
  static int
674
824
  check_ellipsis_invariants(const ndt_t *type, ndt_context_t *ctx)
@@ -697,7 +847,7 @@ strcmp_null(const char *s, const char *t)
697
847
  }
698
848
 
699
849
  static int
700
- check_function_invariants(ndt_t * const *types, int64_t nin, int64_t nargs,
850
+ check_function_invariants(const ndt_t **types, int64_t nin, int64_t nargs,
701
851
  ndt_context_t *ctx)
702
852
  {
703
853
  int64_t count = 0;
@@ -746,7 +896,7 @@ error:
746
896
  }
747
897
 
748
898
  static bool
749
- is_elemwise(ndt_t * const *types, int64_t nargs)
899
+ is_elemwise(const ndt_t **types, int64_t nargs)
750
900
  {
751
901
  for (int64_t i = 0; i < nargs; i++) {
752
902
  if ((types[i]->ndim == 1 && types[i]->tag == EllipsisDim) ||
@@ -765,7 +915,7 @@ is_elemwise(ndt_t * const *types, int64_t nargs)
765
915
  /******************************************************************************/
766
916
 
767
917
  ndt_t *
768
- ndt_new(enum ndt tag, ndt_context_t *ctx)
918
+ ndt_new(enum ndt tag, uint32_t flags, ndt_context_t *ctx)
769
919
  {
770
920
  ndt_t *t;
771
921
 
@@ -776,17 +926,19 @@ ndt_new(enum ndt tag, ndt_context_t *ctx)
776
926
 
777
927
  t->tag = tag;
778
928
  t->access = Abstract;
779
- t->flags = 0;
929
+ t->flags = flags;
780
930
  t->ndim = 0;
781
931
 
782
932
  t->datasize = 0;
783
933
  t->align = UINT16_MAX;
784
934
 
935
+ t->refcnt = 1;
936
+
785
937
  return t;
786
938
  }
787
939
 
788
940
  static ndt_t *
789
- ndt_new_extra(enum ndt tag, int64_t n, ndt_context_t *ctx)
941
+ ndt_new_extra(enum ndt tag, int64_t n, uint32_t flags, ndt_context_t *ctx)
790
942
  {
791
943
  bool overflow = 0;
792
944
  ndt_t *t;
@@ -805,12 +957,14 @@ ndt_new_extra(enum ndt tag, int64_t n, ndt_context_t *ctx)
805
957
 
806
958
  t->tag = tag;
807
959
  t->access = Abstract;
808
- t->flags = 0;
960
+ t->flags = flags;
809
961
  t->ndim = 0;
810
962
 
811
963
  t->datasize = 0;
812
964
  t->align = UINT16_MAX;
813
965
 
966
+ t->refcnt = 1;
967
+
814
968
  return t;
815
969
  }
816
970
 
@@ -828,12 +982,12 @@ ndt_function_new(int64_t nargs, ndt_context_t *ctx)
828
982
  return NULL;
829
983
  }
830
984
 
831
- t = ndt_new_extra(Function, extra, ctx);
985
+ t = ndt_new_extra(Function, extra, 0, ctx);
832
986
  if (t == NULL) {
833
987
  return NULL;
834
988
  }
835
989
  t->Function.nargs = nargs;
836
- t->Function.types = (ndt_t **)t->extra;
990
+ t->Function.types = (const ndt_t **)t->extra;
837
991
 
838
992
  for (i = 0; i < nargs; i++) {
839
993
  t->Function.types[i] = NULL;
@@ -843,7 +997,7 @@ ndt_function_new(int64_t nargs, ndt_context_t *ctx)
843
997
  }
844
998
 
845
999
  ndt_t *
846
- ndt_tuple_new(enum ndt_variadic flag, int64_t shape, ndt_context_t *ctx)
1000
+ ndt_tuple_new(enum ndt_variadic flag, int64_t shape, bool opt, ndt_context_t *ctx)
847
1001
  {
848
1002
  ndt_t *t = NULL;
849
1003
  bool overflow = 0;
@@ -870,14 +1024,14 @@ ndt_tuple_new(enum ndt_variadic flag, int64_t shape, ndt_context_t *ctx)
870
1024
  return NULL;
871
1025
  }
872
1026
 
873
- t = ndt_new_extra(Tuple, extra, ctx);
1027
+ t = ndt_new_extra(Tuple, extra, opt, ctx);
874
1028
  if (t == NULL) {
875
1029
  return NULL;
876
1030
  }
877
1031
 
878
1032
  t->Tuple.flag = flag;
879
1033
  t->Tuple.shape = shape;
880
- t->Tuple.types = (ndt_t **)t->extra;
1034
+ t->Tuple.types = (const ndt_t **)t->extra;
881
1035
  t->Concrete.Tuple.offset = (int64_t *)(t->extra + offset_offset);
882
1036
  t->Concrete.Tuple.align = (uint16_t *)(t->extra + align_offset);
883
1037
  t->Concrete.Tuple.pad = (uint16_t *)(t->extra + pad_offset);
@@ -893,7 +1047,7 @@ ndt_tuple_new(enum ndt_variadic flag, int64_t shape, ndt_context_t *ctx)
893
1047
  }
894
1048
 
895
1049
  ndt_t *
896
- ndt_record_new(enum ndt_variadic flag, int64_t shape, ndt_context_t *ctx)
1050
+ ndt_record_new(enum ndt_variadic flag, int64_t shape, bool opt, ndt_context_t *ctx)
897
1051
  {
898
1052
  ndt_t *t = NULL;
899
1053
  bool overflow = 0;
@@ -923,7 +1077,7 @@ ndt_record_new(enum ndt_variadic flag, int64_t shape, ndt_context_t *ctx)
923
1077
  return NULL;
924
1078
  }
925
1079
 
926
- t = ndt_new_extra(Record, extra, ctx);
1080
+ t = ndt_new_extra(Record, extra, opt, ctx);
927
1081
  if (t == NULL) {
928
1082
  return NULL;
929
1083
  }
@@ -931,7 +1085,7 @@ ndt_record_new(enum ndt_variadic flag, int64_t shape, ndt_context_t *ctx)
931
1085
  t->Record.flag = flag;
932
1086
  t->Record.shape = shape;
933
1087
  t->Record.names = (char **)t->extra;
934
- t->Record.types = (ndt_t **)(t->extra + types_offset);
1088
+ t->Record.types = (const ndt_t **)(t->extra + types_offset);
935
1089
  t->Concrete.Record.offset = (int64_t *)(t->extra + offset_offset);
936
1090
  t->Concrete.Record.align = (uint16_t *)(t->extra + align_offset);
937
1091
  t->Concrete.Record.pad = (uint16_t *)(t->extra + pad_offset);
@@ -947,7 +1101,41 @@ ndt_record_new(enum ndt_variadic flag, int64_t shape, ndt_context_t *ctx)
947
1101
  return t;
948
1102
  }
949
1103
 
950
- void
1104
+ ndt_t *
1105
+ ndt_union_new(int64_t ntags, bool opt, ndt_context_t *ctx)
1106
+ {
1107
+ ndt_t *t = NULL;
1108
+ bool overflow = 0;
1109
+ int64_t extra;
1110
+ int64_t types_offset;
1111
+ int64_t i;
1112
+
1113
+ types_offset = MULi64(ntags, sizeof(char *), &overflow);
1114
+ extra = MULi64(2, types_offset, &overflow);
1115
+
1116
+ if (overflow) {
1117
+ ndt_err_format(ctx, NDT_ValueError, "union size too large");
1118
+ return NULL;
1119
+ }
1120
+
1121
+ t = ndt_new_extra(Union, extra, opt, ctx);
1122
+ if (t == NULL) {
1123
+ return NULL;
1124
+ }
1125
+
1126
+ t->Union.ntags = ntags;
1127
+ t->Union.tags = (char **)t->extra;
1128
+ t->Union.types = (const ndt_t **)(t->extra + types_offset);
1129
+
1130
+ for (i = 0; i < ntags; i++) {
1131
+ t->Union.tags[i] = NULL;
1132
+ t->Union.types[i] = NULL;
1133
+ }
1134
+
1135
+ return t;
1136
+ }
1137
+
1138
+ static void
951
1139
  ndt_del(ndt_t *t)
952
1140
  {
953
1141
  if (t == NULL) {
@@ -957,29 +1145,27 @@ ndt_del(ndt_t *t)
957
1145
  switch (t->tag) {
958
1146
  case Module: {
959
1147
  ndt_free(t->Module.name);
960
- ndt_del(t->Module.type);
1148
+ ndt_decref(t->Module.type);
961
1149
  goto free_type;
962
1150
  }
963
1151
 
964
1152
  case Function: {
965
1153
  int64_t i;
966
1154
  for (i = 0; i < t->Function.nargs; i++) {
967
- ndt_del(t->Function.types[i]);
1155
+ ndt_decref(t->Function.types[i]);
968
1156
  }
969
1157
  goto free_type;
970
1158
  }
971
1159
 
972
1160
  case FixedDim: {
973
- ndt_del(t->FixedDim.type);
1161
+ ndt_decref(t->FixedDim.type);
974
1162
  goto free_type;
975
1163
  }
976
1164
 
977
- case VarDim: {
978
- ndt_del(t->VarDim.type);
1165
+ case VarDim: case VarDimElem: {
1166
+ ndt_decref(t->VarDim.type);
979
1167
  if (ndt_is_concrete(t)) {
980
- if (t->Concrete.VarDim.flag == InternalOffsets) {
981
- ndt_free((int32_t *)t->Concrete.VarDim.offsets);
982
- }
1168
+ ndt_decref_offsets(t->Concrete.VarDim.offsets);
983
1169
  ndt_free(t->Concrete.VarDim.slices);
984
1170
  }
985
1171
  goto free_type;
@@ -987,20 +1173,25 @@ ndt_del(ndt_t *t)
987
1173
 
988
1174
  case SymbolicDim: {
989
1175
  ndt_free(t->SymbolicDim.name);
990
- ndt_del(t->SymbolicDim.type);
1176
+ ndt_decref(t->SymbolicDim.type);
991
1177
  goto free_type;
992
1178
  }
993
1179
 
994
1180
  case EllipsisDim: {
995
1181
  ndt_free(t->EllipsisDim.name);
996
- ndt_del(t->EllipsisDim.type);
1182
+ ndt_decref(t->EllipsisDim.type);
1183
+ goto free_type;
1184
+ }
1185
+
1186
+ case Array: {
1187
+ ndt_decref(t->Array.type);
997
1188
  goto free_type;
998
1189
  }
999
1190
 
1000
1191
  case Tuple: {
1001
1192
  int64_t i;
1002
1193
  for (i = 0; i < t->Tuple.shape; i++) {
1003
- ndt_del(t->Tuple.types[i]);
1194
+ ndt_decref(t->Tuple.types[i]);
1004
1195
  }
1005
1196
  goto free_type;
1006
1197
  }
@@ -1009,25 +1200,34 @@ ndt_del(ndt_t *t)
1009
1200
  int64_t i;
1010
1201
  for (i = 0; i < t->Record.shape; i++) {
1011
1202
  ndt_free(t->Record.names[i]);
1012
- ndt_del(t->Record.types[i]);
1203
+ ndt_decref(t->Record.types[i]);
1204
+ }
1205
+ goto free_type;
1206
+ }
1207
+
1208
+ case Union: {
1209
+ int64_t i;
1210
+ for (i = 0; i < t->Union.ntags; i++) {
1211
+ ndt_free(t->Union.tags[i]);
1212
+ ndt_decref(t->Union.types[i]);
1013
1213
  }
1014
1214
  goto free_type;
1015
1215
  }
1016
1216
 
1017
1217
  case Ref: {
1018
- ndt_del(t->Ref.type);
1218
+ ndt_decref(t->Ref.type);
1019
1219
  goto free_type;
1020
1220
  }
1021
1221
 
1022
1222
  case Constr: {
1023
1223
  ndt_free(t->Constr.name);
1024
- ndt_del(t->Constr.type);
1224
+ ndt_decref(t->Constr.type);
1025
1225
  goto free_type;
1026
1226
  }
1027
1227
 
1028
1228
  case Nominal: {
1029
1229
  ndt_free(t->Nominal.name);
1030
- ndt_del(t->Nominal.type);
1230
+ ndt_decref(t->Nominal.type);
1031
1231
  goto free_type;
1032
1232
  }
1033
1233
 
@@ -1044,17 +1244,16 @@ ndt_del(ndt_t *t)
1044
1244
  case AnyKind: case ScalarKind:
1045
1245
  case FixedStringKind: case FixedString:
1046
1246
  case FixedBytesKind: case FixedBytes:
1047
- case String: case Bytes: case Char:
1048
- case Bool:
1049
- case SignedKind:
1050
- case Int8: case Int16: case Int32: case Int64:
1051
- case UnsignedKind:
1052
- case Uint8: case Uint16: case Uint32: case Uint64:
1053
- case FloatKind:
1054
- case Float16: case Float32: case Float64:
1055
- case ComplexKind:
1056
- case Complex32: case Complex64: case Complex128:
1247
+ case Bytes: case Char:
1057
1248
  goto free_type;
1249
+
1250
+ case String:
1251
+ case Bool:
1252
+ case SignedKind: case Int8: case Int16: case Int32: case Int64:
1253
+ case UnsignedKind: case Uint8: case Uint16: case Uint32: case Uint64:
1254
+ case FloatKind: case BFloat16: case Float16: case Float32: case Float64:
1255
+ case ComplexKind: case BComplex32: case Complex32: case Complex64: case Complex128:
1256
+ return;
1058
1257
  }
1059
1258
 
1060
1259
  /* NOT REACHED: tags should be exhaustive. */
@@ -1065,43 +1264,150 @@ free_type:
1065
1264
  ndt_free(t);
1066
1265
  }
1067
1266
 
1267
+ void
1268
+ ndt_incref(const ndt_t *t)
1269
+ {
1270
+ if (ndt_is_static(t)) {
1271
+ return;
1272
+ }
1068
1273
 
1069
- /******************************************************************************/
1070
- /* Type functions */
1071
- /******************************************************************************/
1274
+ ndt_t *u = (ndt_t *)t;
1275
+ #ifdef _MSC_VER
1276
+ (void)InterlockedIncrement64(&u->refcnt);
1277
+ #else
1278
+ ++u->refcnt;
1279
+ #endif
1280
+ }
1072
1281
 
1073
- /* Set the option flag of a type */
1074
- ndt_t *
1075
- ndt_option(ndt_t *t)
1282
+ void
1283
+ ndt_decref(const ndt_t *t)
1076
1284
  {
1077
- t->flags |= NDT_OPTION;
1078
- return t;
1285
+ if (t == NULL || ndt_is_static(t)) {
1286
+ return;
1287
+ }
1288
+
1289
+ ndt_t *u = (ndt_t *)t;
1290
+ #ifdef _MSC_VER
1291
+ if (InterlockedDecrement64(&u->refcnt) == 0) {
1292
+ ndt_del(u);
1293
+ }
1294
+ #else
1295
+ if (--u->refcnt == 0) {
1296
+ ndt_del(u);
1297
+ }
1298
+ #endif
1079
1299
  }
1080
1300
 
1301
+ void
1302
+ ndt_move(const ndt_t **dst, const ndt_t *src)
1303
+ {
1304
+ ndt_decref(*dst);
1305
+ *dst = src;
1306
+ }
1307
+
1308
+
1309
+ ndt_offsets_t *
1310
+ ndt_offsets_new(int32_t size, ndt_context_t *ctx)
1311
+ {
1312
+ ndt_offsets_t *offsets;
1313
+
1314
+ offsets = ndt_alloc(1, sizeof *offsets);
1315
+ if (offsets == NULL) {
1316
+ return ndt_memory_error(ctx);
1317
+ }
1318
+
1319
+ offsets->v = ndt_calloc(size, sizeof *offsets->v);
1320
+ if (offsets->v == NULL) {
1321
+ ndt_free(offsets);
1322
+ return ndt_memory_error(ctx);
1323
+ }
1324
+
1325
+ offsets->refcnt = 1;
1326
+ offsets->n = size;
1327
+
1328
+ return offsets;
1329
+ }
1330
+
1331
+ ndt_offsets_t *
1332
+ ndt_offsets_from_ptr(int32_t *ptr, int32_t size, ndt_context_t *ctx)
1333
+ {
1334
+ ndt_offsets_t *offsets;
1335
+
1336
+ offsets = ndt_alloc(1, sizeof *offsets);
1337
+ if (offsets == NULL) {
1338
+ ndt_free(ptr);
1339
+ return ndt_memory_error(ctx);
1340
+ }
1341
+ offsets->refcnt = 1;
1342
+ offsets->n = size;
1343
+ offsets->v = ptr;
1344
+
1345
+ return offsets;
1346
+ }
1347
+
1348
+ void
1349
+ ndt_incref_offsets(const ndt_offsets_t *x)
1350
+ {
1351
+ ndt_offsets_t *offsets = (ndt_offsets_t *)x;
1352
+ #ifdef _MSC_VER
1353
+ (void)InterlockedIncrement64(&offsets->refcnt);
1354
+ #else
1355
+ ++offsets->refcnt;
1356
+ #endif
1357
+ }
1358
+
1359
+ void
1360
+ ndt_decref_offsets(const ndt_offsets_t *x)
1361
+ {
1362
+ ndt_offsets_t *offsets = (ndt_offsets_t *)x;
1363
+
1364
+ if (offsets == NULL) {
1365
+ return;
1366
+ }
1367
+
1368
+ #ifdef _MSC_VER
1369
+ if (InterlockedDecrement64(&offsets->refcnt) == 0) {
1370
+ ndt_free((void *)offsets->v);
1371
+ ndt_free(offsets);
1372
+ }
1373
+ #else
1374
+ if (--offsets->refcnt == 0) {
1375
+ ndt_free((void *)offsets->v);
1376
+ ndt_free(offsets);
1377
+ }
1378
+ #endif
1379
+ }
1380
+
1381
+
1382
+ /******************************************************************************/
1383
+ /* Type functions */
1384
+ /******************************************************************************/
1385
+
1081
1386
  /* Abstract namespace type */
1082
- ndt_t *
1083
- ndt_module(char *name, ndt_t *type, ndt_context_t *ctx)
1387
+ const ndt_t *
1388
+ ndt_module(char *name, const ndt_t *type, ndt_context_t *ctx)
1084
1389
  {
1085
1390
  ndt_t *t;
1086
1391
 
1087
- t = ndt_new(Module, ctx);
1392
+ t = ndt_new(Module, 0, ctx);
1088
1393
  if (t == NULL) {
1089
1394
  ndt_free(name);
1090
- ndt_del(type);
1091
1395
  return NULL;
1092
1396
  }
1093
1397
 
1398
+ ndt_incref(type);
1399
+
1094
1400
  /* abstract type */
1095
1401
  t->Module.name = name;
1096
1402
  t->Module.type = type;
1097
- t->flags = ndt_subtree_flags(type);
1403
+ t->flags |= ndt_subtree_flags(type);
1098
1404
 
1099
1405
  return t;
1100
1406
  }
1101
1407
 
1102
1408
  /* Abstract function signatures */
1103
- ndt_t *
1104
- ndt_function(ndt_t * const *types, int64_t nargs, int64_t nin, int64_t nout,
1409
+ const ndt_t *
1410
+ ndt_function(const ndt_t **types, int64_t nargs, int64_t nin, int64_t nout,
1105
1411
  ndt_context_t *ctx)
1106
1412
  {
1107
1413
  ndt_t *t;
@@ -1110,16 +1416,12 @@ ndt_function(ndt_t * const *types, int64_t nargs, int64_t nin, int64_t nout,
1110
1416
  assert(0 <= nin && 0 <= nout && nargs == nin+nout);
1111
1417
 
1112
1418
  if (!check_function_invariants(types, nin, nargs, ctx)) {
1113
- ndt_type_array_clear((ndt_t **)types, nargs);
1114
1419
  return NULL;
1115
1420
  }
1116
1421
 
1117
1422
  /* abstract type */
1118
1423
  t = ndt_function_new(nargs, ctx);
1119
1424
  if (t == NULL) {
1120
- for (i = 0; i < nargs; i++) {
1121
- ndt_del(types[i]);
1122
- }
1123
1425
  return NULL;
1124
1426
  }
1125
1427
  t->Function.elemwise = is_elemwise(types, nargs);
@@ -1127,6 +1429,7 @@ ndt_function(ndt_t * const *types, int64_t nargs, int64_t nin, int64_t nout,
1127
1429
  t->Function.nout = nout;
1128
1430
 
1129
1431
  for (i = 0; i < nargs; i++) {
1432
+ ndt_incref(types[i]);
1130
1433
  t->Function.types[i] = types[i];
1131
1434
  t->flags |= ndt_dim_flags(types[i]);
1132
1435
  }
@@ -1134,10 +1437,10 @@ ndt_function(ndt_t * const *types, int64_t nargs, int64_t nin, int64_t nout,
1134
1437
  return t;
1135
1438
  }
1136
1439
 
1137
- ndt_t *
1138
- ndt_any_kind(ndt_context_t *ctx)
1440
+ const ndt_t *
1441
+ ndt_any_kind(bool opt, ndt_context_t *ctx)
1139
1442
  {
1140
- return ndt_new(AnyKind, ctx);
1443
+ return ndt_new(AnyKind, opt, ctx);
1141
1444
  }
1142
1445
 
1143
1446
 
@@ -1150,10 +1453,12 @@ ndt_any_kind(ndt_context_t *ctx)
1150
1453
  * is assumed to be either a dtype with ndim==0 or a FixedDim.
1151
1454
  */
1152
1455
  static inline int64_t
1153
- fixed_step(ndt_t *type, int64_t step, bool *overflow)
1456
+ fixed_step(const ndt_t *type, int64_t step, bool *overflow)
1154
1457
  {
1155
1458
  assert(ndt_is_concrete(type));
1156
1459
  assert(type->tag != VarDim);
1460
+ assert(type->tag != VarDimElem);
1461
+ assert(type->tag != Array);
1157
1462
 
1158
1463
  if (step != INT64_MAX) {
1159
1464
  return step;
@@ -1175,7 +1480,7 @@ fixed_step(ndt_t *type, int64_t step, bool *overflow)
1175
1480
  }
1176
1481
 
1177
1482
  static inline int64_t
1178
- fixed_datasize(ndt_t *type, int64_t shape, int64_t step, int64_t itemsize,
1483
+ fixed_datasize(const ndt_t *type, int64_t shape, int64_t step, int64_t itemsize,
1179
1484
  bool *overflow)
1180
1485
  {
1181
1486
  int64_t index_range;
@@ -1191,16 +1496,18 @@ fixed_datasize(ndt_t *type, int64_t shape, int64_t step, int64_t itemsize,
1191
1496
  datasize = MULi64(index_range, itemsize, overflow);
1192
1497
  return ADDi64(datasize, type->datasize, overflow);
1193
1498
  }
1194
-
1195
- static ndt_t *
1499
+
1500
+ static const ndt_t *
1196
1501
  _ndt_to_fortran(const ndt_t *t, int64_t step, ndt_context_t *ctx)
1197
1502
  {
1198
1503
  bool overflow = 0;
1199
- ndt_t *dt;
1504
+ const ndt_t *u;
1505
+ const ndt_t *dt;
1200
1506
  int64_t next_step;
1201
1507
 
1202
1508
  if (t->ndim == 0) {
1203
- return ndt_copy(t, ctx);
1509
+ ndt_incref(t);
1510
+ return t;
1204
1511
  }
1205
1512
 
1206
1513
  next_step = MULi64(step, t->FixedDim.shape, &overflow);
@@ -1216,11 +1523,13 @@ _ndt_to_fortran(const ndt_t *t, int64_t step, ndt_context_t *ctx)
1216
1523
  return NULL;
1217
1524
  }
1218
1525
 
1219
- return ndt_fixed_dim(dt, t->FixedDim.shape, step, ctx);
1526
+ u = ndt_fixed_dim(dt, t->FixedDim.shape, step, ctx);
1527
+ ndt_decref(dt);
1528
+ return u;
1220
1529
  }
1221
1530
 
1222
1531
  /* Return a copy of a C-contiguous array in Fortran order. */
1223
- ndt_t *
1532
+ const ndt_t *
1224
1533
  ndt_to_fortran(const ndt_t *t, ndt_context_t *ctx)
1225
1534
  {
1226
1535
  if (ndt_is_abstract(t)) {
@@ -1238,14 +1547,13 @@ ndt_to_fortran(const ndt_t *t, ndt_context_t *ctx)
1238
1547
  return _ndt_to_fortran(t, 1, ctx);
1239
1548
  }
1240
1549
 
1241
- ndt_t *
1242
- ndt_fixed_dim(ndt_t *type, int64_t shape, int64_t step, ndt_context_t *ctx)
1550
+ const ndt_t *
1551
+ ndt_fixed_dim(const ndt_t *type, int64_t shape, int64_t step, ndt_context_t *ctx)
1243
1552
  {
1244
1553
  ndt_t *t;
1245
1554
  bool overflow = 0;
1246
1555
 
1247
- if (!check_type_invariants(type, ctx)) {
1248
- ndt_del(type);
1556
+ if (!check_fixed_invariants(type, ctx)) {
1249
1557
  return NULL;
1250
1558
  }
1251
1559
 
@@ -1255,16 +1563,18 @@ ndt_fixed_dim(ndt_t *type, int64_t shape, int64_t step, ndt_context_t *ctx)
1255
1563
  }
1256
1564
 
1257
1565
  /* abstract type */
1258
- t = ndt_new(FixedDim, ctx);
1566
+ t = ndt_new(FixedDim, 0, ctx);
1259
1567
  if (t == NULL) {
1260
- ndt_del(type);
1261
1568
  return NULL;
1262
1569
  }
1263
1570
  t->FixedDim.tag = RequireNA;
1264
1571
  t->FixedDim.shape = shape;
1572
+
1573
+ ndt_incref(type);
1265
1574
  t->FixedDim.type = type;
1575
+
1266
1576
  t->ndim = type->ndim + 1;
1267
- t->flags = ndt_dim_flags(type);
1577
+ t->flags |= ndt_dim_flags(type);
1268
1578
 
1269
1579
  t->Concrete.FixedDim.itemsize = 0;
1270
1580
  t->Concrete.FixedDim.step = INT64_MAX;
@@ -1283,18 +1593,18 @@ ndt_fixed_dim(ndt_t *type, int64_t shape, int64_t step, ndt_context_t *ctx)
1283
1593
 
1284
1594
  if (overflow) {
1285
1595
  ndt_err_format(ctx, NDT_ValueError, "data size too large");
1286
- ndt_del(t);
1596
+ ndt_decref(t);
1287
1597
  return NULL;
1288
1598
  }
1289
1599
 
1290
1600
  return t;
1291
1601
  }
1292
1602
 
1293
- ndt_t *
1294
- ndt_fixed_dim_tag(ndt_t *type, enum ndt_contig tag, int64_t shape, int64_t step,
1603
+ const ndt_t *
1604
+ ndt_fixed_dim_tag(const ndt_t *type, enum ndt_contig tag, int64_t shape, int64_t step,
1295
1605
  ndt_context_t *ctx)
1296
1606
  {
1297
- ndt_t *t = ndt_fixed_dim(type, shape, step, ctx);
1607
+ ndt_t *t = (ndt_t *)ndt_fixed_dim(type, shape, step, ctx);
1298
1608
  if (t == NULL) {
1299
1609
  return NULL;
1300
1610
  }
@@ -1307,31 +1617,29 @@ ndt_fixed_dim_tag(ndt_t *type, enum ndt_contig tag, int64_t shape, int64_t step,
1307
1617
  return t;
1308
1618
  }
1309
1619
 
1310
- ndt_t *
1311
- ndt_abstract_var_dim(ndt_t *type, ndt_context_t *ctx)
1620
+ const ndt_t *
1621
+ ndt_abstract_var_dim(const ndt_t *type, bool opt, ndt_context_t *ctx)
1312
1622
  {
1313
1623
  ndt_t *t = NULL;
1314
1624
 
1315
1625
  if (!check_abstract_var_invariants(type, ctx)) {
1316
- ndt_del(type);
1317
1626
  return NULL;
1318
1627
  }
1319
1628
 
1320
1629
  /* abstract type */
1321
- t = ndt_new(VarDim, ctx);
1630
+ t = ndt_new(VarDim, opt, ctx);
1322
1631
  if (t == NULL) {
1323
- ndt_del(type);
1324
1632
  return NULL;
1325
1633
  }
1634
+ ndt_incref(type);
1326
1635
  t->VarDim.type = type;
1636
+
1327
1637
  t->ndim = type->ndim+1;
1328
- t->flags = ndt_dim_flags(type);
1638
+ t->flags |= ndt_dim_flags(type);
1329
1639
 
1330
1640
  /* concrete access */
1331
1641
  t->access = Abstract;
1332
- t->Concrete.VarDim.flag = ExternalOffsets;
1333
1642
  t->Concrete.VarDim.itemsize = 0;
1334
- t->Concrete.VarDim.noffsets = 0;
1335
1643
  t->Concrete.VarDim.offsets = NULL;
1336
1644
  t->Concrete.VarDim.nslices = 0;
1337
1645
  t->Concrete.VarDim.slices = NULL;
@@ -1355,17 +1663,16 @@ ndt_var_indices(int64_t *res_start, int64_t *res_step, const ndt_t *t,
1355
1663
  int32_t i;
1356
1664
 
1357
1665
  assert(ndt_is_concrete(t));
1358
- assert(t->tag == VarDim);
1666
+ assert(t->tag == VarDim || t->tag == VarDimElem);
1359
1667
 
1360
- if (index < 0 || index+1 >= t->Concrete.VarDim.noffsets) {
1361
- ndt_err_format(ctx, NDT_ValueError,
1362
- "var dim index out of range: index=%" PRIi64 ", noffsets=%" PRIi32,
1363
- index, t->Concrete.VarDim.noffsets);
1668
+ if (index < 0 || index+1 >= t->Concrete.VarDim.offsets->n) {
1669
+ ndt_err_format(ctx, NDT_IndexError,
1670
+ "index with value %" PRIi64 " out of bounds", index);
1364
1671
  return -1;
1365
1672
  }
1366
1673
 
1367
- list_start = t->Concrete.VarDim.offsets[index];
1368
- list_stop = t->Concrete.VarDim.offsets[index+1];
1674
+ list_start = t->Concrete.VarDim.offsets->v[index];
1675
+ list_stop = t->Concrete.VarDim.offsets->v[index+1];
1369
1676
  list_shape = list_stop - list_start;
1370
1677
 
1371
1678
  *res_start = 0;
@@ -1387,6 +1694,52 @@ ndt_var_indices(int64_t *res_start, int64_t *res_step, const ndt_t *t,
1387
1694
  return res_shape;
1388
1695
  }
1389
1696
 
1697
+ /* Same as ndt_var_indices(), but skips empty slices in the stack. */
1698
+ int64_t
1699
+ ndt_var_indices_non_empty(int64_t *res_start, int64_t *res_step, const ndt_t *t,
1700
+ int64_t index, ndt_context_t *ctx)
1701
+ {
1702
+ int64_t list_start, list_stop, list_shape;
1703
+ int64_t start, stop, step;
1704
+ int64_t shape, res_shape;
1705
+ const ndt_slice_t *slices;
1706
+ int32_t i;
1707
+
1708
+ assert(ndt_is_concrete(t));
1709
+ assert(t->tag == VarDim || t->tag == VarDimElem);
1710
+
1711
+ if (index < 0 || index+1 >= t->Concrete.VarDim.offsets->n) {
1712
+ ndt_err_format(ctx, NDT_IndexError,
1713
+ "index with value %" PRIi64 " out of bounds", index);
1714
+ return -1;
1715
+ }
1716
+
1717
+ list_start = t->Concrete.VarDim.offsets->v[index];
1718
+ list_stop = t->Concrete.VarDim.offsets->v[index+1];
1719
+ list_shape = list_stop - list_start;
1720
+
1721
+ *res_start = 0;
1722
+ *res_step = 1;
1723
+ res_shape = list_shape;
1724
+ slices = t->Concrete.VarDim.slices;
1725
+
1726
+ for (i = 0; i < t->Concrete.VarDim.nslices; i++) {
1727
+ start = slices[i].start;
1728
+ stop = slices[i].stop;
1729
+ step = slices[i].step;
1730
+ shape = ndt_slice_adjust_indices(res_shape, &start, &stop, step);
1731
+ if (shape > 0) {
1732
+ res_shape = shape;
1733
+ *res_start += (start * *res_step);
1734
+ *res_step *= step;
1735
+ }
1736
+ }
1737
+
1738
+ *res_start += list_start;
1739
+
1740
+ return res_shape;
1741
+ }
1742
+
1390
1743
  ndt_slice_t *
1391
1744
  ndt_var_add_slice(int32_t *nslices, const ndt_t *t,
1392
1745
  int64_t start, int64_t stop, int64_t step,
@@ -1395,8 +1748,12 @@ ndt_var_add_slice(int32_t *nslices, const ndt_t *t,
1395
1748
  int n = t->Concrete.VarDim.nslices;
1396
1749
  ndt_slice_t *slices;
1397
1750
 
1398
- assert(ndt_is_concrete(t));
1399
- assert(t->tag == VarDim);
1751
+ if (t->tag != VarDim || ndt_is_abstract(t)) {
1752
+ ndt_err_format(ctx, NDT_RuntimeError,
1753
+ "ndt_var_add_slice: internal_error: argument must be a "
1754
+ "concrete var dim");
1755
+ return NULL;
1756
+ }
1400
1757
 
1401
1758
  if (n == INT_MAX) {
1402
1759
  ndt_err_format(ctx, NDT_RuntimeError, "slice stack overflow");
@@ -1418,12 +1775,11 @@ ndt_var_add_slice(int32_t *nslices, const ndt_t *t,
1418
1775
  return slices;
1419
1776
  }
1420
1777
 
1421
- ndt_t *
1422
- ndt_var_dim(ndt_t *type,
1423
- enum ndt_offsets flag,
1424
- int32_t noffsets, const int32_t *offsets,
1778
+ const ndt_t *
1779
+ ndt_var_dim(const ndt_t *type,
1780
+ const ndt_offsets_t *offsets,
1425
1781
  int32_t nslices, ndt_slice_t *slices,
1426
- ndt_context_t *ctx)
1782
+ bool opt, ndt_context_t *ctx)
1427
1783
  {
1428
1784
  bool overflow = 0;
1429
1785
  ndt_t *t;
@@ -1432,37 +1788,33 @@ ndt_var_dim(ndt_t *type,
1432
1788
  assert(offsets != NULL);
1433
1789
  assert(!!nslices == !!slices);
1434
1790
 
1435
- if (!check_var_invariants(flag, type, ctx)) {
1436
- ndt_del(type);
1791
+ if (!check_var_invariants(type, ctx)) {
1437
1792
  goto error;
1438
1793
  }
1439
1794
 
1440
- if (noffsets < 2) {
1795
+ if (offsets->n < 2) {
1441
1796
  ndt_err_format(ctx, NDT_InvalidArgumentError, "var_dim: noffsets < 2");
1442
- ndt_del(type);
1443
1797
  goto error;
1444
1798
  }
1445
1799
 
1446
1800
  if (!ndt_is_concrete(type)) {
1447
1801
  ndt_err_format(ctx, NDT_InvalidArgumentError,
1448
1802
  "var_dim: expected concrete type");
1449
- ndt_del(type);
1450
1803
  goto error;
1451
1804
  }
1452
1805
 
1453
1806
  switch (type->tag) {
1454
- case VarDim:
1455
- if (offsets[noffsets-1] != type->Concrete.VarDim.noffsets-1) {
1807
+ case VarDim: case VarDimElem:
1808
+ if (offsets->v[offsets->n-1] != type->Concrete.VarDim.offsets->n-1) {
1456
1809
  ndt_err_format(ctx, NDT_ValueError,
1457
1810
  "var_dim: missing or invalid number of offset arguments");
1458
- ndt_del(type);
1459
1811
  goto error;
1460
1812
  }
1461
1813
  datasize = type->datasize;
1462
1814
  itemsize = type->Concrete.VarDim.itemsize;
1463
1815
  break;
1464
1816
  default:
1465
- datasize = MULi64(offsets[noffsets-1], type->datasize, &overflow);
1817
+ datasize = MULi64(offsets->v[offsets->n-1], type->datasize, &overflow);
1466
1818
  itemsize = type->datasize;
1467
1819
  break;
1468
1820
  }
@@ -1470,27 +1822,26 @@ ndt_var_dim(ndt_t *type,
1470
1822
  if (overflow) {
1471
1823
  ndt_err_format(ctx, NDT_ValueError,
1472
1824
  "overflow in creating var dimension");
1473
- ndt_del(type);
1474
1825
  goto error;
1475
1826
  }
1476
1827
 
1477
1828
  /* abstract type */
1478
- t = ndt_new(VarDim, ctx);
1829
+ t = ndt_new(VarDim, opt, ctx);
1479
1830
  if (t == NULL) {
1480
- ndt_del(type);
1481
1831
  goto error;
1482
1832
  }
1833
+ ndt_incref(type);
1834
+ ndt_incref_offsets(offsets);
1835
+
1483
1836
  t->VarDim.type = type;
1484
1837
  t->ndim = type->ndim+1;
1485
- t->flags = ndt_dim_flags(type);
1838
+ t->flags |= ndt_dim_flags(type);
1486
1839
 
1487
1840
  /* concrete access */
1488
1841
  t->access = Concrete;
1489
1842
  t->datasize = datasize;
1490
1843
  t->align = type->align;
1491
- t->Concrete.VarDim.flag = flag;
1492
1844
  t->Concrete.VarDim.itemsize = itemsize;
1493
- t->Concrete.VarDim.noffsets = noffsets;
1494
1845
  t->Concrete.VarDim.offsets = offsets;
1495
1846
  t->Concrete.VarDim.nslices = nslices;
1496
1847
  t->Concrete.VarDim.slices = slices;
@@ -1499,44 +1850,42 @@ ndt_var_dim(ndt_t *type,
1499
1850
 
1500
1851
 
1501
1852
  error:
1502
- if (flag == InternalOffsets) {
1503
- ndt_free((int32_t *)offsets);
1504
- }
1505
1853
  ndt_free(slices);
1506
1854
  return NULL;
1507
1855
  }
1508
1856
 
1509
- ndt_t *
1510
- ndt_symbolic_dim(char *name, ndt_t *type, ndt_context_t *ctx)
1857
+ const ndt_t *
1858
+ ndt_symbolic_dim(char *name, const ndt_t *type, ndt_context_t *ctx)
1511
1859
  {
1512
1860
  ndt_t *t;
1513
1861
 
1514
- if (!check_type_invariants(type, ctx)) {
1862
+ if (!check_fixed_invariants(type, ctx)) {
1515
1863
  ndt_free(name);
1516
- ndt_del(type);
1517
1864
  return NULL;
1518
1865
  }
1519
1866
 
1520
1867
  /* abstract type */
1521
- t = ndt_new(SymbolicDim, ctx);
1868
+ t = ndt_new(SymbolicDim, 0, ctx);
1522
1869
  if (t == NULL) {
1523
1870
  ndt_free(name);
1524
- ndt_del(type);
1525
1871
  return NULL;
1526
1872
  }
1527
1873
  t->SymbolicDim.tag = RequireNA;
1528
1874
  t->SymbolicDim.name = name;
1875
+
1876
+ ndt_incref(type);
1529
1877
  t->SymbolicDim.type = type;
1878
+
1530
1879
  t->ndim = type->ndim + 1;
1531
- t->flags = ndt_dim_flags(type);
1880
+ t->flags |= ndt_dim_flags(type);
1532
1881
 
1533
1882
  return t;
1534
1883
  }
1535
1884
 
1536
- ndt_t *
1537
- ndt_symbolic_dim_tag(char *name, ndt_t *type, enum ndt_contig tag, ndt_context_t *ctx)
1885
+ const ndt_t *
1886
+ ndt_symbolic_dim_tag(char *name, const ndt_t *type, enum ndt_contig tag, ndt_context_t *ctx)
1538
1887
  {
1539
- ndt_t *t = ndt_symbolic_dim(name, type, ctx);
1888
+ ndt_t *t = (ndt_t *)ndt_symbolic_dim(name, type, ctx);
1540
1889
  if (t == NULL) {
1541
1890
  return NULL;
1542
1891
  }
@@ -1545,15 +1894,14 @@ ndt_symbolic_dim_tag(char *name, ndt_t *type, enum ndt_contig tag, ndt_context_t
1545
1894
  return t;
1546
1895
  }
1547
1896
 
1548
- ndt_t *
1549
- ndt_ellipsis_dim(char *name, ndt_t *type, ndt_context_t *ctx)
1897
+ const ndt_t *
1898
+ ndt_ellipsis_dim(char *name, const ndt_t *type, ndt_context_t *ctx)
1550
1899
  {
1551
1900
  ndt_t *t;
1552
1901
  uint32_t flags;
1553
1902
 
1554
1903
  if (!check_ellipsis_invariants(type, ctx)) {
1555
1904
  ndt_free(name);
1556
- ndt_del(type);
1557
1905
  return NULL;
1558
1906
  }
1559
1907
 
@@ -1561,30 +1909,31 @@ ndt_ellipsis_dim(char *name, ndt_t *type, ndt_context_t *ctx)
1561
1909
  if (flags & NDT_ELLIPSIS) {
1562
1910
  ndt_err_format(ctx, NDT_ValueError, "more than one ellipsis");
1563
1911
  ndt_free(name);
1564
- ndt_del(type);
1565
1912
  return NULL;
1566
1913
  }
1567
1914
 
1568
1915
  /* abstract type */
1569
- t = ndt_new(EllipsisDim, ctx);
1916
+ t = ndt_new(EllipsisDim, 0, ctx);
1570
1917
  if (t == NULL) {
1571
1918
  ndt_free(name);
1572
- ndt_del(type);
1573
1919
  return NULL;
1574
1920
  }
1575
1921
  t->EllipsisDim.tag = RequireNA;
1576
1922
  t->EllipsisDim.name = name;
1923
+
1924
+ ndt_incref(type);
1577
1925
  t->EllipsisDim.type = type;
1578
- t->flags = flags | NDT_ELLIPSIS;
1926
+
1927
+ t->flags |= (flags|NDT_ELLIPSIS);
1579
1928
  t->ndim = type->ndim + 1;
1580
1929
 
1581
1930
  return t;
1582
1931
  }
1583
1932
 
1584
- ndt_t *
1585
- ndt_ellipsis_dim_tag(char *name, ndt_t *type, enum ndt_contig tag, ndt_context_t *ctx)
1933
+ const ndt_t *
1934
+ ndt_ellipsis_dim_tag(char *name, const ndt_t *type, enum ndt_contig tag, ndt_context_t *ctx)
1586
1935
  {
1587
- ndt_t *t = ndt_ellipsis_dim(name, type, ctx);
1936
+ ndt_t *t = (ndt_t *)ndt_ellipsis_dim(name, type, ctx);
1588
1937
  if (t == NULL) {
1589
1938
  return NULL;
1590
1939
  }
@@ -1686,9 +2035,44 @@ init_concrete_fields(ndt_t *t, int64_t *offsets, uint16_t *align, uint16_t *pad,
1686
2035
  return 0;
1687
2036
  }
1688
2037
 
1689
- ndt_t *
1690
- ndt_tuple(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1691
- uint16_opt_t align, uint16_opt_t pack, ndt_context_t *ctx)
2038
+ /*
2039
+ * Initialize the access information of a concrete union.
2040
+ * Assumptions:
2041
+ * 1) t->tag == Union
2042
+ * 2) t->access == Concrete
2043
+ * 3) 0 <= i < ntags ==> fields[i].access == Concrete
2044
+ * 4) len(fields) == ntags
2045
+ */
2046
+ static int
2047
+ init_concrete_tags(ndt_t *t, const ndt_field_t *fields, int64_t ntags,
2048
+ ndt_context_t *ctx)
2049
+ {
2050
+ int64_t maxsize = 0;
2051
+ int64_t i;
2052
+
2053
+ for (i = 0; i < ntags; i++) {
2054
+ assert(fields[i].access == Concrete);
2055
+ assert(fields[i].type->access == Concrete);
2056
+
2057
+ if (fields[i].type->flags & NDT_REF) {
2058
+ ndt_err_format(ctx, NDT_ValueError,
2059
+ "union types cannot contain references");
2060
+ return -1;
2061
+ }
2062
+
2063
+ maxsize = max_i64(fields[i].type->datasize, maxsize);
2064
+ }
2065
+
2066
+ assert(t->access == Concrete);
2067
+ t->align = 1;
2068
+ t->datasize = 1+maxsize;
2069
+
2070
+ return 0;
2071
+ }
2072
+
2073
+ const ndt_t *
2074
+ ndt_tuple(enum ndt_variadic flag, const ndt_field_t *fields, int64_t shape,
2075
+ uint16_opt_t align, uint16_opt_t pack, bool opt, ndt_context_t *ctx)
1692
2076
  {
1693
2077
  ndt_t *t;
1694
2078
  int64_t i;
@@ -1697,15 +2081,13 @@ ndt_tuple(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1697
2081
 
1698
2082
  for (i = 0; i < shape; i++) {
1699
2083
  if (!check_type_invariants(fields[i].type, ctx)) {
1700
- ndt_field_array_del(fields, shape);
1701
2084
  return NULL;
1702
2085
  }
1703
2086
  }
1704
2087
 
1705
2088
  /* abstract type */
1706
- t = ndt_tuple_new(flag, shape, ctx);
2089
+ t = ndt_tuple_new(flag, shape, opt, ctx);
1707
2090
  if (t == NULL) {
1708
- ndt_field_array_del(fields, shape);
1709
2091
  return NULL;
1710
2092
  }
1711
2093
 
@@ -1724,17 +2106,16 @@ ndt_tuple(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1724
2106
  fields[i].Concrete.explicit_align) {
1725
2107
  ndt_err_format(ctx, NDT_InvalidArgumentError,
1726
2108
  "explicit field alignment in abstract tuple");
1727
- ndt_field_array_del(fields, shape);
1728
2109
  ndt_free(t);
1729
2110
  return NULL;
1730
2111
  }
1731
2112
  }
1732
2113
  for (i = 0; i < shape; i++) {
1733
2114
  assert(fields[i].name == NULL);
2115
+ ndt_incref(fields[i].type);
1734
2116
  t->Tuple.types[i] = fields[i].type;
1735
2117
  t->flags |= ndt_subtree_flags(fields[i].type);
1736
2118
  }
1737
- ndt_free(fields);
1738
2119
  return t;
1739
2120
  }
1740
2121
  else {
@@ -1743,23 +2124,22 @@ ndt_tuple(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1743
2124
  t->Concrete.Tuple.align,
1744
2125
  t->Concrete.Tuple.pad,
1745
2126
  fields, shape, align, pack, ctx) < 0) {
1746
- ndt_field_array_del(fields, shape);
1747
2127
  ndt_free(t);
1748
2128
  return NULL;
1749
2129
  }
1750
2130
  for (i = 0; i < shape; i++) {
1751
2131
  assert(fields[i].name == NULL);
2132
+ ndt_incref(fields[i].type);
1752
2133
  t->Tuple.types[i] = fields[i].type;
1753
2134
  t->flags |= ndt_subtree_flags(fields[i].type);
1754
2135
  }
1755
- ndt_free(fields);
1756
2136
  return t;
1757
2137
  }
1758
2138
  }
1759
2139
 
1760
- ndt_t *
1761
- ndt_record(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1762
- uint16_opt_t align, uint16_opt_t pack, ndt_context_t *ctx)
2140
+ const ndt_t *
2141
+ ndt_record(enum ndt_variadic flag, const ndt_field_t *fields, int64_t shape,
2142
+ uint16_opt_t align, uint16_opt_t pack, bool opt, ndt_context_t *ctx)
1763
2143
  {
1764
2144
  ndt_t *t;
1765
2145
  int64_t i;
@@ -1768,15 +2148,13 @@ ndt_record(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1768
2148
 
1769
2149
  for (i = 0; i < shape; i++) {
1770
2150
  if (!check_type_invariants(fields[i].type, ctx)) {
1771
- ndt_field_array_del(fields, shape);
1772
2151
  return NULL;
1773
2152
  }
1774
2153
  }
1775
2154
 
1776
2155
  /* abstract type */
1777
- t = ndt_record_new(flag, shape, ctx);
2156
+ t = ndt_record_new(flag, shape, opt, ctx);
1778
2157
  if (t == NULL) {
1779
- ndt_field_array_del(fields, shape);
1780
2158
  return NULL;
1781
2159
  }
1782
2160
 
@@ -1795,18 +2173,23 @@ ndt_record(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1795
2173
  fields[i].Concrete.explicit_align) {
1796
2174
  ndt_err_format(ctx, NDT_InvalidArgumentError,
1797
2175
  "explicit field alignment in abstract tuple");
1798
- /* at this point names and types still belong to the fields */
1799
- ndt_field_array_del(fields, shape);
1800
2176
  ndt_free(t);
1801
2177
  return NULL;
1802
2178
  }
1803
2179
  }
1804
2180
  for (i = 0; i < shape; i++) {
1805
- t->Record.names[i] = fields[i].name;
2181
+ char *s = ndt_strdup(fields[i].name, ctx);
2182
+ if (s == NULL) {
2183
+ ndt_decref(t);
2184
+ return NULL;
2185
+ }
2186
+ t->Record.names[i] = s;
2187
+
2188
+ ndt_incref(fields[i].type);
1806
2189
  t->Record.types[i] = fields[i].type;
2190
+
1807
2191
  t->flags |= ndt_subtree_flags(fields[i].type);
1808
2192
  }
1809
- ndt_free(fields);
1810
2193
  return t;
1811
2194
  }
1812
2195
  else {
@@ -1815,39 +2198,159 @@ ndt_record(enum ndt_variadic flag, ndt_field_t *fields, int64_t shape,
1815
2198
  t->Concrete.Record.align,
1816
2199
  t->Concrete.Record.pad,
1817
2200
  fields, shape, align, pack, ctx) < 0) {
1818
- /* at this point names and types still belong to the fields */
1819
- ndt_field_array_del(fields, shape);
1820
2201
  ndt_free(t);
1821
2202
  return NULL;
1822
2203
  }
1823
2204
  for (i = 0; i < shape; i++) {
1824
- t->Record.names[i] = fields[i].name;
2205
+ char *s = ndt_strdup(fields[i].name, ctx);
2206
+ if (s == NULL) {
2207
+ ndt_decref(t);
2208
+ return NULL;
2209
+ }
2210
+ t->Record.names[i] = s;
2211
+
2212
+ ndt_incref(fields[i].type);
1825
2213
  t->Record.types[i] = fields[i].type;
2214
+
1826
2215
  t->flags |= ndt_subtree_flags(fields[i].type);
1827
2216
  }
1828
- ndt_free(fields);
1829
2217
  return t;
1830
2218
  }
1831
2219
  }
1832
2220
 
1833
- ndt_t *
1834
- ndt_ref(ndt_t *type, ndt_context_t *ctx)
2221
+ const ndt_t *
2222
+ ndt_union(const ndt_field_t *fields, int64_t ntags, bool opt,
2223
+ ndt_context_t *ctx)
2224
+ {
2225
+ ndt_t *t;
2226
+ int64_t i;
2227
+
2228
+ if (ntags == 0 || fields == NULL) {
2229
+ ndt_err_format(ctx, NDT_ValueError, "unions cannot be empty");
2230
+ return NULL;
2231
+ }
2232
+
2233
+ if (ntags > 255) {
2234
+ ndt_err_format(ctx, NDT_ValueError, "union too large (max 255 members)");
2235
+ return NULL;
2236
+ }
2237
+
2238
+ for (i = 0; i < ntags; i++) {
2239
+ if (!check_type_invariants(fields[i].type, ctx)) {
2240
+ return NULL;
2241
+ }
2242
+ }
2243
+
2244
+ /* abstract type */
2245
+ t = ndt_union_new(ntags, opt, ctx);
2246
+ if (t == NULL) {
2247
+ return NULL;
2248
+ }
2249
+
2250
+ /* check concrete access */
2251
+ t->access = Concrete;
2252
+ for (i = 0; i < ntags; i++) {
2253
+ if (fields[i].access == Abstract) {
2254
+ t->access = Abstract;
2255
+ }
2256
+ }
2257
+
2258
+ if (t->access == Abstract) {
2259
+ /* check if any field has explicit 'align' or 'pack' attributes */
2260
+ for (i = 0; i < ntags; i++) {
2261
+ if (fields[i].access == Concrete &&
2262
+ fields[i].Concrete.explicit_align) {
2263
+ ndt_err_format(ctx, NDT_InvalidArgumentError,
2264
+ "explicit field alignment in abstract tuple");
2265
+ ndt_free(t);
2266
+ return NULL;
2267
+ }
2268
+ }
2269
+ for (i = 0; i < ntags; i++) {
2270
+ char *s = ndt_strdup(fields[i].name, ctx);
2271
+ if (s == NULL) {
2272
+ ndt_decref(t);
2273
+ return NULL;
2274
+ }
2275
+ t->Union.tags[i] = s;
2276
+
2277
+ ndt_incref(fields[i].type);
2278
+ t->Union.types[i] = fields[i].type;
2279
+
2280
+ t->flags |= ndt_subtree_flags(fields[i].type);
2281
+ }
2282
+ return t;
2283
+ }
2284
+ else {
2285
+ if (init_concrete_tags(t, fields, ntags, ctx) < 0) {
2286
+ ndt_free(t);
2287
+ return NULL;
2288
+ }
2289
+
2290
+ for (i = 0; i < ntags; i++) {
2291
+ char *s = ndt_strdup(fields[i].name, ctx);
2292
+ if (s == NULL) {
2293
+ ndt_decref(t);
2294
+ return NULL;
2295
+ }
2296
+ t->Union.tags[i] = s;
2297
+
2298
+ ndt_incref(fields[i].type);
2299
+ t->Union.types[i] = fields[i].type;
2300
+
2301
+ t->flags |= ndt_subtree_flags(fields[i].type);
2302
+ }
2303
+ return t;
2304
+ }
2305
+ }
2306
+
2307
+ const ndt_t *
2308
+ ndt_array(const ndt_t *type, bool opt, ndt_context_t *ctx)
2309
+ {
2310
+ ndt_t *t;
2311
+
2312
+ if (!check_array_invariants(type, ctx)) {
2313
+ return NULL;
2314
+ }
2315
+
2316
+ /* abstract type */
2317
+ t = ndt_new(Array, opt|NDT_POINTER, ctx);
2318
+ if (t == NULL) {
2319
+ return NULL;
2320
+ }
2321
+ ndt_incref(type);
2322
+ t->Array.itemsize = type->datasize;
2323
+ t->Array.type = type;
2324
+
2325
+ t->flags |= ndt_subtree_flags(type);
2326
+ t->ndim = type->ndim + 1;
2327
+
2328
+ /* concrete access */
2329
+ t->access = type->access;
2330
+ t->datasize = sizeof(ndt_array_t);
2331
+ t->align = alignof(ndt_array_t);
2332
+
2333
+ return t;
2334
+ }
2335
+
2336
+ const ndt_t *
2337
+ ndt_ref(const ndt_t *type, bool opt, ndt_context_t *ctx)
1835
2338
  {
1836
2339
  ndt_t *t;
1837
2340
 
1838
2341
  if (!check_type_invariants(type, ctx)) {
1839
- ndt_del(type);
1840
2342
  return NULL;
1841
2343
  }
1842
2344
 
1843
2345
  /* abstract type */
1844
- t = ndt_new(Ref, ctx);
2346
+ t = ndt_new(Ref, opt|NDT_POINTER|NDT_REF, ctx);
1845
2347
  if (t == NULL) {
1846
- ndt_del(type);
1847
2348
  return NULL;
1848
2349
  }
2350
+ ndt_incref(type);
1849
2351
  t->Ref.type = type;
1850
- t->flags = ndt_subtree_flags(type);
2352
+
2353
+ t->flags |= ndt_subtree_flags(type);
1851
2354
 
1852
2355
  /* concrete access */
1853
2356
  t->access = type->access;
@@ -1857,28 +2360,29 @@ ndt_ref(ndt_t *type, ndt_context_t *ctx)
1857
2360
  return t;
1858
2361
  }
1859
2362
 
1860
- ndt_t *
1861
- ndt_constr(char *name, ndt_t *type, ndt_context_t *ctx)
2363
+ const ndt_t *
2364
+ ndt_constr(char *name, const ndt_t *type, bool opt, ndt_context_t *ctx)
1862
2365
  {
1863
2366
  ndt_t *t;
1864
2367
 
1865
2368
  if (!check_type_invariants(type, ctx)) {
1866
2369
  ndt_free(name);
1867
- ndt_del(type);
1868
2370
  return NULL;
1869
2371
  }
1870
2372
 
1871
- t = ndt_new(Constr, ctx);
2373
+ t = ndt_new(Constr, opt, ctx);
1872
2374
  if (t == NULL) {
1873
2375
  ndt_free(name);
1874
- ndt_del(type);
1875
2376
  return NULL;
1876
2377
  }
1877
2378
 
1878
2379
  /* abstract type */
1879
2380
  t->Constr.name = name;
2381
+
2382
+ ndt_incref(type);
1880
2383
  t->Constr.type = type;
1881
- t->flags = ndt_subtree_flags(type);
2384
+
2385
+ t->flags |= ndt_subtree_flags(type);
1882
2386
 
1883
2387
  /* concrete access */
1884
2388
  t->access = type->access;
@@ -1890,8 +2394,8 @@ ndt_constr(char *name, ndt_t *type, ndt_context_t *ctx)
1890
2394
  return t;
1891
2395
  }
1892
2396
 
1893
- ndt_t *
1894
- ndt_nominal(char *name, ndt_t *type, ndt_context_t *ctx)
2397
+ const ndt_t *
2398
+ ndt_nominal(char *name, const ndt_t *type, bool opt, ndt_context_t *ctx)
1895
2399
  {
1896
2400
  const ndt_typedef_t *d;
1897
2401
  ndt_t *t;
@@ -1899,7 +2403,6 @@ ndt_nominal(char *name, ndt_t *type, ndt_context_t *ctx)
1899
2403
  d = ndt_typedef_find(name, ctx);
1900
2404
  if (d == NULL) {
1901
2405
  ndt_free(name);
1902
- ndt_del(type);
1903
2406
  return NULL;
1904
2407
  }
1905
2408
 
@@ -1911,29 +2414,25 @@ ndt_nominal(char *name, ndt_t *type, ndt_context_t *ctx)
1911
2414
  "type is not an instance of %s", name);
1912
2415
  }
1913
2416
  ndt_free(name);
1914
- ndt_del(type);
1915
2417
  return NULL;
1916
2418
  }
1917
2419
  }
1918
2420
  else {
1919
- type = ndt_copy(d->type, ctx);
1920
- if (type == NULL) {
1921
- ndt_free(name);
1922
- return NULL;
1923
- }
2421
+ type = d->type;
1924
2422
  }
2423
+ ndt_incref(type);
1925
2424
 
1926
2425
  /* abstract type */
1927
- t = ndt_new(Nominal, ctx);
2426
+ t = ndt_new(Nominal, opt, ctx);
1928
2427
  if (t == NULL) {
1929
2428
  ndt_free(name);
1930
- ndt_del(type);
2429
+ ndt_decref(type);
1931
2430
  return NULL;
1932
2431
  }
1933
2432
  t->Nominal.name = name;
1934
2433
  t->Nominal.type = type;
1935
2434
  t->Nominal.meth = &d->meth;
1936
- t->flags = ndt_subtree_flags(type);
2435
+ t->flags |= ndt_subtree_flags(type);
1937
2436
 
1938
2437
  /* concrete access */
1939
2438
  t->access = type->access;
@@ -1948,10 +2447,10 @@ ndt_nominal(char *name, ndt_t *type, ndt_context_t *ctx)
1948
2447
  /* Scalar types */
1949
2448
  /******************************************************************************/
1950
2449
 
1951
- ndt_t *
1952
- ndt_scalar_kind(ndt_context_t *ctx)
2450
+ const ndt_t *
2451
+ ndt_scalar_kind(bool opt, ndt_context_t *ctx)
1953
2452
  {
1954
- return ndt_new(ScalarKind, ctx);
2453
+ return ndt_new(ScalarKind, opt, ctx);
1955
2454
  }
1956
2455
 
1957
2456
  /* Define a sort order for the typed values in the categorical set. */
@@ -1964,8 +2463,8 @@ cmp(const void *x, const void *y)
1964
2463
  return ndt_value_compare(p, q);
1965
2464
  }
1966
2465
 
1967
- ndt_t *
1968
- ndt_categorical(ndt_value_t *types, int64_t ntypes, ndt_context_t *ctx)
2466
+ const ndt_t *
2467
+ ndt_categorical(const ndt_value_t *types, int64_t ntypes, bool opt, ndt_context_t *ctx)
1969
2468
  {
1970
2469
  ndt_value_t *tmp;
1971
2470
  ndt_t *t;
@@ -1993,7 +2492,7 @@ ndt_categorical(ndt_value_t *types, int64_t ntypes, ndt_context_t *ctx)
1993
2492
  ndt_free(tmp);
1994
2493
 
1995
2494
  /* abstract type */
1996
- t = ndt_new(Categorical, ctx);
2495
+ t = ndt_new(Categorical, opt, ctx);
1997
2496
  if (t == NULL) {
1998
2497
  ndt_value_array_del(types, ntypes);
1999
2498
  return NULL;
@@ -2009,20 +2508,20 @@ ndt_categorical(ndt_value_t *types, int64_t ntypes, ndt_context_t *ctx)
2009
2508
  return t;
2010
2509
  }
2011
2510
 
2012
- ndt_t *
2013
- ndt_fixed_string_kind(ndt_context_t *ctx)
2511
+ const ndt_t *
2512
+ ndt_fixed_string_kind(bool opt, ndt_context_t *ctx)
2014
2513
  {
2015
- return ndt_new(FixedStringKind, ctx);
2514
+ return ndt_new(FixedStringKind, opt, ctx);
2016
2515
  }
2017
2516
 
2018
- ndt_t *
2019
- ndt_fixed_string(int64_t size, enum ndt_encoding encoding, ndt_context_t *ctx)
2517
+ const ndt_t *
2518
+ ndt_fixed_string(int64_t size, enum ndt_encoding encoding, bool opt, ndt_context_t *ctx)
2020
2519
  {
2021
2520
  bool overflow = 0;
2022
2521
  ndt_t *t;
2023
2522
 
2024
2523
  /* abstract type */
2025
- t = ndt_new(FixedString, ctx);
2524
+ t = ndt_new(FixedString, opt, ctx);
2026
2525
  if (t == NULL) {
2027
2526
  return NULL;
2028
2527
  }
@@ -2037,21 +2536,21 @@ ndt_fixed_string(int64_t size, enum ndt_encoding encoding, ndt_context_t *ctx)
2037
2536
  if (overflow) {
2038
2537
  ndt_err_format(ctx, NDT_ValueError,
2039
2538
  "overflow while creating fixed string");
2040
- ndt_del(t);
2539
+ ndt_decref(t);
2041
2540
  return NULL;
2042
2541
  }
2043
2542
 
2044
2543
  return t;
2045
2544
  }
2046
2545
 
2047
- ndt_t *
2048
- ndt_fixed_bytes_kind(ndt_context_t *ctx)
2546
+ const ndt_t *
2547
+ ndt_fixed_bytes_kind(bool opt, ndt_context_t *ctx)
2049
2548
  {
2050
- return ndt_new(FixedBytesKind, ctx);
2549
+ return ndt_new(FixedBytesKind, opt, ctx);
2051
2550
  }
2052
2551
 
2053
- ndt_t *
2054
- ndt_fixed_bytes(int64_t size, uint16_opt_t align_attr, ndt_context_t *ctx)
2552
+ const ndt_t *
2553
+ ndt_fixed_bytes(int64_t size, uint16_opt_t align_attr, bool opt, ndt_context_t *ctx)
2055
2554
  {
2056
2555
  ndt_t *t;
2057
2556
  uint16_t align;
@@ -2068,7 +2567,7 @@ ndt_fixed_bytes(int64_t size, uint16_opt_t align_attr, ndt_context_t *ctx)
2068
2567
  }
2069
2568
 
2070
2569
  /* abstract type */
2071
- t = ndt_new(FixedBytes, ctx);
2570
+ t = ndt_new(FixedBytes, opt, ctx);
2072
2571
  if (t == NULL) {
2073
2572
  return NULL;
2074
2573
  }
@@ -2083,27 +2582,8 @@ ndt_fixed_bytes(int64_t size, uint16_opt_t align_attr, ndt_context_t *ctx)
2083
2582
  return t;
2084
2583
  }
2085
2584
 
2086
- ndt_t *
2087
- ndt_string(ndt_context_t *ctx)
2088
- {
2089
- ndt_t *t;
2090
-
2091
- /* abstract type */
2092
- t = ndt_new(String, ctx);
2093
- if (t == NULL) {
2094
- return NULL;
2095
- }
2096
-
2097
- /* concrete access */
2098
- t->access = Concrete;
2099
- t->datasize = sizeof(char *);
2100
- t->align = alignof(char *);
2101
-
2102
- return t;
2103
- }
2104
-
2105
- ndt_t *
2106
- ndt_bytes(uint16_opt_t target_align, ndt_context_t *ctx)
2585
+ const ndt_t *
2586
+ ndt_bytes(uint16_opt_t target_align, bool opt, ndt_context_t *ctx)
2107
2587
  {
2108
2588
  ndt_t *t;
2109
2589
  uint16_t align;
@@ -2114,7 +2594,7 @@ ndt_bytes(uint16_opt_t target_align, ndt_context_t *ctx)
2114
2594
  }
2115
2595
 
2116
2596
  /* abstract type */
2117
- t = ndt_new(Bytes, ctx);
2597
+ t = ndt_new(Bytes, opt|NDT_POINTER, ctx);
2118
2598
  if (t == NULL) {
2119
2599
  return NULL;
2120
2600
  }
@@ -2128,13 +2608,13 @@ ndt_bytes(uint16_opt_t target_align, ndt_context_t *ctx)
2128
2608
  return t;
2129
2609
  }
2130
2610
 
2131
- ndt_t *
2132
- ndt_char(enum ndt_encoding encoding, ndt_context_t *ctx)
2611
+ const ndt_t *
2612
+ ndt_char(enum ndt_encoding encoding, bool opt, ndt_context_t *ctx)
2133
2613
  {
2134
2614
  ndt_t *t;
2135
2615
 
2136
2616
  /* abstract type */
2137
- t = ndt_new(Char, ctx);
2617
+ t = ndt_new(Char, opt|NDT_CHAR, ctx);
2138
2618
  if (t == NULL) {
2139
2619
  return NULL;
2140
2620
  }
@@ -2148,122 +2628,7 @@ ndt_char(enum ndt_encoding encoding, ndt_context_t *ctx)
2148
2628
  return t;
2149
2629
  }
2150
2630
 
2151
- ndt_t *
2152
- ndt_signed_kind(ndt_context_t *ctx)
2153
- {
2154
- return ndt_new(SignedKind, ctx);
2155
- }
2156
-
2157
- ndt_t *
2158
- ndt_unsigned_kind(ndt_context_t *ctx)
2159
- {
2160
- return ndt_new(UnsignedKind, ctx);
2161
- }
2162
-
2163
- ndt_t *
2164
- ndt_float_kind(ndt_context_t *ctx)
2165
- {
2166
- return ndt_new(FloatKind, ctx);
2167
- }
2168
-
2169
- ndt_t *
2170
- ndt_complex_kind(ndt_context_t *ctx)
2171
- {
2172
- return ndt_new(ComplexKind, ctx);
2173
- }
2174
-
2175
- ndt_t *
2176
- ndt_primitive(enum ndt tag, uint32_t flags, ndt_context_t *ctx)
2177
- {
2178
- ndt_t *t;
2179
-
2180
- if (flags != 0 && flags != NDT_LITTLE_ENDIAN && flags != NDT_BIG_ENDIAN) {
2181
- ndt_err_format(ctx, NDT_ValueError,
2182
- "flags argument must be 0 or NDT_LITTLE_ENDIAN or NDT_BIG_ENDIAN");
2183
- return NULL;
2184
- }
2185
-
2186
- /* abstract type */
2187
- t = ndt_new(tag, ctx);
2188
- if (t == NULL) {
2189
- return NULL;
2190
- }
2191
- t->flags |= flags;
2192
-
2193
- /* concrete access */
2194
- t->access = Concrete;
2195
-
2196
- switch(tag) {
2197
- case Bool:
2198
- t->datasize = sizeof(bool);
2199
- t->align = alignof(bool);
2200
- break;
2201
- case Int8:
2202
- t->datasize = sizeof(int8_t);
2203
- t->align = alignof(int8_t);
2204
- break;
2205
- case Int16:
2206
- t->datasize = sizeof(int16_t);
2207
- t->align = alignof(int16_t);
2208
- break;
2209
- case Int32:
2210
- t->datasize = sizeof(int32_t);
2211
- t->align = alignof(int32_t);
2212
- break;
2213
- case Int64:
2214
- t->datasize = sizeof(int64_t);
2215
- t->align = alignof(int64_t);
2216
- break;
2217
- case Uint8:
2218
- t->datasize = sizeof(uint8_t);
2219
- t->align = alignof(uint8_t);
2220
- break;
2221
- case Uint16:
2222
- t->datasize = sizeof(uint16_t);
2223
- t->align = alignof(uint16_t);
2224
- break;
2225
- case Uint32:
2226
- t->datasize = sizeof(uint32_t);
2227
- t->align = alignof(uint32_t);
2228
- break;
2229
- case Uint64:
2230
- t->datasize = sizeof(uint64_t);
2231
- t->align = alignof(uint64_t);
2232
- break;
2233
- case Float16:
2234
- t->datasize = 2;
2235
- t->align = 2;
2236
- break;
2237
- case Float32:
2238
- t->datasize = sizeof(float);
2239
- t->align = alignof(float);
2240
- break;
2241
- case Float64:
2242
- t->datasize = sizeof(double);
2243
- t->align = alignof(double);
2244
- break;
2245
- case Complex32:
2246
- t->datasize = 4;
2247
- t->align = 2;
2248
- break;
2249
- case Complex64:
2250
- t->datasize = sizeof(ndt_complex64_t);
2251
- t->align = alignof(ndt_complex64_t);
2252
- break;
2253
- case Complex128:
2254
- t->datasize = sizeof(ndt_complex128_t);
2255
- t->align = alignof(ndt_complex128_t);
2256
- break;
2257
- default:
2258
- ndt_err_format(ctx, NDT_ValueError, "not a primitive type"),
2259
- ndt_free(t);
2260
- return NULL;
2261
- }
2262
-
2263
- return t;
2264
- }
2265
-
2266
- ndt_t *
2631
+ const ndt_t *
2267
2632
  ndt_signed(int size, uint32_t flags, ndt_context_t *ctx)
2268
2633
  {
2269
2634
  switch (size) {
@@ -2278,7 +2643,7 @@ ndt_signed(int size, uint32_t flags, ndt_context_t *ctx)
2278
2643
  }
2279
2644
  }
2280
2645
 
2281
- ndt_t *
2646
+ const ndt_t *
2282
2647
  ndt_unsigned(int size, uint32_t flags, ndt_context_t *ctx)
2283
2648
  {
2284
2649
  switch (size) {
@@ -2293,7 +2658,7 @@ ndt_unsigned(int size, uint32_t flags, ndt_context_t *ctx)
2293
2658
  }
2294
2659
  }
2295
2660
 
2296
- ndt_t *
2661
+ const ndt_t *
2297
2662
  ndt_from_alias(enum ndt_alias tag, uint32_t flags, ndt_context_t *ctx)
2298
2663
  {
2299
2664
  switch (tag) {
@@ -2306,13 +2671,13 @@ ndt_from_alias(enum ndt_alias tag, uint32_t flags, ndt_context_t *ctx)
2306
2671
  }
2307
2672
  }
2308
2673
 
2309
- ndt_t *
2674
+ const ndt_t *
2310
2675
  ndt_typevar(char *name, ndt_context_t *ctx)
2311
2676
  {
2312
2677
  ndt_t *t;
2313
2678
 
2314
2679
  /* abstract type */
2315
- t = ndt_new(Typevar, ctx);
2680
+ t = ndt_new(Typevar, 0, ctx);
2316
2681
  if (t == NULL) {
2317
2682
  ndt_free(name);
2318
2683
  return NULL;