lsppasc.red 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. module lsppasc; %% GENTRAN LISP-to-PASCAL Translation Module %%
  2. %% Author: John Fitch and James Davenport after Barbara L. Gates %%
  3. %% November 1987 %%
  4. % Entry Point: PASCCode
  5. symbolic$
  6. fluid '(!*gendecs)$
  7. switch gendecs$
  8. % User-Accessible Global Variables %
  9. global '(pasclinelen!* minpasclinelen!* !*pasccurrind!* pasccurrind!*
  10. tablen!* pascfuncname!*)$
  11. share pasclinelen!*, minpasclinelen!*,
  12. pasccurrind!*, tablen!*, pascfuncname!*$
  13. pasccurrind!* := 0$
  14. minpasclinelen!* := 40$
  15. pasclinelen!* := 70$
  16. !*pasccurrind!* := 0$ %current level of indentation for PASCAL code
  17. global '(!*do!* !*for!*)$
  18. global '(!*posn!* !$!#)$
  19. %% %%
  20. %% LISP-to-PASCAL Translation Functions %%
  21. %% %%
  22. put('pascal,'formatter,'formatpasc);
  23. put('pascal,'codegen,'pasccode);
  24. put('pascal,'proctem,'procpasctem);
  25. put('pascal,'gendecs,'pascdecs);
  26. put('pascal,'assigner,'mkfpascassign);
  27. put('pascal,'boolean!-type,'boolean);
  28. symbolic procedure pasc!-symtabput(name,type,value);
  29. % Like symtabput, but indirects through TYPE declarations.
  30. % has to be recursive
  31. begin
  32. scalar basetype, origtype, wastypedecl;
  33. basetype:=car value;
  34. if basetype = 'TYPE then <<
  35. wastypedecl:=t;
  36. value:=cdr value;
  37. basetype:=car value >>;
  38. origtype:=symtabget(name,basetype) or symtabget('!*main!*,basetype);
  39. if pairp origtype then origtype:=cdr origtype; % strip off name;
  40. if pairp origtype and car origtype = 'TYPE
  41. then value:= (cadr origtype). append(cdr value,cddr origtype);
  42. if wastypedecl
  43. then symtabput(name,type,'TYPE . value)
  44. else symtabput(name,type,value);
  45. end;
  46. %% Control Function %%
  47. procedure pasccode forms;
  48. for each f in forms conc
  49. if atom f then
  50. pascexp f
  51. else if car f memq '(!:rd!: !:cr!: !:crn!: !:gi!:) then
  52. pascexp f
  53. else if lispstmtp f or lispstmtgpp f then
  54. if !*gendecs then
  55. begin
  56. scalar r;
  57. r := append(pascdecs symtabget('!*main!*, '!*decs!*),
  58. pascstmt f);
  59. symtabrem('!*main!*, '!*decs!*);
  60. return r
  61. end
  62. else
  63. pascstmt f
  64. else if lispdefp f then
  65. pascproc f
  66. else
  67. pascexp f$
  68. %% Procedure Translation %%
  69. procedure pascproc deff;
  70. begin
  71. scalar type, name, params, paramtypes, vartypes, body, r;
  72. name := cadr deff;
  73. if onep length (body := cdddr deff) and lispstmtgpp car body then
  74. << body := cdar body;
  75. if null car body then body := cdr body >>;
  76. if (type := symtabget(name, name)) then
  77. << type := cadr type; symtabrem(name, name) >>;
  78. params := symtabget(name, '!*params!*) or caddr deff;
  79. symtabrem(name, '!*params!*);
  80. for each dec in symtabget(name, '!*decs!*) do
  81. if car dec memq params
  82. then paramtypes := append(paramtypes, list dec)
  83. else if cadr dec neq 'TYPE then
  84. vartypes := append(vartypes, list dec);
  85. r := mkfpascprocdec(type, name, params, paramtypes);
  86. if !*gendecs then
  87. << r:= append(r,list(mkpasctab(),'label,mkpascterpri()));
  88. indentpasclevel(+1);
  89. r:= append(r,list(mkpasctab(),'99999, '!;, mkpascterpri()));
  90. indentpasclevel(-1);
  91. r := append(r, pascdecs vartypes) >>;
  92. r:= append(r, mkfpascbegingp() );
  93. indentpasclevel(+1);
  94. r := append(r, for each s in body
  95. conc pascstmt s);
  96. indentpasclevel(-1);
  97. r:=append(r,list(mkpasctab(), 99999, '!:, mkpascterpri()));
  98. r := append(r, mkfpascendgp());
  99. if !*gendecs then
  100. << symtabrem(name, nil); symtabrem(name, '!*decs!*) >>;
  101. return r
  102. end$
  103. %% Generation of Declarations %%
  104. procedure pascdecs decs;
  105. begin scalar r;
  106. decs:=for each r in decs conc
  107. if cadr r eq 'type then nil else list r;
  108. if decs then <<
  109. indentpasclevel(+1);
  110. decs:=for each tl in formtypelists decs
  111. conc mkfpascdec(car tl, cdr tl);
  112. indentpasclevel(-1);
  113. r:=append(list(mkpasctab(),'var, mkpascterpri()), decs) >>;
  114. return r
  115. end$
  116. %% Expression Translation %%
  117. procedure pascexp exp;
  118. pascexp1(exp, 0)$
  119. procedure pascexp1(exp, wtin);
  120. if atom exp then
  121. list pascname exp
  122. else
  123. if onep length exp then
  124. pascname exp
  125. else if optype car exp then
  126. begin
  127. scalar wt, op, res;
  128. wt := pascprecedence car exp;
  129. op := pascop car exp;
  130. exp := cdr exp;
  131. if onep length exp then
  132. res := op . pascexp1(car exp, wt)
  133. else
  134. <<
  135. res := pascexp1(car exp, wt);
  136. if op eq '!+ then
  137. while exp := cdr exp do
  138. <<
  139. if atom car exp or caar exp neq 'minus then
  140. res := append(res, list op);
  141. res := append(res, pascexp1(car exp, wt))
  142. >>
  143. else
  144. while exp := cdr exp do
  145. res := append(append(res, list op),
  146. pascexp1(car exp, wt))
  147. >>;
  148. if wtin >= wt then res := insertparens res;
  149. return res
  150. end
  151. else if car exp eq 'literal then
  152. pascliteral exp
  153. else if car exp eq 'range then
  154. append(pascexp cadr exp, '!.!. . pascexp caddr exp)
  155. else if car exp eq '!:rd!: then
  156. begin scalar mt;
  157. integer dotpos,!:lower!-sci!:,!:upper!-sci!:; % this forces most
  158. % numbers to exponential format
  159. mt := rd!:explode exp;
  160. exp := car mt;
  161. mt := cadr mt + caddr mt - 1;
  162. exp := append(list('literal,car exp, '!.),cdr exp);
  163. if null (mt = 0) then exp := append(exp, list('!e,mt));
  164. return pascliteral exp;
  165. end
  166. else if car exp memq '(!:cr!: !:crn!: !:gi!:) then
  167. gentranerr('e,exp,"Pascal doesn't support complex data",nil)
  168. else if arrayeltp exp then
  169. if cddr exp and ((caddr exp) equal '!.!.) then
  170. pascname car exp . pascinsertbrackets cdr exp
  171. else pascname car exp .
  172. pascinsertbrackets cdr foreach s in cdr exp conc
  173. '!, . pascexp1(s, 0)
  174. else
  175. begin
  176. scalar op, res;
  177. op := pascname car exp;
  178. exp := cdr exp;
  179. res := pascexp1(car exp, 0);
  180. while exp := cdr exp do
  181. res := append(append(res, list '!,), pascexp1(car exp, 0));
  182. return op . insertparens res
  183. end$
  184. procedure pascop op;
  185. get(op, '!*pascop!*) or op$
  186. put('or, '!*pascop!*, 'or )$
  187. put('and, '!*pascop!*, 'and )$
  188. put('not, '!*pascop!*, 'not )$
  189. put('equal, '!*pascop!*, '!= )$
  190. put('neq, '!*pascop!*, '!<!>)$
  191. put('greaterp, '!*pascop!*, '!> )$
  192. put('geq, '!*pascop!*, '!>!=)$
  193. put('lessp, '!*pascop!*, '!< )$
  194. put('leq, '!*pascop!*, '!<!=)$
  195. put('plus, '!*pascop!*, '!+ )$
  196. put('times, '!*pascop!*, '!* )$
  197. put('quotient, '!*pascop!*, '!/ )$
  198. put('minus, '!*pascop!*, '!- )$
  199. put('expt, '!*pascop!*, '!*!*)$
  200. procedure pascname a;
  201. if stringp a then
  202. stringtopascatom a % convert a to atom containing ''s
  203. else
  204. get(a, '!*pascname!*) or a$
  205. procedure stringtopascatom a;
  206. intern compress
  207. foreach c in append('!' . explode2 a, list '!')
  208. conc list('!!, c)$
  209. put('true, '!*pascname!*, 'true)$
  210. put('false, '!*pascname!*, 'false)$
  211. procedure pascprecedence op;
  212. get(op, '!*pascprecedence!*) or 9$
  213. put('or, '!*pascprecedence!*, 1)$
  214. put('and, '!*pascprecedence!*, 2)$
  215. put('equal, '!*pascprecedence!*, 3)$
  216. put('neq, '!*pascprecedence!*, 3)$
  217. put('greaterp, '!*pascprecedence!*, 4)$
  218. put('geq, '!*pascprecedence!*, 4)$
  219. put('lessp, '!*pascprecedence!*, 4)$
  220. put('leq, '!*pascprecedence!*, 4)$
  221. put('plus, '!*pascprecedence!*, 5)$
  222. put('times, '!*pascprecedence!*, 6)$
  223. put('quotient, '!*pascprecedence!*, 6)$
  224. put('expt, '!*pascprecedence!*, 7)$
  225. put('not, '!*pascprecedence!*, 8)$
  226. put('minus, '!*pascprecedence!*, 8)$
  227. %% Statement Translation %%
  228. procedure pascstmt stmt;
  229. if null stmt then
  230. nil
  231. else if lisplabelp stmt then
  232. pasclabel stmt % Are there labels?
  233. else if car stmt eq 'literal then
  234. pascliteral stmt
  235. else if lispassignp stmt then
  236. pascassign stmt
  237. else if lispcondp stmt then
  238. pascif stmt
  239. else if lispgop stmt then % Is there a go?
  240. pascgoto stmt
  241. else if lispreturnp stmt then
  242. pascreturn stmt
  243. else if lispstopp stmt then
  244. pascstop stmt
  245. else if lisprepeatp stmt then
  246. pascrepeat stmt
  247. else if lispwhilep stmt then
  248. pascwhile stmt
  249. else if lispforp stmt then
  250. pascfor stmt
  251. else if lispstmtgpp stmt then
  252. pascstmtgp stmt
  253. else if lispdefp stmt then
  254. pascproc stmt
  255. else
  256. pascexpstmt stmt$
  257. procedure pascassign stmt;
  258. mkfpascassign(cadr stmt, caddr stmt)$
  259. procedure pascstop stmt;
  260. mkfpascstop()$
  261. procedure pascexpstmt exp;
  262. append(mkpasctab() . pascexp exp, list('!;, mkpascterpri()))$
  263. procedure pascfor stmt;
  264. begin
  265. scalar r, variable, loexp, stepexp, hiexp, stmtlst;
  266. variable := cadr stmt;
  267. stmt := cddr stmt;
  268. loexp := caar stmt;
  269. stepexp := cadar stmt;
  270. hiexp := caddar stmt;
  271. stmtlst := cddr stmt;
  272. r := mkfpascfor(variable, loexp, hiexp, stepexp);
  273. indentpasclevel(+1);
  274. %% ?? Should not the stmtlst have only one member??
  275. r := append(r, foreach st in stmtlst conc pascstmt st);
  276. indentpasclevel(-1);
  277. return r
  278. end$
  279. procedure pascgoto stmt;
  280. begin
  281. scalar stmtnum;
  282. if not ( stmtnum := get(cadr stmt, '!*stmtnum!*) ) then
  283. stmtnum := put(cadr stmt, '!*stmtnum!*, genstmtnum());
  284. return mkfpascgo stmtnum
  285. end$
  286. procedure pascif stmt;
  287. begin
  288. scalar r, st;
  289. r := mkfpascif caadr stmt;
  290. indentpasclevel(+1);
  291. st := seqtogp cdadr stmt;
  292. if eqcar(st, 'cond) and length st=2 then
  293. st := mkstmtgp(0, list st);
  294. r := append(r, pascstmt st);
  295. indentpasclevel(-1);
  296. stmt := cddr stmt;
  297. if stmt then
  298. <<
  299. r := append(r, mkfpascelse());
  300. indentpasclevel(+1);
  301. st := seqtogp cdar stmt;
  302. if eqcar(st, 'cond) and length st=2 then
  303. st := mkstmtgp(0, list st);
  304. r := append(r, pascstmt st);
  305. indentpasclevel(-1)
  306. >>;
  307. return r
  308. end$
  309. procedure pasclabel label;
  310. mkfpasclabel label$
  311. procedure pascliteral stmt;
  312. mkfpascliteral cdr stmt$
  313. procedure pascrepeat stmt;
  314. begin
  315. scalar r, stmtlst, logexp;
  316. stmt := reverse cdr stmt;
  317. logexp := car stmt;
  318. stmtlst := reverse cdr stmt;
  319. r := mkfpascrepeat();
  320. indentpasclevel(+1);
  321. r := append(r, foreach st in stmtlst conc pascstmt st);
  322. r:=removefinalsemicolon(r); % Remove final semicolon
  323. indentpasclevel(-1);
  324. return append(r, mkfpascuntil logexp)
  325. end$
  326. procedure pascreturn stmt;
  327. if cdr stmt then
  328. begin scalar r;
  329. r := mkfpascbegingp();
  330. indentpasclevel(+1);
  331. r := append(r, mkfpascassign(pascfuncname!*, cadr stmt));
  332. r := append(r, mkfpascreturn());
  333. r := removefinalsemicolon(r); % Remove final semicolon
  334. indentpasclevel(-1);
  335. return append(r, mkfpascendgp())
  336. end
  337. else
  338. mkfpascreturn()$
  339. procedure pascstmtgp 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 := mkfpascbegingp();
  347. indentpasclevel(+1);
  348. r := append(r, for each stmt in stmtgp conc pascstmt stmt);
  349. r:=removefinalsemicolon(r); % Remove final semicolon
  350. indentpasclevel(-1);
  351. return append(r, mkfpascendgp())
  352. end$
  353. procedure pascwhile stmt;
  354. begin
  355. scalar r, logexp, stmtlst;
  356. logexp := cadr stmt;
  357. stmtlst := cddr stmt;
  358. r := mkfpascwhile logexp;
  359. indentpasclevel(+1);
  360. r := append(r, foreach st in stmtlst conc pascstmt st);
  361. indentpasclevel(-1);
  362. return r
  363. end$
  364. procedure removefinalsemicolon r;
  365. begin scalar rr;
  366. r:=reversip r;
  367. if car r eq '!; then return reversip cdr r;
  368. if not ('!; memq r) then return reversip r;
  369. rr:=r;
  370. while not (cadr rr eq '!;) do << rr := cdr rr >>;
  371. rplacd(rr, cddr rr);
  372. return reversip r
  373. end$
  374. %% %%
  375. %% Pascal Code Formatting Functions %%
  376. %% %%
  377. %% Statement Formatting %%
  378. % A macro used to prevent things with *pascname*
  379. % properties being evaluated in certain circumstances. MCD 28.3.94
  380. symbolic smacro procedure pascexp_name(u);
  381. if atom u then
  382. list(u)
  383. else
  384. rplaca(pascexp ('dummyArrayToken . cdr u), car u)$
  385. procedure mkfpascassign(lhs, rhs);
  386. begin
  387. scalar st;
  388. st := append(pascexp_name lhs, '!:!= . pascexp rhs);
  389. return append(mkpasctab() . st, list('!;, mkpascterpri()))
  390. end$
  391. procedure mkfpascbegingp;
  392. list(mkpasctab(), 'begin, mkpascterpri())$
  393. symbolic procedure mkfpascdec (type, varlist);
  394. begin scalar simplet, arrayt;
  395. varlist := for each v in varlist do
  396. if atom v then simplet := v . simplet
  397. else
  398. arrayt :=
  399. (car v . cdr for each dim in cdr v conc
  400. if eqcar(dim,'range)
  401. then list ('!, , cadr dim, '!.!., caddr dim )
  402. else list ('!, , 0, '!.!., dim ))
  403. . arrayt;
  404. return append(if simplet
  405. then append(mkpasctab() .
  406. for each v in insertcommas simplet conc pascexp v,
  407. (list('!:! , type, '!;, mkpascterpri()))),
  408. for each v in arrayt conc
  409. append(mkpasctab() . car pascexp car v. '!:! .
  410. 'array . insertbrackets cdr v,
  411. list('! of! , type, '!;, mkpascterpri())))
  412. end;
  413. procedure mkfpascdo;
  414. list(mkpasctab(), !*do!*, mkpascterpri())$
  415. procedure mkfpascuntil exp;
  416. append(append(list(mkpasctab(), 'until, '! ),
  417. pascexp exp),
  418. list('!;, mkpascterpri() ));
  419. procedure mkfpascelse;
  420. list(mkpasctab(), 'else, mkpascterpri())$
  421. procedure mkfpascendgp;
  422. list(mkpasctab(), 'end, '!;, mkpascterpri())$
  423. procedure mkfpascstop;
  424. list(mkpasctab(), 'svr, '!(, '!0, '!), '!;, mkpascterpri())$
  425. procedure mkfpascfor(var1, lo, hi, stepexp);
  426. <<
  427. stepexp := if stepexp = 1 then list('! , 'to, '! ) else
  428. if (stepexp = -1) or (stepexp = '(minus 1)) then
  429. list('! , 'downto, '! ) else list('error);
  430. hi:=append(pascexp hi,list('! , !*do!*, mkpascterpri()));
  431. hi:=append(pascexp lo, nconc(stepexp, hi));
  432. append(list(mkpasctab(), !*for!*, '! , var1, '!:!=), hi)
  433. >>$
  434. procedure mkfpascgo label;
  435. list(mkpasctab(), 'goto, '! , label, '!;, mkpascterpri())$
  436. procedure mkfpascif exp;
  437. append(append(list(mkpasctab(), 'if, '! ), pascexp exp),
  438. list('! , 'then, mkpascterpri()))$
  439. procedure mkfpasclabel label;
  440. list(label, '!:, mkpascterpri())$
  441. procedure mkfpascliteral args;
  442. for each a in args conc
  443. if a eq 'tab!* then
  444. list mkpasctab()
  445. else if a eq 'cr!* then
  446. list mkpascterpri()
  447. else if pairp a then
  448. pascexp a
  449. else
  450. list stripquotes a$
  451. procedure mkfpascprocdec(type, name, params, paramtypes);
  452. << pascfuncname!* := name;
  453. params := append('!( . cdr for each p in params
  454. conc '!, . pascdum(p, paramtypes),
  455. list '!));
  456. if type then
  457. append(mkpasctab() . 'function . '! . pascexp name,
  458. append(params,list( '!:, type, '!;, mkpascterpri())))
  459. else
  460. append(mkpasctab() . 'procedure . '! . pascexp name,
  461. append(params, list('!;, mkpascterpri())))
  462. >>$
  463. symbolic procedure pascdum (p,types);
  464. begin scalar type;
  465. type := pascgettype(p,types);
  466. type := if atom type then list type
  467. else if null cdr type then type
  468. else append('array .
  469. insertbrackets
  470. cdr for each dim in cdr type conc
  471. if eqcar(dim,'range)
  472. then list('!,,cadr dim,'!.!.,caddr dim)
  473. else list ('!, , 0, '!.!., dim ),
  474. list ('! of! , car type));
  475. return p . '!: . type
  476. end;
  477. symbolic procedure pascgettype(p,types);
  478. if null types then 'default
  479. else if p memq car types then cdr car types
  480. else pascgettype(p,cdr types);
  481. procedure mkfpascrepeat;
  482. list(mkpasctab(), 'repeat, mkpascterpri())$
  483. procedure mkfpascreturn;
  484. list(mkpasctab(), 'goto, '! , 99999, '!;,
  485. '!{return!}, mkpascterpri())$
  486. procedure mkfpascwhile exp;
  487. append(append(list(mkpasctab(), 'while, '! , '!(), pascexp exp),
  488. list('!), mkpascterpri()))$
  489. %% Indentation Control %%
  490. procedure mkpasctab;
  491. list('pasctab, pasccurrind!*)$
  492. procedure indentpasclevel n;
  493. pasccurrind!* := pasccurrind!* + n * tablen!*$
  494. procedure mkpascterpri;
  495. list 'pascterpri$
  496. %% %%
  497. %% Misc. Functions %%
  498. %% %%
  499. procedure pascinsertbrackets exp;
  500. '![ . append(exp, list '!] )$
  501. %% PASCAL Code Formatting & Printing Functions %%
  502. procedure formatpasc lst;
  503. begin
  504. scalar linelen;
  505. linelen := linelength 300;
  506. !*posn!* := 0;
  507. for each elt in lst do
  508. if pairp elt then lispeval elt
  509. else
  510. <<
  511. if !*posn!* + length explode2 elt > pasclinelen!* then
  512. pasccontline();
  513. pprin2 elt
  514. >>;
  515. linelength linelen
  516. end$
  517. procedure pasccontline;
  518. <<
  519. pascterpri();
  520. pasctab !*pasccurrind!*;
  521. pprin2 " "
  522. >>$
  523. procedure pascterpri;
  524. pterpri()$
  525. procedure pasctab n;
  526. <<
  527. !*pasccurrind!* := min0(n, pasclinelen!* - minpasclinelen!*);
  528. if (n := !*pasccurrind!* - !*posn!*) > 0 then pprin2 nspaces n
  529. >>$
  530. %% PASCAL %%
  531. %% John Fitch %%
  532. global '(pascfuncname!*)$
  533. share pascfuncname!*$
  534. symbolic procedure procpasctem;
  535. begin
  536. scalar c;
  537. c:=flushspaces readch();
  538. while not (c eq !$eof!$ or c eq '!.)
  539. do c:=flushspaces procpasctem1(c);
  540. end;
  541. symbolic procedure procpasctem1 c;
  542. begin
  543. scalar l,w, linelen;
  544. linelen := linelength 150;
  545. pprin2 c;
  546. while c neq !$eof!$ and w neq 'END do <<
  547. if c eq !$eol!$ then
  548. << pterpri(); c := readch() >>
  549. else if c eq '!{ then << c := procpasccomm(); w:= nil >>
  550. else if c eq '!; then
  551. << c := procactive(); pprin2 c; w:=nil >>;
  552. if null w then <<
  553. if liter c then l:= list c;
  554. c := readch();
  555. while liter c or digit c or c eq '!_ do
  556. << pprin2 c; l:=c . l; c := readch() >>;
  557. w:=intern compress reverse l;
  558. l:=nil >>;
  559. if w eq 'VAR then c:=procpascvar c
  560. else if w eq 'CONST then c:=procpascconst c
  561. else if w eq 'TYPE then c:=procpasctype c
  562. else if w memq '(FUNCTION PROCEDURE OPERATOR)
  563. then c:=procfuncoperheading(w,c)
  564. else if w eq 'BEGIN then c:= NIL . procpasctem1 c
  565. else if w neq 'END then <<
  566. while c neq '!; do <<
  567. if c eq '!{ then c := procpasccomm()
  568. else << pprin2 c; c := readch() >> >>;
  569. pprin2 c;
  570. c:=nil . readch() >>;
  571. % recursive, since PASCAL is
  572. if w eq 'END then <<
  573. c:=flushspaces c;
  574. if not ( c memq '(!; !.)) then
  575. gentranerr('e,nil,"END not followed by ; or .",nil);
  576. pprin2 c; c:=readch() >>
  577. else <<
  578. w:=car c;
  579. c:=flushspaces cdr c; >>
  580. >>;
  581. linelength linelen;
  582. return c;
  583. end$
  584. symbolic procedure procpasctype c;
  585. % TYPE ...; ...; ... %
  586. begin
  587. scalar w,l;
  588. next:
  589. while not liter c do <<
  590. if c eq !$eol!$ then pterpri() else pprin2 c;
  591. c:=readch() >>;
  592. l:=nil;
  593. while liter c or digit c or c eq '!_ do
  594. << pprin2 c; l:=c . l; c := readch() >>;
  595. w:=intern compress reverse l;
  596. if w memq '(FUNCTION PROCEDURE OPERATOR CONST VAR)
  597. then return w . c;
  598. c:=flushspaces c;
  599. if c neq '!= then
  600. gentranerr('e,nil,"Malformed TYPE declaration", nil);
  601. l:=readpascaltype c;
  602. c:=car l;
  603. pasc!-symtabput(pascfuncname!*,w,'TYPE . cdr l);
  604. goto next;
  605. end;
  606. symbolic procedure procpascvar c;
  607. % VAR ...; ...; ... %
  608. begin
  609. scalar name,l,namelist;
  610. next:
  611. while not liter c do <<
  612. if c eq !$eol!$ then pterpri() else pprin2 c;
  613. c:=readch() >>;
  614. l:=nil;
  615. while liter c or digit c or c eq '!_ do
  616. << pprin2 c; l:=c . l; c := readch() >>;
  617. name:=intern compress reverse l;
  618. if name memq '(FUNCTION PROCEDURE OPERATOR CONST VAR BEGIN)
  619. then return name . c;
  620. c:=flushspaces c;
  621. namelist:=list name;
  622. while (c = '!, ) do <<
  623. pprin2 c;
  624. c:=flushspaces readch();
  625. l:=nil;
  626. while liter c or digit c or c eq '!_ do
  627. << pprin2 c; l:=c . l; c := readch() >>;
  628. name:=intern compress reverse l;
  629. namelist:= name . namelist;
  630. c:=flushspaces c >>;
  631. if c neq '!: then gentranerr('e,nil,"Malformed VAR declaration", nil);
  632. l:=readpascaltype c;
  633. c:=car l;
  634. for each name in namelist do
  635. pasc!-symtabput(pascfuncname!*,name, cdr l);
  636. goto next;
  637. end;
  638. symbolic procedure procpasccomm;
  639. % { ... } %
  640. begin
  641. scalar c;
  642. pprin2 '!{;
  643. c := readch();
  644. while c neq '!} do
  645. <<
  646. if c eq !$eol!$
  647. then pterpri()
  648. else pprin2 c;
  649. c := readch()
  650. >>;
  651. pprin2 c;
  652. c := readch();
  653. return c
  654. end$
  655. symbolic procedure procfuncoperheading(keyword,c);
  656. % returns the word after the procedure, and the character delimiting it
  657. begin
  658. scalar lst, name, i, ty, args, myargs;
  659. c:=flushspaces c;
  660. while not(seprp c or c eq '!( or c eq '!: ) do
  661. << name := aconc(name, c); pprin2 c; c := readch() >>;
  662. name := intern compress name;
  663. put('!$0, '!*pascalname!*, name);
  664. symtabput(name,'!*type!*,keyword);
  665. pascfuncname!*:=name;
  666. c:=flushspaces c;
  667. if c eq '!( then <<
  668. i := 1;
  669. pprin2 c;
  670. c := readch();
  671. while c neq '!) do
  672. << c:=flushspacescommas c;
  673. name := list c;
  674. pprin2 c;
  675. while not (seprp (c := readch()) or
  676. c memq list('!,, '!), '!:)) do
  677. << name := aconc(name, c); pprin2 c >>;
  678. put(intern compress append(explode2 '!$, explode2 i),
  679. '!*pascalname!*,
  680. name:=intern compress name);
  681. myargs := name . myargs;
  682. i := add1 i;
  683. if c eq '!: then <<
  684. ty:=readpascaltype(c);
  685. c:=car ty; ty:=cdr ty;
  686. foreach n in myargs do
  687. pasc!-symtabput(pascfuncname!*,n,ty);
  688. args:=append(myargs,args);
  689. myargs:=nil;
  690. if (c eq '!;) then << pprin2 c; c:=readch() >>
  691. >>;
  692. c:=flushspaces c
  693. >>;
  694. !$!# := sub1 i;
  695. >>
  696. else !$!# :=0;
  697. if c neq '!: then
  698. << pprin2 c;
  699. while not (((c := readch()) eq '!:) or (c eq !$eol!$)) do
  700. pprin2 c >>;
  701. if c eq '!: then
  702. <<
  703. ty := readpascaltype c;
  704. pasc!-symtabput(name,name,cdr ty);
  705. c:=car ty
  706. >>;
  707. if numberp i then
  708. while get(name := intern compress append(explode2 '!$, explode2 i),
  709. '!*pascalname!*) do
  710. << remprop(name, '!*pascalname!*); i:=sub1 i >>;
  711. lst:=nil;
  712. c:=flushspaces c;
  713. while liter c or digit c or c eq '!_ do
  714. << pprin2 c; lst:=c . lst; c := readch() >>;
  715. if lst then
  716. lst:=intern compress reverse lst;
  717. return lst . c
  718. end$
  719. symbolic procedure readpascaltype(c);
  720. begin
  721. scalar ty;
  722. pprin2 c;
  723. c := flushspaces readch();
  724. ty := list c;
  725. pprin2 c;
  726. while not (seprp (c := readch()) or c memq list('!;, '!), '![ )) do
  727. << ty := aconc(ty, c); pprin2 c >>;
  728. ty := intern compress ty;
  729. if ty eq 'array then return readpascalarraydeclaration(c)
  730. else return c . list ty;
  731. end;
  732. symbolic procedure readpascalarraydeclaration (c);
  733. begin
  734. scalar lo,hi,ty;
  735. ty:= nil;
  736. c:=flushspaces c;
  737. if not (c eq '![) then
  738. gentranerr(c,nil,"invalid pascal array declaration",nil);
  739. pprin2 c;
  740. l: c:=flushspaces readch();
  741. lo:= list c;
  742. pprin2 c;
  743. while not (seprp (c := readch()) or c eq '!.) do
  744. << lo:=aconc(lo,c); pprin2 c >>;
  745. lo := compress lo;
  746. c:=flushspaces c;
  747. if not numberp lo then lo:=intern lo;
  748. pprin2 c;
  749. c:=readch();
  750. if not (c eq '!.) then
  751. gentranerr (c,nil,".. not found in array declaration",nil);
  752. pprin2 c;
  753. c:=flushspaces readch();
  754. hi:= list c;
  755. pprin2 c;
  756. while not (seprp (c := readch()) or c memq list('!,, '!])) do
  757. << hi:=aconc(hi,c); pprin2 c >>;
  758. hi := compress hi;
  759. if not numberp hi then hi:=intern hi;
  760. ty:= hi . ty;
  761. pprin2 c;
  762. c:=flushspaces c;
  763. if c eq '!] then
  764. << ty:= reverse ty;
  765. c:=flushspaces readch();
  766. if not(c memq '( !o !O)) then gentranerr(c,nil,"not 'of'",nil);
  767. pprin2 c;
  768. c:=readch();
  769. if not(c memq '( !f !F)) then gentranerr(c,nil,"not 'of'",nil);
  770. pprin2 c;
  771. c:=readpascaltype(readch());
  772. return car c . append(cdr c,ty) >>;
  773. goto l;
  774. end;
  775. procedure procpascheader c;
  776. begin
  777. scalar name, i;
  778. while seprp c and c neq !$eol!$ do
  779. << pprin2 c; c := readch() >>;
  780. while not(seprp c or c memq list('!{, '!;, '!()) do
  781. << name := aconc(name, c); pprin2 c; c := readch() >>;
  782. if c memq list(!$eol!$, '!{, '!;) then return c;
  783. while seprp c and c neq !$eol!$ do
  784. << pprin2 c; c := readch() >>;
  785. if c neq '!( then return c;
  786. name := intern compress name;
  787. if not !*gendecs then
  788. pasc!-symtabput(name, nil, nil);
  789. put('!$0, '!*cname!*, name);
  790. pprin2 c;
  791. i := 1;
  792. c := readch();
  793. while c neq '!) do
  794. << c:=flushspacescommas c;
  795. name := list c;
  796. pprin2 c;
  797. while not(seprp (c := readch()) or c memq list('!,, '!))) do
  798. << name := aconc(name, c); pprin2 c >>;
  799. put(intern compress append(explode2 '!$, explode2 i),
  800. '!*cname!*,
  801. intern compress name);
  802. i := add1 i;
  803. c:=flushspaces c;
  804. >>;
  805. !$!# := sub1 i;
  806. while get(name := intern compress append(explode2 '!$, explode2 i),
  807. '!*cname!*) do
  808. remprop(name, '!*cname!*);
  809. return procpascfunction c
  810. end$
  811. procedure procpascfunction c;
  812. begin
  813. scalar block!-count;
  814. while c neq '!{ do
  815. if c eq '!; then
  816. c := procactive()
  817. else if c eq !$eol!$ then
  818. << pterpri(); c := readch() >>
  819. else
  820. << pprin2 c; c := readch() >>;
  821. pprin2 c;
  822. block!-count := 1;
  823. c := readch();
  824. while block!-count > 0 do
  825. if c eq 'begin then
  826. << block!-count := add1 block!-count;
  827. pprin2 c; c := readch() >>
  828. else if c eq 'end then
  829. << block!-count := sub1 block!-count; pprin2 c; c := readch() >>
  830. else if c eq '!{ then
  831. c := procpasccomm()
  832. else if c eq '!; then
  833. c := procactive()
  834. else if c eq !$eol!$ then
  835. << pterpri(); c := readch() >>
  836. else
  837. << pprin2 c; c := readch() >>;
  838. return c
  839. end$
  840. % misc routines - JHD 15.12.87
  841. endmodule;
  842. end;