Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ lines its run must print, and the gates run on the mini cluster.
bend2/main.ts the CLI; imported, the .bend loader for bun and node
bend2/base.bend the base library
bend2/bend.lean the core, mechanized in Lean
bend2/effs/ one file per IO effect, per backend
bend2/effs/ IO effect sources per backend; related effects may share
bend2/pack/ package.json, tsconfig.json, bun.lock
bend2/docs/ the papers' Typst sources, the film, gen_pins.ts (the
record pins on this Mac), gen_charts.ts (the landing
Expand Down
12 changes: 6 additions & 6 deletions bend2/base.bend
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,13 @@ def File.read(file: File, max: U32) ->

def File.read_bytes(file: File, max: U32) ->
IO(File & Result<&1, &1, U32 & String, List<&2, U32>>):
import "./effs/file_read_bytes.c"
import "./effs/file_read_bytes.js"
import "./effs/file_read.c"
import "./effs/file_read.js"

def File.read_at(file: File, offset: U32, max: U32) ->
IO(File & Result<&1, &1, U32 & String, List<&2, U32>>):
import "./effs/file_read_at.c"
import "./effs/file_read_at.js"
import "./effs/file_read.c"
import "./effs/file_read.js"

def File.size(file: File) ->
IO(File & Result<&1, &1, U32 & String, U32>):
Expand All @@ -286,8 +286,8 @@ def File.write(file: File, data: String) ->

def File.write_bytes(file: File, data: List<&2, U32>) ->
IO(File & Result<&1, &1, U32 & String, Unit>):
import "./effs/file_write_bytes.c"
import "./effs/file_write_bytes.js"
import "./effs/file_write.c"
import "./effs/file_write.js"

def File.close(file: File) -> IO(Unit):
import "./effs/file_close.c"
Expand Down
70 changes: 66 additions & 4 deletions bend2/effs/file_read.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ static void file_read_call(IoWork* w) {
w->size = io_sys_end(w, read(fd, w->data, w->word));
}

static Term file_read_start(Term file, U32 max, IoWork* w,
IoCall call, IoPack pack) {
w->hand = (intptr_t)io_hand_v(file);
w->word = max < INT32_MAX ? max : INT32_MAX;
w->data = io_mem(malloc(w->word + 1));
return io_work(w, call, pack);
}

#ifdef CID_FILE_READ

static Term file_read_pack(Env e, IoWork* w) {
Term r = w->code ? io_fail(e, w->code, NULL)
: io_done(e, io_str(e, w->data, w->size));
Expand All @@ -14,12 +24,64 @@ static Term file_read_pack(Env e, IoWork* w) {
}

Term file_read_run(Env e, Term* f, IoWork* w) {
w->hand = (intptr_t)io_hand_v(f[0]);
w->word = f[1] < INT32_MAX ? f[1] : INT32_MAX;
w->data = io_mem(malloc(w->word + 1));
return io_work(w, file_read_call, file_read_pack);
return file_read_start(f[0], f[1], w, file_read_call, file_read_pack);
}

static void __attribute__((constructor)) file_read_use(void) {
io_eff(CID_FILE_READ, file_read_run, 0);
}

#endif

#if defined(CID_FILE_READ_BYTES) || defined(CID_FILE_READ_AT)

// The bytes as they are (0..255), one List cell each; a text reader
// would decode them as UTF-8.
static Term file_read_bytes_pack(Env e, IoWork* w) {
Term r;
if (w->code) {
r = io_fail(e, w->code, NULL);
} else {
Term xs = term_pak(CID_NIL, 0);
for (u64 i = w->size; i > 0; i -= 1) {
xs = io_node(e, CID_CON, ((uint8_t*)w->data)[i - 1], xs);
}
r = io_done(e, xs);
}
free(w->data);
return io_tup(e, io_hand(w->hand), r);
}

#endif

#ifdef CID_FILE_READ_BYTES

Term file_read_bytes_run(Env e, Term* f, IoWork* w) {
return file_read_start(f[0], f[1], w, file_read_call, file_read_bytes_pack);
}

static void __attribute__((constructor)) file_read_bytes_use(void) {
io_eff(CID_FILE_READ_BYTES, file_read_bytes_run, 0);
}

#endif

#ifdef CID_FILE_READ_AT

// The bytes at an offset, as file_read_bytes gives them; the position of
// the file does not move.
static void file_read_at_call(IoWork* w) {
int fd = (int)w->hand;
w->size = io_sys_end(w, pread(fd, w->data, w->word, (off_t)w->made));
}

Term file_read_at_run(Env e, Term* f, IoWork* w) {
w->made = (intptr_t)f[1];
return file_read_start(f[0], f[2], w, file_read_at_call, file_read_bytes_pack);
}

static void __attribute__((constructor)) file_read_at_use(void) {
io_eff(CID_FILE_READ_AT, file_read_at_run, 0);
}

#endif
29 changes: 23 additions & 6 deletions bend2/effs/file_read.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
// File
// ====

function file_read(file, max) {
function file_read_with(file, max, offset, pack) {
const sys = io_sys();
const fd = file;
const len = Math.min(max, 2147483647);
const b = new Uint8Array(Math.max(len, 1));
const n = Number(sys.read(fd, sys.ptr(b), len));
if (n < 0) {
return io_tup(file, io_fail(sys.errno()));
const n = Number(offset === null ? sys.read(file, sys.ptr(b), len)
: sys.pread(file, sys.ptr(b), len, BigInt(offset)));
return io_tup(file, n < 0 ? io_fail(sys.errno()) : io_done(pack(b, n)));
}

function file_read_list(b, n) {
let xs = { $: "Nil" };
for (let i = n; i > 0; i -= 1) {
xs = { $: "Con", head: b[i - 1], tail: xs };
}
return io_tup(file, io_done(io_text(b, n)));
return xs;
}

function file_read(file, max) {
return file_read_with(file, max, null, io_text);
}

function file_read_bytes(file, max) {
return file_read_with(file, max, null, file_read_list);
}

function file_read_at(file, offset, max) {
return file_read_with(file, max, offset, file_read_list);
}
36 changes: 0 additions & 36 deletions bend2/effs/file_read_at.c

This file was deleted.

18 changes: 0 additions & 18 deletions bend2/effs/file_read_at.js

This file was deleted.

35 changes: 0 additions & 35 deletions bend2/effs/file_read_bytes.c

This file was deleted.

18 changes: 0 additions & 18 deletions bend2/effs/file_read_bytes.js

This file was deleted.

36 changes: 36 additions & 0 deletions bend2/effs/file_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ static Term file_write_pack(Env e, IoWork* w) {
return io_tup(e, io_hand(w->hand), r);
}

#ifdef CID_FILE_WRITE

Term file_write_run(Env e, Term* f, IoWork* w) {
w->hand = (intptr_t)io_hand_v(f[0]);
w->data = io_cstr(e, f[1], &w->size);
Expand All @@ -26,3 +28,37 @@ Term file_write_run(Env e, Term* f, IoWork* w) {
static void __attribute__((constructor)) file_write_use(void) {
io_eff(CID_FILE_WRITE, file_write_run, 0);
}

#endif

#ifdef CID_FILE_WRITE_BYTES

// The bytes as they are (0..255), one List cell each; a value past 255
// fails with EINVAL before any byte is written.
Term file_write_bytes_run(Env e, Term* f, IoWork* w) {
u64 cap = 64;
Term xs = f[1];
w->hand = (intptr_t)io_hand_v(f[0]);
w->code = 0;
w->size = 0;
w->data = io_mem(malloc(cap));
while (term_aux(xs) == CID_CON) {
Term fb[2];
spare_free(e, cls_fit(2), ctr_take(e, xs, 2, fb));
if (w->size == cap) {
cap *= 2;
w->data = io_mem(realloc(w->data, cap));
}
w->code = fb[0] > 255 ? EINVAL : w->code;
w->data[w->size++] = (char)fb[0];
xs = fb[1];
}
return w->code ? file_write_pack(e, w)
: io_work(w, file_write_call, file_write_pack);
}

static void __attribute__((constructor)) file_write_bytes_use(void) {
io_eff(CID_FILE_WRITE_BYTES, file_write_bytes_run, 0);
}

#endif
18 changes: 16 additions & 2 deletions bend2/effs/file_write.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// File
// ====

function file_write(file, data) {
function file_write_buffer(file, b) {
const fs = require("fs");
const fd = file;
const b = io_bytes(data);
let at = 0;
try {
while (at < b.length) {
Expand All @@ -15,3 +14,18 @@ function file_write(file, data) {
return io_tup(file, io_fail(Math.abs(e.errno ?? 5)));
}
}

function file_write(file, data) {
return file_write_buffer(file, io_bytes(data));
}

function file_write_bytes(file, data) {
const bytes = [];
for (let xs = data; xs.$ === "Con"; xs = xs.tail) {
bytes.push(xs.head);
}
if (bytes.some((x) => x > 255)) {
return io_tup(file, io_fail(22));
}
return file_write_buffer(file, Uint8Array.from(bytes));
}
46 changes: 0 additions & 46 deletions bend2/effs/file_write_bytes.c

This file was deleted.

Loading