Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement remove, remove_all and mkdir #426

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ fn main() {
.flag("-diag-suppress=177") // variable was declared but never referenced
.flag("-diag-suppress=550") // variable was set but never used
.flag("-diag-suppress=20039") // a __host__ function redeclared with __device__, hence treated as a __host__ __device__ function
.flag("-diag-suppress=68") // integer conversion resulted in a change of sign
imaqtkatt marked this conversation as resolved.
Show resolved Hide resolved
.flag("-diag-suppress=2464") // conversion from a string literal to "char *" is deprecated
imaqtkatt marked this conversation as resolved.
Show resolved Hide resolved
.compile("hvm-cu");

println!("cargo:rustc-cfg=feature=\"cuda\"");
Expand Down
4 changes: 2 additions & 2 deletions src/hvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ static inline Port enter(Net* net, Port var) {
}

// Atomically Links `A ~ B`.
static inline void link(Net* net, TM* tm, Port A, Port B) {
static inline void link_ports(Net* net, TM* tm, Port A, Port B) {
// Attempts to directionally point `A ~> B`
while (true) {
// If `A` is NODE: swap `A` and `B`, and continue
Expand Down Expand Up @@ -842,7 +842,7 @@ static inline void link(Net* net, TM* tm, Port A, Port B) {

// Links `A ~ B` (as a pair).
static inline void link_pair(Net* net, TM* tm, Pair AB) {
link(net, tm, get_fst(AB), get_snd(AB));
link_ports(net, tm, get_fst(AB), get_snd(AB));
}

// Interactions
Expand Down
76 changes: 76 additions & 0 deletions src/run.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <ftw.h>
#include "hvm.c"

// Readback: λ-Encoded Ctr
Expand Down Expand Up @@ -716,6 +719,76 @@ Port io_dl_close(Net* net, Book* book, Port argm) {
return inject_ok(net, new_port(ERA, 0));
}

// Deletes a single file or an empty directory at the specified path.
// Returns Ok(None) if successful, or Err(reason) if an error occurs.
// This function attempts to remove both files and empty directories without
// first checking the type of the path.
// Returns: Result<*, IOError<i24>>
Port io_remove(Net* net, Book* book, Port argm) {
Str path = readback_str(net, book, argm);

int result = remove(path.buf);
free(path.buf);

if (result == 0) {
return inject_ok(net, new_port(ERA, 0));
} else {
return inject_io_err_inner(net, new_port(NUM, new_i24(errno)));
}
}

int remove_all_aux(const char* path, const struct stat* stat, int flags, struct FTW* ftw) {
return remove(path);
}

int remove_all(const char* path) {
struct stat st;
if (stat(path, &st) != 0) {
return remove(path);
}
if (S_ISDIR(st.st_mode)) {
return nftw(path, remove_all_aux, 32, FTW_DEPTH | FTW_PHYS);
} else {
return remove(path);
}
}

// Removes any file or directory recursively at the specified path.
// it will delete the directory and all its contents.
// Returns Ok(None) if successful, or Err(reason) if an error occurs.
// Note: For non-recursive deletion of an empty directory,
// this function behaves the same as delete_file(path).
// Returns: Result<*, IOError<i24>>
Port io_remove_all(Net* net, Book* book, Port argm) {
Str path = readback_str(net, book, argm);

int res = remove_all(path.buf);
free(path.buf);

if (0 == res) {
return inject_ok(net, new_port(ERA, 0));
} else {
return inject_io_err_inner(net, new_port(NUM, new_i24(errno)));
}
}

// Creates a new directory with the given path.
// Returns Ok(None) if sucessfull, or Err(reason) if an error occurs.
// Returns: Result<*, IOError<i24>>
Port io_mkdir(Net* net, Book* book, Port argm) {
Str name = readback_str(net, book, argm);

const mode_t mode = 0777;
int status = mkdir(name.buf, mode);
free(name.buf);

if (status) {
return inject_io_err_inner(net, new_port(NUM, new_i24(errno)));
} else {
return inject_ok(net, new_port(ERA, 0));
}
}

// Book Loader
// -----------

Expand All @@ -731,6 +804,9 @@ void book_init(Book* book) {
book->ffns_buf[book->ffns_len++] = (FFn){"DL_OPEN", io_dl_open};
book->ffns_buf[book->ffns_len++] = (FFn){"DL_CALL", io_dl_call};
book->ffns_buf[book->ffns_len++] = (FFn){"DL_CLOSE", io_dl_open};
book->ffns_buf[book->ffns_len++] = (FFn){"RM", io_remove};
book->ffns_buf[book->ffns_len++] = (FFn){"RM_ALL", io_remove_all};
book->ffns_buf[book->ffns_len++] = (FFn){"MKDIR", io_mkdir};
}

// Monadic IO Evaluator
Expand Down
77 changes: 77 additions & 0 deletions src/run.cu
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
imaqtkatt marked this conversation as resolved.
Show resolved Hide resolved
#include <ftw.h>
#include "hvm.cu"

// Readback: λ-Encoded Ctr
Expand Down Expand Up @@ -834,6 +838,76 @@ Port io_dl_close(GNet* gnet, Book* book, Port argm) {
return gnet_inject_ok(gnet, new_port(ERA, 0));
}

// Removes a single file or an empty directory at the specified path.
// Returns Ok(None) if successful, or Err(reason) if an error occurs.
// This function attempts to remove both files and empty directories without
// first checking the type of the path.
// Returns: Result<*, IOError<i24>>
Port io_remove(GNet* gnet, Port argm) {
Str s = gnet_readback_str(gnet, argm);

int result = remove(s.buf);
free(s.buf);

if (result == 0) {
return gnet_inject_ok(gnet, new_port(ERA, 0));
} else {
return gnet_inject_io_err_inner(gnet, new_port(NUM, new_i24(errno)));
}
}

int remove_all_aux(const char* path, const struct stat* stat, int flags, struct FTW* ftw) {
return remove(path);
}

int remove_all(const char* path) {
struct stat st;
if (stat(path, &st) != 0) {
return remove(path);
}
if (S_ISDIR(st.st_mode)) {
return nftw(path, remove_all_aux, 32, FTW_DEPTH | FTW_PHYS);
} else {
return remove(path);
}
}

// Removes any file or directory recursively at the specified path.
// it will delete the directory and all its contents.
// Returns Ok(None) if successful, or Err(reason) if an error occurs.
// Note: For non-recursive deletion of an empty directory,
// this function behaves the same as delete_file(path).
// Returns: Result<*, IOError<i24>>
Port io_remove_all(GNet* gnet, Port argm) {
Str path = gnet_readback_str(gnet, argm);

int res = remove_all(path.buf);
free(path.buf);

if (0 == res) {
return gnet_inject_ok(gnet, new_port(ERA, 0));
} else {
return gnet_inject_io_err_inner(gnet, new_port(NUM, new_i24(errno)));
}
}

// Creates a new directory with the given path.
// Returns Ok(None) if sucessfull, or Err(reason) if an error occurs.
// Returns: Result<*, IOError<i24>>
Port io_mkdir(GNet* gnet, Port argm) {
Str name = gnet_readback_str(gnet, argm);

const mode_t mode = 0777;
int status = mkdir(name.buf, mode);
free(name.buf);

if (status) {
return gnet_inject_io_err_inner(gnet, new_port(NUM, new_i24(errno)));
} else {
return gnet_inject_ok(gnet, new_port(ERA, 0));
}
}

void book_init(Book* book) {
book->ffns_buf[book->ffns_len++] = (FFn){"READ", io_read};
book->ffns_buf[book->ffns_len++] = (FFn){"OPEN", io_open};
Expand All @@ -846,6 +920,9 @@ void book_init(Book* book) {
book->ffns_buf[book->ffns_len++] = (FFn){"DL_OPEN", io_dl_open};
book->ffns_buf[book->ffns_len++] = (FFn){"DL_CALL", io_dl_call};
book->ffns_buf[book->ffns_len++] = (FFn){"DL_CLOSE", io_dl_open};
book->ffns_buf[book->ffns_len++] = (FFn){"RM", io_remove};
book->ffns_buf[book->ffns_len++] = (FFn){"RM_ALL", io_remove_all};
book->ffns_buf[book->ffns_len++] = (FFn){"MKDIR", io_mkdir};

cudaMemcpyToSymbol(BOOK, book, sizeof(Book));
}
Expand Down
19 changes: 19 additions & 0 deletions tests/programs/io/mkdir.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#{
Creates the batata directory and then removes it.
#}

test-io = 1

mkdir path =
(call "MKDIR" path)

rm_all path =
(call "RM_ALL" path)

main =
let path = "./batata"
with IO {
ask * = (mkdir path)
ask s = (rm_all path)
(wrap s)
}
16 changes: 16 additions & 0 deletions tests/programs/io/remove_all_file.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#{
Calls the rm_all function with a file path as argument.
#}

test-io = 1

rm_all path =
(call "RM_ALL" path)

main =
let temp = "./temp.txt"
with IO {
ask * = (IO/FS/write_file temp (String/encode_utf8 "Contents"))
ask s = (rm_all temp)
(wrap s)
}
35 changes: 35 additions & 0 deletions tests/programs/io/remove_all_recursive.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#{
Creates the following tree structure and then removes A and its children.
A
|-- a.txt
|-- AA
| `-- aa.txt
`-- AB
`-- ab.txt
#}

test-io = 1

mkdir path =
(call "MKDIR" path)

rm_all path =
(call "RM_ALL" path)

test =
with IO {
ask * = (mkdir "A")
ask * = (mkdir "A/AA")
ask * = (mkdir "A/AB")
ask * = (IO/FS/write_file "A/a.txt" (String/encode_utf8 "a"))
ask * = (IO/FS/write_file "A/AA/aa.txt" (String/encode_utf8 "aa"))
ask * = (IO/FS/write_file "A/AB/ab.txt" (String/encode_utf8 "ab"))
ask s = (rm_all "./A")
(wrap s)
}

main =
with IO {
ask res = (test)
(wrap res)
}
18 changes: 18 additions & 0 deletions tests/programs/io/remove_empty_dir.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#{
Uses the rm function to remove an empty directory.
#}

test-io = 1

mkdir path =
(call "MKDIR" path)

rm path =
(call "RM" path)

main =
with IO {
ask * = (mkdir "temp")
ask s = (rm "temp")
(wrap s)
}
16 changes: 16 additions & 0 deletions tests/programs/io/remove_file.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#{
Creates a temporary file and then removes it.
#}

test-io = 1

rm path =
(call "RM" path)

main =
let path = "./temp.txt"
with IO {
ask * = (IO/FS/write_file path (String/encode_utf8 "Contents"))
ask s = (rm path)
(wrap s)
}
15 changes: 15 additions & 0 deletions tests/programs/io/remove_non_existing_file.bend
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#{
Tries to remove a non existing file.
#}

test-io = 1

rm path =
(call "RM" path)

main =
use path = "./non_existing.txt"
with IO {
ask s = (rm path)
(wrap s)
}
Loading