lspfor.red 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. module lspfor; %% GENTRAN LISP-to-FORTRAN Translation Module %%
  2. %% Author: Barbara L. Gates %%
  3. %% December 1986 %%
  4. % Updates:
  5. % M. Warns 7 Oct 89 Patch in FORTEXP1 for negative constant exponents
  6. % and integer arguments of functions like SQRT added.
  7. % M.C. Dewar and J.H. Davenport 8 Jan 88 Double precision etc. added.
  8. % Entry Point: FortCode
  9. symbolic$
  10. % To allow Fortran-90 Extensions:
  11. fluid '(!*f90)$
  12. switch f90$
  13. fluid '(!*gendecs)$
  14. switch gendecs$
  15. fluid '(!*getdecs)$
  16. fluid '(!*makecalls)$
  17. switch makecalls$
  18. !*makecalls := t$
  19. % User-Accessible Global Variables %
  20. global '(gentranlang!* fortlinelen!* minfortlinelen!*
  21. fortcurrind!* !*fortcurrind!* tablen!*)$
  22. share fortcurrind!*, fortlinelen!*, minfortlinelen!*, tablen!*$
  23. fortcurrind!* := 0$
  24. !*fortcurrind!* := 6$ %current level of indentation for FORTRAN code
  25. fortlinelen!* := 72$
  26. minfortlinelen!* := 40$
  27. % Double Precision Switch (defaults to OFF) - mcd 13/1/88 %
  28. fluid '(!*double);
  29. % !*double := t;
  30. switch double;
  31. % GENTRAN Global Variables %
  32. global '(!*notfortranfuns!* !*endofloopstack!* !*subprogname!*)$
  33. !*notfortranfuns!*:= '(acosh asinh atanh cot dilog ei erf sec)$
  34. %mcd 10/11/87
  35. !*endofloopstack!* := nil$
  36. !*subprogname!* := nil$ %name of subprogram being generated
  37. global '(!*do!* deftype!*)$
  38. % The following ought to be all the legal Fortran types mcd 19/11/87.
  39. global '(!*legalforttypes!*);
  40. !*legalforttypes!* := '(real integer complex real!*8 complex!*16 logical
  41. implicit! integer implicit! real
  42. implicit! complex implicit! real!*8
  43. implicit! complex!*16 implicit! logical)$
  44. global '(!*stdout!*)$
  45. global '(!*posn!* !$!#);
  46. %% %%
  47. %% LISP-to-FORTRAN Translation Functions %%
  48. %% %%
  49. put('fortran,'formatter,'formatfort);
  50. put('fortran,'codegen,'fortcode);
  51. put('fortran,'proctem,'procforttem);
  52. put('fortran,'gendecs,'fortdecs);
  53. put('fortran,'assigner,'mkffortassign);
  54. put('fortran,'boolean!-type,'logical);
  55. %% Control Function %%
  56. symbolic procedure fortcode forms;
  57. for each f in forms conc
  58. if atom f then
  59. fortexp f
  60. else if car f memq '(!:rd!: !:cr!: !:crn!: !:gi!:) then
  61. fortexp f
  62. else if lispstmtp f or lispstmtgpp f then
  63. if !*gendecs then
  64. begin
  65. scalar r;
  66. r := append(fortdecs symtabget('!*main!*, '!*decs!*),
  67. fortstmt f);
  68. symtabrem('!*main!*, '!*decs!*);
  69. return r
  70. end
  71. else
  72. fortstmt f
  73. else if lispdefp f then
  74. fortsubprog f
  75. else
  76. fortexp f$
  77. %% Subprogram Translation %%
  78. symbolic procedure fortsubprog deff;
  79. begin
  80. scalar type, stype, name, params, body, lastst, r;
  81. name := !*subprogname!* := cadr deff;
  82. if onep length (body := cdddr deff) and lispstmtgpp car body then
  83. << body := cdar body; if null car body then body := cdr body >>;
  84. if lispreturnp (lastst := car reverse body) then
  85. body := append(body, list '(end))
  86. else if not lispendp lastst then
  87. body := append(body, list('(return), '(end)));
  88. type := symtabget(name, name);
  89. if type then type := cadr type;
  90. stype := symtabget(name, '!*type!*) or
  91. ( if type or functionformp(body, name)
  92. then 'function
  93. else 'subroutine );
  94. symtabrem(name, '!*type!*);
  95. params := symtabget(name, '!*params!*) or caddr deff;
  96. symtabrem(name, '!*params!*);
  97. if !*getdecs and null type and stype eq 'function
  98. then type := deftype!*;
  99. if type then
  100. << symtabrem(name, name);
  101. % Generate the correct double precision type name - mcd 28/1/88 %
  102. if !*double then
  103. if type memq '(real real*8) then
  104. type := 'double! precision
  105. else if type eq 'complex then
  106. type := 'complex!*16;
  107. >>;
  108. r := mkffortsubprogdec(type, stype, name, params);
  109. if !*gendecs then
  110. r := append(r, fortdecs symtabget(name, '!*decs!*));
  111. r := append(r, for each s in body
  112. conc fortstmt s);
  113. if !*gendecs then
  114. << symtabrem(name, nil); symtabrem(name, '!*decs!*) >>;
  115. return r
  116. end$
  117. %% Generation of Declarations %%
  118. symbolic procedure fortdecs decs;
  119. for each tl in formtypelists decs
  120. conc mkffortdec(car tl, cdr tl)$
  121. %% Expression Translation %%
  122. procedure fortexp exp;
  123. fortexp1(exp, 0)$
  124. symbolic procedure fortexp1(exp, wtin);
  125. if atom exp then
  126. list fortranname exp
  127. else
  128. if listp exp and onep length exp then
  129. fortranname exp
  130. else if optype car exp then
  131. begin
  132. scalar wt, op, res;
  133. wt := fortranprecedence car exp;
  134. op := fortranop car exp;
  135. exp := cdr exp;
  136. if onep length exp then
  137. res := op . fortexp1(car exp, wt)
  138. else
  139. <<
  140. res := fortexp1(car exp, wt);
  141. if op eq '!+ then
  142. while exp := cdr exp do
  143. <<
  144. if atom car exp or caar exp neq 'minus then
  145. res := append(res, list op);
  146. res := append(res, fortexp1(car exp, wt))
  147. >>
  148. else if op eq '!*!* then
  149. while exp := cdr exp do
  150. begin
  151. if numberp car exp and lessp(car exp, 0) then
  152. res := append(append(res, list op),
  153. insertparens fortexp1(car exp, wt))
  154. else
  155. res := append(append(res, list op),
  156. fortexp1(car exp, wt))
  157. end
  158. else
  159. while exp := cdr exp do
  160. res := append(append(res, list op),
  161. fortexp1(car exp, wt))
  162. >>;
  163. if wtin >= wt then res := insertparens res;
  164. return res
  165. end
  166. else if car exp eq 'literal then
  167. fortliteral exp
  168. else if car exp eq 'range
  169. then append(fortexp cadr exp,'!: . fortexp caddr exp)
  170. else if car exp eq '!:rd!: then
  171. if smallfloatp cdr exp then
  172. list cdr exp
  173. else
  174. begin scalar mt; % Print bigfloats more naturally. MCD 26/2/90
  175. integer dotpos,!:lower!-sci!:,!:upper!-sci!:;
  176. % This forces most numbers to exponential format.
  177. mt := rd!:explode exp;
  178. exp := car mt;
  179. mt := cadr mt + caddr mt - 1;
  180. exp := append(list('literal,car exp, '!.),cdr exp);
  181. if null (mt = 0) then
  182. exp := append(exp,
  183. list(if !*double then '!D else '!E,mt))
  184. else if !*double then
  185. exp := append(exp,'(!D 0));
  186. return fortliteral exp;
  187. end
  188. else if car exp eq '!:crn!: then
  189. fortexp1(!*crn2cr exp,wtin)
  190. else if car exp eq '!:gi!: then
  191. fortexp1(!*gi2cr exp,wtin)
  192. else if car exp eq '!:cr!: then
  193. if !*double and !*f90 then
  194. ('CMPLX!().append(fortexp1(cons('!:rd!:,cadr exp),wtin),
  195. ('!,).append(fortexp1(cons('!:rd!:,cddr exp),wtin),
  196. list( '!, , 'KIND!(!1!.!0!D!0!) , '!) ))
  197. )
  198. else
  199. ('CMPLX!().append(fortexp1(cons('!:rd!:,cadr exp),wtin),
  200. ('!,).append(fortexp1(cons('!:rd!:,cddr exp),wtin),
  201. list '!)))
  202. % We must make this list up at run time, since there's
  203. % a CONC loop that relies on being able to RPLAC into it.
  204. % Yuck. JHD/MCD 19.6.89
  205. else
  206. begin scalar op, res, intrinsic;
  207. intrinsic := get(car exp, '!*fortranname!*);
  208. op := fortranname car exp;
  209. exp := cdr exp;
  210. % Make the arguments of intrinsic functions real if we aren't
  211. % sure. Note that we can't simply evaluate the argument and
  212. % test that, unless it is a constant. MCD 7/11/89.
  213. res := cdr foreach u in exp conc
  214. '!, . if not intrinsic then
  215. fortexp1(u,0)
  216. else if fixp u then
  217. list float u
  218. else if isfloat u or memq(op,'(real dble)) then
  219. fortexp1(u,0)
  220. else
  221. (fortranname 'real . insertparens fortexp1(u,0));
  222. return op . insertparens res
  223. end;
  224. symbolic procedure isfloat u;
  225. % Returns T if u is a float or a list whose car is an intrinsic
  226. % function name. MCD 7/11/89.
  227. floatp(u) or (idp u and declared!-as!-float(u) ) or
  228. pairp(u) and (car u eq '!:rd!: or
  229. get(car u,'!*fortranname!*) or
  230. declared!-as!-float(car u) );
  231. procedure fortranop op;
  232. get(op, '!*fortranop!*) or op$
  233. put('or, '!*fortranop!*, '!.or!. )$
  234. put('and, '!*fortranop!*, '!.and!.)$
  235. put('not, '!*fortranop!*, '!.not!.)$
  236. put('equal, '!*fortranop!*, '!.eq!. )$
  237. put('neq, '!*fortranop!*, '!.ne!. )$
  238. put('greaterp, '!*fortranop!*, '!.gt!. )$
  239. put('geq, '!*fortranop!*, '!.ge!. )$
  240. put('lessp, '!*fortranop!*, '!.lt!. )$
  241. put('leq, '!*fortranop!*, '!.le!. )$
  242. put('plus, '!*fortranop!*, '!+ )$
  243. put('times, '!*fortranop!*, '!* )$
  244. put('quotient, '!*fortranop!*, '/ )$
  245. put('minus, '!*fortranop!*, '!- )$
  246. put('expt, '!*fortranop!*, '!*!* )$
  247. % This procedure (and FORTRANNAME, RATFORNAME properties, and
  248. % the DOUBLE flag) are shared between FORTRAN and RATFOR
  249. procedure fortranname a; % Amended mcd 10/11/87
  250. if stringp a then
  251. stringtoatom a % convert a to atom containing "'s
  252. else
  253. << if a memq !*notfortranfuns!* then
  254. << wrs cdr !*stdout!*;
  255. prin2 "*** WARNING: ";
  256. prin1 a;
  257. prin2t " is not an intrinsic Fortran function";
  258. >>$
  259. if !*double then
  260. get(a, '!*doublename!*) or a
  261. else
  262. get(a, '!*fortranname!*) or a
  263. >>$
  264. put('true, '!*fortranname!*, '!.true!. )$
  265. put('false, '!*fortranname!*, '!.false!.)$
  266. %% mcd 10/11/87
  267. %% Reduce functions' equivalent Fortran 77 real function names
  268. put('abs,'!*fortranname!*, 'abs)$
  269. put('sqrt,'!*fortranname!*, 'sqrt)$
  270. put('exp,'!*fortranname!*, 'exp)$
  271. put('log,'!*fortranname!*, 'alog)$
  272. put('ln,'!*fortranname!*, 'alog)$
  273. put('sin,'!*fortranname!*, 'sin)$
  274. put('cos,'!*fortranname!*, 'cos)$
  275. put('tan,'!*fortranname!*, 'tan)$
  276. put('acos,'!*fortranname!*, 'acos)$
  277. put('asin,'!*fortranname!*, 'asin)$
  278. put('atan,'!*fortranname!*, 'atan)$
  279. put('sinh,'!*fortranname!*, 'sinh)$
  280. put('cosh,'!*fortranname!*, 'cosh)$
  281. put('tanh,'!*fortranname!*, 'tanh)$
  282. put('real,'!*fortranname!*, 'real)$
  283. put('max,'!*fortranname!*, 'amax1)$
  284. put('min,'!*fortranname!*, 'amin1)$
  285. %% Reduce function's equivalent Fortran 77 double-precision names
  286. put('abs,'!*doublename!*, 'dabs)$
  287. put('sqrt,'!*doublename!*, 'dsqrt)$
  288. put('exp,'!*doublename!*, 'dexp)$
  289. put('log,'!*doublename!*, 'dlog)$
  290. put('ln,'!*doublename!*, 'dlog)$
  291. put('sin,'!*doublename!*, 'dsin)$
  292. put('cos,'!*doublename!*, 'dcos)$
  293. put('tan,'!*doublename!*, 'dtan)$
  294. put('acos,'!*doublename!*, 'dacos)$
  295. put('asin,'!*doublename!*, 'dasin)$
  296. put('atan,'!*doublename!*, 'datan)$
  297. put('sinh,'!*doublename!*, 'dsinh)$
  298. put('cosh,'!*doublename!*, 'dcosh)$
  299. put('tanh,'!*doublename!*, 'dtanh)$
  300. put('true, '!*doublename!*, '!.true!. )$
  301. put('false, '!*doublename!*, '!.false!.)$
  302. put('real,'!*doublename!*, 'dble)$
  303. put('max,' !*doublename!*, 'dmax1)$
  304. put('min, '!*doublename!*, 'dmin1)$
  305. %% end of mcd
  306. procedure fortranprecedence op;
  307. get(op, '!*fortranprecedence!*) or 9$
  308. put('or, '!*fortranprecedence!*, 1)$
  309. put('and, '!*fortranprecedence!*, 2)$
  310. put('not, '!*fortranprecedence!*, 3)$
  311. put('equal, '!*fortranprecedence!*, 4)$
  312. put('neq, '!*fortranprecedence!*, 4)$
  313. put('greaterp, '!*fortranprecedence!*, 4)$
  314. put('geq, '!*fortranprecedence!*, 4)$
  315. put('lessp, '!*fortranprecedence!*, 4)$
  316. put('leq, '!*fortranprecedence!*, 4)$
  317. put('plus, '!*fortranprecedence!*, 5)$
  318. put('times, '!*fortranprecedence!*, 6)$
  319. put('quotient, '!*fortranprecedence!*, 6)$
  320. put('minus, '!*fortranprecedence!*, 7)$
  321. put('expt, '!*fortranprecedence!*, 8)$
  322. %% Statement Translation %%
  323. procedure fortstmt stmt;
  324. if null stmt then
  325. nil
  326. else if lisplabelp stmt then
  327. fortstmtnum stmt
  328. else if car stmt eq 'literal then
  329. fortliteral stmt
  330. else if lispreadp stmt then
  331. fortread stmt
  332. else if lispassignp stmt then
  333. fortassign stmt
  334. else if lispprintp stmt then
  335. fortwrite stmt
  336. else if lispcondp stmt then
  337. fortif stmt
  338. else if lispbreakp stmt then
  339. fortbreak stmt
  340. else if lispgop stmt then
  341. fortgoto stmt
  342. else if lispreturnp stmt then
  343. fortreturn stmt
  344. else if lispstopp stmt then
  345. fortstop stmt
  346. else if lispendp stmt then
  347. fortend stmt
  348. else if lispwhilep stmt then
  349. fortwhile stmt
  350. else if lisprepeatp stmt then
  351. fortrepeat stmt
  352. else if lispforp stmt then
  353. fortfor stmt
  354. else if lispstmtgpp stmt then
  355. fortstmtgp stmt
  356. else if lispdefp stmt then
  357. fortsubprog stmt
  358. else if lispcallp stmt then
  359. fortcall stmt$
  360. procedure fortassign stmt;
  361. mkffortassign(cadr stmt, caddr stmt)$
  362. procedure fortbreak stmt;
  363. if null !*endofloopstack!* then
  364. gentranerr('e, nil, "BREAK NOT INSIDE LOOP - CANNOT BE TRANSLATED",
  365. nil)
  366. else if atom car !*endofloopstack!* then
  367. begin
  368. scalar n1;
  369. n1 := genstmtnum();
  370. rplaca(!*endofloopstack!*, list(car !*endofloopstack!*, n1));
  371. return mkffortgo n1
  372. end
  373. else
  374. mkffortgo cadar !*endofloopstack!*$
  375. procedure fortcall stmt;
  376. mkffortcall(car stmt, cdr stmt)$
  377. procedure fortfor stmt;
  378. begin
  379. scalar n1, result, var, loexp, stepexp, hiexp, stmtlst;
  380. var := cadr stmt;
  381. stmt := cddr stmt;
  382. loexp := caar stmt;
  383. stepexp := cadar stmt;
  384. hiexp := caddar stmt;
  385. stmtlst := cddr stmt;
  386. n1 := genstmtnum();
  387. !*endofloopstack!* := n1 . !*endofloopstack!*;
  388. result := mkffortdo(n1, var, loexp, hiexp, stepexp);
  389. indentfortlevel(+1);
  390. result := append(result, for each st in stmtlst conc fortstmt st);
  391. indentfortlevel(-1);
  392. result := append(result, mkffortcontinue n1);
  393. if pairp car !*endofloopstack!* then
  394. result := append(result, mkffortcontinue cadar !*endofloopstack!*);
  395. !*endofloopstack!* := cdr !*endofloopstack!*;
  396. return result
  397. end$
  398. procedure fortend stmt;
  399. mkffortend()$
  400. procedure fortgoto stmt;
  401. begin
  402. scalar stmtnum;
  403. if not ( stmtnum := get(cadr stmt, '!*stmtnum!*) ) then
  404. stmtnum := put(cadr stmt, '!*stmtnum!*, genstmtnum());
  405. return mkffortgo stmtnum
  406. end$
  407. symbolic procedure fortif stmt;
  408. begin scalar r, st;
  409. r := mkffortif caadr stmt;
  410. indentfortlevel(+1);
  411. st := seqtogp cdadr stmt;
  412. if eqcar(st, 'cond) and length st=2 then
  413. st := mkstmtgp(0, list st);
  414. r := append(r, fortstmt st);
  415. indentfortlevel(-1);
  416. stmt := cdr stmt;
  417. while (stmt := cdr stmt) and caar stmt neq t do
  418. <<
  419. r := append(r, mkffortelseif caar stmt);
  420. indentfortlevel(+1);
  421. st := seqtogp cdar stmt;
  422. if eqcar(st, 'cond) and length st=2 then
  423. st := mkstmtgp(0, list st);
  424. r := append(r, fortstmt st);
  425. indentfortlevel(-1)
  426. >>;
  427. if stmt then
  428. <<
  429. r := append(r, mkffortelse());
  430. indentfortlevel(+1);
  431. st := seqtogp cdar stmt;
  432. if eqcar(st, 'cond) and length st=2 then
  433. st := mkstmtgp(0, list st);
  434. r := append(r, fortstmt st);
  435. indentfortlevel(-1)
  436. >>;
  437. return append(r,mkffortendif());
  438. end$
  439. symbolic procedure mkffortif exp;
  440. append(append(list(mkforttab(), 'if, '! , '!(), fortexp exp),
  441. list('!),'! , 'then , mkfortterpri()))$
  442. symbolic procedure mkffortelseif exp;
  443. append(append(list(mkforttab(), 'else, '! , 'if, '! , '!(),
  444. fortexp exp),
  445. list('!), 'then, mkcterpri()))$
  446. symbolic procedure mkffortelse();
  447. list(mkforttab(), 'else, mkfortterpri())$
  448. symbolic procedure mkffortendif();
  449. list(mkforttab(), 'endif, mkfortterpri())$
  450. procedure fortliteral stmt;
  451. mkffortliteral cdr stmt$
  452. procedure fortread stmt;
  453. mkffortread cadr stmt$
  454. procedure fortrepeat stmt;
  455. begin
  456. scalar n, result, stmtlst, logexp;
  457. stmtlst := reverse cdr stmt;
  458. logexp := car stmtlst;
  459. stmtlst := reverse cdr stmtlst;
  460. n := genstmtnum();
  461. !*endofloopstack!* := 'dummy . !*endofloopstack!*;
  462. result := mkffortcontinue n;
  463. indentfortlevel(+1);
  464. result := append(result, for each st in stmtlst conc fortstmt st);
  465. indentfortlevel(-1);
  466. result := append(result, mkffortifgo(list('not, logexp), n));
  467. if pairp car !*endofloopstack!* then
  468. result := append(result, mkffortcontinue cadar !*endofloopstack!*);
  469. !*endofloopstack!* := cdr !*endofloopstack!*;
  470. return result
  471. end$
  472. procedure fortreturn stmt;
  473. if onep length stmt then
  474. mkffortreturn()
  475. else if !*subprogname!* then
  476. append(mkffortassign(!*subprogname!*, cadr stmt), mkffortreturn())
  477. else
  478. gentranerr('e, nil,
  479. "RETURN NOT INSIDE FUNCTION - CANNOT BE TRANSLATED",
  480. nil)$
  481. procedure fortstmtgp stmtgp;
  482. <<
  483. if car stmtgp eq 'progn then
  484. stmtgp := cdr stmtgp
  485. else
  486. stmtgp := cddr stmtgp;
  487. for each stmt in stmtgp conc fortstmt stmt
  488. >>$
  489. procedure fortstmtnum label;
  490. begin
  491. scalar stmtnum;
  492. if not ( stmtnum := get(label, '!*stmtnum!*) ) then
  493. stmtnum := put(label, '!*stmtnum!*, genstmtnum());
  494. return mkffortcontinue stmtnum
  495. end$
  496. procedure fortstop stmt;
  497. mkffortstop()$
  498. procedure fortwhile stmt;
  499. begin
  500. scalar n1, n2, result, logexp, stmtlst;
  501. logexp := cadr stmt;
  502. stmtlst := cddr stmt;
  503. n1 := genstmtnum();
  504. n2 := genstmtnum();
  505. !*endofloopstack!* := n2 . !*endofloopstack!*;
  506. result := append(list(n1, '! ), mkffortifgo(list('not, logexp), n2));
  507. indentfortlevel(+1);
  508. result := append(result, for each st in stmtlst conc fortstmt st);
  509. result := append(result, mkffortgo n1);
  510. indentfortlevel(-1);
  511. result := append(result, mkffortcontinue n2);
  512. if pairp car !*endofloopstack!* then
  513. result := append(result, mkffortcontinue cadar !*endofloopstack!*);
  514. !*endofloopstack!* := cdr !*endofloopstack!*;
  515. return result
  516. end$
  517. procedure fortwrite stmt;
  518. mkffortwrite cdr stmt$
  519. %% %%
  520. %% FORTRAN Code Formatting Functions %%
  521. %% %%
  522. %% Statement Formatting %%
  523. % A macro used to prevent things with *fortranname* or *doublename*
  524. % properties being evaluated in certain circumstances. MCD 28.3.94
  525. symbolic smacro procedure fortexp_name(u);
  526. if atom u then list(u)
  527. else rplaca(fortexp ('dummyArrayToken . cdr u), car u)$
  528. symbolic procedure mkffortassign(lhs, rhs);
  529. append(append(mkforttab() . fortexp_name lhs, '!= . fortexp rhs),
  530. list mkfortterpri())$
  531. symbolic procedure mkffortcall(fname, params);
  532. % Installed the switch makecalls 18/11/88 mcd.
  533. <<
  534. if params then
  535. params := append(append(list '!(,
  536. for each p in insertcommas params
  537. conc fortexp p),
  538. list '!));
  539. % If we want to generate bits of statements, then what might
  540. % appear a subroutine call may in fact be a function reference.
  541. if !*makecalls then
  542. append(append(list(mkforttab(), 'call, '! ), fortexp fname),
  543. append(params, list mkfortterpri()))
  544. else
  545. append(fortexp fname,params)
  546. >>$
  547. procedure mkffortcontinue stmtnum;
  548. list(stmtnum, '! , mkforttab(), 'continue, mkfortterpri())$
  549. symbolic procedure mkffortdec(type, varlist); %Ammended mcd 13/11/87
  550. <<
  551. if type equal 'scalar then type := deftype!*;
  552. if type and null (type memq !*legalforttypes!*) then
  553. gentranerr('e,type,"Illegal Fortran type. ",nil);
  554. type := type or 'dimension;
  555. % Generate the correct double precision type name - mcd 14/1/88 %
  556. if !*double then
  557. if type memq '(real real*8) then
  558. type := 'double! precision
  559. else if type memq '(implicit! real implicit! real*8) then
  560. type := 'implicit! double! precision
  561. else if type eq 'complex then
  562. type := 'complex!*16
  563. else if type eq 'implicit! complex then
  564. type := 'implicit! complex!*16;
  565. varlist := for each v in insertcommas varlist
  566. conc fortexp_name v;
  567. if implicitp type then
  568. append(list(mkforttab(), type, '! , '!(),
  569. append(varlist, list('!), mkfortterpri())))
  570. else
  571. append(list(mkforttab(), type, '! ),
  572. append(varlist,list mkfortterpri()))
  573. >>$
  574. procedure mkffortdo(stmtnum, var, lo, hi, incr);
  575. <<
  576. if onep incr then
  577. incr := nil
  578. else if incr then
  579. incr := '!, . fortexp incr;
  580. append(append(append(list(mkforttab(), !*do!*, '! , stmtnum, '! ),
  581. fortexp var),
  582. append('!= . fortexp lo, '!, . fortexp hi)),
  583. append(incr, list mkfortterpri()))
  584. >>$
  585. procedure mkffortend;
  586. list(mkforttab(), 'end, mkfortterpri())$
  587. procedure mkffortgo stmtnum;
  588. list(mkforttab(), 'goto, '! , stmtnum, mkfortterpri())$
  589. procedure mkffortifgo(exp, stmtnum);
  590. append(append(list(mkforttab(), 'if, '! , '!(), fortexp exp),
  591. list('!), '! , 'goto, '! , stmtnum, mkfortterpri()))$
  592. symbolic procedure mkffortliteral args;
  593. begin scalar !*lower;
  594. return for each a in args conc
  595. if a eq 'tab!* then list mkforttab()
  596. else if a eq 'cr!* then list mkfortterpri()
  597. else if pairp a then fortexp a
  598. else list stripquotes a
  599. end$
  600. procedure mkffortread var;
  601. append(list(mkforttab(), 'read, '!(!*!,!*!), '! ),
  602. append(fortexp var, list mkfortterpri()))$
  603. procedure mkffortreturn;
  604. list(mkforttab(), 'return, mkfortterpri())$
  605. procedure mkffortstop;
  606. list(mkforttab(), 'stop, mkfortterpri())$
  607. procedure mkffortsubprogdec(type, stype, name, params);
  608. <<
  609. if params then
  610. params := append('!( . for each p in insertcommas params
  611. conc fortexp p,
  612. list '!));
  613. if type then
  614. type := list(mkforttab(), type, '! , stype, '! )
  615. else
  616. type := list(mkforttab(), stype, '! );
  617. append(append(type, fortexp name),
  618. append(params, list mkfortterpri()))
  619. >>$
  620. procedure mkffortwrite arglist;
  621. append(append(list(mkforttab(), 'write, '!(!*!,!*!), '! ),
  622. for each arg in insertcommas arglist conc fortexp arg),
  623. list mkfortterpri())$
  624. %% Indentation Control %%
  625. procedure mkforttab;
  626. list('forttab, fortcurrind!* + 6)$
  627. procedure indentfortlevel n;
  628. fortcurrind!* := fortcurrind!* + n * tablen!*$
  629. procedure mkfortterpri;
  630. list 'fortterpri$
  631. %% FORTRAN Code Formatting & Printing Functions %%
  632. fluid '(maxint);
  633. maxint := 2**31-1;
  634. symbolic procedure formatfort lst;
  635. begin scalar linelen,str,!*lower;
  636. linelen := linelength 300;
  637. !*posn!* := 0;
  638. for each elt in lst do
  639. if pairp elt then lispeval elt
  640. else
  641. <<
  642. if fixp elt and (elt>maxint or elt<-maxint) then
  643. elt := cdr i2rd!* elt;
  644. str:=explode2 elt;
  645. if floatp elt then
  646. if !*double then
  647. if memq('!e,str)
  648. then str:=subst('!D,'!e,str)
  649. else if memq('!E,str) % some LISPs use E not e
  650. then str:=subst('!D,'!E,str)
  651. else str:=append(str,'(D !0))
  652. else if memq('!e,str) then
  653. str:=subst('!E,'!e,str);
  654. % get the casing conventions correct
  655. if !*posn!* + length str > fortlinelen!* then
  656. fortcontline();
  657. for each u in str do pprin2 u
  658. >>;
  659. linelength linelen
  660. end$
  661. procedure fortcontline;
  662. <<
  663. fortterpri();
  664. pprin2 " .";
  665. forttab !*fortcurrind!*;
  666. pprin2 " "
  667. >>$
  668. procedure fortterpri;
  669. pterpri()$
  670. procedure forttab n;
  671. <<
  672. !*fortcurrind!* := max(min0(n, fortlinelen!* - minfortlinelen!*),6);
  673. if (n := !*fortcurrind!* - !*posn!*) > 0 then pprin2 nspaces n
  674. >>$
  675. %% FORTRAN Template routines%%
  676. symbolic procedure procforttem;
  677. begin scalar c, linelen, !*lower;
  678. linelen := linelength 150;
  679. c := procfortcomm();
  680. while c neq !$eof!$ do
  681. if c memq '(!F !f !S !s)
  682. then <<pprin2 c; c := procsubprogheading c>>
  683. else if c eq !$eol!$
  684. then <<pterpri(); c := procfortcomm()>>
  685. else if c eq '!; then c := procactive()
  686. else <<pprin2 c; c := readch()>>;
  687. linelength linelen
  688. end$
  689. procedure procfortcomm;
  690. % <col 1>C ... <cr> %
  691. % <col 1>c ... <cr> %
  692. begin
  693. scalar c;
  694. while (c := readch()) memq '(!C !c) do
  695. <<
  696. pprin2 c;
  697. repeat
  698. if (c := readch()) neq !$eol!$ then
  699. pprin2 c
  700. until c eq !$eol!$;
  701. pterpri()
  702. >>;
  703. return c
  704. end$
  705. %% This function is shared between FORTRAN and RATFOR %%
  706. procedure procsubprogheading c;
  707. % Altered to allow an active statement to be included in a subprogram
  708. % heading. This is more flexible than forbidding it as in the previous
  709. % version, although it does mean that where such a statement occurs the
  710. % value of !$!# may be incorrect. MCD 21/11/90
  711. begin
  712. scalar lst, name, i, propname;
  713. lst := if c memq '(!F !f)
  714. then '((!U !u) (!N !n) (!C !c) (!T !t) (!I !i) (!O !o)
  715. (!N !n))
  716. else '((!U !u) (!B !b) (!R !r) (!O !o) (!U !u)
  717. (!T !t) (!I !i) (!N !n) (!E !e));
  718. while lst and (c := readch()) memq car lst do
  719. << pprin2 c; lst := cdr lst >>;
  720. if lst then return c;
  721. c:=flushspaces readch();
  722. while not(seprp c or c eq '!() do
  723. << name := aconc(name, c); pprin2 c; c := readch() >>;
  724. name := intern compress name;
  725. if not !*gendecs then
  726. symtabput(name, nil, nil);
  727. propname := if gentranlang!* eq 'fortran
  728. then '!*fortranname!*
  729. else '!*ratforname!*;
  730. put('!$0, propname, name);
  731. c:=flushspaces c;
  732. if c neq '!( then return c;
  733. i := 1;
  734. pprin2 c;
  735. c := readch();
  736. while c neq '!) and c neq '!; do
  737. <<
  738. while c neq '!; and (seprp c or c eq '!,) do
  739. <<
  740. if c eq !$eol!$
  741. then pterpri()
  742. else pprin2 c;
  743. c := readch()
  744. >>;
  745. if c neq '!; then
  746. <<
  747. name := list c;
  748. pprin2 c;
  749. while not (seprp (c := readch())
  750. or c memq list('!,,'!;, '!))) do
  751. << name := aconc(name, c); pprin2 c >>;
  752. put(intern compress append(explode2 '!$, explode2 i),
  753. propname,
  754. intern compress name);
  755. i := add1 i;
  756. c:=flushspaces c;
  757. >>;
  758. >>;
  759. !$!# := sub1 i;
  760. while get(name := intern compress append(explode2 '!$, explode2 i),
  761. propname) do
  762. remprop(name, propname);
  763. return c
  764. end$
  765. endmodule;
  766. end;