ref: 3400b0428b9147012553c6f2280147d8dc99bbf1
parent: c4d04d5ed7a782baf87e5beea2a2d95e31bebc5b
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Oct 6 09:32:25 EDT 2015
Fix up error handling for syswrap+posixy.myr
--- a/bench/runbench.myr
+++ b/bench/runbench.myr
@@ -13,15 +13,6 @@
std.put("total:\t{}s\n", tot);
}
-
-generic perror = {a : @a::(numeric,integral), msg : byte[:] -> @a
- if a < 0
- std.fatal("{}", msg)
- else
- -> a
- ;;
-}
-
const timeit = {prog -> flt64
var avg, m, d, x, n : flt64
@@ -49,10 +40,10 @@
if pid < 0
std.fatal("Could not fork\n");
elif pid == 0
- infd = perror(std.open("/dev/zero", std.Ordonly), "could not open /dev/zero")
- outfd = perror(std.open("/dev/null", std.Owronly), "could not open /dev/null")
- perror(std.dup2(infd, 0), "could not redirect stdin")
- perror(std.dup2(outfd, 1), "could not redirect stdout")
+ infd = std.try(std.open("/dev/zero", std.Ordonly))
+ outfd = std.try(std.open("/dev/null", std.Owronly))
+ std.try(std.dup2(infd, 0))
+ std.try(std.dup2(outfd, 1))
std.execv(prog, [prog][:])
std.fatal("Failed to exec\n")
else
--- a/doc/lang.txt
+++ b/doc/lang.txt
@@ -818,6 +818,8 @@
7. STANDARD LIBRARY:
+ This is documented separately.
+
8. GRAMMAR:
9. FUTURE DIRECTIONS:
--- a/doc/mc.1
+++ b/doc/mc.1
@@ -15,6 +15,11 @@
.I filename.myr
then the the object file that is generated will be named
.I filename.o.
+.PP
+Any text between the first '+' in the file name and the suffix are
+stripped. This functionality is used to specify system tags for
+tools like 'mbld'.
+.PP
If the filename does not end with the suffix
.I .myr
then the suffix
--- a/lib/bio/bio.myr
+++ b/lib/bio/bio.myr
@@ -49,7 +49,7 @@
const flush : (f : file# -> bool)
/* seeking */
- const seek : (f : file#, std.off -> std.off)
+ const seek : (f : file#, std.off -> std.result(std.off, ioerr))
/* single unit operations */
const putb : (f : file#, b : byte -> status(std.size))
@@ -133,13 +133,9 @@
/* open the file, and return it */
const sysopen = {path, mode, openmode, perm
- var fd
-
- fd = std.openmode(path, openmode, perm castto(int64))
- if fd < 0
- -> `std.Fail "could not open fd"
- else
- -> `std.Ok mkfile(fd, mode)
+ match std.openmode(path, openmode, perm castto(int64))
+ | `std.Ok fd: -> `std.Ok mkfile(fd, mode)
+ | `std.Fail e: -> `std.Fail "could not open fd"
;;
}
@@ -189,8 +185,8 @@
returning the number of bytes read.
*/
const read = {f, dst
- var n, d
- var count
+ var count : std.size
+ var d : byte[:]
/* Clear the error state so we can retry */
if f.lasterr != 0
@@ -218,21 +214,22 @@
/* Read the rest directly from the fd */
d = dst[count:]
while dst.len > 0
- n = std.read(f.fd, d)
- if n == 0
+ match std.read(f.fd, d)
+ | `std.Ok 0:
break
- elif n < 0
- if count > 0
- f.lasterr = n castto(std.errno)
+ | `std.Ok n:
+ count += n
+ d = d[n:]
+ | `std.Fail err:
+ if count == 0
+ -> `Err errtype(err)
+ else
+ f.lasterr = err
;;
break
;;
- count += n
- d = d[n:]
;;
- if n < 0 && count == 0
- -> `Err errtype(n)
- elif count == 0
+ if count == 0
-> `Eof
else
-> `Ok dst[:count]
@@ -256,7 +253,10 @@
const seek = {f, off
flush(f)
- -> std.seek(f.fd, off, std.Seekset)
+ match std.seek(f.fd, off, std.Seekset)
+ | `std.Ok ret: -> `std.Ok ret
+ | `std.Fail e: -> `std.Fail errtype(e)
+ ;;
}
/* writes a single byte to the output stream */
@@ -581,19 +581,19 @@
/* blats a buffer to an fd */
const writebuf = {fd, src
- var n
var count
count = 0
while src.len != 0
- n = std.write(fd, src)
- if n == 0
+ match std.write(fd, src)
+ | `std.Ok 0:
-> `Eof
- elif n < 0
- -> `Err errtype(n)
+ | `std.Ok n:
+ count += n
+ src = src[n:]
+ | `std.Fail e:
+ -> `Err errtype(e)
;;
- count += n
- src = src[n:]
;;
:writedone
-> `Ok count
@@ -606,7 +606,6 @@
the read buffer.
*/
const fill = {f, min
- var n
var count
count = 0
@@ -615,27 +614,28 @@
-> `Err geterr(f)
;;
while count < min
- n = std.read(f.fd, f.rbuf[f.rend:])
/*
If we've already read data, we don't want to
throw it away, so we report a successful short
read, and then error on the next read.
*/
- if n == 0
+ match std.read(f.fd, f.rbuf[f.rend:])
+ | `std.Ok 0:
break
- elif n < 0
+ | `std.Ok n:
+ count += n
+ f.rend += n
+ | `std.Fail e:
if count > 0
- f.lasterr = n castto(std.errno)
+ f.lasterr = e
+ else
+ -> `Err errtype(e)
;;
break
;;
- count += n
- f.rend += n
;;
- if n < 0 && count == 0
- -> `Err errtype(n)
- elif count == 0
+ if count == 0
-> `Eof
else
-> `Ok count
@@ -647,10 +647,10 @@
e = f.lasterr
f.lasterr = 0
- -> errtype(e castto(std.size))
+ -> errtype(e)
}
-const errtype : (e : std.size -> ioerr )= {e : std.size -> ioerr
+const errtype : (e : std.errno -> ioerr )= {e : std.errno -> ioerr
var errno
errno = e castto(std.errno)
--- a/lib/std/blat.myr
+++ b/lib/std/blat.myr
@@ -1,4 +1,5 @@
use "syswrap.use"
+use "result.use"
pkg std =
const blat : (path : byte[:], buf : byte[:], perm : int64 -> bool)
@@ -6,27 +7,26 @@
;;
const blat = {path, buf, perm
- var fd
-
- fd = openmode(path, Ocreat|Owronly, perm)
- if fd < 0
- -> false
+ match openmode(path, Ocreat|Owronly, perm)
+ | `Ok fd: -> fblat(fd, buf)
+ | `Fail e: -> false
;;
- -> fblat(fd, buf)
}
const fblat = {fd, buf
- var written, n
+ var count
- n = 0
+ count = 0
while true
- written = write(fd, buf[n:])
- if written <= 0
- goto done
+ match write(fd, buf[count:])
+ | `Fail e: -> false
+ | `Ok n:
+ if n == 0
+ break
+ ;;
+ count += n
;;
- n += written
;;
-:done
- -> written == 0 && n == buf.len
+ -> count == buf.len
}
--- a/lib/std/execvp.myr
+++ b/lib/std/execvp.myr
@@ -8,8 +8,8 @@
use "syswrap.use"
pkg std =
- const execvp : (cmd : byte[:], args : byte[:][:] -> int64)
- const execvpe : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
+ const execvp : (cmd : byte[:], args : byte[:][:] -> errno)
+ const execvpe : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> errno)
;;
const execvp = {cmd, args
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -9,6 +9,7 @@
use "introspect.use"
use "intparse.use"
use "option.use"
+use "result.use"
use "sleq.use"
use "slpush.use"
use "strbuf.use"
@@ -529,15 +530,18 @@
}
const writeall = {fd, buf
- var n, len
+ var len
len = 0
while true
- n = write(fd, buf)
- if n <= 0 || n >= len
- break
+ match write(fd, buf[len:])
+ | `Fail err: break
+ | `Ok n:
+ len += n
+ if n == 0 || len == buf.len
+ break
+ ;;
;;
- len += n
;;
-> len
}
--- a/lib/std/result.myr
+++ b/lib/std/result.myr
@@ -1,5 +1,3 @@
-use "die.use"
-
pkg std =
type result(@a, @b) = union
`Ok @a
--- a/lib/std/slurp.myr
+++ b/lib/std/slurp.myr
@@ -3,41 +3,42 @@
use "result.use"
use "extremum.use"
use "syswrap.use"
+use "errno.use"
use "types.use"
pkg std =
- const slurp : (path : byte[:] -> result(byte[:], byte[:]))
- const fslurp : (path : fd -> result(byte[:], byte[:]))
+ const slurp : (path : byte[:] -> result(byte[:], errno))
+ const fslurp : (path : fd -> result(byte[:], errno))
;;
const Bufstart = 4096
const slurp = {path
- var fd
- fd = open(path, Ordonly)
- if fd < 0
- -> `Fail "Could not open file"
+ match open(path, Ordonly)
+ | `Ok fd: -> fslurp(fd)
+ | `Fail e: -> `Fail e
;;
- -> fslurp(fd)
}
const fslurp = {fd
var len, bufsz
var buf
- var n
len = 0
bufsz = Bufstart
buf = slalloc(bufsz)
while true
- n = read(fd, buf[len:])
- if n <= 0
- goto done
+ match read(fd, buf[len:])
+ | `Ok n:
+ if n == 0
+ -> `Ok buf[:len]
+ ;;
+ len += n
+ bufsz *= 2
+ buf = slgrow(buf, bufsz)
+ | `Fail e:
+ -> `Fail e
;;
- len += n
- bufsz *= 2
- buf = slgrow(buf, bufsz)
;;
-:done
- -> `Ok buf[:len]
+ die("unreachable")
}
--- a/lib/std/spork.myr
+++ b/lib/std/spork.myr
@@ -3,10 +3,11 @@
use "fmt.use"
use "result.use"
use "syswrap.use"
+use "errno.use"
pkg std =
- const spork : (cmd : byte[:][:] -> result((pid, fd, fd), int))
- const sporkfd : (cmd : byte[:][:], infd : fd, outfd : fd -> result(pid, int))
+ const spork : (cmd : byte[:][:] -> result((pid, fd, fd), errno))
+ const sporkfd : (cmd : byte[:][:], infd : fd, outfd : fd -> result(pid, errno))
;;
const spork = {cmd
@@ -14,13 +15,13 @@
var err
/* open up pipes */
- err = pipe(&infds)
- if err != 0
- -> `Fail (-err castto(int))
+ err = pipe(&infds)
+ if err != Enone
+ -> `Fail err
;;
err = pipe(&outfds)
- if err != 0
- -> `Fail (-err castto(int))
+ if err != Enone
+ -> `Fail err
;;
match sporkfd(cmd, infds[0] castto(fd), outfds[1] castto(fd))
@@ -35,7 +36,7 @@
}
const sporkfd = {cmd, infd, outfd
- var pid
+ var pid, err
pid = fork()
/* error */
@@ -44,16 +45,22 @@
/* child */
elif pid == 0
/* stdin/stdout for our communication. */
- if dup2(infd castto(fd), 0) != 0
- fatal("unable to set stdin\n")
+ match dup2(infd castto(fd), 0)
+ | `Ok _: /* nothing */
+ | `Fail e: -> `Fail e
;;
- if dup2(outfd castto(fd), 1) != 1
- fatal("unable to set stdout\n")
+ match dup2(outfd castto(fd), 1)
+ | `Ok _: /* nothing */
+ | `Fail e: -> `Fail e
;;
close(infd)
close(outfd)
- execvp(cmd[0], cmd) < 0
- fatal("failed to exec {}\n", cmd[0])
+ err = execvp(cmd[0], cmd)
+ if err != Enone
+ -> `Fail err
+ ;;
+ /* if fork succeeds, we never return */
+ die("unreachable")
/* parent */
else
-> `Ok pid
--- a/lib/std/syswrap+posixy.myr
+++ b/lib/std/syswrap+posixy.myr
@@ -1,8 +1,9 @@
use sys
use "cstrconv.use"
+use "errno.use"
use "option.use"
+use "result.use"
use "types.use"
-use "errno.use"
pkg std =
type fd = sys.fd
@@ -29,23 +30,22 @@
const Ordwr : fdopt = sys.Ordwr castto(fdopt)
const Ocreat : fdopt = sys.Ocreat castto(fdopt)
const Otrunc : fdopt = sys.Otrunc castto(fdopt)
- const Oappend : fdopt = sys.Oappend castto(fdopt)
const Odir : fdopt = sys.Odir castto(fdopt)
/* fd stuff */
- const open : (path : byte[:], opts : fdopt -> fd)
- const openmode : (path : byte[:], opts : fdopt, mode : int64 -> fd)
- const close : (fd : fd -> int64)
- const creat : (path : byte[:], mode : int64 -> fd)
- const read : (fd : fd, buf : byte[:] -> size)
- const write : (fd : fd, buf : byte[:] -> size)
- const pipe : (fds : fd[2]# -> int64)
- const seek : (fd : fd, delta : off, whence : whence -> off)
- const dup2 : (ofd : fd, nfd : fd -> fd)
+ const open : (path : byte[:], opts : fdopt -> result(fd, errno))
+ const openmode : (path : byte[:], opts : fdopt, mode : int64 -> result(fd, errno))
+ const close : (fd : fd -> errno)
+ const creat : (path : byte[:], mode : int64 -> result(fd, errno))
+ const read : (fd : fd, buf : byte[:] -> result(size, errno))
+ const write : (fd : fd, buf : byte[:] -> result(size, errno))
+ const pipe : (fds : fd[2]# -> errno)
+ const seek : (fd : fd, delta : off, whence : whence -> result(off, errno))
+ const dup2 : (ofd : fd, nfd : fd -> result(fd, errno))
/* useful/portable bits of stat */
- const fmtime : (f : byte[:] -> option(time))
- const fsize : (f : byte[:] -> option(off))
+ const fmtime : (f : byte[:] -> result(time, errno))
+ const fsize : (f : byte[:] -> result(off, errno))
const fexists : (f : byte[:] -> bool)
/* useful/portable bits of uname */
@@ -60,27 +60,28 @@
const getpid : ( -> pid)
const suicide : ( -> void)
const fork : (-> pid)
- const execv : (cmd : byte[:], args : byte[:][:] -> int64)
- const execve : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
- const waitpid : (pid:pid, loc:int32#, opt : int64 -> int64)
+ const execv : (cmd : byte[:], args : byte[:][:] -> errno)
+ const execve : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> errno)
pkglocal const Canunmap : bool = true
pkglocal const getmem : (sz : size -> byte#)
pkglocal const freemem : (p : byte#, sz : size -> void)
pkglocal const curtime : (-> time)
+ pkglocal const waitpid : (pid:pid, loc:int32#, opt : int64 -> int64)
;;
/* fd stuff */
-const open = {path, opts; -> sys.open(path, opts castto(sys.fdopt)) castto(fd)}
-const openmode = {path, opts, mode; -> sys.openmode(path, opts castto(sys.fdopt), mode) castto(fd)}
-const close = {fd; -> sys.close(fd castto(sys.fd))}
-const creat = {path, mode; -> sys.creat(path, mode) castto(fd)}
-const read = {fd, buf; -> sys.read(fd castto(sys.fd), buf) castto(size)}
-const write = {fd, buf; -> sys.write(fd castto(sys.fd), buf) castto(size)}
-const pipe = {fds; -> sys.pipe(fds castto(sys.fd[2]#))}
-const seek = {fd, delta, whence; -> sys.lseek(fd castto(sys.fd), delta castto(sys.off), whence castto(sys.whence)) castto(off)}
-const dup2 = {ofd, nfd; -> sys.dup2(ofd castto(sys.fd), nfd castto(sys.fd)) castto(fd)}
+const open = {path, opts; -> check(sys.open(path, opts castto(sys.fdopt)))}
+const openmode = {path, opts, mode; -> check(sys.openmode(path, opts castto(sys.fdopt), mode))}
+const close = {fd; -> sys.close(fd castto(sys.fd)) castto(errno)}
+const creat = {path, mode; -> check(sys.creat(path, mode))}
+const read = {fd, buf; -> check(sys.read(fd castto(sys.fd), buf))}
+const write = {fd, buf; -> check(sys.write(fd castto(sys.fd), buf))}
+const pipe = {fds; -> sys.pipe(fds castto(sys.fd[2]#)) castto(errno)}
+const seek = {fd, delta, whence; -> check(sys.lseek(fd castto(sys.fd), delta castto(sys.off), whence castto(sys.whence)))}
+const dup2 = {ofd, nfd; -> check(sys.dup2(ofd castto(sys.fd), nfd castto(sys.fd)) castto(fd))}
+
/* path manipulation */
const mkdir = {path, mode; -> sys.mkdir(path, mode)}
const chdir = {path; -> sys.chdir(path) == 0}
@@ -99,8 +100,8 @@
const getpid = {; -> sys.getpid() castto(pid)}
const suicide = {; sys.kill(sys.getpid(), 6)} /* kill self with sigabort */
const fork = {; -> sys.fork() castto(pid)}
-const execv = {cmd, args; -> sys.execv(cmd, args)}
-const execve = {cmd, args, env; -> sys.execve(cmd, args, env)}
+const execv = {cmd, args; -> sys.execv(cmd, args) castto(errno)}
+const execve = {cmd, args, env; -> sys.execve(cmd, args, env) castto(errno)}
const sleep = {time; sys.sleep(time)}
/* memory stuff */
@@ -125,24 +126,34 @@
}
const fmtime = {path
- var sb
+ var sb, r
var sec, nsec
- if sys.stat(path, &sb) == 0
+ r = sys.stat(path, &sb)
+ if r >= 0
sec = sb.mtime.sec castto(time)
nsec = sb.mtime.nsec castto(time)
- -> `Some sec*1000 + nsec/1_000_000
+ -> `Ok sec*1000 + nsec/1_000_000
else
- -> `None
+ -> check(r)
;;
}
const fsize = {path
- var sb
+ var sb, r
- if sys.stat(path, &sb) == 0
- -> `Some (sb.size castto(off))
+ r = sys.stat(path, &sb)
+ if r >= 0
+ -> `Ok (sb.size castto(off))
else
- -> `None
+ -> check(r)
+ ;;
+}
+
+generic check = {e : @a::(integral, numeric) -> result(@b, errno)
+ if e < 0
+ -> `Fail e castto(errno)
+ else
+ -> `Ok e castto(@b)
;;
}
--- a/mbld/build.myr
+++ b/mbld/build.myr
@@ -479,12 +479,12 @@
up to date.
*/
match std.fmtime(src)
- | `std.Some mt: srcmt = mt
- | `std.None: std.fatal("could not stat {}\n", src)
+ | `std.Ok mt: srcmt = mt
+ | `std.Fail e: std.fatal("could not stat {}: {}\n", src, e)
;;
match std.fmtime(dst)
- | `std.Some mt: dstmt = mt
- | `std.None: -> false
+ | `std.Ok mt: dstmt = mt
+ | `std.Fail e: -> false
;;
-> srcmt <= dstmt
}