ndtypes 0.2.0dev5 → 0.2.0dev6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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;