@effekt-lang/effekt 0.2.2 → 0.3.0

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 (96) hide show
  1. package/bin/effekt +0 -0
  2. package/bin/effekt.sh +1 -1
  3. package/libraries/chez/common/effekt_primitives.ss +10 -2
  4. package/libraries/chez/common/immutable/cslist.effekt +13 -7
  5. package/libraries/chez/common/mutable/dict.effekt +8 -10
  6. package/libraries/chez/common/text/regex.effekt +7 -9
  7. package/libraries/common/args.effekt +95 -0
  8. package/libraries/common/array.effekt +225 -0
  9. package/libraries/common/bench.effekt +60 -0
  10. package/libraries/common/buffer.effekt +123 -0
  11. package/libraries/common/bytes.effekt +125 -0
  12. package/libraries/{chez/common/immutable → common}/dequeue.effekt +18 -4
  13. package/libraries/common/effekt.effekt +764 -0
  14. package/libraries/common/exception.effekt +122 -0
  15. package/libraries/common/io/console.effekt +66 -0
  16. package/libraries/common/io/error.effekt +365 -0
  17. package/libraries/common/io/files.effekt +282 -0
  18. package/libraries/common/io/network.effekt +105 -0
  19. package/libraries/common/io/time.effekt +15 -0
  20. package/libraries/common/io.effekt +158 -0
  21. package/libraries/{llvm/immutable → common}/list.effekt +83 -74
  22. package/libraries/common/option.effekt +72 -0
  23. package/libraries/common/process.effekt +10 -0
  24. package/libraries/common/queue.effekt +140 -0
  25. package/libraries/common/ref.effekt +63 -0
  26. package/libraries/common/result.effekt +45 -0
  27. package/libraries/{ml/immutable → common}/seq.effekt +30 -19
  28. package/libraries/common/string.effekt +395 -0
  29. package/libraries/common/test.effekt +98 -0
  30. package/libraries/js/effekt_builtins.js +37 -6
  31. package/libraries/js/io.js +143 -0
  32. package/libraries/js/mutable/map.effekt +8 -9
  33. package/libraries/js/text/regex.effekt +7 -8
  34. package/libraries/js/unsafe/cont.effekt +2 -2
  35. package/libraries/js/web/dom.effekt +13 -13
  36. package/libraries/llvm/array.c +53 -0
  37. package/libraries/llvm/buffer.c +181 -76
  38. package/libraries/llvm/forward-declare-c.ll +27 -8
  39. package/libraries/llvm/io.c +543 -1
  40. package/libraries/llvm/io.ll +19 -0
  41. package/libraries/llvm/main.c +3 -1
  42. package/libraries/llvm/ref.c +45 -0
  43. package/libraries/llvm/rts.ll +496 -354
  44. package/libraries/llvm/types.c +23 -0
  45. package/libraries/ml/effekt.sml +2 -0
  46. package/libraries/ml/internal/mllist.effekt +9 -0
  47. package/libraries/ml/internal/mloption.effekt +18 -0
  48. package/libraries/ml/random.effekt +9 -9
  49. package/libraries/ml/text/regex.effekt +14 -19
  50. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
  51. package/licenses/mit license - mit-license.html +527 -57
  52. package/licenses/the bsd license - bsd-license.html +530 -55
  53. package/licenses/the mit license - mit.html +528 -58
  54. package/package.json +2 -2
  55. package/libraries/chez/callcc/effekt.effekt +0 -221
  56. package/libraries/chez/common/effekt_matching.ss +0 -100
  57. package/libraries/chez/common/immutable/list.effekt +0 -643
  58. package/libraries/chez/common/immutable/option.effekt +0 -39
  59. package/libraries/chez/common/immutable/result.effekt +0 -29
  60. package/libraries/chez/common/io/args.effekt +0 -20
  61. package/libraries/chez/common/mutable/array.effekt +0 -27
  62. package/libraries/chez/common/mutable/heap.effekt +0 -12
  63. package/libraries/chez/common/test.effekt +0 -59
  64. package/libraries/chez/common/text/string.effekt +0 -46
  65. package/libraries/chez/lift/effekt.effekt +0 -217
  66. package/libraries/chez/monadic/effekt.effekt +0 -218
  67. package/libraries/js/effekt.effekt +0 -284
  68. package/libraries/js/effekt_matching.js +0 -79
  69. package/libraries/js/immutable/dequeue.effekt +0 -78
  70. package/libraries/js/immutable/list.effekt +0 -643
  71. package/libraries/js/immutable/option.effekt +0 -49
  72. package/libraries/js/immutable/result.effekt +0 -29
  73. package/libraries/js/io/args.effekt +0 -9
  74. package/libraries/js/io/async.effekt +0 -28
  75. package/libraries/js/io/async.js +0 -2
  76. package/libraries/js/io/file.effekt +0 -50
  77. package/libraries/js/io/file_include.js +0 -13
  78. package/libraries/js/mutable/array.effekt +0 -98
  79. package/libraries/js/mutable/heap.effekt +0 -32
  80. package/libraries/js/test.effekt +0 -59
  81. package/libraries/js/text/string.effekt +0 -64
  82. package/libraries/llvm/effekt.effekt +0 -243
  83. package/libraries/llvm/immutable/option.effekt +0 -53
  84. package/libraries/llvm/immutable/result.effekt +0 -29
  85. package/libraries/llvm/io/args.effekt +0 -24
  86. package/libraries/llvm/text/string.effekt +0 -179
  87. package/libraries/ml/effekt.effekt +0 -267
  88. package/libraries/ml/immutable/dequeue.effekt +0 -81
  89. package/libraries/ml/immutable/list.effekt +0 -674
  90. package/libraries/ml/immutable/option.effekt +0 -53
  91. package/libraries/ml/immutable/result.effekt +0 -29
  92. package/libraries/ml/internal/option.effekt +0 -18
  93. package/libraries/ml/io/args.effekt +0 -41
  94. package/libraries/ml/mutable/array.effekt +0 -43
  95. package/libraries/ml/test.effekt +0 -60
  96. package/libraries/ml/text/string.effekt +0 -81
