This section
provides an overview of Alef's process creation and
communication primitives. Later
sections then expand on this groundwork.
proc func(1, 2);
chan(int) c;
alloc c; /* allocate channel named 'c' */
c <-= 1+1; /* send a 2 on channel `c' */
int i;
i = <-c; /* assign value received on c to i */
func(<-c); /* pass value received on c to func */
#include <alef.h>
void
receive(chan(byte*) c)
{
byte *s;
s = <-c;
print("%s\n", s);
terminate(nil);
}
void
main(void)
{
chan(byte*) c;
alloc c;
proc receive(c);
c <-= "hello world";
print("done\n");
terminate(nil);
}
aggr Point {
int x;
int y;
};
typedef struct {
int x;
int y;
} Point;
aggr Circle {
int radius;
Point;
};
Circle c;
aggr Line {
Point p1;
Point p2;
};
Line ln;
Point p;
Circle c;
p = c;
int
eqpt(Point p1, Point p2)
{
return p1.x == p2.x && p1.y == p2.y;
}
void
main(void)
{
Point p;
Circle c;
if(eqpt(c, p)) ...
}
if(eqpt(&c, &p)) ...
aggr Shape {
int type;
union {
Circle;
Line;
};
};
Shape s;
Shape s;
memset(&s.Circle, 0, sizeof(s.Circle));
tuple(int, byte*, int) t;
tuple(int, tuple(byte, byte*), int) t;
(1+2, "abc", var)
tuple(int, int, byte*) t;
byte i;
t = (0, (int) i, "abc");
t = (tuple (int, int, byte*)) (0, i, "abc");
float a;
byte *b;
tuple(int, int, byte*) t;
t = (100, 200, "xyz");
(nil, a, b) = t;
Circle c;
Point p;
int rad;
(rad, p) = c;
Circle c;
c = (Circle)(3, (1.0,1.0));
c = (3, (Point)(1.0,1.0));
c = (3, (1,1));
int a, b;
(b,a) = (a,b);
Point
midpoint(Point p1, Point p2)
{
return ((p1.x+p2.x)/2,(p1.y+p2.y)/2);
}
void
main(void)
{
Point p;
p = midpoint((1,1), (3,1));
}
tuple(int, uint, byte*)
strtoui(byte* str, int base)
{
int val;
while(*str != 0 && whitespace(*str))
str++;
if(str == nil || *str == 0)
return(0, 0, str);
while(*str && !whitespace(*str)) {
if(!validdigit(*str, base))
return (-1, val, str+1);
/* extract digit into val */
str++;
}
return(1, val, str);
}
int ret;
uint val;
byte *p, *newp;
while(*p) {
(ret, val, newp) = strtoui(p, 10);
if(ret == 0)
break;
if(ret < 0) {
*newp = 0;
print("bad number %s\n", p);
} else
print("%d\n", val);
p = newp;
}
tuple(int, byte*, byte*) func();
int a;
byte *b, *c;
(a, b, c) = func();
print("tuple = (%d %s %s)\n", a, b, c);
void
kbdproc(chan(int) kbdc)
{
byte c;
int n, fd, ctlfd;
fd = open("/dev/cons", OREAD);
ctlfd = open("/dev/consctl", OWRITE);
write(ctlfd, "rawon", 5); /* set raw mode */
for(;;) {
n = read(fd, &c, 1);
if(n <= 0 || c == 0x04) {
kbdc <-= -1;
return;
}
n = processinput(c);
if(n)
kbdc <-= n;
}
}
void
main(void)
{
int r;
chan(int) kbd;
alloc kbd;
proc kbdproc(kbd);
for(;;) {
r = <-kbd;
if(r < 0)
terminate(nil);
/* process the input value */
}
}
aggr Mevent {
Point;
int buttons;
};
alt {
case <-c0: /* receive & discard input on channel c0 */
break;
case r = <-c1: /* receive input on channel c1 into r*/
break;
case c2 <-= 1: /* send 1 on c2 when there is a receiver*/
break;
}
void
mouseproc(chan(Mevent) mc)
{
int fd, n;
byte buf[1024];
Mevent m;
fd = open("/dev/mouse", OREAD);
for(;;) {
n = read(fd, buf, sizeof(buf));
if(n <= 0)
continue;
m = decodemouse(buf, n);
mc <-= m;
}
}
void
main(void)
{
int r;
Mevent m;
chan(int) kbd;
chan(Mevent) mouse;
alloc kbd, mouse;
proc kbdproc(kbd), mouseproc(mouse);
for(;;) {
alt {
case r = <-kbd:
if(r < 0)
terminate(nil);
/* process keyboard input */
break;
case m = <-mouse:
/* process mouse event */
break;
}
}
}
int kbdpid, mousepid;
void
kbdproc(chan(int) kbdc, chan(int) termc)
{
byte c;
int n, fd, ctlfd;
kbdpid = getpid();
fd = open("/dev/cons", OREAD);
ctlfd = open("/dev/consctl", OWRITE);
write(ctlfd, "rawon", 5); /* set raw mode */
for(;;) {
n = read(fd, &c, 1);
if(n <= 0 || c == EOF) {
termc <-= -1;
return;
}
n = processinput(c);
if(n)
kbdc <-= n;
}
}
void
mouseproc(chan(Mevent) mc, chan(int) termc)
{
int fd, n;
byte buf[1024];
Mevent m;
mousepid = getpid();
fd = open("/dev/mouse", OREAD);
for(;;) {
n = read(fd, buf, sizeof(buf));
if(n < 0) {
termc <-= 1;
return;
}
m = decodemouse(buf, n);
mc <-= m;
}
}
void
main(void)
{
int r;
Mevent m;
chan(int) kbd, term;
chan(Mevent) mouse;
alloc kbd, mouse, term;
proc kbdproc(kbd, term), mouseproc(mouse, term);
for(;;) {
alt {
case <-term: /* kill slave processes */
postnote(PNPROC, mousepid, "kill");
postnote(PNPROC, kbdpid, "kill");
exits(nil);
case r = <-kbd:
/* process keyboard input */
break;
case m = <-mouse:
/* process mouse event */
break;
}
}
}
chan(int)[100] kbd;
void
kbdtask(chan(int) kbdc)
{
int r;
for(;;) {
r = <-kbdc;
/* process keyboard input */
}
}
void
mousetask(chan(Mevent) mc)
{
Mevent m;
for(;;) {
m = <-mc;
/* process mouse input */
}
}
void
main(void)
{
chan(int)[100] kbd;
chan(int) term;
chan(Mevent) mouse;
alloc kbd, mouse, term;
proc kbdproc(kbd, term), mouseproc(mouse, term);
task kbdtask(kbd), mousetask(mouse);
<-term; /* main thread blocks here */
postnote(PNPROC, mousepid, "kill");
postnote(PNPROC, kbdpid, "kill");
exits(nil);
}
if(?ch)
a = <-ch;
chan(int)[1] dummy;
alloc dummy;
dummy <-= 1; /* fill the channel */
while(?ch)
alt {
case a = <-ch:
/* process message */
break 2; /* break from while loop */
case <-dummy:
dummy <-= 1; /* refill channel */
break;
}
void
alarmproc(chan(tuple(int, chan(int))) alrmch)
{
uint t;
int a, dt;
chan(int)[1] dummy;
chan(int) reply;
alarmpid = getpid();
alloc dummy;
dummy <-= 1;
alist = nil;
t = msec();
for(;;) {
if(alist == nil) {
/* no alarms - get client request */
(a, reply) = <-alrmch;
addalarm(alist, a, reply);
t = msec();
} else while(?alrmch) {
alt {
case (a, reply) = <-alrmch:
addalarm(alist, a, reply);
break 2;
case <-dummy:
dummy <-= 1;
break;
}
}
sleep(1); /* sleep 1ms */
dt = msec()-t;
t += dt;
for(each alarm in alist) {
if(alarm.msec <= dt) {
/* send alarm to client */
alarm.ch <-= 1;
deletealarm(alarm);
} else
alarm.msec -= dt;
}
}
}
void
mousetask(chan(Mevent) mc, chan(tuple(int, chan(int))) alarm)
{
Mevent m, lastm;
chan(int) dummy, ch;
alloc dummy;
ch = dummy;
for(;;) {
alt {
case m = <-mc:
if((m.buttons&0x07) == 0)
break;
if(ch == dummy) {
/* no alarm pending */
alloc ch;
alarm <-= (500, ch);
lastm = m;
} else {
task consumealarm(ch);
ch = dummy;
if(lastm.buttons == m.buttons
&& eqpt(lastm.Point, m.Point))
doubleclick(m);
else
singleclick(m);
}
break;
case <-ch: /* alarm expired */
unalloc ch;
ch = dummy;
singleclick(lastm);
break;
}
}
}
void
consumealarm(chan(int) ch)
{
<-ch;
unalloc ch;
}
void
main(void)
{
chan(int)[100] kbd;
chan(int) term;
chan(Mevent) mouse;
chan(tuple(int, chan(int))) alarm;
alloc kbd, mouse, term, alarm;
proc kbdproc(kbd, term), mouseproc(mouse, term),
alarmproc(alarm);
task kbdtask(kbd), mousetask(mouse, alarm);
<-term; /* main thread blocks here */
postnote(PNPROC, mousepid, "kill");
postnote(PNPROC, kbdpid, "kill");
postnote(PNPROC, alarmpid, "kill");
exits(nil);
}
chan(int)[100] ch[2];
alloc ch[0], ch[1];
adt Mevent {
Point;
int buttons;
int fill(*Mevent, byte*, int);
};
adt Mouse {
Mevent;
extern chan(Mevent) ch;
chan(int) term;
int fd;
int pid;
Mouse* init(byte*, chan(int));
void close(*Mouse);
intern void mproc(*Mouse);
};
adt Keyboard {
extern chan(int)[100] ch;
chan(int) term;
int kbdfd;
int ctlfd;
int pid;
Keyboard* init(byte*, chan(int));
void close(*Keyboard);
int ctl(*Keyboard, byte*);
intern void kproc(*Keyboard);
};
int
Mevent.fill(Mevent *m, byte *buf, int n)
{
if(n < 10)
return 0;
/* decode 'buf' into 'm' */
return 1;
}
Mouse*
Mouse.init(byte *device, chan(int) term)
{
Mouse *m;
alloc m;
m->fd = open(device, OREAD);
if(m->fd < 0) {
unalloc m;
return nil;
}
alloc m->ch;
m->term = term;
proc m->mproc();
return m;
}
void
Mouse.close(Mouse *m)
{
if(m->pid)
postnote(PNPROC, m->pid, "kill");
}
void
Mouse.mproc(Mouse *m)
{
int n;
byte buf[1024];
m->pid = getpid();
for(;;) {
n = read(m->fd, buf, sizeof(buf));
if(n < 0) {
m->term <-= -1;
continue;
}
if(m->fill(buf, n))
m->ch <-= m->Mevent;
}
}
proc m->mproc();
Keyboard*
Keyboard.init(byte *device, chan(int) term)
{
Keyboard *k;
byte buf[128];
alloc k;
k->kbdfd = open(device, OREAD);
if(k->kbdfd < 0) {
unalloc k;
return nil;
}
sprint(buf, "%sctl", device);
k->ctlfd = open(buf, OWRITE);
if(k->ctlfd < 0) {
unalloc k;
close(k->kbdfd);
return nil;
}
alloc k->ch;
k->term = term;
k->ctl("rawon");
proc k->kproc();
return k;
}
void
Keyboard.kproc(Keyboard *k)
{
byte c;
int n;
k->pid = getpid();
for(;;) {
n = read(k->kbdfd, &c, 1);
if(n <= 0 || c == EOF) {
k->term <-= -1;
continue;
}
n = processinput(c);
if(n)
k->ch <-= n;
}
}
void
Keyboard.close(Keyboard *k)
{
if(k->pid)
postnote(PNPROC, k->pid, "kill");
}
int
Keyboard.ctl(Keyboard *k, byte *msg)
{
return write(k->ctlfd, msg, strlen(msg));
}
Keyboard k, *kp;
k.ctl("rawon");
kp->ctl("rawon");
void
main(void)
{
Mouse *m;
Keyboard *k;
chan(tuple(int, chan(int))) alarm;
chan(int) term;
alloc term, alarm;
m = .Mouse.init("/dev/mouse", term);
if(m == nil)
exits("mouse");
k = .Keyboard.init("/dev/cons", term);
if(k == nil) {
m->close();
exits("keyboard");
}
proc alarmproc(alarm);
task kbdtask(k->ch), mousetask(m->ch, alarm);
<-term; /* main thread blocks here */
k->close();
m->close();
postnote(PNPROC, alarmpid, "kill");
exits(nil);
}
n = write(-1, buf, len);
check n == len, "write error";
test.l:7:main() write error, errstr(file not open)
void (*ALEFcheck)(byte*, byte*);
byte*
findfile(byte *dirname, byte *string)
{
int n, dirfd, fd;
byte *buf, buf2[512];
Dir d;
n = strlen(string);
buf = malloc(n);
rescue {
unalloc buf;
return nil;
}
dirfd = open(dirname, OREAD);
if(dirfd < 0)
raise;
rescue closedir{
close(dirfd);
raise;
}
while(dirread(dirfd, &d, sizeof(d)) == DIRLEN) {
sprint(buf2, "%s/%s", dirname, d.name);
fd = open(buf2, OREAD);
if(fd < 0)
continue;
rescue {
close(fd);
continue;
}
if(read(fd, buf, n) <= 0)
raise;
close(fd);
if(strncmp(buf, string, n) == 0) {
close(dirfd);
unalloc buf;
buf = malloc(strlen(d.name)+1);
strcpy(buf, d.name);
return buf;
}
}
werrstr("no match");
raise closedir;
return nil; /* needed to fool compiler */
}
par {
statement 1;
statement 2;
...
statement n;
}
void
main(int, byte **argv)
{
byte *active, *passive;
int fd, n;
fd = open(argv[1], OREAD);
check fd >= 0, "open error";
active = malloc(BUFSIZE);
passive = malloc(BUFSIZE);
n = decode(fd, active, BUFSIZE); /* first block */
check n > 0, "read error";
while(active != nil) {
par {
display(active, BUFSIZE);
if(decode(fd, passive, BUFSIZE) <= 0)
passive = nil;
}
(active, passive) = (passive, active);
waitforinput();
}
}
typedef byte* Ptrs[5];
byte **p;
int *ip;
Ptrs *c;
alloc p, ip, c;
alloc *c[0], *c[1], *c[2], *c[3], *c[4];
alloc c, *c[0], *c[1], *c[2], *c[3], *c[4];
alloc c, *c[0::5];
int i, a[10];
a[i=0::10] = i;
print("%d ", a[0::10]);
typedef float Matrix[4][4];
void mul(Matrix r, Matrix a, Matrix b){
int i, j, k;
r[0::4][0::4] = 0;
r[i=0::4][j=0::4] += a[i][k=0::4]*b[k][j];
}
<unguarded code>
!{
<code in guarded block>
}
<unguarded code>
intern int fd = -1;
int
time()
{
int t;
byte b[20];
memset(b, 0, sizeof(b));
if(fd < 0)
fd = open("/dev/time", OREAD|OCEXEC);
if(fd >= 0) {
seek(fd, 0, 0);
read(fd, b, sizeof(b));
}
t = atoi(b);
return t;
}
if(fd >= 0) !{
seek(fd, 0, 0);
read(fd, b, sizeof(b));
}
!{
if(fd < 0)
fd = open("/dev/time", OREAD|OCEXEC);
if(fd >= 0) {
seek(fd, 0, 0);
read(fd, b, sizeof(b));
}
}
int
avg(int n, ...)
{
int i, tot;
tot = 0;
for(i = 0; i < n; i++)
tot += ((int*)...)[i];
return tot/n;
}
byte *argv0;
void
fatal(byte *fmt, ...)
{
byte buf[1024], *p;
p = doprint(buf, buf+sizeof(buf), fmt, ...);
*p = 0;
fprint(2, "%s: %s\n", argv0, buf);
exits(buf);
}
void stateA(chan(int));
void stateB(chan(int));
void stateC(chan(int));
int readcpid;
void
readc(chan(int) c)
{
int fd, fd2;
byte ch;
readcpid = getpid();
fd = open("/dev/cons", OREAD);
fd2 = open("/dev/consctl", OWRITE);
check fd >= 0 && fd2 >= 0, "keyboard open";
write(fd2, "rawon", 5);
for(;;) {
check read(fd, &ch, 1) == 1, "read error";
c <-= ch;
}
}
void
stateA(chan(int) c)
{
print("A");
switch(<-c) {
default:
case '1': become stateA(c);
case '2': become stateB(c);
case '3': become stateC(c);
}
}
void
stateB(chan(int) c)
{
print("B");
switch(<-c) {
default:
case '3':
case '1': become stateB(c);
case '2': become stateA(c);
}
}
void
stateC(chan(int) c)
{
print("C");
switch(<-c) {
default: become stateC(c);
case '1': become stateA(c);
case '2': become stateB(c);
case '3': print("\n"); /* terminal state */
break;
}
if(readcpid)
postnote(PNPROC,readcpid, "kill");
exits(nil);
}
void
main(void)
{
chan(int) c;
alloc c;
proc readc(c);
stateA(c);
}
void
main(int, byte**)
{
...
}