nomen-lang 0.0.19 → 0.2.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.
- package/NOMEN_AGENTS.md +57 -12
- package/core/System/Array.nm +11 -11
- package/core/System/Buffer.nm +2 -2
- package/core/System/Channel.nm +146 -12
- package/core/System/ClassBuffer.nm +2 -2
- package/core/System/Console.nm +28 -17
- package/core/System/Controls/Button.nm +96 -8
- package/core/System/Controls/CheckBox.nm +117 -12
- package/core/System/Controls/Container.nm +114 -8
- package/core/System/Controls/Text.nm +98 -8
- package/core/System/Controls/TextBox.nm +120 -10
- package/core/System/Controls/Window.nm +231 -23
- package/core/System/Graph.nm +1 -1
- package/core/System/Init.nm +4 -8
- package/core/System/LinkedList.nm +1 -1
- package/core/System/List.nm +3 -3
- package/core/System/Map.nm +5 -5
- package/core/System/Math.nm +10 -32
- package/core/System/Result.nm +1 -1
- package/core/System/Set.nm +4 -4
- package/core/System/Stream/Directory.nm +189 -63
- package/core/System/Stream/DirectoryError.nm +21 -0
- package/core/System/Stream/File.nm +339 -141
- package/core/System/Stream/FileError.nm +21 -0
- package/core/System/Stream/Http.nm +109 -44
- package/core/System/Stream/HttpError.nm +20 -0
- package/core/System/String.nm +83 -69
- package/core/System/StringBuilder.nm +11 -13
- package/core/System/Task.nm +46 -12
- package/core/System/Test.nm +1 -1
- package/core/System/Text/Json.nm +5 -3
- package/core/System/Text/JsonTree.nm +23 -14
- package/core/System/Text/Regex.nm +124 -64
- package/core/System/Tree.nm +1 -1
- package/core/System/bool.nm +4 -9
- package/core/System/char.nm +3 -9
- package/core/System/float.nm +2 -1
- package/core/System/float32.nm +44 -0
- package/core/System/float64.nm +44 -0
- package/core/System/int.nm +3 -9
- package/core/System/int16.nm +47 -0
- package/core/System/int32.nm +47 -0
- package/core/System/int64.nm +3 -9
- package/core/System/int8.nm +3 -9
- package/core/System/ufloat.nm +44 -0
- package/core/System/ufloat32.nm +44 -0
- package/core/System/ufloat64.nm +44 -0
- package/core/System/uint.nm +3 -9
- package/core/System/uint16.nm +47 -0
- package/core/System/uint32.nm +47 -0
- package/core/System/uint64.nm +3 -9
- package/core/System/uint8.nm +3 -9
- package/core/docs/System/Channel.md +2 -0
- package/core/docs/System/Result.md +5 -1
- package/core/docs/System/Task.md +1 -1
- package/dist/index.mjs +38794 -21299
- package/package.json +38 -34
- package/src/args.ts +11 -0
- package/src/index.ts +21 -3
- package/src/init.ts +1 -1
- package/src/test.ts +48 -4
- package/src/types/Config.ts +2 -0
|
@@ -5,16 +5,27 @@
|
|
|
5
5
|
* automatically by its `#destroy` when it goes out of scope. Read methods set
|
|
6
6
|
* the `eof` flag when the end of the file is reached.
|
|
7
7
|
*
|
|
8
|
+
* Every operation that can fail returns a `Result` whose error side is a
|
|
9
|
+
* `FileError`; a handle whose `open` failed (or that was closed) reports
|
|
10
|
+
* `FileError.not_open` from subsequent operations instead of crashing.
|
|
11
|
+
*
|
|
8
12
|
* var File w = File()
|
|
9
|
-
* w.open("notes.txt", "w")
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
+
* match w.open("notes.txt", "w") {
|
|
14
|
+
* case .ok(ok) -> {
|
|
15
|
+
* w.writeLine("hello")
|
|
16
|
+
* w.writeLine("world")
|
|
17
|
+
* w.close()
|
|
18
|
+
* }
|
|
19
|
+
* case .error(e) -> Console.write("could not open")
|
|
20
|
+
* }
|
|
13
21
|
*
|
|
14
22
|
* var File r = File()
|
|
15
|
-
* r.open("notes.txt", "r")
|
|
16
|
-
*
|
|
17
|
-
*
|
|
23
|
+
* match r.open("notes.txt", "r") {
|
|
24
|
+
* case .ok(ok) -> {
|
|
25
|
+
* const string first = r.readLine() // Result<string, FileError>
|
|
26
|
+
* }
|
|
27
|
+
* case .error(e) -> Console.write("could not open")
|
|
28
|
+
* }
|
|
18
29
|
*
|
|
19
30
|
* Static one-shot helpers do the open/read/close in one call:
|
|
20
31
|
*
|
|
@@ -26,48 +37,132 @@
|
|
|
26
37
|
pub struct File {
|
|
27
38
|
var uint64 handle = 0
|
|
28
39
|
pub var eof = false
|
|
40
|
+
// errno of the last operation; 0 = success. Raw #arch bodies set it,
|
|
41
|
+
// the Result-returning wrappers map it to FileError.
|
|
42
|
+
var int error = 0
|
|
43
|
+
|
|
44
|
+
// Maps an errno to its FileError case.
|
|
45
|
+
func error_of = (int err, out FileError) {
|
|
46
|
+
switch {
|
|
47
|
+
case err == 2 {
|
|
48
|
+
return FileError.not_found
|
|
49
|
+
}
|
|
50
|
+
case err == 9 {
|
|
51
|
+
return FileError.not_open
|
|
52
|
+
}
|
|
53
|
+
case err == 13 {
|
|
54
|
+
return FileError.access_denied
|
|
55
|
+
}
|
|
56
|
+
case err == 17 {
|
|
57
|
+
return FileError.already_exists
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return FileError.other
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
29
64
|
|
|
30
65
|
// Open the file at `path` with a C mode string ("r", "w", "a", …).
|
|
31
|
-
|
|
66
|
+
// Stores the handle and records errno (0 on success) in `error`.
|
|
67
|
+
func raw_open = (ref self, string path, string mode) {
|
|
68
|
+
```
|
|
69
|
+
#arch: c
|
|
70
|
+
#scope: file
|
|
71
|
+
#include <errno.h>
|
|
72
|
+
```
|
|
32
73
|
```
|
|
33
74
|
#arch: c
|
|
34
75
|
self->handle = (unsigned long long)fopen(path, mode);
|
|
76
|
+
if (self->handle) {
|
|
77
|
+
self->error = 0;
|
|
78
|
+
} else {
|
|
79
|
+
self->error = errno;
|
|
80
|
+
}
|
|
35
81
|
```
|
|
36
82
|
```
|
|
37
83
|
#arch: aarch64
|
|
84
|
+
// Fat-string ABI: path = (x1, x2), mode = (x3, x4).
|
|
38
85
|
mov x0, x1
|
|
39
|
-
mov x1,
|
|
86
|
+
mov x1, x3
|
|
40
87
|
bl _fopen
|
|
41
88
|
str x0, [x19, #8]
|
|
89
|
+
cbnz x0, .Lfile_open_ok
|
|
90
|
+
bl ___error
|
|
91
|
+
ldr w0, [x0]
|
|
92
|
+
str x0, [x19, #24]
|
|
93
|
+
b .Lfile_open_end
|
|
94
|
+
.Lfile_open_ok:
|
|
95
|
+
str xzr, [x19, #24]
|
|
96
|
+
.Lfile_open_end:
|
|
42
97
|
```
|
|
43
98
|
}
|
|
44
99
|
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
pub func
|
|
100
|
+
// Open the file at `path` with a C mode string ("r", "w", "a", …).
|
|
101
|
+
// `.ok(true)` on success; `.error(FileError)` otherwise.
|
|
102
|
+
pub func open = (ref self, string path, string mode, out Result<bool, FileError>) {
|
|
103
|
+
self.raw_open(path, mode)
|
|
104
|
+
if self.error == 0 {
|
|
105
|
+
return Result.ok(true)
|
|
106
|
+
}
|
|
107
|
+
return Result.error(File.error_of(self.error))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Close the handle, recording errno in `error` (0 on success). Also
|
|
111
|
+
// performed automatically by #destroy; calling close explicitly releases
|
|
112
|
+
// the resource early.
|
|
113
|
+
func raw_close = (ref self) {
|
|
48
114
|
```
|
|
49
115
|
#arch: c
|
|
50
116
|
if (self->handle) {
|
|
51
|
-
fclose((FILE*)(unsigned long long)self->handle)
|
|
52
|
-
|
|
117
|
+
if (fclose((FILE*)(unsigned long long)self->handle)) {
|
|
118
|
+
self->error = errno;
|
|
119
|
+
} else {
|
|
120
|
+
self->handle = 0;
|
|
121
|
+
self->error = 0;
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
self->error = 0;
|
|
53
125
|
}
|
|
54
126
|
```
|
|
55
127
|
```
|
|
56
128
|
#arch: aarch64
|
|
57
129
|
ldr x0, [x19, #8]
|
|
58
|
-
cbz x0, .
|
|
130
|
+
cbz x0, .Lfile_close_clean
|
|
59
131
|
bl _fclose
|
|
60
|
-
.
|
|
132
|
+
cbnz w0, .Lfile_close_err
|
|
61
133
|
str xzr, [x19, #8]
|
|
134
|
+
str xzr, [x19, #24]
|
|
135
|
+
b .Lfile_close_end
|
|
136
|
+
.Lfile_close_err:
|
|
137
|
+
bl ___error
|
|
138
|
+
ldr w0, [x0]
|
|
139
|
+
str x0, [x19, #24]
|
|
140
|
+
b .Lfile_close_end
|
|
141
|
+
.Lfile_close_clean:
|
|
142
|
+
str xzr, [x19, #24]
|
|
143
|
+
.Lfile_close_end:
|
|
62
144
|
```
|
|
63
145
|
}
|
|
64
146
|
|
|
147
|
+
// Close the handle. Also performed automatically by #destroy; calling
|
|
148
|
+
// close explicitly releases the resource early. Closing an unopened (or
|
|
149
|
+
// already closed) File is `.ok(true)`.
|
|
150
|
+
pub func close = (ref self, out Result<bool, FileError>) {
|
|
151
|
+
self.raw_close()
|
|
152
|
+
if self.error == 0 {
|
|
153
|
+
return Result.ok(true)
|
|
154
|
+
}
|
|
155
|
+
return Result.error(File.error_of(self.error))
|
|
156
|
+
}
|
|
157
|
+
|
|
65
158
|
// Read every byte from the current position to EOF and return it. Sets
|
|
66
|
-
// `eof`.
|
|
67
|
-
|
|
159
|
+
// `eof` and `error`. Declared `move out string`: the raw body mallocs a
|
|
160
|
+
// fresh buffer and hands ownership to the caller.
|
|
161
|
+
func raw_read_all = (ref self, move out string) {
|
|
68
162
|
```
|
|
69
163
|
#arch: c
|
|
70
164
|
FILE *f = (FILE*)(unsigned long long)self->handle;
|
|
165
|
+
if (!f) { self->error = 9; return (nomen_string){ NULL, 0 }; }
|
|
71
166
|
fseek(f, 0, SEEK_END);
|
|
72
167
|
long size = ftell(f);
|
|
73
168
|
fseek(f, 0, SEEK_SET);
|
|
@@ -75,10 +170,20 @@ pub struct File {
|
|
|
75
170
|
fread(buf, 1, size, f);
|
|
76
171
|
buf[size] = 0;
|
|
77
172
|
self->eof = 1;
|
|
78
|
-
|
|
173
|
+
self->error = 0;
|
|
174
|
+
// size bytes were read — the count is exact, no strlen.
|
|
175
|
+
return (nomen_string){ buf, size };
|
|
79
176
|
```
|
|
80
177
|
```
|
|
81
178
|
#arch: aarch64
|
|
179
|
+
ldr x0, [x19, #8]
|
|
180
|
+
cbnz x0, .Lfile_read_all_go
|
|
181
|
+
mov x0, #9
|
|
182
|
+
str x0, [x19, #24]
|
|
183
|
+
mov x0, #0
|
|
184
|
+
mov x1, #0
|
|
185
|
+
b .return_File_raw_read_all
|
|
186
|
+
.Lfile_read_all_go:
|
|
82
187
|
sub sp, sp, #16
|
|
83
188
|
ldr x0, [x19, #8]
|
|
84
189
|
mov x1, #0
|
|
@@ -105,34 +210,70 @@ pub struct File {
|
|
|
105
210
|
strb wzr, [x0, x1]
|
|
106
211
|
mov w1, #1
|
|
107
212
|
strb w1, [x19, #16]
|
|
213
|
+
str xzr, [x19, #24]
|
|
108
214
|
ldr x0, [sp, #8]
|
|
215
|
+
ldr x1, [sp, #0] // fat len half = size read
|
|
109
216
|
add sp, sp, #16
|
|
110
|
-
b .
|
|
217
|
+
b .return_File_raw_read_all
|
|
111
218
|
```
|
|
112
219
|
return ""
|
|
113
220
|
}
|
|
114
221
|
|
|
222
|
+
// Read every byte from the current position to EOF. `.ok(text)` with the
|
|
223
|
+
// remaining bytes (and `eof` set), or `.error(FileError)` — including
|
|
224
|
+
// `not_open` when the handle was never opened.
|
|
225
|
+
pub func readAll = (ref self, out Result<string, FileError>) {
|
|
226
|
+
const string body = self.raw_read_all()
|
|
227
|
+
if self.error == 0 {
|
|
228
|
+
return Result.ok(body)
|
|
229
|
+
}
|
|
230
|
+
return Result.error(File.error_of(self.error))
|
|
231
|
+
}
|
|
232
|
+
|
|
115
233
|
// Write a string at the current position.
|
|
116
|
-
|
|
234
|
+
func raw_write_all = (ref self, string data) {
|
|
117
235
|
```
|
|
118
236
|
#arch: c
|
|
119
237
|
FILE *f = (FILE*)(unsigned long long)self->handle;
|
|
238
|
+
if (!f) { self->error = 9; return; }
|
|
120
239
|
fputs(data, f);
|
|
240
|
+
self->error = 0;
|
|
121
241
|
```
|
|
122
242
|
```
|
|
123
243
|
#arch: aarch64
|
|
244
|
+
// Fat-string ABI: data = (x1, x2).
|
|
245
|
+
ldr x3, [x19, #8]
|
|
246
|
+
cbnz x3, .Lfile_write_all_go
|
|
247
|
+
mov x0, #9
|
|
248
|
+
str x0, [x19, #24]
|
|
249
|
+
b .return_File_raw_write_all
|
|
250
|
+
.Lfile_write_all_go:
|
|
124
251
|
mov x0, x1
|
|
125
|
-
|
|
252
|
+
mov x1, x3
|
|
126
253
|
bl _fputs
|
|
254
|
+
str xzr, [x19, #24]
|
|
127
255
|
```
|
|
128
256
|
}
|
|
129
257
|
|
|
258
|
+
// Write a string at the current position. `.ok(true)`, or
|
|
259
|
+
// `.error(FileError)` — including `not_open` when the handle was never
|
|
260
|
+
// opened.
|
|
261
|
+
pub func writeAll = (ref self, string data, out Result<bool, FileError>) {
|
|
262
|
+
self.raw_write_all(data)
|
|
263
|
+
if self.error == 0 {
|
|
264
|
+
return Result.ok(true)
|
|
265
|
+
}
|
|
266
|
+
return Result.error(File.error_of(self.error))
|
|
267
|
+
}
|
|
268
|
+
|
|
130
269
|
// Read up to the next '\n' (the newline is not included). Sets `eof`
|
|
131
|
-
// when the end of the file is reached.
|
|
132
|
-
|
|
270
|
+
// when the end of the file is reached and `error` on failure. The raw
|
|
271
|
+
// body mallocs a fresh buffer — `move out string` transfers it.
|
|
272
|
+
func raw_read_line = (ref self, move out string) {
|
|
133
273
|
```
|
|
134
274
|
#arch: c
|
|
135
275
|
FILE *f = (FILE*)(unsigned long long)self->handle;
|
|
276
|
+
if (!f) { self->error = 9; return (nomen_string){ NULL, 0 }; }
|
|
136
277
|
int cap = 16;
|
|
137
278
|
int len = 0;
|
|
138
279
|
char *buf = (char*)malloc(cap);
|
|
@@ -147,10 +288,19 @@ pub struct File {
|
|
|
147
288
|
}
|
|
148
289
|
buf[len] = 0;
|
|
149
290
|
if (c == EOF) self->eof = 1;
|
|
150
|
-
|
|
291
|
+
self->error = 0;
|
|
292
|
+
return (nomen_string){ buf, len };
|
|
151
293
|
```
|
|
152
294
|
```
|
|
153
295
|
#arch: aarch64
|
|
296
|
+
ldr x0, [x19, #8]
|
|
297
|
+
cbnz x0, .Lfile_read_line_go
|
|
298
|
+
mov x0, #9
|
|
299
|
+
str x0, [x19, #24]
|
|
300
|
+
mov x0, #0
|
|
301
|
+
mov x1, #0
|
|
302
|
+
b .return_File_raw_read_line
|
|
303
|
+
.Lfile_read_line_go:
|
|
154
304
|
sub sp, sp, #32
|
|
155
305
|
mov x0, #16
|
|
156
306
|
bl _malloc
|
|
@@ -161,24 +311,24 @@ pub struct File {
|
|
|
161
311
|
ldr x0, [x19, #8]
|
|
162
312
|
bl _fgetc
|
|
163
313
|
str w0, [sp, #24]
|
|
164
|
-
.
|
|
314
|
+
.Lfile_read_line_loop:
|
|
165
315
|
ldr w0, [sp, #24]
|
|
166
316
|
cmp w0, #0
|
|
167
|
-
blt .
|
|
317
|
+
blt .Lfile_read_line_done
|
|
168
318
|
cmp w0, #10
|
|
169
|
-
beq .
|
|
319
|
+
beq .Lfile_read_line_done
|
|
170
320
|
ldr x0, [sp, #16]
|
|
171
321
|
add x0, x0, #1
|
|
172
322
|
ldr x1, [sp, #8]
|
|
173
323
|
cmp x0, x1
|
|
174
|
-
ble .
|
|
324
|
+
ble .Lfile_read_line_store
|
|
175
325
|
ldr x1, [sp, #8]
|
|
176
326
|
lsl x1, x1, #1
|
|
177
327
|
str x1, [sp, #8]
|
|
178
328
|
ldr x0, [sp, #0]
|
|
179
329
|
bl _realloc
|
|
180
330
|
str x0, [sp, #0]
|
|
181
|
-
.
|
|
331
|
+
.Lfile_read_line_store:
|
|
182
332
|
ldr x0, [sp, #0]
|
|
183
333
|
ldr x1, [sp, #16]
|
|
184
334
|
ldr w2, [sp, #24]
|
|
@@ -189,57 +339,99 @@ pub struct File {
|
|
|
189
339
|
ldr x0, [x19, #8]
|
|
190
340
|
bl _fgetc
|
|
191
341
|
str w0, [sp, #24]
|
|
192
|
-
b .
|
|
193
|
-
.
|
|
342
|
+
b .Lfile_read_line_loop
|
|
343
|
+
.Lfile_read_line_done:
|
|
194
344
|
ldr x0, [sp, #0]
|
|
195
345
|
ldr x1, [sp, #16]
|
|
196
346
|
strb wzr, [x0, x1]
|
|
197
347
|
ldr w0, [sp, #24]
|
|
198
348
|
cmp w0, #0
|
|
199
|
-
bge .
|
|
349
|
+
bge .Lfile_read_line_ret
|
|
200
350
|
mov w1, #1
|
|
201
351
|
strb w1, [x19, #16]
|
|
202
|
-
.
|
|
352
|
+
.Lfile_read_line_ret:
|
|
353
|
+
str xzr, [x19, #24]
|
|
203
354
|
ldr x0, [sp, #0]
|
|
355
|
+
ldr x1, [sp, #16] // fat len half
|
|
204
356
|
add sp, sp, #32
|
|
205
|
-
b .
|
|
357
|
+
b .return_File_raw_read_line
|
|
206
358
|
```
|
|
207
359
|
return ""
|
|
208
360
|
}
|
|
209
361
|
|
|
362
|
+
// Read up to the next '\n' (the newline is not included). `.ok(text)`
|
|
363
|
+
// and `eof` set at end of file, or `.error(FileError)`.
|
|
364
|
+
pub func readLine = (ref self, out Result<string, FileError>) {
|
|
365
|
+
const string line = self.raw_read_line()
|
|
366
|
+
if self.error == 0 {
|
|
367
|
+
return Result.ok(line)
|
|
368
|
+
}
|
|
369
|
+
return Result.error(File.error_of(self.error))
|
|
370
|
+
}
|
|
371
|
+
|
|
210
372
|
// Write a string followed by '\n'.
|
|
211
|
-
|
|
373
|
+
func raw_write_line = (ref self, string data) {
|
|
212
374
|
```
|
|
213
375
|
#arch: c
|
|
214
376
|
FILE *f = (FILE*)(unsigned long long)self->handle;
|
|
377
|
+
if (!f) { self->error = 9; return; }
|
|
215
378
|
fputs(data, f);
|
|
216
379
|
fputc('\n', f);
|
|
380
|
+
self->error = 0;
|
|
217
381
|
```
|
|
218
382
|
```
|
|
219
383
|
#arch: aarch64
|
|
384
|
+
// Fat-string ABI: data = (x1, x2).
|
|
385
|
+
ldr x3, [x19, #8]
|
|
386
|
+
cbnz x3, .Lfile_write_line_go
|
|
387
|
+
mov x0, #9
|
|
388
|
+
str x0, [x19, #24]
|
|
389
|
+
b .return_File_raw_write_line
|
|
390
|
+
.Lfile_write_line_go:
|
|
220
391
|
mov x0, x1
|
|
221
|
-
|
|
392
|
+
mov x1, x3
|
|
222
393
|
bl _fputs
|
|
223
394
|
mov w0, #10
|
|
224
395
|
ldr x1, [x19, #8]
|
|
225
396
|
bl _fputc
|
|
397
|
+
str xzr, [x19, #24]
|
|
226
398
|
```
|
|
227
399
|
}
|
|
228
400
|
|
|
401
|
+
// Write a string followed by '\n'. `.ok(true)`, or `.error(FileError)`.
|
|
402
|
+
pub func writeLine = (ref self, string data, out Result<bool, FileError>) {
|
|
403
|
+
self.raw_write_line(data)
|
|
404
|
+
if self.error == 0 {
|
|
405
|
+
return Result.ok(true)
|
|
406
|
+
}
|
|
407
|
+
return Result.error(File.error_of(self.error))
|
|
408
|
+
}
|
|
409
|
+
|
|
229
410
|
// Read up to `size` bytes from the current position. Sets `eof` if fewer
|
|
230
|
-
// than `size` bytes remain.
|
|
231
|
-
|
|
411
|
+
// than `size` bytes remain and `error` on failure. The raw body mallocs a
|
|
412
|
+
// fresh buffer — `move out string` transfers it.
|
|
413
|
+
func raw_read_chunk = (ref self, int size, move out string) {
|
|
232
414
|
```
|
|
233
415
|
#arch: c
|
|
234
416
|
FILE *f = (FILE*)(unsigned long long)self->handle;
|
|
417
|
+
if (!f) { self->error = 9; return (nomen_string){ NULL, 0 }; }
|
|
235
418
|
char *buf = (char*)malloc(size + 1);
|
|
236
419
|
long n = fread(buf, 1, size, f);
|
|
237
420
|
buf[n] = 0;
|
|
238
421
|
if (n < size) self->eof = 1;
|
|
239
|
-
|
|
422
|
+
self->error = 0;
|
|
423
|
+
return (nomen_string){ buf, n };
|
|
240
424
|
```
|
|
241
425
|
```
|
|
242
426
|
#arch: aarch64
|
|
427
|
+
ldr x0, [x19, #8]
|
|
428
|
+
cbnz x0, .Lfile_read_chunk_go
|
|
429
|
+
mov x0, #9
|
|
430
|
+
str x0, [x19, #24]
|
|
431
|
+
mov x0, #0
|
|
432
|
+
mov x1, #0
|
|
433
|
+
b .return_File_raw_read_chunk
|
|
434
|
+
.Lfile_read_chunk_go:
|
|
243
435
|
sub sp, sp, #16
|
|
244
436
|
str x1, [sp, #0]
|
|
245
437
|
ldr x0, [sp, #0]
|
|
@@ -255,34 +447,68 @@ pub struct File {
|
|
|
255
447
|
strb wzr, [x1, x0]
|
|
256
448
|
ldr x2, [sp, #0]
|
|
257
449
|
cmp x0, x2
|
|
258
|
-
bge .
|
|
450
|
+
bge .Lfile_read_chunk_ret
|
|
259
451
|
mov w3, #1
|
|
260
452
|
strb w3, [x19, #16]
|
|
261
|
-
.
|
|
453
|
+
.Lfile_read_chunk_ret:
|
|
454
|
+
str xzr, [x19, #24]
|
|
262
455
|
ldr x0, [sp, #8]
|
|
456
|
+
ldr x1, [sp, #0] // fat len half = bytes read
|
|
263
457
|
add sp, sp, #16
|
|
264
|
-
b .
|
|
458
|
+
b .return_File_raw_read_chunk
|
|
265
459
|
```
|
|
266
460
|
return ""
|
|
267
461
|
}
|
|
268
462
|
|
|
463
|
+
// Read up to `size` bytes from the current position. `.ok(text)`
|
|
464
|
+
// (`eof` set if fewer bytes remained), or `.error(FileError)`.
|
|
465
|
+
pub func readChunk = (ref self, int size, out Result<string, FileError>) {
|
|
466
|
+
const string chunk = self.raw_read_chunk(size)
|
|
467
|
+
if self.error == 0 {
|
|
468
|
+
return Result.ok(chunk)
|
|
469
|
+
}
|
|
470
|
+
return Result.error(File.error_of(self.error))
|
|
471
|
+
}
|
|
472
|
+
|
|
269
473
|
// Write the first `size` bytes of `data` at the current position.
|
|
270
|
-
|
|
474
|
+
func raw_write_chunk = (ref self, string data, int size) {
|
|
271
475
|
```
|
|
272
476
|
#arch: c
|
|
273
477
|
FILE *f = (FILE*)(unsigned long long)self->handle;
|
|
478
|
+
if (!f) { self->error = 9; return; }
|
|
274
479
|
fwrite(data, 1, size, f);
|
|
480
|
+
self->error = 0;
|
|
275
481
|
```
|
|
276
482
|
```
|
|
277
483
|
#arch: aarch64
|
|
484
|
+
// Fat-string ABI: data = (x1, x2), size in x3.
|
|
485
|
+
ldr x4, [x19, #8]
|
|
486
|
+
cbnz x4, .Lfile_write_chunk_go
|
|
487
|
+
mov x0, #9
|
|
488
|
+
str x0, [x19, #24]
|
|
489
|
+
b .return_File_raw_write_chunk
|
|
490
|
+
.Lfile_write_chunk_go:
|
|
278
491
|
mov x0, x1
|
|
492
|
+
mov x2, x3
|
|
279
493
|
mov x1, #1
|
|
280
|
-
|
|
494
|
+
mov x3, x4
|
|
281
495
|
bl _fwrite
|
|
496
|
+
str xzr, [x19, #24]
|
|
282
497
|
```
|
|
283
498
|
}
|
|
284
499
|
|
|
285
|
-
//
|
|
500
|
+
// Write the first `size` bytes of `data` at the current position.
|
|
501
|
+
// `.ok(true)`, or `.error(FileError)`.
|
|
502
|
+
pub func writeChunk = (ref self, string data, int size, out Result<bool, FileError>) {
|
|
503
|
+
self.raw_write_chunk(data, size)
|
|
504
|
+
if self.error == 0 {
|
|
505
|
+
return Result.ok(true)
|
|
506
|
+
}
|
|
507
|
+
return Result.error(File.error_of(self.error))
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// (static) Whether a file exists at `path`. A missing file is `false`,
|
|
511
|
+
// not an error.
|
|
286
512
|
pub func exists = (string path, out bool) {
|
|
287
513
|
```
|
|
288
514
|
#arch: c
|
|
@@ -302,116 +528,88 @@ pub struct File {
|
|
|
302
528
|
return false
|
|
303
529
|
}
|
|
304
530
|
|
|
305
|
-
// (static) Remove the file at `path
|
|
306
|
-
|
|
531
|
+
// (static) Remove the file at `path`; returns errno (0 on success).
|
|
532
|
+
func raw_delete = (string path, out int) {
|
|
307
533
|
```
|
|
308
534
|
#arch: c
|
|
309
|
-
remove(path);
|
|
535
|
+
if (remove(path)) return errno;
|
|
536
|
+
return 0;
|
|
310
537
|
```
|
|
311
538
|
```
|
|
312
539
|
#arch: aarch64
|
|
313
540
|
bl _remove
|
|
314
|
-
|
|
541
|
+
cbz w0, .Lfile_delete_ok
|
|
542
|
+
bl ___error
|
|
543
|
+
ldr w0, [x0]
|
|
544
|
+
b .return_File_raw_delete
|
|
545
|
+
.Lfile_delete_ok:
|
|
546
|
+
mov x0, #0
|
|
547
|
+
b .return_File_raw_delete
|
|
548
|
+
```
|
|
549
|
+
return 0
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// (static) Remove the file at `path`. `.ok(true)`, or
|
|
553
|
+
// `.error(FileError)`.
|
|
554
|
+
pub func delete = (string path, out Result<bool, FileError>) {
|
|
555
|
+
const int err = File.raw_delete(path)
|
|
556
|
+
if err == 0 {
|
|
557
|
+
return Result.ok(true)
|
|
558
|
+
}
|
|
559
|
+
return Result.error(File.error_of(err))
|
|
315
560
|
}
|
|
316
561
|
|
|
317
562
|
// (static) Read the entire contents of `path` in one open/read/close.
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
adr x1, .Lfile_read_all_mode
|
|
338
|
-
bl _fopen
|
|
339
|
-
str x0, [sp, #8]
|
|
340
|
-
cbz x0, .Lfile_read_all_empty
|
|
341
|
-
ldr x0, [sp, #8]
|
|
342
|
-
mov x1, #0
|
|
343
|
-
mov x2, #2
|
|
344
|
-
bl _fseek
|
|
345
|
-
ldr x0, [sp, #8]
|
|
346
|
-
bl _ftell
|
|
347
|
-
str x0, [sp, #16]
|
|
348
|
-
ldr x0, [sp, #8]
|
|
349
|
-
mov x1, #0
|
|
350
|
-
mov x2, #0
|
|
351
|
-
bl _fseek
|
|
352
|
-
ldr x0, [sp, #16]
|
|
353
|
-
add x0, x0, #1
|
|
354
|
-
bl _malloc
|
|
355
|
-
str x0, [sp, #24]
|
|
356
|
-
ldr x0, [sp, #24]
|
|
357
|
-
mov x1, #1
|
|
358
|
-
ldr x2, [sp, #16]
|
|
359
|
-
ldr x3, [sp, #8]
|
|
360
|
-
bl _fread
|
|
361
|
-
ldr x0, [sp, #24]
|
|
362
|
-
ldr x1, [sp, #16]
|
|
363
|
-
strb wzr, [x0, x1]
|
|
364
|
-
ldr x0, [sp, #8]
|
|
365
|
-
bl _fclose
|
|
366
|
-
ldr x0, [sp, #24]
|
|
367
|
-
add sp, sp, #48
|
|
368
|
-
b .return_File_read_all
|
|
369
|
-
.Lfile_read_all_empty:
|
|
370
|
-
adr x0, .Lfile_read_all_empty_str
|
|
371
|
-
bl _strdup
|
|
372
|
-
add sp, sp, #48
|
|
373
|
-
b .return_File_read_all
|
|
374
|
-
.Lfile_read_all_mode: .asciz "r"
|
|
375
|
-
.Lfile_read_all_empty_str: .asciz ""
|
|
376
|
-
.p2align 2
|
|
377
|
-
```
|
|
378
|
-
return ""
|
|
563
|
+
pub func read_all = (string path, out Result<string, FileError>) {
|
|
564
|
+
var Result<string, FileError> result = .error(FileError.other)
|
|
565
|
+
var File f = File()
|
|
566
|
+
match f.open(path, "r") {
|
|
567
|
+
case .ok(did) {
|
|
568
|
+
match f.readAll() {
|
|
569
|
+
case .ok(text) {
|
|
570
|
+
result = .ok(text)
|
|
571
|
+
}
|
|
572
|
+
case .error(e2) {
|
|
573
|
+
result = .error(e2)
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
case .error(e) {
|
|
578
|
+
result = .error(e)
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return result
|
|
379
582
|
}
|
|
380
583
|
|
|
381
584
|
// (static) Write `data` to `path` (replacing any existing contents) in
|
|
382
|
-
// one open/write/close.
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
.Lfile_write_all_done:
|
|
406
|
-
add sp, sp, #32
|
|
407
|
-
b .return_File_write_all
|
|
408
|
-
.Lfile_write_all_mode: .asciz "w"
|
|
409
|
-
.p2align 2
|
|
410
|
-
```
|
|
585
|
+
// one open/write/close. A write failure is reported as `.error`, not
|
|
586
|
+
// silently swallowed (the `must_use` Result discard check forces this to
|
|
587
|
+
// be deliberate).
|
|
588
|
+
pub func write_all = (string path, string data, out Result<bool, FileError>) {
|
|
589
|
+
var Result<bool, FileError> result = .error(FileError.other)
|
|
590
|
+
var File f = File()
|
|
591
|
+
match f.open(path, "w") {
|
|
592
|
+
case .ok(did) {
|
|
593
|
+
match f.writeAll(data) {
|
|
594
|
+
case .ok(did2) {
|
|
595
|
+
result = f.close()
|
|
596
|
+
}
|
|
597
|
+
case .error(e2) {
|
|
598
|
+
var _ = f.close()
|
|
599
|
+
result = .error(e2)
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
case .error(e) {
|
|
604
|
+
result = .error(e)
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return result
|
|
411
608
|
}
|
|
412
609
|
|
|
413
610
|
// Closes the handle if still open (no-op after close). Runs automatically
|
|
414
|
-
// at scope exit, so an unclosed `File` never leaks.
|
|
611
|
+
// at scope exit, so an unclosed `File` never leaks. Best-effort: failures
|
|
612
|
+
// are not reported (use `close` to observe them).
|
|
415
613
|
func #destroy = () {
|
|
416
614
|
```
|
|
417
615
|
#arch: c
|