ref: 05d9123a707dec0eaa0ab079b94e69cdb750c6db
dir: /appl/alphabet/proxy.b/
implement Proxy;
include "sys.m";
sys: Sys;
include "draw.m";
include "sh.m";
include "alphabet/reports.m";
include "alphabet.m";
Debug: con 0;
proxy[Ctxt,Cvt,M,V,EV](ctxt: Ctxt): (
chan of ref Typescmd[EV],
chan of (string, chan of ref Typescmd[V])
) for {
M =>
typesig: fn(m: self M): string;
run: fn(m: self M, ctxt: ref Draw->Context, r: ref Reports->Report, errorc: chan of string,
opts: list of (int, list of V), args: list of V): V;
quit: fn(m: self M);
Ctxt =>
loadtypes: fn(ctxt: self Ctxt, name: string): (chan of ref Proxy->Typescmd[V], string);
type2s: fn(ctxt: self Ctxt, tc: int): string;
alphabet: fn(ctxt: self Ctxt): string;
modules: fn(ctxt: self Ctxt, r: chan of string);
find: fn(ctxt: self Ctxt, s: string): (M, string);
getcvt: fn(ctxt: self Ctxt): Cvt;
Cvt =>
int2ext: fn(cvt: self Cvt, v: V): EV;
ext2int: fn(cvt: self Cvt, ev: EV): V;
free: fn(cvt: self Cvt, v: EV, used: int);
dup: fn(cvt: self Cvt, v: EV): EV;
}
{
sys = load Sys Sys->PATH;
t := chan of ref Typescmd[EV];
newts := chan of (string, chan of ref Typescmd[V]);
spawn proxyproc(ctxt, t, newts);
return (t, newts);
}
proxyproc[Ctxt,Cvt,M,V,EV](
ctxt: Ctxt,
t: chan of ref Typescmd[EV],
newts: chan of (string, chan of ref Typescmd[V])
)
for{
M =>
typesig: fn(m: self M): string;
run: fn(m: self M, ctxt: ref Draw->Context, r: ref Reports->Report, errorc: chan of string,
opts: list of (int, list of V), args: list of V): V;
quit: fn(m: self M);
Ctxt =>
loadtypes: fn(ctxt: self Ctxt, name: string): (chan of ref Proxy->Typescmd[V], string);
type2s: fn(ctxt: self Ctxt, tc: int): string;
alphabet: fn(ctxt: self Ctxt): string;
modules: fn(ctxt: self Ctxt, r: chan of string);
find: fn(ctxt: self Ctxt, s: string): (M, string);
getcvt: fn(ctxt: self Ctxt): Cvt;
Cvt =>
int2ext: fn(cvt: self Cvt, v: V): EV;
ext2int: fn(cvt: self Cvt, ev: EV): V;
free: fn(cvt: self Cvt, v: EV, used: int);
dup: fn(cvt: self Cvt, v: EV): EV;
}
{
typesets: list of (string, chan of ref Typescmd[V]);
cvt := ctxt.getcvt();
for(;;)alt{
gr := <-t =>
if(gr == nil){
for(; typesets != nil; typesets = tl typesets)
(hd typesets).t1 <-= nil;
exit;
}
pick r := gr {
Load =>
(m, err) := ctxt.find(r.cmd);
if(m == nil){
r.reply <-= (nil, err);
}else{
c := chan of ref Modulecmd[EV];
spawn modproxyproc(cvt, m, c);
r.reply <-= (c, nil);
}
Alphabet =>
r.reply <-= ctxt.alphabet();
Free =>
cvt.free(r.v, r.used);
r.reply <-= 0;
Dup =>
r.reply <-= cvt.dup(r.v);
Type2s =>
r.reply <-= ctxt.type2s(r.tc);
Loadtypes =>
ts := typesets;
typesets = nil;
c: chan of ref Typescmd[V];
for(; ts != nil; ts = tl ts){
if((hd ts).t0 == r.name)
c = (hd ts).t1;
else
typesets = hd ts :: typesets;
}
err: string;
if(c == nil)
(c, err) = ctxt.loadtypes(r.name);
if(c == nil)
r.reply <-= (nil, err);
else{
et := chan of ref Typescmd[EV];
spawn extproxyproc(ctxt, ctxt.alphabet(), c, et);
r.reply <-= (et, nil);
}
Modules =>
spawn ctxt.modules(r.reply);
* =>
sys->fprint(sys->fildes(2), "unknown type of proxy request %d\n", tagof gr);
raise "unknown type proxy request";
}
typesets = <-newts :: typesets =>
;
}
}
modproxyproc[Cvt,V,EV,M](cvt: Cvt, m: M, c: chan of ref Modulecmd[EV])
for{
M =>
typesig: fn(m: self M): string;
run: fn(m: self M, ctxt: ref Draw->Context, r: ref Reports->Report, errorc: chan of string,
opts: list of (int, list of V), args: list of V): V;
quit: fn(m: self M);
Cvt =>
int2ext: fn(cvt: self Cvt, v: V): EV;
ext2int: fn(cvt: self Cvt, ev: EV): V;
free: fn(cvt: self Cvt, ev: EV, used: int);
}
{
while((gr := <-c) != nil){
pick r := gr {
Typesig =>
r.reply <-= m.typesig();
Run =>
# XXX could start (or invoke) a new process so that we don't potentially
# block concurrency while we're starting the command.
{
iopts: list of (int, list of V);
for(o := r.opts; o != nil; o = tl o){
il := extlist2intlist(cvt, (hd o).t1);
iopts = ((hd o).t0, il) :: iopts;
}
iopts = revip(iopts);
v := cvt.int2ext(m.run(r.ctxt, r.report, r.errorc, iopts, extlist2intlist(cvt, r.args)));
free(cvt, r.opts, r.args, v != nil);
r.reply <-= v;
} exception {
"type error" =>
if(Debug)
sys->fprint(sys->fildes(2), "error: type conversion failed");
if(r.errorc != nil)
r.errorc <-= "error: type conversion failed";
r.reply <-= nil;
}
}
}
m.quit();
}
extproxyproc[Ctxt,Cvt,V,EV](ctxt: Ctxt, alphabet: string, t: chan of ref Typescmd[V], et: chan of ref Typescmd[EV])
for{
Ctxt =>
type2s: fn(ctxt: self Ctxt, tc: int): string;
getcvt: fn(ctxt: self Ctxt): Cvt;
Cvt =>
int2ext: fn(cvt: self Cvt, v: V): EV;
ext2int: fn(cvt: self Cvt, ev: EV): V;
free: fn(cvt: self Cvt, ev: EV, used: int);
dup: fn(cvt: self Cvt, ev: EV): EV;
}
{
cvt := ctxt.getcvt();
for(;;){
gr := <-et;
if(gr == nil)
break;
pick r := gr {
Load =>
reply := chan of (chan of ref Modulecmd[V], string);
t <-= ref Typescmd[V].Load(r.cmd, reply);
(c, err) := <-reply;
if(c == nil){
r.reply <-= (nil, err);
}else{
ec := chan of ref Modulecmd[EV];
spawn extmodproxyproc(cvt, c, ec);
r.reply <-= (ec, nil);
}
Alphabet =>
t <-= ref Typescmd[V].Alphabet(r.reply);
Free =>
cvt.free(r.v, r.used);
Dup =>
r.reply <-= cvt.dup(r.v);
Type2s =>
for(i := 0; i < len alphabet; i++)
if(alphabet[i] == r.tc)
break;
if(i == len alphabet)
t <-= ref Typescmd[V].Type2s(r.tc, r.reply);
else
r.reply <-= ctxt.type2s(r.tc);
Loadtypes =>
reply := chan of (chan of ref Typescmd[V], string);
t <-= ref Typescmd[V].Loadtypes(r.name, reply);
(c, err) := <-reply;
if(c == nil)
r.reply <-= (nil, err);
else{
t <-= ref Typescmd[V].Alphabet(areply := chan of string);
ec := chan of ref Typescmd[EV];
spawn extproxyproc(ctxt, <-areply, c, ec);
r.reply <-= (ec, nil);
}
Modules =>
t <-= ref Typescmd[V].Modules(r.reply);
* =>
sys->fprint(sys->fildes(2), "unknown type of proxy request %d\n", tagof gr);
raise "unknown type proxy request";
}
}
et <-= nil;
}
extmodproxyproc[Cvt,V,EV](cvt: Cvt, c: chan of ref Modulecmd[V], ec: chan of ref Modulecmd[EV])
for{
Cvt =>
int2ext: fn(cvt: self Cvt, v: V): EV;
ext2int: fn(cvt: self Cvt, ev: EV): V;
free: fn(cvt: self Cvt, ev: EV, used: int);
}
{
while((gr := <-ec) != nil){
pick r := gr {
Typesig =>
c <-= ref Modulecmd[V].Typesig(r.reply);
Run =>
{
iopts: list of (int, list of V);
for(o := r.opts; o != nil; o = tl o){
il := extlist2intlist(cvt, (hd o).t1);
iopts = ((hd o).t0, il) :: iopts;
}
iopts = revip(iopts);
c <-= ref Modulecmd[V].Run(
r.ctxt,
r.report,
r.errorc,
iopts,
extlist2intlist(cvt, r.args),
reply := chan of V
);
v := cvt.int2ext(<-reply);
free(cvt, r.opts, r.args, v != nil);
r.reply <-= v;
}
}
}
}
revip[V](l: list of (int, V)): list of (int, V)
{
m: list of (int, V);
for(; l != nil; l = tl l)
m = hd l :: m;
return m;
}
extlist2intlist[V,EV,Cvt](cvt: Cvt, vl: list of EV): list of V
for{
Cvt =>
int2ext: fn(cvt: self Cvt, v: V): EV;
ext2int: fn(cvt: self Cvt, ev: EV): V;
}
{
l, m: list of V;
for(; vl != nil; vl = tl vl)
l = cvt.ext2int(hd vl) :: l;
for(; l != nil; l = tl l)
m = hd l :: m;
return m;
}
free[V,Cvt](cvt: Cvt, opts: list of (int, list of V), args: list of V, used: int)
for{
Cvt =>
free: fn(cvt: self Cvt, ev: V, used: int);
}
{
for(; args != nil; args = tl args)
cvt.free(hd args, used);
for(; opts != nil; opts = tl opts)
for(args = (hd opts).t1; args != nil; args = tl args)
cvt.free(hd args, used);
}