@@ -1,10 +1,22 @@
1
1
  #ifndef EFFEKT_BUFFER_C
2
2
  #define EFFEKT_BUFFER_C
3
3
 
4
- // NOTE: Buffers are NOT 0-terminated!
5
-
6
4
  #include "stdlib.h"
7
5
  #include <stdint.h>
6
+ #include <string.h> // For memcopy
7
+
8
+ /** We represent buffers like positive types.
9
+ *
10
+ * - The field `tag` contains offset (32bit) and length (32bit), which is equal to
11
+ * the tag (64bit) in Pos;
12
+ * - The field `obj` points to memory with the following layout:
13
+ *
14
+ * +--[ Header ]--+--------------+
15
+ * | Rc | Eraser | Contents ... |
16
+ * +--------------+--------------+
17
+ *
18
+ * The eraser is always a null pointer since it does not need to do anything.
19
+ */
8
20
 
9
21
  // TODO It may be performance-advantageous to implement this C file's semantics
10
22
  // in LLVM, since the linker cannot realistically be asked to satisfactorily
@@ -13,113 +25,123 @@
13
25
  // with clang-generated LLVM from this file's entire translation unit.
14
26
 
15
27
 
16
- // Eight bytes for the reference counter.
17
- // E.g. capacity could later also be stored in the header.
18
- #define BUFFER_HEADER_WIDTH (8)
28
+ struct Pos c_buffer(const uint32_t offset, const uint32_t length, void* obj) {
29
+ return (struct Pos) {
30
+ .tag = ((uint64_t)offset << 32) | (uint32_t)length,
31
+ .obj = obj,
32
+ };
33
+ }
19
34
 
