@effekt-lang/effekt 0.5.0 → 0.7.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.
@@ -0,0 +1,209 @@
1
+ #ifndef EFFEKT_BYTEARRAY_C
2
+ #define EFFEKT_BYTEARRAY_C
3
+
4
+ #include <string.h> // For memcopy
5
+
6
+ /** We represent bytearrays like positive types.
7
+ *
8
+ * - The field `tag` contains the size
9
+ * - The field `obj` points to memory with the following layout:
10
+ *
11
+ * +--[ Header ]--+--------------+
12
+ * | Rc | Eraser | Contents ... |
13
+ * +--------------+--------------+
14
+ *
15
+ * The eraser does nothing.
16
+ */
17
+
18
+
19
+ void c_bytearray_erase_noop(void *envPtr) { (void)envPtr; }
20
+
21
+ struct Pos c_bytearray_new(const Int size) {
22
+ void *objPtr = malloc(sizeof(struct Header) + size);
23
+ struct Header *headerPtr = objPtr;
24
+ *headerPtr = (struct Header) { .rc = 0, .eraser = c_bytearray_erase_noop, };
25
+ return (struct Pos) {
26
+ .tag = size,
27
+ .obj = objPtr,
28
+ };
29
+ }
30
+
31
+ Int c_bytearray_size(const struct Pos arr) {
32
+ return arr.tag;
33
+ }
34
+
35
+ uint8_t* c_bytearray_data(const struct Pos arr) {
36
+ return arr.obj + sizeof(struct Header);
37
+ }
38
+
39
+ Byte c_bytearray_get(const struct Pos arr, const Int index) {
40
+ Byte *dataPtr = arr.obj + sizeof(struct Header);
41
+ Byte element = dataPtr[index];
42
+ return element;
43
+ }
44
+
45
+ struct Pos c_bytearray_set(const struct Pos arr, const Int index, const Byte value) {
46
+ Byte *dataPtr = arr.obj + sizeof(struct Header);
47
+ dataPtr[index] = value;
48
+ return Unit;
49
+ }
50
+
51
+ struct Pos c_bytearray_construct(const uint64_t n, const uint8_t *data) {
52
+ struct Pos arr = c_bytearray_new(n);
53
+
54
+ memcpy(c_bytearray_data(arr), data, n);
55
+
56
+ return arr;
57
+ }
58
+
59
+ // Complex Operations
60
+
61
+ struct Pos c_bytearray_from_nullterminated_string(const char *data) {
62
+ uint64_t n = 0;
63
+ while (data[++n]);
64
+
65
+ return c_bytearray_construct(n, (uint8_t*)data);
66
+ }
67
+
68
+ char* c_bytearray_into_nullterminated_string(const struct Pos arr) {
69
+ uint64_t size = c_bytearray_size(arr);
70
+
71
+ char* result = (char*)malloc(size + 1);
72
+
73
+ memcpy(result, c_bytearray_data(arr), size);
74
+
75
+ result[size] = '\0';
76
+
77
+ // TODO we should erase the input
78
+ return result;
79
+ }
80
+
81
+ // TODO do this in Effekt
82
+ struct Pos c_bytearray_show_Int(const Int n) {
83
+ char str[24];
84
+ sprintf(str, "%" PRId64, n);
85
+ return c_bytearray_from_nullterminated_string(str);
86
+ }
87
+
88
+ // TODO do this in Effekt
89
+ struct Pos c_bytearray_show_Char(const uint64_t n) {
90
+ char str[5] = {0}; // Max 4 bytes for UTF-8 + 1 for null terminator
91
+ unsigned char *buf = (unsigned char *)str;
92
+
93
+ if (n < 0x80) { // 1-byte sequence
94
+ buf[0] = (unsigned char)n;
95
+ } else if (n < 0x800) { // 2-byte sequence
96
+ buf[0] = (unsigned char)(0xC0 | (n >> 6));
97
+ buf[1] = (unsigned char)(0x80 | (n & 0x3F));
98
+ } else if (n < 0x10000) { // 3-byte sequence
99
+ buf[0] = (unsigned char)(0xE0 | (n >> 12));
100
+ buf[1] = (unsigned char)(0x80 | ((n >> 6) & 0x3F));
101
+ buf[2] = (unsigned char)(0x80 | (n & 0x3F));
102
+ } else if (n < 0x110000) { // 4-byte sequence
103
+ buf[0] = (unsigned char)(0xF0 | (n >> 18));
104
+ buf[1] = (unsigned char)(0x80 | ((n >> 12) & 0x3F));
105
+ buf[2] = (unsigned char)(0x80 | ((n >> 6) & 0x3F));
106
+ buf[3] = (unsigned char)(0x80 | (n & 0x3F));
107
+ }
108
+
109
+ return c_bytearray_from_nullterminated_string(str);
110
+ }
111
+
112
+ // TODO do this in Effekt
113
+ struct Pos c_bytearray_show_Byte(const Byte n) {
114
+ char str[4]; // Byte values range from 0 to 255, 3 characters + null terminator
115
+ sprintf(str, "%" PRIu8, n);
116
+ return c_bytearray_from_nullterminated_string(str);
117
+ }
118
+
119
+ // TODO do this in Effekt
120
+ struct Pos c_bytearray_show_Double(const Double x) {
121
+ char str[64]; // TODO is this large enough? Possibly use snprintf first
122
+ sprintf(str, "%g", x);
123
+ return c_bytearray_from_nullterminated_string(str);
124
+ }
125
+
126
+ // TODO do this in Effekt
127
+ struct Pos c_bytearray_concatenate(const struct Pos left, const struct Pos right) {
128
+ const struct Pos concatenated = c_bytearray_new(c_bytearray_size(left) + c_bytearray_size(right));
129
+ for (int64_t j = 0; j < c_bytearray_size(concatenated); ++j)
130
+ c_bytearray_data(concatenated)[j]
131
+ = j < c_bytearray_size(left)
132
+ ? c_bytearray_data(left)[j]
133
+ : c_bytearray_data(right)[j - c_bytearray_size(left)];
134
+
135
+ erasePositive(left);
136
+ erasePositive(right);
137
+ return concatenated;
138
+ }
139
+
140
+ // TODO do this in Effekt
141
+ struct Pos c_bytearray_equal(const struct Pos left, const struct Pos right) {
142
+ uint64_t left_size = c_bytearray_size(left);
143
+ uint64_t right_size = c_bytearray_size(right);
144
+ if (left_size != right_size) {
145
+ erasePositive(left);
146
+ erasePositive(right);
147
+ return BooleanFalse;
148
+ }
149
+ for (uint64_t j = 0; j < left_size; ++j) {
150
+ if (c_bytearray_data(left)[j] != c_bytearray_data(right)[j]) {
151
+ erasePositive(left);
152
+ erasePositive(right);
153
+ return BooleanFalse;
154
+ }
155
+ }
156
+ erasePositive(left);
157
+ erasePositive(right);
158
+ return BooleanTrue;
159
+ }
160
+
161
+ // TODO deprecate
162
+ struct Pos c_bytearray_substring(const struct Pos str, uint64_t start, uint64_t end) {
163
+ const struct Pos substr = c_bytearray_new(end - start);
164
+ for (int64_t j = 0; j < c_bytearray_size(substr); ++j) {
165
+ c_bytearray_data(substr)[j] = c_bytearray_data(str)[start+j];
166
+ }
167
+ erasePositive(str);
168
+ return substr;
169
+ }
170
+
171
+ // TODO deprecate
172
+ uint32_t c_bytearray_character_at(const struct Pos str, const uint64_t index) {
173
+ const uint8_t *bytes = c_bytearray_data(str);
174
+ uint8_t first_byte = bytes[index];
175
+ uint32_t character = 0;
176
+
177
+ uint32_t length = c_bytearray_size(str);
178
+
179
+ if (first_byte < 0x80) {
180
+ // Single-byte character (0xxxxxxx)
181
+ character = first_byte;
182
+ } else if ((first_byte & 0xE0) == 0xC0) {
183
+ // Two-byte character (110xxxxx 10xxxxxx)
184
+ if (index + 1 < length) {
185
+ character = ((first_byte & 0x1F) << 6) |
186
+ (bytes[index + 1] & 0x3F);
187
+ }
188
+ } else if ((first_byte & 0xF0) == 0xE0) {
189
+ // Three-byte character (1110xxxx 10xxxxxx 10xxxxxx)
190
+ if (index + 2 < length) {
191
+ character = ((first_byte & 0x0F) << 12) |
192
+ ((bytes[index + 1] & 0x3F) << 6) |
193
+ (bytes[index + 2] & 0x3F);
194
+ }
195
+ } else if ((first_byte & 0xF8) == 0xF0) {
196
+ // Four-byte character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
197
+ if (index + 3 < length) {
198
+ character = ((first_byte & 0x07) << 18) |
199
+ ((bytes[index + 1] & 0x3F) << 12) |
200
+ ((bytes[index + 2] & 0x3F) << 6) |
201
+ (bytes[index + 3] & 0x3F);
202
+ }
203
+ }
204
+
205
+ erasePositive(str);
206
+ return character;
207
+ }
208
+
209
+ #endif
@@ -8,29 +8,6 @@ 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, ptr)
12
- declare %Pos @c_buffer_concatenate(%Pos, %Pos)
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)
19
-
20
- declare %Pos @c_buffer_eq(%Pos, %Pos)
21
- declare %Pos @c_buffer_substring(%Pos, i64, i64)
22
- declare i64 @c_buffer_length(%Pos)
23
- declare i64 @c_buffer_toInt(%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
11
  declare void @hole()
35
12
 
36
13
  declare %Pos @c_ref_fresh(%Pos)
@@ -41,3 +18,26 @@ declare %Pos @c_array_new(%Int)
41
18
  declare %Int @c_array_size(%Pos)
42
19
  declare %Pos @c_array_get(%Pos, %Int)
43
20
  declare %Pos @c_array_set(%Pos, %Int, %Pos)
21
+
22
+ declare %Pos @c_bytearray_new(%Int)
23
+ declare %Int @c_bytearray_size(%Pos)
24
+ declare %Byte @c_bytearray_get(%Pos, %Int)
25
+ declare %Pos @c_bytearray_set(%Pos, %Int, %Byte)
26
+
27
+ declare ptr @c_bytearray_data(%Pos)
28
+ declare %Pos @c_bytearray_construct(i64, ptr)
29
+
30
+ declare %Pos @c_bytearray_from_nullterminated_string(ptr)
31
+ declare ptr @c_bytearray_into_nullterminated_string(%Pos)
32
+
33
+ declare %Pos @c_bytearray_show_Int(i64)
34
+ declare %Pos @c_bytearray_show_Char(i32)
35
+ declare %Pos @c_bytearray_show_Byte(i8)
36
+ declare %Pos @c_bytearray_show_Double(double)
37
+
38
+ declare %Pos @c_bytearray_concatenate(%Pos, %Pos)
39
+ declare %Pos @c_bytearray_equal(%Pos, %Pos)
40
+
41
+ declare %Pos @c_bytearray_substring(%Pos, i64, i64)
42
+ declare %Int @c_bytearray_character_at(%Pos, i64)
43
+
@@ -20,8 +20,8 @@ void c_io_println_Double(const Double x) {
20
20
  }
21
21
 
22
22
  void c_io_println_String(String text) {
23
- for (uint64_t j = 0; j < c_buffer_length(text); ++j)
24
- putchar(c_buffer_bytes(text)[j]);
23
+ for (int64_t j = 0; j < c_bytearray_size(text); ++j)
24
+ putchar(c_bytearray_data(text)[j]);
25
25
  erasePositive(text);
26
26
  putchar('\n');
27
27
  }
@@ -34,7 +34,7 @@ void c_io_println_String(String text) {
34
34
  // Share memory between Effekt-buffers and libuv buffers
35
35
  // -----------------------------------------------------
36
36
  // A libuv buffer is a {ptr, i64} where i64 is the capacity
37
- // while our buffer (from buffer.c, which is ref-counted) is a %Pos with a
37
+ // while our buffer (from bytearray.c, which is ref-counted) is a %Pos with a
38
38
  // pointer and a length. The data ptr is shared between the two such that
39
39
  // libuv (and underlying mechanisms) can directly write into our buffer without
40
40
  // copying. Since our buffer is ref-counted, this has the advantage that we
@@ -96,10 +96,10 @@ int modeFlags(struct Pos mode) {
96
96
  }
97
97
  }
98
98
 
99
- void c_fs_open(struct Pos path, struct Pos mode, Stack stack) {
99
+ void c_fs_open(String path, struct Pos mode, Stack stack) {
100
100
 
101
101
  // Convert the Effekt String to a 0-terminated string
102
- char* path_str = c_buffer_as_null_terminated_string(path);
102
+ char* path_str = c_bytearray_into_nullterminated_string(path);
103
103
  erasePositive((struct Pos) path);
104
104
 
105
105
  // Convert the Effekt String representing the opening mode to libuv flags
@@ -123,17 +123,16 @@ void c_fs_open(struct Pos path, struct Pos mode, Stack stack) {
123
123
  return;
124
124
  }
125
125
 
126
- void c_fs_read(Int fd, struct Pos buffer, Int offset, Stack stack) {
126
+ void c_fs_read(Int file, struct Pos buffer, Int offset, Int size, Int position, Stack stack) {
127
127
 
128
- char* bytes = (char*)c_buffer_bytes(buffer); // libuv expects signed integers
129
- uv_buf_t buf = uv_buf_init(bytes, c_buffer_length(buffer));
128
+ uv_buf_t buf = uv_buf_init((char*)(c_bytearray_data(buffer) + offset), size);
130
129
  // erasePositive(buffer);
131
130
  // TODO we should erase the buffer but abort if this was the last reference
132
131
 
133
132
  uv_fs_t* request = malloc(sizeof(uv_fs_t));
134
133
  request->data = stack;
135
134
 
136
- int result = uv_fs_read(uv_default_loop(), request, fd, &buf, 1, offset, c_resume_int_fs);
135
+ int result = uv_fs_read(uv_default_loop(), request, file, &buf, 1, position, c_resume_int_fs);
137
136
 
138
137
  if (result < 0) {
139
138
  uv_fs_req_cleanup(request);
@@ -142,17 +141,16 @@ void c_fs_read(Int fd, struct Pos buffer, Int offset, Stack stack) {
142
141
  }
143
142
  }
144
143
 
145
- void c_fs_write(Int fd, struct Pos buffer, Int offset, Stack stack) {
144
+ void c_fs_write(Int file, struct Pos buffer, Int offset, Int size, Int position, Stack stack) {
146
145
 
147
- char* bytes = (char*)c_buffer_bytes(buffer); // libuv expects signed integers
148
- uv_buf_t buf = uv_buf_init(bytes, c_buffer_length(buffer));
146
+ uv_buf_t buf = uv_buf_init((char*)(c_bytearray_data(buffer) + offset), size);
149
147
  // erasePositive(buffer);
150
148
  // TODO we should erase the buffer but abort if this was the last reference
151
149
 
152
150
  uv_fs_t* request = malloc(sizeof(uv_fs_t));
153
151
  request->data = stack;
154
152
 
155
- int result = uv_fs_write(uv_default_loop(), request, fd, &buf, 1, offset, c_resume_int_fs);
153
+ int result = uv_fs_write(uv_default_loop(), request, file, &buf, 1, position, c_resume_int_fs);
156
154
 
157
155
  if (result < 0) {
158
156
  uv_fs_req_cleanup(request);
@@ -161,12 +159,12 @@ void c_fs_write(Int fd, struct Pos buffer, Int offset, Stack stack) {
161
159
  }
162
160
  }
163
161
 
164
- void c_fs_close(Int fd, Stack stack) {
162
+ void c_fs_close(Int file, Stack stack) {
165
163
 
166
164
  uv_fs_t* request = malloc(sizeof(uv_fs_t));
167
165
  request->data = stack;
168
166
 
169
- int result = uv_fs_close(uv_default_loop(), request, fd, c_resume_int_fs);
167
+ int result = uv_fs_close(uv_default_loop(), request, file, c_resume_int_fs);
170
168
 
171
169
  if (result < 0) {
172
170
  uv_fs_req_cleanup(request);
@@ -11,7 +11,7 @@
11
11
 
12
12
  #include "sanity.c"
13
13
  #include "types.c"
14
- #include "buffer.c"
14
+ #include "bytearray.c"
15
15
  #include "io.c"
16
16
  #include "hole.c"
17
17
  #include "ref.c"
@@ -25,9 +25,9 @@ char** program_argv;
25
25
 
26
26
  struct Pos c_get_arg(uint64_t idx) {
27
27
  if(idx < (uint64_t)program_argc) {
28
- return c_buffer_construct_from_null_terminated_string(program_argv[idx]);
28
+ return c_bytearray_from_nullterminated_string(program_argv[idx]);
29
29
  } else {
30
- return c_buffer_construct_zeroed(1);
30
+ return c_bytearray_new(0);
31
31
  }
32
32
  }
33
33
  uint64_t c_get_argc() {