proc.red 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. module proc; % Procedure statement.
  2. % Author: Anthony C. Hearn.
  3. % Copyright (c) 1991 RAND. All rights reserved.
  4. fluid '(!*nosmacros !*redeflg!* fname!* ftype!*);
  5. global '(!*argnochk !*comp !*lose !*micro!-version cursym!* erfg!*
  6. ftypes!*);
  7. fluid '(!*defn);
  8. !*lose := t;
  9. ftypes!* := '(expr fexpr macro);
  10. symbolic procedure mkprogn(u,v);
  11. if eqcar(v,'progn) then 'progn . u . cdr v else list('progn,u,v);
  12. symbolic procedure formproc(u,vars,mode);
  13. begin scalar body,fname!*,name,type,varlis,x,y;
  14. u := cdr u;
  15. name := fname!* := car u;
  16. if cadr u then mode := cadr u; % overwrite previous mode
  17. u := cddr u;
  18. type := ftype!* := car u;
  19. if flagp(name,'lose) and (!*lose or null !*defn)
  20. then return progn(lprim list(name,
  21. "not defined (LOSE flag)"),
  22. nil)
  23. else if !*redeflg!* and getd name
  24. then lprim list(name,"redefined");
  25. varlis := cadr u;
  26. u := caddr u;
  27. x := if eqcar(u,'rblock) then cadr u else nil;
  28. y := pairxvars(varlis,x,vars,mode);
  29. if x then u := car u . rplaca!*(cdr u,cdr y);
  30. body:= form1(u,car y,mode); % FORMC here would add REVAL.
  31. if !*nosmacros and type eq 'smacro then type := 'expr;
  32. if not(type eq 'smacro) and get(name,'smacro)
  33. then lprim list("SMACRO",name,"redefined");
  34. symbvarlst(varlis,body,mode);
  35. if type eq 'expr then body := list('de,name,varlis,body)
  36. else if type eq 'fexpr then body := list('df,name,varlis,body)
  37. else if type eq 'macro then body := list('dm,name,varlis,body)
  38. else if (x := get(type,'procfn))
  39. then return apply3(x,name,varlis,body)
  40. else body := list('putc,
  41. mkquote name,
  42. mkquote type,
  43. mkquote list('lambda,varlis,body));
  44. if not(mode eq 'symbolic)
  45. then body :=
  46. mkprogn(list('flag,mkquote list name,mkquote 'opfn),body);
  47. if !*argnochk and type memq '(expr smacro)
  48. then body := mkprogn(list('put,mkquote name,
  49. mkquote 'number!-of!-args,
  50. length varlis),
  51. body);
  52. if !*defn and type memq '(fexpr macro smacro)
  53. then lispeval body;
  54. return if !*micro!-version and type memq '(fexpr macro smacro)
  55. then nil
  56. else body
  57. end;
  58. put('procedure,'formfn,'formproc);
  59. symbolic procedure pairxvars(u,v,vars,mode);
  60. %Pairs procedure variables and their modes, taking into account
  61. %the convention which allows a top level prog to change the mode
  62. %of such a variable;
  63. begin scalar x,y;
  64. a: if null u then return append(reversip!* x,vars) . v
  65. else if (y := atsoc(car u,v))
  66. then <<v := delete(y,v);
  67. if not(cdr y eq 'scalar) then x := (car u . cdr y) . x
  68. else x := (car u . mode) . x>>
  69. else if null idp car u or get(car u,'infix) or get(car u,'stat)
  70. then symerr(list("Invalid parameter:",car u),nil)
  71. else x := (car u . mode) . x;
  72. u := cdr u;
  73. go to a
  74. end;
  75. symbolic procedure procstat1 mode;
  76. begin scalar bool,u,type,x,y,z;
  77. bool := erfg!*;
  78. if fname!* then progn(bool := t, go to a5)
  79. else if cursym!* eq 'procedure then type := 'expr
  80. else progn(type := cursym!*,scan());
  81. if not(cursym!* eq 'procedure) then go to a5;
  82. if !*reduce4 then go to a1;
  83. x := errorset!*('(xread (quote proc)),nil);
  84. if errorp x then go to a3
  85. else if atom (x := car x) then x := list x; % No arguments.
  86. fname!* := car x; % Function name.
  87. if idp fname!* % and null(type memq ftypes!*)
  88. and (null fname!*
  89. or (z := gettype fname!*)
  90. and null(z memq '(procedure operator)))
  91. then progn(typerr(list(z,fname!*),"procedure"), go to a3);
  92. u := cdr x;
  93. y := u; % Variable list.
  94. if idlistp y then x := car x . y
  95. else lprie list(y,"invalid as parameter list");
  96. go to a2;
  97. a1: fname!* := scan();
  98. if not idp fname!*
  99. then progn(typerr(fname!*,"procedure name"), go to a3);
  100. scan();
  101. y := errorset!*(list('read_param_list,mkquote mode),nil);
  102. if errorp y then go to a3;
  103. y := car y;
  104. if cursym!* eq '!*colon!* then mode := read_type();
  105. a2: if idp fname!* and not getd fname!* then flag(list fname!*,'fnc);
  106. % To prevent invalid use of function name in body.
  107. a3: if eof!*>0 then progn(cursym!* := '!*semicol!*, go to a4);
  108. z := errorset!*('(xread t),nil);
  109. if not errorp z then z := car z;
  110. % if not atom z and eqcar(car z,'!*comment!*) then z := cadr z;
  111. if null erfg!*
  112. then z :=
  113. list('procedure,if null !*reduce4 then car x else fname!*,
  114. mode,type,y,z);
  115. a4: remflag(list fname!*,'fnc);
  116. fname!* := nil;
  117. if erfg!* then progn(z := nil,if not bool then error1());
  118. return z;
  119. a5: errorset!*('(symerr (quote procedure) t),nil);
  120. go to a3
  121. end;
  122. symbolic procedure procstat; procstat1 nil;
  123. deflist ('((procedure procstat) (expr procstat) (fexpr procstat)
  124. (emb procstat) (macro procstat) (smacro procstat)),
  125. 'stat);
  126. % Next line refers to bootstrapping process.
  127. if get('symbolic,'stat) eq 'procstat then remprop('symbolic,'stat);
  128. deflist('((lisp symbolic)),'newnam);
  129. endmodule;
  130. end;