20
- uint64_t c_buffer_length(const struct Pos buffer) {
21
- return buffer.tag;
35
+ void c_buffer_erase_noop(void *envPtr) { (void)envPtr; }
36
+
37
+ uint64_t c_buffer_offset(const struct Pos buffer) {
38
+ return (uint32_t)(buffer.tag >> 32); // Extract offset from the upper 32 bits
22
39
  }
23
40
 
24
- // NOTE: This assumes a homogenously used byte order.
25
- uint64_t *c_buffer_refcount(const struct Pos buffer) {
26
- return (uint64_t *) (buffer.obj + 0);
41
+ // Function to get the length from Pos
42
+ // WARNING: This does not erase the Pos argument!
43
+ uint64_t c_buffer_length(const struct Pos buffer) {
44
+ return (uint32_t)(buffer.tag & 0xFFFFFFFF); // Extract length from the lower 32 bits
27
45
  }
28
46
 
29
47
  uint8_t *c_buffer_bytes(const struct Pos buffer) {
30
- return (uint8_t *) (buffer.obj + BUFFER_HEADER_WIDTH);
48
+ return (uint8_t *) (buffer.obj + sizeof(struct Header) + c_buffer_offset(buffer));
31
49
  }
32
50
 
33
-
34
51
  struct Pos c_buffer_construct(const uint64_t n, const uint8_t *data) {
35
- uint8_t *obj = malloc(BUFFER_HEADER_WIDTH + n * sizeof *obj);
36
- ASSERT_NON_NULL(obj)
52
+ uint8_t *obj = (uint8_t *)malloc(sizeof(struct Header) + n * sizeof *obj);
53
+ ASSERT_NON_NULL(obj);
37
54
 
38
- // reference count (a reference count of zero means one sole owner)
39
- for (uint64_t j = 0; j < BUFFER_HEADER_WIDTH; ++j)
40
- obj[j] = 0;
55
+ struct Header *header = (void*) obj;
56
+ *header = (struct Header) { .rc = 0, .eraser = c_buffer_erase_noop, };
41
57
 
42
- // data
43
- for (uint64_t j = 0; j < n; ++j)
44
- obj[BUFFER_HEADER_WIDTH + j] = data[j];
58
+ // Copy data
59
+ memcpy(obj + sizeof(struct Header), data, n);
45
60
 
46
- return (struct Pos) {
47
- .tag = n,
48
- .obj = obj,
49
- };
61
+ return c_buffer(0, n, obj);
50
62
  }
51
63
 
52
- void c_buffer_destruct(const struct Pos buffer) {
53
- free(buffer.obj);
64
+ struct Pos c_buffer_construct_zeroed(const uint64_t n) {
65
+ uint8_t *zeroes = calloc(sizeof(struct Header) + n, sizeof *zeroes);
66
+ ASSERT_NON_NULL(zeroes)
67
+
68
+ struct Header *header = (void*) zeroes;
69
+ *header = (struct Header) { .rc = 0, .eraser = c_buffer_erase_noop, };
70
+
71
+ return c_buffer(0, n, zeroes);
54
72
  }
55
73
 
74
+ struct Pos c_buffer_construct_uninitialized(const uint64_t n) {
75
+ uint8_t *data = malloc(sizeof(struct Header) + n * sizeof *data);
76
+ ASSERT_NON_NULL(data)
56
77
 
57
- void c_buffer_refcount_increment(const struct Pos buffer) {
58
- if (DEBUG_REFCOUNT) {
59
- fprintf(stderr, "c_buffer_refcount_increment((struct Pos) "
60
- "{ .tag = %" PRIu64 ", .obj = %p }): from %" PRIu64 "\n",
61
- buffer.tag, buffer.obj, *(c_buffer_refcount(buffer)));
62
- fflush(stderr);
63
- }
78
+ struct Header *header = (void*) data;
79
+ *header = (struct Header) { .rc = 0, .eraser = c_buffer_erase_noop, };
64
80
 
65
- (*c_buffer_refcount(buffer))++;
81
+ return c_buffer(0, n, data);
66
82
  }
67
83
 
68
- void c_buffer_refcount_decrement(const struct Pos buffer) {
69
- if (DEBUG_REFCOUNT) {
70
- fprintf(stderr, "c_buffer_refcount_decrement((struct Pos) "
71
- "{ .tag = %" PRIu64 ", .obj = %p }): from %" PRIu64 "\n",
72
- buffer.tag, buffer.obj, *(c_buffer_refcount(buffer)));
73
- fflush(stderr);
74
- }
84
+ struct Pos c_buffer_slice(struct Pos buffer, const uint64_t offset, const uint64_t length) {
75
85
 
76
- if (!(*c_buffer_refcount(buffer))--)
77
- c_buffer_destruct(buffer);
78
- }
86
+ if ((c_buffer_offset(buffer) + offset + length) > c_buffer_length(buffer))
87
+ return buffer;
79
88
 
89
+ return c_buffer(c_buffer_offset(buffer) + offset, length, buffer.obj);
90
+ }
80
91
 
81
- struct Pos c_buffer_construct_zeroed(const uint64_t n) {
82
- uint8_t *zeroes = calloc(n, sizeof *zeroes);
83
- ASSERT_NON_NULL(zeroes)
84
- const struct Pos buffer = c_buffer_construct(n, zeroes);
85
- free(zeroes);
86
- return buffer;
92
+ struct Pos c_buffer_clone(const struct Pos buffer) {
93
+ return c_buffer_construct(c_buffer_length(buffer), c_buffer_bytes(buffer));
87
94
  }
88
95
 
89
- void c_buffer_truncate(struct Pos buffer, const uint64_t n) {
90
- if (n > c_buffer_length(buffer))
96
+ void c_buffer_copy(const struct Pos from, struct Pos to, uint64_t startFrom, uint64_t startTo, uint64_t length) {
97
+ // Check bounds
98
+ if ((startFrom + length > c_buffer_length(from)) || (startTo + length > c_buffer_length(to))) {
91
99
  return;
92
- buffer.tag = n;
93
- }
100
+ }
94
101
 
95
- struct Pos c_buffer_copy(const struct Pos buffer) {
96
- return c_buffer_construct(c_buffer_length(buffer), c_buffer_bytes(buffer));
102
+ // Get pointers to the source and destination slices
103
+ uint8_t *from_bytes = c_buffer_bytes(from) + startFrom;
104
+ uint8_t *to_bytes = c_buffer_bytes(to) + startTo;
105
+
106
+ // Copy bytes from `from` to `to`
107
+ memcpy(to_bytes, from_bytes, length);
97
108
  }
98
109
 
99
110
 
100
- // incurs a malloc: the returned pointer needs to be managed
101
- char *c_buffer_as_null_terminated_string(const struct Pos buffer) {
102
- // Zero runes are represented as non-minimal utf8 in the null-terminated
103
- // string. As such, a count reveals the necessary number of bytes.
111
+ /**
112
+ * Converts a buffer to a null-terminated string, handling zero bytes by encoding them as non-minimal UTF-8 sequences.
113
+ *
114
+ * Note: the returned pointer needs to be managed manually!
115
+ *
116
+ * @param buffer The buffer to convert.
117
+ * @return A null-terminated string representing the contents of the buffer.
118
+ */
119
+ char* c_buffer_as_null_terminated_string(const struct Pos buffer) {
120
+ uint64_t length = c_buffer_length(buffer);
104
121
  uint64_t zero_runes = 0;
105
- for (uint64_t j = 0; j < c_buffer_length(buffer); ++j)
106
- zero_runes += !c_buffer_bytes(buffer)[j];
122
+ uint8_t* bytes = c_buffer_bytes(buffer);
123
+
124
+ // Count zero runes
125
+ for (uint64_t j = 0; j < length; ++j) {
126
+ zero_runes += !bytes[j];
127
+ }
107
128
 
108
- const uint64_t n = c_buffer_length(buffer) + zero_runes;
109
- char *buf = (char *) malloc((n+1) * sizeof *buf);
129
+ // Allocate buffer for the null-terminated string
130
+ uint64_t n = length + zero_runes;
131
+ char *buf = (char *) malloc((n + 1) * sizeof(*buf));
110
132
  ASSERT_NON_NULL(buf)
111
133
 
112
134
  uint64_t i = 0;
113
- for (uint64_t j = 0; j < c_buffer_length(buffer); ++j) {
114
- buf[i++] = c_buffer_bytes(buffer)[j];
115
- if (!buf[i]) {
116
- buf[i] = 0xc0; // 0b110.00000
117
- buf[i++] = 0x80; // 0b10.000000
135
+ for (uint64_t j = 0; j < length; ++j) {
136
+ buf[i++] = bytes[j];
137
+ if (buf[i-1] == 0) {
138
+ buf[i-1] = 0xc0; // 0b11000000
139
+ buf[i++] = 0x80; // 0b10000000
118
140
  }
119
141
  }
120
142
 
121
- // null-terminated
122
- buf[n] = '\00';
143
+ // Null-terminate the string
144
+ buf[n] = '\0';
123
145
 
124
146
  return buf;
125
147
  }
@@ -140,18 +162,29 @@ struct Pos c_buffer_concatenate(const struct Pos left, const struct Pos right) {
140
162
  = j < c_buffer_length(left)
141
163
  ? c_buffer_bytes(left)[j]
142
164
  : c_buffer_bytes(right)[j - c_buffer_length(left)];
165
+
166
+ erasePositive(left);
167
+ erasePositive(right);
143
168
  return concatenated;
144
169
  }
145
170
 
146
171
  struct Pos c_buffer_eq(const struct Pos left, const struct Pos right) {
147
172
  uint64_t left_len = c_buffer_length(left);
148
173
  uint64_t right_len = c_buffer_length(right);
149
- if(left_len != right_len) return BooleanFalse;
150
- for(uint64_t j = 0; j < left_len; ++j) {
151
- if(c_buffer_bytes(left)[j] != c_buffer_bytes(right)[j]) {
174
+ if (left_len != right_len) {
175
+ erasePositive(left);
176
+ erasePositive(right);
177
+ return BooleanFalse;
178
+ }
179
+ for (uint64_t j = 0; j < left_len; ++j) {
180
+ if (c_buffer_bytes(left)[j] != c_buffer_bytes(right)[j]) {
181
+ erasePositive(left);
182
+ erasePositive(right);
152
183
  return BooleanFalse;
153
184
  }
154
185
  }
186
+ erasePositive(left);
187
+ erasePositive(right);
155
188
  return BooleanTrue;
156
189
  }
157
190
 
@@ -160,6 +193,7 @@ struct Pos c_buffer_substring(const struct Pos str, uint64_t start, uint64_t end
160
193
  for (uint64_t j = 0; j < c_buffer_length(substr); ++j) {
161
194
  c_buffer_bytes(substr)[j] = c_buffer_bytes(str)[start+j];
162
195
  }
196
+ erasePositive(str);
163
197
  return substr;
164
198
  }
165
199
 
@@ -168,14 +202,85 @@ struct Pos c_buffer_show_Int(const Int n) {
168
202
  sprintf(str, "%" PRId64, n);
169
203
  return c_buffer_construct_from_null_terminated_string(str);
170
204
  }
205
+
206
+ struct Pos c_buffer_show_Byte(const uint8_t n) {
207
+ char str[4]; // Byte values range from 0 to 255, 3 characters + null terminator
208
+ sprintf(str, "%" PRIu8, n);
209
+ return c_buffer_construct_from_null_terminated_string(str);
210
+ }
211
+
212
+ struct Pos c_buffer_show_Char(const uint64_t n) {
213
+ char str[5] = {0}; // Max 4 bytes for UTF-8 + 1 for null terminator
214
+ unsigned char *buf = (unsigned char *)str;
215
+
216
+ if (n < 0x80) { // 1-byte sequence
217
+ buf[0] = (unsigned char)n;
218
+ } else if (n < 0x800) { // 2-byte sequence
219
+ buf[0] = (unsigned char)(0xC0 | (n >> 6));
220
+ buf[1] = (unsigned char)(0x80 | (n & 0x3F));
221
+ } else if (n < 0x10000) { // 3-byte sequence
222
+ buf[0] = (unsigned char)(0xE0 | (n >> 12));
223
+ buf[1] = (unsigned char)(0x80 | ((n >> 6) & 0x3F));
224
+ buf[2] = (unsigned char)(0x80 | (n & 0x3F));
225
+ } else if (n < 0x110000) { // 4-byte sequence
226
+ buf[0] = (unsigned char)(0xF0 | (n >> 18));
227
+ buf[1] = (unsigned char)(0x80 | ((n >> 12) & 0x3F));
228
+ buf[2] = (unsigned char)(0x80 | ((n >> 6) & 0x3F));
229
+ buf[3] = (unsigned char)(0x80 | (n & 0x3F));
230
+ }
231
+
232
+ return c_buffer_construct_from_null_terminated_string(str);
233
+ }
234
+
171
235
  struct Pos c_buffer_show_Double(const Double x) {
172
236
  char str[64]; // TODO is this large enough? Possibly use snprintf first
173
237
  sprintf(str, "%g", x);
174
238
  return c_buffer_construct_from_null_terminated_string(str);
175
239
  }
176
240
 
177
- uint64_t c_buffer_index(const struct Pos str, const uint64_t index) {
178
- return c_buffer_bytes(str)[index];
241
+ uint64_t c_buffer_index(const struct Pos buffer, const uint64_t index) {
242
+ return c_buffer_bytes(buffer)[index];
243
+ }
244
+
245
+ void c_buffer_set(struct Pos buffer, const uint64_t index, uint8_t value) {
246
+ c_buffer_bytes(buffer)[index] = value;
247
+ }
248
+
249
+ uint32_t c_buffer_character_at(const struct Pos buffer, const uint64_t index) {
250
+ const uint8_t *bytes = c_buffer_bytes(buffer);
251
+ uint8_t first_byte = bytes[index];
252
+ uint32_t character = 0;
253
+
254
+ uint32_t length = c_buffer_length(buffer);
255
+
256
+ if (first_byte < 0x80) {
257
+ // Single-byte character (0xxxxxxx)
258
+ character = first_byte;
259
+ } else if ((first_byte & 0xE0) == 0xC0) {
260
+ // Two-byte character (110xxxxx 10xxxxxx)
261
+ if (index + 1 < length) {
262
+ character = ((first_byte & 0x1F) << 6) |
263
+ (bytes[index + 1] & 0x3F);
264
+ }
265
+ } else if ((first_byte & 0xF0) == 0xE0) {
266
+ // Three-byte character (1110xxxx 10xxxxxx 10xxxxxx)
267
+ if (index + 2 < length) {
268
+ character = ((first_byte & 0x0F) << 12) |
269
+ ((bytes[index + 1] & 0x3F) << 6) |
270
+ (bytes[index + 2] & 0x3F);
271
+ }
272
+ } else if ((first_byte & 0xF8) == 0xF0) {
273
+ // Four-byte character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
274
+ if (index + 3 < length) {
275
+ character = ((first_byte & 0x07) << 18) |
276
+ ((bytes[index + 1] & 0x3F) << 12) |
277
+ ((bytes[index + 2] & 0x3F) << 6) |
278
+ (bytes[index + 3] & 0x3F);
279
+ }
280
+ }
281
+
282
+ erasePositive(buffer);
283
+ return character;
179
284
  }
180
285
 
181
286
  #endif
@@ -8,17 +8,36 @@ declare void @c_io_println_Int(%Int)
8
8
  declare void @c_io_println_Double(%Double)
9
9
  declare void @c_io_println_String(%Pos)
10
10
 
11
- declare %Pos @c_buffer_construct(i64, i8*)
12
- declare void @c_buffer_refcount_increment(%Pos)
13
- declare void @c_buffer_refcount_decrement(%Pos)
11
+ declare %Pos @c_buffer_construct(i64, ptr)
14
12
  declare %Pos @c_buffer_concatenate(%Pos, %Pos)
15
-
16
- declare void @hole()
13
+ declare ptr @c_buffer_as_null_terminated_string(%Pos)
14
+ declare %Pos @c_buffer_construct_from_null_terminated_string(ptr)
15
+ declare ptr @c_buffer_construct_uninitialized(i64)
16
+ declare ptr @c_buffer_bytes(ptr)
17
+ declare void @c_buffer_copy(%Pos, %Pos, i64, i64, i64)
18
+ declare %Pos @c_buffer_clone(%Pos)
17
19
 
18
20
  declare %Pos @c_buffer_eq(%Pos, %Pos)
19
21
  declare %Pos @c_buffer_substring(%Pos, i64, i64)
20
22
  declare i64 @c_buffer_length(%Pos)
21
23
  declare i64 @c_buffer_toInt(%Pos)
22
- declare %Pos @c_buffer_show_Int(%Pos)
23
- declare %Pos @c_buffer_show_Double(%Pos)
24
- declare %Int @c_buffer_index(%Pos)
24
+ declare %Pos @c_buffer_show_Int(i64)
25
+ declare %Pos @c_buffer_show_Char(i32)
26
+ declare %Pos @c_buffer_show_Byte(i8)
27
+ declare %Pos @c_buffer_show_Double(double)
28
+ declare %Int @c_buffer_index(%Pos, i64)
29
+ declare void @c_buffer_set(%Pos, i64, i8)
30
+ declare %Int @c_buffer_character_at(%Pos, i64)
31
+
32
+ declare %Pos @c_buffer_slice(%Pos, i64, i64)
33
+
34
+ declare void @hole()
35
+
36
+ declare %Pos @c_ref_fresh(%Pos)
37
+ declare %Pos @c_ref_get(%Pos)
38
+ declare %Pos @c_ref_set(%Pos, %Pos)
39
+
40
+ declare %Pos @c_array_new(%Int)
41
+ declare %Int @c_array_size(%Pos)
42
+ declare %Pos @c_array_get(%Pos, %Int)
43
+ declare %Pos @c_array_set(%Pos, %Int, %Pos)