Skip to content

Commit e914e0a

Browse files
migrate Dir functionality
1 parent 08e14d4 commit e914e0a

File tree

6 files changed

+219
-28
lines changed

6 files changed

+219
-28
lines changed

ci/all_tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ MIGRATED_EXAMPLES=(
1919
"env-test"
2020
"file-test"
2121
"print-test"
22+
"dir-test"
2223
)
2324

2425
# Build the platform using build.sh

ci/expect_scripts/dir-test.exp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/expect
2+
3+
# uncomment line below for debugging
4+
# exp_internal 1
5+
6+
set timeout 7
7+
8+
source ./ci/expect_scripts/shared-code.exp
9+
10+
spawn $env(EXAMPLES_DIR)dir-test
11+
12+
expect "Created test-dir\r\n" {
13+
expect "Created test-nested/a/b/c\r\n" {
14+
expect -re "Contents: test-nested/a\r\n" {
15+
expect "Cleaned up!\r\n" {
16+
expect eof {
17+
check_exit_and_segfault
18+
}
19+
}
20+
}
21+
}
22+
}
23+
24+
puts stderr "\nExpect script failed: output was different from expected value. uncomment `exp_internal 1` to debug."
25+
exit 1

examples/dir-test.roc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
app [main!] { pf: platform "../platform/main.roc" }
2+
3+
import pf.Dir
4+
import pf.Stdout
5+
6+
main! : List(Str) => Try({}, [Exit(I32)])
7+
main! = |_args| {
8+
# Create a single directory
9+
Dir.create!("test-dir")
10+
Stdout.line!("Created test-dir")
11+
12+
# Create nested directories
13+
Dir.create_all!("test-nested/a/b/c")
14+
Stdout.line!("Created test-nested/a/b/c")
15+
16+
# List directory contents
17+
entries = Dir.list!("test-nested")
18+
Stdout.line!("Contents: ${Str.join_with(entries, ", ")}")
19+
20+
# Clean up
21+
Dir.delete_empty!("test-dir")
22+
Dir.delete_all!("test-nested")
23+
Stdout.line!("Cleaned up!")
24+
25+
Ok({})
26+
}

platform/Dir.roc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
Dir := [].{
2+
## **NotFound** - An entity was not found, often a file.
3+
##
4+
## **PermissionDenied** - The operation lacked the necessary privileges to complete.
5+
##
6+
## **AlreadyExists** - An entity already exists, often a file.
7+
##
8+
## **NotADirectory** - The path was not a directory when a directory was expected.
9+
##
10+
## **NotEmpty** - The directory is not empty.
11+
##
12+
## **Other** - A custom error that does not fall under any other I/O error kind.
13+
IOErr := [
14+
NotFound,
15+
PermissionDenied,
16+
AlreadyExists,
17+
NotADirectory,
18+
NotEmpty,
19+
Other(Str),
20+
]
21+
22+
## Creates a new, empty directory at the provided path.
23+
##
24+
## If the parent directories do not exist, they will not be created.
25+
## Use [Dir.create_all!] to create parent directories as needed.
26+
create! : Str => {}
27+
28+
## Creates a new, empty directory at the provided path, including any parent directories.
29+
##
30+
## If the directory already exists, this will succeed without error.
31+
create_all! : Str => {}
32+
33+
## Deletes an empty directory.
34+
##
35+
## Fails if the directory is not empty. Use [Dir.delete_all!] to delete
36+
## a directory and all its contents.
37+
delete_empty! : Str => {}
38+
39+
## Deletes a directory and all of its contents recursively.
40+
##
41+
## Use with caution!
42+
delete_all! : Str => {}
43+
44+
## Lists the contents of a directory.
45+
##
46+
## Returns the paths of all files and directories within the specified directory.
47+
list! : Str => List(Str)
48+
}

platform/main.roc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
platform ""
22
requires {} { main! : List(Str) => Try({}, [Exit(I32)]) }
3-
exposes [Env, File, Stdin, Stdout, Stderr]
3+
exposes [Dir, Env, File, Stdin, Stdout, Stderr]
44
packages {}
55
provides { main_for_host! : "main_for_host" }
66
targets: {
@@ -13,6 +13,7 @@ platform ""
1313
}
1414
}
1515

16+
import Dir
1617
import Env
1718
import File
1819
import Stdin

src/lib.rs

Lines changed: 117 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,92 @@ extern "C" fn roc_crashed_fn(roc_crashed: *const RocCrashed, _env: *mut c_void)
174174
// Hosted Functions (sorted alphabetically by fully-qualified name)
175175
// ============================================================================
176176

