module block; % Block statement and related operators.
% Author: Anthony C. Hearn.
% Copyright (c) 1993 RAND. All rights reserved.
fluid '(!*blockp !*novarmsg !*rlisp88);
global '(!*vars!* cursym!* nxtsym!*);
flag('(novarmsg),'switch);
% ***** GO statement *****
symbolic procedure gostat;
begin scalar var;
var := if eq(scan(),'to) then scan() else cursym!*;
scan();
return list('go,var)
end;
put('go,'stat,'gostat);
put('goto,'newnam,'go);
% ***** Declaration Statement *****
symbolic procedure decl u;
begin scalar varlis,w;
a: if cursym!* eq '!*semicol!* then go to c
else if cursym!* eq 'local and !*reduce4 then nil
else if not flagp(cursym!*,'type) then return varlis
else if !*reduce4 then typerr(cursym!*,"local declaration");
w := cursym!*;
scan();
if null !*reduce4
then if cursym!* eq 'procedure then return procstat1 w
else varlis
:= append(varlis,pairvars(remcomma xread1 nil,nil,w))
else varlis := append(varlis,read_param_list nil);
if not(cursym!* eq '!*semicol!*) or null u then symerr(nil,t);
c: scan();
go to a
end;
put('integer,'initvalue!*,0);
symbolic procedure decstat;
% Called if a declaration occurs at the top level or not first
% in a block.
begin scalar x,y,z;
if !*blockp then symerr('block,t);
x := cursym!*;
y := nxtsym!*;
z := decl nil;
if y neq 'procedure
then rerror('rlisp,7,list(x,"invalid outside block"));
return z
end;
flag('(integer real scalar),'type);
symbolic procedure blocktyperr u;
% Type declaration found at wrong position.
rerror('rlisp,8,list(u,"invalid except at head of block"));
% ***** Block Statement *****
symbolic procedure mapovercar u;
begin scalar x;
a: if u then progn(x := caar u . x, u := cdr u, go to a);
return reversip!* x
end;
symbolic procedure blockstat;
begin scalar hold,varlis,x,!*blockp;
!*blockp := t;
scan();
if cursym!* memq '(nil !*rpar!*)
then rerror('rlisp,9,"BEGIN invalid");
varlis := decl t;
a: if cursym!* eq 'end and not(nxtsym!* eq '!:) then go to b;
x := xread1 nil;
if eqcar(x,'end) then go to c;
not(cursym!* eq 'end) and scan();
if x
then progn((if eqcar(x,'equal)
then lprim list("top level",cadr x,"= ... in block")),
hold := aconc!*(hold,x));
go to a;
b: comm1 'end;
c: return mkblock(varlis,hold)
end;
symbolic procedure mkblock(u,v); 'rblock . (u . v);
putd('rblock,'macro,
'(lambda (u) (cons 'prog (cons (mapovercar (cadr u)) (cddr u)))));
symbolic procedure symbvarlst(vars,body,mode);
begin scalar x,y;
if null(mode eq 'symbolic) then return nil;
y := vars;
a: if null y then return nil;
x := if pairp car y then caar y else car y;
if not fluidp x and not globalp x and not smemq(x,body)
and not !*novarmsg
then lprim list("local variable",x,"in procedure",
fname!*,"not used");
y := cdr y;
go to a
end;
symbolic procedure formblock(u,vars,mode);
progn(symbvarlst(cadr u,cddr u,mode),
'prog . append(initprogvars cadr u,
formprog1(cddr u,append(cadr u,vars),mode)));
symbolic procedure initprogvars u;
begin scalar x,y,z;
a: if null u then return(reversip!* x . reversip!* y)
else if (z := get(caar u,'initvalue!*))
or (z := get(cdar u,'initvalue!*))
then y := mksetq(caar u,z) . y;
x := caar u . x;
u := cdr u;
go to a
end;
symbolic procedure formprog(u,vars,mode);
'prog . cadr u . formprog1(cddr u,pairvars(cadr u,vars,mode),mode);
symbolic procedure formprog1(u,vars,mode);
if null u then nil
else if null car u then formprog1(cdr u,vars,mode)
% remove spurious NILs, probably generated by FOR statements.
else if atom car u then car u . formprog1(cdr u,vars,mode)
else if idp caar u and flagp(caar u,'modefn)
then if !*rlisp88 and null(caar u eq 'symbolic)
then typerr("algebraic expression","Rlisp88 form")
else formc(cadar u,vars,caar u) . formprog1(cdr u,vars,mode)
else formc(car u,vars,mode) . formprog1(cdr u,vars,mode);
put('rblock,'formfn,'formblock);
put('prog,'formfn,'formprog);
put('begin,'stat,'blockstat);
% ***** Return Statement *****
symbolic procedure retstat;
if not !*blockp then symerr(nil,t)
else begin scalar !*blockp; % To prevent RETURN within a RETURN.
return list('return,
if flagp(scan(),'delim) then nil else xread1 t)
end;
put('return,'stat,'retstat);
endmodule;
end;