lsprat.red 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. module lsprat; %% GENTRAN LISP-to-RATFOR Translation Module %%
  2. %% Author: Barbara L. Gates %%
  3. %% December 1986 %%
  4. % Updates:
  5. % M.C. Dewar and J.H. Davenport 8 Jan 88 Double precision check added.
  6. % Entry Point: RatCode
  7. symbolic$
  8. fluid '(!*double !*gendecs !*getdecs);
  9. switch gendecs$
  10. fluid '(!*makecalls)$
  11. switch makecalls$
  12. !*makecalls := t$
  13. % User-Accessible Global Variables %
  14. global '(minratlinelen!* ratlinelen!* !*ratcurrind!*
  15. ratcurrind!* tablen!*)$
  16. share ratcurrind!*, minratlinelen!*, ratlinelen!*, tablen!*$
  17. ratcurrind!* := 0$
  18. minratlinelen!* := 40$
  19. ratlinelen!* := 80$
  20. !*ratcurrind!* := 0$ %current level of indentation for RATFOR code
  21. global '(deftype!* !*do!* !*notfortranfuns!* !*legalforttypes!*)$
  22. global '(!*stdout!*)$
  23. global '(!*posn!* !$!#)$
  24. %% %%
  25. %% LISP-to-RATFOR Translation Functions %%
  26. %% %%
  27. put('ratfor,'formatter,'formatrat);
  28. put('ratfor,'codegen,'ratcode);
  29. put('ratfor,'proctem,'procrattem);
  30. put('ratfor,'gendecs,'ratdecs);
  31. put('ratfor,'assigner,'mkfratassign);
  32. put('ratfor,'boolean!-type,'logical);
  33. %% Control Function %%
  34. procedure ratcode forms;
  35. for each f in forms conc
  36. if atom f then
  37. ratexp f
  38. else if car f memq '(!:rd!: !:cr!: !:crn!: !:gi!:) then
  39. ratexp f
  40. else if lispstmtp f or lispstmtgpp f then
  41. if !*gendecs then
  42. begin
  43. scalar r;
  44. r := append(ratdecs symtabget('!*main!*, '!*decs!*),
  45. ratstmt f);
  46. symtabrem('!*main!*, '!*decs!*);
  47. return r
  48. end
  49. else
  50. ratstmt f
  51. else if lispdefp f then
  52. ratsubprog f
  53. else
  54. ratexp f$
  55. %% Subprogram Translation %%
  56. symbolic procedure ratsubprog deff;
  57. begin
  58. scalar type, stype, name, params, body, lastst, r;
  59. name := cadr deff;
  60. if onep length(body := cdddr deff) and lispstmtgpp car body then
  61. << body := cdar body; if null car body then body := cdr body >>;
  62. if lispreturnp (lastst := car reverse body) then
  63. body := append(body, list '(end))
  64. else if not lispendp lastst then
  65. body := append(body, list('(return), '(end)));
  66. type := cadr symtabget(name, name);
  67. stype := symtabget(name, '!*type!*) or
  68. ( if type or functionformp(body, name)
  69. then 'function
  70. else 'subroutine );
  71. symtabrem(name, '!*type!*);
  72. params := symtabget(name, '!*params!*) or caddr deff;
  73. symtabrem(name, '!*params!*);
  74. if !*getdecs and null type and stype eq 'function
  75. then type := deftype!*;
  76. if type then
  77. << symtabrem(name, name);
  78. % Generate the correct double precision type name - mcd 28/1/88 %
  79. if !*double then
  80. if type memq '(real real*8) then
  81. type := 'double! precision
  82. else if type eq 'complex then
  83. type := 'complex!*16;
  84. >>;
  85. r := mkfratsubprogdec(type, stype, name, params);
  86. if !*gendecs then
  87. r := append(r, ratdecs symtabget(name, '!*decs!*));
  88. r := append(r, for each s in body
  89. conc ratstmt s);
  90. if !*gendecs then
  91. << symtabrem(name, nil); symtabrem(name, '!*decs!*) >>;
  92. return r
  93. end$
  94. %% Generation of Declarations %%
  95. procedure ratdecs decs;
  96. for each tl in formtypelists decs
  97. conc mkfratdec(car tl, cdr tl)$
  98. %% Expression Translation %%
  99. procedure ratexp exp;
  100. ratexp1(exp, 0)$
  101. procedure ratexp1(exp, wtin);
  102. if atom exp then
  103. list fortranname exp
  104. else
  105. if onep length exp then
  106. fortranname exp
  107. else if optype car exp then
  108. begin
  109. scalar wt, op, res;
  110. wt := ratforprecedence car exp;
  111. op := ratforop car exp;
  112. exp := cdr exp;
  113. if onep length exp then
  114. res := op . ratexp1(car exp, wt)
  115. else
  116. <<
  117. res := ratexp1(car exp, wt);
  118. if op eq '!+ then
  119. while exp := cdr exp do
  120. <<
  121. if atom car exp or caar exp neq 'minus then
  122. res := append(res, list op);
  123. res := append(res, ratexp1(car exp, wt))
  124. >>
  125. else
  126. while exp := cdr exp do
  127. res := append(append(res, list op),
  128. ratexp1(car exp, wt))
  129. >>;
  130. if wtin >= wt then res := insertparens res;
  131. return res
  132. end
  133. else if car exp eq 'literal then
  134. ratliteral exp
  135. else if car exp eq 'range
  136. then append(fortexp cadr exp,'!: . fortexp caddr exp)
  137. else if car exp eq '!:rd!: then
  138. begin scalar mt;
  139. integer dotpos,!:lower!-sci!:,!:upper!-sci!:; % this forces most
  140. % numbers to exponential format
  141. mt := rd!:explode exp;
  142. exp := car mt;
  143. mt := cadr mt + caddr mt - 1;
  144. exp := append(list('literal,car exp, '!.),cdr exp);
  145. if null (mt = 0) then
  146. exp := append(exp, list(if !*double then '!d else '!e,mt))
  147. else if !*double then
  148. exp := append(exp,'(!e 0));
  149. return ratliteral exp;
  150. end
  151. else if car exp memq '(!:cr!: !:crn!: !:gi!:) then
  152. begin scalar re,im;
  153. re := explode if smallfloatp cadr exp then cadr exp
  154. else caadr exp;
  155. re := if memq ('!e, re) then
  156. subst('d,'!e,re)
  157. else if memq ('!e, re) then
  158. subst('d,'!e,re)
  159. else if !*double then
  160. append(re,'(d 0))
  161. else
  162. append(re,'(e 0));
  163. im := explode if smallfloatp cddr exp then cddr exp
  164. else caddr exp;
  165. im := if memq ('!e, im) then
  166. subst('d,'!e,im)
  167. else if memq ('!e, im) then
  168. subst('d,'!e,im)
  169. else if !*double then
  170. append(im,'(d 0))
  171. else
  172. append(im,'(e 0));
  173. return ('!().append(re,('!,).append(im,'(!))));
  174. end
  175. else
  176. begin
  177. scalar op, res;
  178. op := fortranname car exp;
  179. exp := cdr exp;
  180. res := ratexp1(car exp, 0);
  181. while exp := cdr exp do
  182. res := append(append(res, list '!,), ratexp1(car exp, 0));
  183. return op . insertparens res
  184. end$
  185. procedure ratforop op;
  186. get(op, '!*ratforop!*) or op$
  187. put('or, '!*ratforop!*, '| )$
  188. put('and, '!*ratforop!*, '& )$
  189. put('not, '!*ratforop!*, '!! )$
  190. put('equal, '!*ratforop!*, '!=!=)$
  191. put('neq, '!*ratforop!*, '!!!=)$
  192. put('greaterp, '!*ratforop!*, '> )$
  193. put('geq, '!*ratforop!*, '!>!=)$
  194. put('lessp, '!*ratforop!*, '< )$
  195. put('leq, '!*ratforop!*, '!<!=)$
  196. put('plus, '!*ratforop!*, '!+ )$
  197. put('times, '!*ratforop!*, '* )$
  198. put('quotient, '!*ratforop!*, '/ )$
  199. put('minus, '!*ratforop!*, '!- )$
  200. put('expt, '!*ratforop!*, '!*!*)$
  201. procedure ratforprecedence op;
  202. get(op, '!*ratforprecedence!*) or 9$
  203. put('or, '!*ratforprecedence!*, 1)$
  204. put('and, '!*ratforprecedence!*, 2)$
  205. put('not, '!*ratforprecedence!*, 3)$
  206. put('equal, '!*ratforprecedence!*, 4)$
  207. put('neq, '!*ratforprecedence!*, 4)$
  208. put('greaterp, '!*ratforprecedence!*, 4)$
  209. put('geq, '!*ratforprecedence!*, 4)$
  210. put('lessp, '!*ratforprecedence!*, 4)$
  211. put('leq, '!*ratforprecedence!*, 4)$
  212. put('plus, '!*ratforprecedence!*, 5)$
  213. put('times, '!*ratforprecedence!*, 6)$
  214. put('quotient, '!*ratforprecedence!*, 6)$
  215. put('minus, '!*ratforprecedence!*, 7)$
  216. put('expt, '!*ratforprecedence!*, 8)$
  217. %% Statement Translation %%
  218. procedure ratstmt stmt;
  219. if null stmt then
  220. nil
  221. else if lisplabelp stmt then
  222. ratstmtnum stmt
  223. else if car stmt eq 'literal then
  224. ratliteral stmt
  225. else if lispreadp stmt then
  226. ratread stmt
  227. else if lispassignp stmt then
  228. ratassign stmt
  229. else if lispprintp stmt then
  230. ratwrite stmt
  231. else if lispcondp stmt then
  232. ratif stmt
  233. else if lispbreakp stmt then
  234. ratbreak stmt
  235. else if lispgop stmt then
  236. ratgoto stmt
  237. else if lispreturnp stmt then
  238. ratreturn stmt
  239. else if lispstopp stmt then
  240. ratstop stmt
  241. else if lispendp stmt then
  242. ratend stmt
  243. else if lisprepeatp stmt then
  244. ratrepeat stmt
  245. else if lispwhilep stmt then
  246. ratwhile stmt
  247. else if lispforp stmt then
  248. ratforfor stmt
  249. else if lispstmtgpp stmt then
  250. ratstmtgp stmt
  251. else if lispdefp stmt then
  252. ratsubprog stmt
  253. else if lispcallp stmt then
  254. ratcall stmt$
  255. procedure ratassign stmt;
  256. mkfratassign(cadr stmt, caddr stmt)$
  257. procedure ratbreak stmt;
  258. mkfratbreak()$
  259. procedure ratcall stmt;
  260. mkfratcall(car stmt, cdr stmt)$
  261. procedure ratforfor stmt;
  262. begin
  263. scalar r, var, loexp, stepexp, hiexp, stmtlst;
  264. var := cadr stmt;
  265. stmt := cddr stmt;
  266. loexp := caar stmt;
  267. stepexp := cadar stmt;
  268. hiexp := caddar stmt;
  269. stmtlst := cddr stmt;
  270. r := mkfratdo(var, loexp, hiexp, stepexp);
  271. indentratlevel(+1);
  272. r := append(r, foreach st in stmtlst conc ratstmt st);
  273. indentratlevel(-1);
  274. return r
  275. end$
  276. procedure ratend stmt;
  277. mkfratend()$
  278. procedure ratgoto stmt;
  279. begin
  280. scalar stmtnum;
  281. stmtnum := get(cadr stmt, '!*stmtnum!*) or
  282. put(cadr stmt, '!*stmtnum!*, genstmtnum());
  283. return mkfratgo stmtnum
  284. end$
  285. procedure ratif stmt;
  286. begin
  287. scalar r, st;
  288. r := mkfratif caadr stmt;
  289. indentratlevel(+1);
  290. st := seqtogp cdadr stmt;
  291. if eqcar(st, 'cond) and length st=2 then
  292. st := mkstmtgp(0, list st);
  293. r := append(r, ratstmt st);
  294. indentratlevel(-1);
  295. stmt := cdr stmt;
  296. while (stmt := cdr stmt) and caar stmt neq t do
  297. <<
  298. r := append(r, mkfratelseif caar stmt);
  299. indentratlevel(+1);
  300. st := seqtogp cdar stmt;
  301. if eqcar(st, 'cond) and length st=2 then
  302. st := mkstmtgp(0, list st);
  303. r := append(r, ratstmt st);
  304. indentratlevel(-1)
  305. >>;
  306. if stmt then
  307. <<
  308. r := append(r, mkfratelse());
  309. indentratlevel(+1);
  310. st := seqtogp cdar stmt;
  311. if eqcar(st, 'cond) and length st=2 then
  312. st := mkstmtgp(0, list st);
  313. r := append(r, ratstmt st);
  314. indentratlevel(-1)
  315. >>;
  316. return r
  317. end$
  318. procedure ratliteral stmt;
  319. mkfratliteral cdr stmt$
  320. procedure ratread stmt;
  321. mkfratread cadr stmt$
  322. procedure ratrepeat stmt;
  323. begin
  324. scalar r, stmtlst, logexp;
  325. stmt := reverse cdr stmt;
  326. logexp := car stmt;
  327. stmtlst := reverse cdr stmt;
  328. r := mkfratrepeat();
  329. indentratlevel(+1);
  330. r := append(r, foreach st in stmtlst conc ratstmt st);
  331. indentratlevel(-1);
  332. return append(r, mkfratuntil logexp)
  333. end$
  334. procedure ratreturn stmt;
  335. if cdr stmt then
  336. mkfratreturn cadr stmt
  337. else
  338. mkfratreturn nil$
  339. procedure ratstmtgp stmtgp;
  340. begin
  341. scalar r;
  342. if car stmtgp eq 'progn then
  343. stmtgp := cdr stmtgp
  344. else
  345. stmtgp := cddr stmtgp;
  346. r := mkfratbegingp();
  347. indentratlevel(+1);
  348. r := append(r, for each stmt in stmtgp conc ratstmt stmt);
  349. indentratlevel(-1);
  350. return append(r, mkfratendgp())
  351. end$
  352. procedure ratstmtnum label;
  353. begin
  354. scalar stmtnum;
  355. stmtnum := get(label, '!*stmtnum!*) or
  356. put(label, '!*stmtnum!*, genstmtnum());
  357. return mkfratcontinue stmtnum
  358. end$
  359. procedure ratstop stmt;
  360. mkfratstop()$
  361. procedure ratwhile stmt;
  362. begin
  363. scalar r, logexp, stmtlst;
  364. logexp := cadr stmt;
  365. stmtlst := cddr stmt;
  366. r := mkfratwhile logexp;
  367. indentratlevel(+1);
  368. r := append(r, foreach st in stmtlst conc ratstmt st);
  369. indentratlevel(-1);
  370. return r
  371. end$
  372. procedure ratwrite stmt;
  373. mkfratwrite cdr stmt$
  374. %% %%
  375. %% RATFOR Code Formatting Functions %%
  376. %% %%
  377. %% Statement Formatting %%
  378. % A macro used to prevent things with *fortranname* or *doublename*
  379. % properties being evaluated in certain circumstances. MCD 28.3.94
  380. symbolic smacro procedure ratexp_name(u);
  381. if atom u then list(u)
  382. else rplaca(ratexp ('dummyArrayToken . cdr u), car u)$
  383. procedure mkfratassign(lhs, rhs);
  384. append(append(mkrattab() . ratexp_name lhs, '!= . ratexp rhs),
  385. list mkratterpri())$
  386. procedure mkfratbegingp;
  387. list(mkrattab(), '!{, mkratterpri())$
  388. procedure mkfratbreak;
  389. list(mkrattab(), 'break, mkratterpri())$
  390. procedure mkfratcall(fname, params);
  391. % Installed the switch makecalls 18/11/88 mcd.
  392. <<
  393. if params then
  394. params := append(append(list '!(,
  395. for each p in insertcommas params
  396. conc ratexp p),
  397. list '!));
  398. % If we want to generate bits of statements, then what might
  399. % appear a subroutine call may in fact be a function reference.
  400. if !*makecalls then
  401. append(append(list(mkrattab(), 'call, '! ), ratexp fname),
  402. append(params, list mkratterpri()))
  403. else
  404. append(ratexp fname,params)
  405. >>$
  406. procedure mkfratcontinue stmtnum;
  407. list(stmtnum, '! , mkrattab(), 'continue, mkratterpri())$
  408. symbolic procedure mkfratdec(type, varlist); %Ammended mcd 3/12/87
  409. <<
  410. if type equal 'scalar then type := deftype!*;
  411. if type and null (type memq !*legalforttypes!*) then
  412. gentranerr('e,type,"Illegal Ratfor type. ",nil);
  413. type := type or 'dimension;
  414. % Generate the correct double precision type name - mcd 14/1/88 %
  415. if !*double then
  416. if type memq '(real real*8) then
  417. type := 'double! precision
  418. else if type memq '(implicit! real implicit! real*8) then
  419. type := 'implicit! double! precision
  420. else if type eq 'complex then
  421. type := 'complex!*16
  422. else if type eq 'implicit! complex then
  423. type := 'implicit! complex!*16;
  424. varlist := for each v in insertcommas varlist
  425. conc ratexp_name v;
  426. if implicitp type then
  427. append(list(mkrattab(), type, '! , '!(),
  428. append(varlist, list('!), mkratterpri())))
  429. else
  430. append(list(mkrattab(), type, '! ),
  431. append(varlist, list mkratterpri()))
  432. >>$
  433. procedure mkfratdo(var, lo, hi, incr);
  434. <<
  435. if onep incr then
  436. incr := nil
  437. else if incr then
  438. incr := '!, . ratexp incr;
  439. append(append(append(list(mkrattab(), !*do!*, '! ), ratexp var),
  440. append('!= . ratexp lo, '!, . ratexp hi)),
  441. append(incr, list mkratterpri()))
  442. >>$
  443. procedure mkfratelse;
  444. list(mkrattab(), 'else, mkratterpri())$
  445. procedure mkfratelseif exp;
  446. append(append(list(mkrattab(), 'else, '! , 'if, '! , '!(), ratexp exp),
  447. list('!), mkratterpri()))$
  448. procedure mkfratend;
  449. list(mkrattab(), 'end, mkratterpri())$
  450. procedure mkfratendgp;
  451. list(mkrattab(), '!}, mkratterpri())$
  452. procedure mkfratgo stmtnum;
  453. list(mkrattab(), 'goto, '! , stmtnum, mkratterpri())$
  454. procedure mkfratif exp;
  455. append(append(list(mkrattab(), 'if, '! , '!(), ratexp exp),
  456. list('!), mkratterpri()))$
  457. procedure mkfratliteral args;
  458. for each a in args conc
  459. if a eq 'tab!* then
  460. list mkrattab()
  461. else if a eq 'cr!* then
  462. list mkratterpri()
  463. else if pairp a then
  464. ratexp a
  465. else
  466. list stripquotes a$
  467. procedure mkfratread var;
  468. append(list(mkrattab(), 'read, '!(!*!,!*!), '! ),
  469. append(ratexp var, list mkratterpri()))$
  470. procedure mkfratrepeat;
  471. list(mkrattab(), 'repeat, mkratterpri())$
  472. procedure mkfratreturn exp;
  473. if exp then
  474. append(append(list(mkrattab(), 'return, '!(), ratexp exp),
  475. list('!), mkratterpri()))
  476. else
  477. list(mkrattab(), 'return, mkratterpri())$
  478. procedure mkfratstop;
  479. list(mkrattab(), 'stop, mkratterpri())$
  480. procedure mkfratsubprogdec(type, stype, name, params);
  481. <<
  482. if params then
  483. params := append('!( . for each p in insertcommas params
  484. conc ratexp p,
  485. list '!));
  486. if type then
  487. type := list(mkrattab(), type, '! , stype, '! )
  488. else
  489. type := list(mkrattab(), stype, '! );
  490. append(append(type, ratexp name),
  491. append(params,list mkratterpri()))
  492. >>$
  493. procedure mkfratuntil logexp;
  494. append(list(mkrattab(), 'until, '! , '!(),
  495. append(ratexp logexp, list('!), mkratterpri())))$
  496. procedure mkfratwhile exp;
  497. append(append(list(mkrattab(), 'while, '! , '!(), ratexp exp),
  498. list('!), mkratterpri()))$
  499. procedure mkfratwrite arglist;
  500. append(append(list(mkrattab(), 'write, '!(!*!,!*!), '! ),
  501. for each arg in insertcommas arglist conc ratexp arg),
  502. list mkratterpri())$
  503. %% Indentation Control %%
  504. procedure mkrattab;
  505. list('rattab, ratcurrind!*)$
  506. procedure indentratlevel n;
  507. ratcurrind!* := ratcurrind!* + n * tablen!*$
  508. procedure mkratterpri;
  509. list 'ratterpri$
  510. %% RATFOR Code Formatting & Printing Functions %%
  511. procedure formatrat lst;
  512. begin
  513. scalar linelen,str;
  514. linelen := linelength 300;
  515. !*posn!* := 0;
  516. for each elt in lst do
  517. if pairp elt then lispeval elt
  518. else
  519. << str:=explode2 elt;
  520. if floatp elt then
  521. if !*double then
  522. if memq('!e,str)
  523. then str:=subst('D,'!e,str)
  524. else if memq('E,str) % Some LISPs use E not e
  525. then str:=subst('D,'E,str)
  526. else str:=append(str,'(D !0))
  527. else str:=subst('E,'!e,str);
  528. % get the casing conventions correct
  529. if !*posn!* + length str > ratlinelen!* then
  530. ratcontline();
  531. for each u in str do pprin2 u
  532. >>;
  533. linelength linelen
  534. end$
  535. procedure ratcontline;
  536. <<
  537. ratterpri();
  538. rattab !*ratcurrind!*;
  539. pprin2 " "
  540. >>$
  541. procedure ratterpri;
  542. pterpri()$
  543. procedure rattab n;
  544. <<
  545. !*ratcurrind!* := min0(n, ratlinelen!* - minratlinelen!*);
  546. if (n := !*ratcurrind!* - !*posn!*) > 0 then pprin2 nspaces n
  547. >>$
  548. %% RATFOR template processing %%
  549. procedure procrattem;
  550. begin
  551. scalar c, linelen;
  552. linelen := linelength 150;
  553. c := readch();
  554. while c neq !$eof!$ do
  555. if c memq '(!F !f !S !s) then
  556. <<
  557. pprin2 c;
  558. c := procsubprogheading c
  559. >>
  560. else if c eq '!# then
  561. c := procratcomm()
  562. else if c eq '!; then
  563. c := procactive()
  564. else if c eq !$eol!$ then
  565. <<
  566. pterpri();
  567. c := readch()
  568. >>
  569. else
  570. <<
  571. pprin2 c;
  572. c := readch()
  573. >>;
  574. linelength linelen
  575. end$
  576. procedure procratcomm;
  577. % # ... <cr> %
  578. begin
  579. scalar c;
  580. pprin2 '!#;
  581. while (c := readch()) neq !$eol!$ do
  582. pprin2 c;
  583. pterpri();
  584. return readch()
  585. end$
  586. endmodule;
  587. end;