177-
/// Hosted function: Env.cwd! (index 0)
177+
/// Hosted function: Dir.create! (index 0)
178+
/// Takes Str, returns {}
179+
extern "C" fn hosted_dir_create(
180+
_ops: *const RocOps,
181+
_ret_ptr: *mut c_void,
182+
args_ptr: *mut c_void,
183+
) {
184+
unsafe {
185+
let path = args_ptr as *const RocStr;
186+
let _ = fs::create_dir((*path).as_str());
187+
}
188+
}
189+
190+
/// Hosted function: Dir.create_all! (index 1)
191+
/// Takes Str, returns {}
192+
extern "C" fn hosted_dir_create_all(
193+
_ops: *const RocOps,
194+
_ret_ptr: *mut c_void,
195+
args_ptr: *mut c_void,
196+
) {
197+
unsafe {
198+
let path = args_ptr as *const RocStr;
199+
let _ = fs::create_dir_all((*path).as_str());
200+
}
201+
}
202+
203+
/// Hosted function: Dir.delete_all! (index 2)
204+
/// Takes Str, returns {}
205+
extern "C" fn hosted_dir_delete_all(
206+
_ops: *const RocOps,
207+
_ret_ptr: *mut c_void,
208+
args_ptr: *mut c_void,
209+
) {
210+
unsafe {
211+
let path = args_ptr as *const RocStr;
212+
let _ = fs::remove_dir_all((*path).as_str());
213+
}
214+
}
215+
216+
/// Hosted function: Dir.delete_empty! (index 3)
217+
/// Takes Str, returns {}
218+
extern "C" fn hosted_dir_delete_empty(
219+
_ops: *const RocOps,
220+
_ret_ptr: *mut c_void,
221+
args_ptr: *mut c_void,
222+
) {
223+
unsafe {
224+
let path = args_ptr as *const RocStr;
225+
let _ = fs::remove_dir((*path).as_str());
226+
}
227+
}
228+
229+
/// Hosted function: Dir.list! (index 4)
230+
/// Takes Str, returns List(Str)
231+
extern "C" fn hosted_dir_list(
232+
ops: *const RocOps,
233+
ret_ptr: *mut c_void,
234+
args_ptr: *mut c_void,
235+
) {
236+
let roc_ops = unsafe { &*ops };
237+
let path = unsafe {
238+
let args = args_ptr as *const RocStr;
239+
(*args).as_str().to_string()
240+
};
241+
242+
let entries: Vec<String> = fs::read_dir(&path)
243+
.map(|rd| {
244+
rd.filter_map(|entry| {
245+
entry.ok().map(|e| e.path().to_string_lossy().into_owned())
246+
})
247+
.collect()
248+
})
249+
.unwrap_or_default();
250+
251+
let mut list = RocList::with_capacity(entries.len(), roc_ops);
252+
for entry in entries {
253+
let roc_str = RocStr::from_str(&entry, roc_ops);
254+
list.push(roc_str, roc_ops);
255+
}
256+
257+
unsafe {
258+
*(ret_ptr as *mut RocList<RocStr>) = list;
259+
}
260+
}
261+
262+
/// Hosted function: Env.cwd! (index 5)
178263
/// Takes {}, returns Str
179264
extern "C" fn hosted_env_cwd(
180265
ops: *const RocOps,
@@ -191,7 +276,7 @@ extern "C" fn hosted_env_cwd(
191276
}
192277
}
193278

194-
/// Hosted function: Env.exe_path! (index 1)
279+
/// Hosted function: Env.exe_path! (index 6)
195280
/// Takes {}, returns Str
196281
extern "C" fn hosted_env_exe_path(
197282
ops: *const RocOps,
@@ -208,7 +293,7 @@ extern "C" fn hosted_env_exe_path(
208293
}
209294
}
210295

211-
/// Hosted function: Env.var! (index 2)
296+
/// Hosted function: Env.var! (index 7)
212297
/// Takes Str, returns Str
213298
extern "C" fn hosted_env_var(
214299
ops: *const RocOps,
@@ -227,7 +312,7 @@ extern "C" fn hosted_env_var(
227312
}
228313
}
229314

230-
/// Hosted function: File.delete! (index 3)
315+
/// Hosted function: File.delete! (index 8)
231316
/// Takes Str (path), returns {}
232317
extern "C" fn hosted_file_delete(
233318
_ops: *const RocOps,
@@ -241,7 +326,7 @@ extern "C" fn hosted_file_delete(
241326
let _ = fs::remove_file(path);
242327
}
243328

244-
/// Hosted function: File.read_bytes! (index 4)
329+
/// Hosted function: File.read_bytes! (index 9)
245330
/// Takes Str (path), returns List(U8)
246331
extern "C" fn hosted_file_read_bytes(
247332
ops: *const RocOps,
@@ -263,7 +348,7 @@ extern "C" fn hosted_file_read_bytes(
263348
}
264349
}
265350

266-
/// Hosted function: File.read_utf8! (index 5)
351+
/// Hosted function: File.read_utf8! (index 10)
267352
/// Takes Str (path), returns Str
268353
extern "C" fn hosted_file_read_utf8(
269354
ops: *const RocOps,
@@ -282,7 +367,7 @@ extern "C" fn hosted_file_read_utf8(
282367
}
283368
}
284369

285-
/// Hosted function: File.write_bytes! (index 6)
370+
/// Hosted function: File.write_bytes! (index 11)
286371
/// Takes (Str, List(U8)), returns {}
287372
extern "C" fn hosted_file_write_bytes(
288373
_ops: *const RocOps,
@@ -297,7 +382,7 @@ extern "C" fn hosted_file_write_bytes(
297382
}
298383
}
299384

300-
/// Hosted function: File.write_utf8! (index 7)
385+
/// Hosted function: File.write_utf8! (index 12)
301386
/// Takes (Str, Str), returns {}
302387
extern "C" fn hosted_file_write_utf8(
303388
_ops: *const RocOps,
@@ -312,7 +397,7 @@ extern "C" fn hosted_file_write_utf8(
312397
}
313398
}
314399

315-
/// Hosted function: Stderr.line! (index 8)
400+
/// Hosted function: Stderr.line! (index 13)
316401
/// Takes Str, returns {}
317402
extern "C" fn hosted_stderr_line(
318403
_ops: *const RocOps,
@@ -329,7 +414,7 @@ extern "C" fn hosted_stderr_line(
329414
}
330415
}
331416

332-
/// Hosted function: Stderr.write! (index 9)
417+
/// Hosted function: Stderr.write! (index 14)
333418
/// Takes Str, returns {}
334419
extern "C" fn hosted_stderr_write(
335420
_ops: *const RocOps,
@@ -346,7 +431,7 @@ extern "C" fn hosted_stderr_write(
346431
}
347432
}
348433

349-
/// Hosted function: Stdin.line! (index 10)
434+
/// Hosted function: Stdin.line! (index 15)
350435
/// Takes {}, returns Str
351436
extern "C" fn hosted_stdin_line(
352437
ops: *const RocOps,
@@ -367,7 +452,7 @@ extern "C" fn hosted_stdin_line(
367452
}
368453
}
369454

370-
/// Hosted function: Stdout.line! (index 11)
455+
/// Hosted function: Stdout.line! (index 16)
371456
/// Takes Str, returns {}
372457
extern "C" fn hosted_stdout_line(
373458
_ops: *const RocOps,
@@ -384,7 +469,7 @@ extern "C" fn hosted_stdout_line(
384469
}
385470
}
386471

387-
/// Hosted function: Stdout.write! (index 12)
472+
/// Hosted function: Stdout.write! (index 17)
388473
/// Takes Str, returns {}
389474
extern "C" fn hosted_stdout_write(
390475
_ops: *const RocOps,
@@ -402,20 +487,25 @@ extern "C" fn hosted_stdout_write(
402487
}
403488

404489
/// Array of hosted function pointers, sorted alphabetically by fully-qualified name.
405-
static HOSTED_FNS: [HostedFn; 13] = [
406-
hosted_env_cwd, // Env.cwd! (index 0)
407-
hosted_env_exe_path, // Env.exe_path! (index 1)
408-
hosted_env_var, // Env.var! (index 2)
409-
hosted_file_delete, // File.delete! (index 3)
410-
hosted_file_read_bytes, // File.read_bytes! (index 4)
411-
hosted_file_read_utf8, // File.read_utf8! (index 5)
412-
hosted_file_write_bytes, // File.write_bytes! (index 6)
413-
hosted_file_write_utf8, // File.write_utf8! (index 7)
414-
hosted_stderr_line, // Stderr.line! (index 8)
415-
hosted_stderr_write, // Stderr.write! (index 9)
416-
hosted_stdin_line, // Stdin.line! (index 10)
417-
hosted_stdout_line, // Stdout.line! (index 11)
418-
hosted_stdout_write, // Stdout.write! (index 12)
490+
static HOSTED_FNS: [HostedFn; 18] = [
491+
hosted_dir_create, // Dir.create! (index 0)
492+
hosted_dir_create_all, // Dir.create_all! (index 1)
493+
hosted_dir_delete_all, // Dir.delete_all! (index 2)
494+
hosted_dir_delete_empty, // Dir.delete_empty! (index 3)
495+
hosted_dir_list, // Dir.list! (index 4)
496+
hosted_env_cwd, // Env.cwd! (index 5)
497+
hosted_env_exe_path, // Env.exe_path! (index 6)
498+
hosted_env_var, // Env.var! (index 7)
499+
hosted_file_delete, // File.delete! (index 8)
500+
hosted_file_read_bytes, // File.read_bytes! (index 9)
501+
hosted_file_read_utf8, // File.read_utf8! (index 10)
502+
hosted_file_write_bytes, // File.write_bytes! (index 11)
503+
hosted_file_write_utf8, // File.write_utf8! (index 12)
504+
hosted_stderr_line, // Stderr.line! (index 13)
505+
hosted_stderr_write, // Stderr.write! (index 14)
506+
hosted_stdin_line, // Stdin.line! (index 15)
507+
hosted_stdout_line, // Stdout.line! (index 16)
508+
hosted_stdout_write, // Stdout.write! (index 17)
419509
];
420510

421511
/// Build a RocList<RocStr> from command-line arguments.

0 commit comments

Comments
 (0)