pstatmnt.pas 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Florian Klaempfl
  4. Does the parsing of the statements
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pstatmnt;
  19. interface
  20. uses tree;
  21. var
  22. { true, if we are in a except block }
  23. in_except_block : boolean;
  24. { reads a block }
  25. function block(islibrary : boolean) : ptree;
  26. { reads an assembler block }
  27. function assembler_block : ptree;
  28. implementation
  29. uses
  30. cobjects,scanner,globals,symtable,aasm,pass_1,
  31. types,hcodegen,files,verbose
  32. { processor specific stuff }
  33. {$ifdef i386}
  34. ,i386
  35. ,rai386
  36. ,ratti386
  37. ,radi386
  38. ,tgeni386
  39. {$endif}
  40. {$ifdef m68k}
  41. ,m68k
  42. ,tgen68k
  43. ,ag68kmit
  44. ,ra68k
  45. ,ag68kgas
  46. ,ag68kmot
  47. {$endif}
  48. { parser specific stuff, be careful consume is also defined to }
  49. { read assembler tokens }
  50. ,pbase,pexpr,pdecl;
  51. function statement : ptree;forward;
  52. function if_statement : ptree;
  53. var
  54. ex,if_a,else_a : ptree;
  55. begin
  56. consume(_IF);
  57. ex:=expr;
  58. consume(_THEN);
  59. if token<>_ELSE then
  60. if_a:=statement
  61. else
  62. if_a:=nil;
  63. if token=_ELSE then
  64. begin
  65. consume(_ELSE);
  66. else_a:=statement;
  67. end
  68. else
  69. else_a:=nil;
  70. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  71. end;
  72. { creates a block (list) of statements, til the next END token }
  73. function statements_til_end : ptree;
  74. var
  75. first,last : ptree;
  76. begin
  77. first:=nil;
  78. while token<>_END do
  79. begin
  80. if first=nil then
  81. begin
  82. last:=gennode(statementn,nil,statement);
  83. first:=last;
  84. end
  85. else
  86. begin
  87. last^.left:=gennode(statementn,nil,statement);
  88. last:=last^.left;
  89. end;
  90. if token<>SEMICOLON then
  91. break
  92. else
  93. consume(SEMICOLON);
  94. while token=SEMICOLON do
  95. consume(SEMICOLON);
  96. end;
  97. consume(_END);
  98. statements_til_end:=gensinglenode(blockn,first);
  99. end;
  100. function case_statement : ptree;
  101. var
  102. { contains the label number of currently parsed case block }
  103. aktcaselabel : plabel;
  104. wurzel : pcaserecord;
  105. { the typ of the case expression }
  106. casedef : pdef;
  107. procedure newcaselabel(l,h : longint);
  108. var
  109. hcaselabel : pcaserecord;
  110. procedure insertlabel(var p : pcaserecord);
  111. begin
  112. if p=nil then p:=hcaselabel
  113. else
  114. if (p^._low>hcaselabel^._low) and
  115. (p^._low>hcaselabel^._high) then
  116. insertlabel(p^.less)
  117. else if (p^._high<hcaselabel^._low) and
  118. (p^._high<hcaselabel^._high) then
  119. insertlabel(p^.greater)
  120. else Message(parser_e_double_caselabel);
  121. end;
  122. begin
  123. new(hcaselabel);
  124. hcaselabel^.less:=nil;
  125. hcaselabel^.greater:=nil;
  126. hcaselabel^.statement:=aktcaselabel;
  127. getlabel(hcaselabel^._at);
  128. hcaselabel^._low:=l;
  129. hcaselabel^._high:=h;
  130. insertlabel(wurzel);
  131. end;
  132. var
  133. code,caseexpr,p,instruc,elseblock : ptree;
  134. hl1,hl2 : longint;
  135. ranges : boolean;
  136. begin
  137. consume(_CASE);
  138. caseexpr:=expr;
  139. { determines result type }
  140. cleartempgen;
  141. do_firstpass(caseexpr);
  142. casedef:=caseexpr^.resulttype;
  143. if not(is_ordinal(casedef)) then
  144. Message(parser_e_ordinal_expected);
  145. consume(_OF);
  146. wurzel:=nil;
  147. ranges:=false;
  148. instruc:=nil;
  149. repeat
  150. getlabel(aktcaselabel);
  151. {aktcaselabel^.is_used:=true; }
  152. { an instruction has may be more case labels }
  153. repeat
  154. p:=expr;
  155. cleartempgen;
  156. do_firstpass(p);
  157. if (p^.treetype=rangen) then
  158. begin
  159. { type checking for case statements }
  160. if not is_subequal(casedef, p^.left^.resulttype) then
  161. Message(parser_e_case_mismatch);
  162. { type checking for case statements }
  163. if not is_subequal(casedef, p^.right^.resulttype) then
  164. Message(parser_e_case_mismatch);
  165. hl1:=get_ordinal_value(p^.left);
  166. hl2:=get_ordinal_value(p^.right);
  167. testrange(casedef,hl1);
  168. testrange(casedef,hl2);
  169. newcaselabel(hl1,hl2);
  170. ranges:=true;
  171. end
  172. else
  173. begin
  174. { type checking for case statements }
  175. if not is_subequal(casedef, p^.resulttype) then
  176. Message(parser_e_case_mismatch);
  177. hl1:=get_ordinal_value(p);
  178. testrange(casedef,hl1);
  179. newcaselabel(hl1,hl1);
  180. end;
  181. disposetree(p);
  182. if token=COMMA then consume(COMMA)
  183. else break;
  184. until false;
  185. consume(COLON);
  186. { handles instruction block }
  187. p:=gensinglenode(labeln,statement);
  188. p^.labelnr:=aktcaselabel;
  189. { concats instruction }
  190. instruc:=gennode(statementn,instruc,p);
  191. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  192. consume(SEMICOLON);
  193. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  194. if (token=_ELSE) or (token=_OTHERWISE) then
  195. begin
  196. if token=_ELSE then consume(_ELSE)
  197. else consume(_OTHERWISE);
  198. elseblock:=statements_til_end;
  199. end
  200. else
  201. begin
  202. elseblock:=nil;
  203. consume(_END);
  204. end;
  205. code:=gencasenode(caseexpr,instruc,wurzel);
  206. code^.elseblock:=elseblock;
  207. case_statement:=code;
  208. end;
  209. function repeat_statement : ptree;
  210. var
  211. first,last,p_e : ptree;
  212. begin
  213. consume(_REPEAT);
  214. first:=nil;
  215. while token<>_UNTIL do
  216. begin
  217. if first=nil then
  218. begin
  219. last:=gennode(statementn,nil,statement);
  220. first:=last;
  221. end
  222. else
  223. begin
  224. last^.left:=gennode(statementn,nil,statement);
  225. last:=last^.left;
  226. end;
  227. if token<>SEMICOLON then
  228. break;
  229. consume(SEMICOLON);
  230. while token=SEMICOLON do
  231. consume(SEMICOLON);
  232. end;
  233. consume(_UNTIL);
  234. first:=gensinglenode(blockn,first);
  235. p_e:=expr;
  236. repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
  237. end;
  238. function while_statement : ptree;
  239. var
  240. p_e,p_a : ptree;
  241. begin
  242. consume(_WHILE);
  243. p_e:=expr;
  244. consume(_DO);
  245. p_a:=statement;
  246. while_statement:=genloopnode(whilen,p_e,p_a,nil,false);
  247. end;
  248. function for_statement : ptree;
  249. var
  250. p_e,tovalue,p_a : ptree;
  251. backward : boolean;
  252. begin
  253. { parse loop header }
  254. consume(_FOR);
  255. p_e:=expr;
  256. if token=_DOWNTO then
  257. begin
  258. consume(_DOWNTO);
  259. backward:=true;
  260. end
  261. else
  262. begin
  263. consume(_TO);
  264. backward:=false;
  265. end;
  266. tovalue:=expr;
  267. consume(_DO);
  268. { ... now the instruction }
  269. p_a:=statement;
  270. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  271. end;
  272. function _with_statement : ptree;
  273. var
  274. right,hp,p : ptree;
  275. i,levelcount : longint;
  276. withsymtable,symtab : psymtable;
  277. obj : pobjectdef;
  278. begin
  279. Must_be_valid:=false;
  280. p:=expr;
  281. do_firstpass(p);
  282. right:=nil;
  283. case p^.resulttype^.deftype of
  284. objectdef : begin
  285. obj:=pobjectdef(p^.resulttype);
  286. levelcount:=0;
  287. while assigned(obj) do
  288. begin
  289. symtab:=obj^.publicsyms;
  290. withsymtable:=new(psymtable,init(symtable.withsymtable));
  291. withsymtable^.wurzel:=symtab^.wurzel;
  292. withsymtable^.next:=symtablestack;
  293. symtablestack:=withsymtable;
  294. obj:=obj^.childof;
  295. inc(levelcount);
  296. end;
  297. end;
  298. recorddef : begin
  299. symtab:=precdef(p^.resulttype)^.symtable;
  300. levelcount:=1;
  301. withsymtable:=new(psymtable,init(symtable.withsymtable));
  302. withsymtable^.wurzel:=symtab^.wurzel;
  303. withsymtable^.next:=symtablestack;
  304. symtablestack:=withsymtable;
  305. end;
  306. else
  307. begin
  308. Message(parser_e_false_with_expr);
  309. { try to recover from error }
  310. if token=COMMA then
  311. begin
  312. consume(COMMA);
  313. {$ifdef tp}
  314. hp:=_with_statement;
  315. {$else}
  316. hp:=_with_statement();
  317. {$endif}
  318. end
  319. else
  320. begin
  321. consume(_DO);
  322. { ignore all }
  323. if token<>SEMICOLON then
  324. statement;
  325. end;
  326. _with_statement:=nil;
  327. exit;
  328. end;
  329. end;
  330. if token=COMMA then
  331. begin
  332. consume(COMMA);
  333. {$ifdef tp}
  334. right:=_with_statement;
  335. {$else}
  336. right:=_with_statement();
  337. {$endif}
  338. end
  339. else
  340. begin
  341. consume(_DO);
  342. if token<>SEMICOLON then
  343. right:=statement
  344. else
  345. right:=nil;
  346. end;
  347. for i:=1 to levelcount do
  348. symtablestack:=symtablestack^.next;
  349. _with_statement:=genwithnode(withsymtable,p,right,levelcount);
  350. end;
  351. function with_statement : ptree;
  352. begin
  353. consume(_WITH);
  354. with_statement:=_with_statement;
  355. end;
  356. function raise_statement : ptree;
  357. var
  358. p1,p2 : ptree;
  359. begin
  360. p1:=nil;
  361. p2:=nil;
  362. consume(_RAISE);
  363. if token<>SEMICOLON then
  364. begin
  365. p1:=expr;
  366. if (token=ID) and (pattern='AT') then
  367. begin
  368. consume(ID);
  369. p2:=expr;
  370. end;
  371. end
  372. else
  373. begin
  374. if not(in_except_block) then
  375. Message(parser_e_no_reraise_possible);
  376. end;
  377. raise_statement:=gennode(raisen,p1,p2);
  378. end;
  379. function try_statement : ptree;
  380. var
  381. p_try_block,p_finally_block,first,last,
  382. p_default,e1,e2,p_specific : ptree;
  383. old_in_except_block : boolean;
  384. begin
  385. p_default:=nil;
  386. p_specific:=nil;
  387. { read statements to try }
  388. consume(_TRY);
  389. first:=nil;
  390. while (token<>_FINALLY) and (token<>_EXCEPT) do
  391. begin
  392. if first=nil then
  393. begin
  394. last:=gennode(statementn,nil,statement);
  395. first:=last;
  396. end
  397. else
  398. begin
  399. last^.left:=gennode(statementn,nil,statement);
  400. last:=last^.left;
  401. end;
  402. if token<>SEMICOLON then
  403. break;
  404. consume(SEMICOLON);
  405. emptystats;
  406. end;
  407. p_try_block:=gensinglenode(blockn,first);
  408. if token=_FINALLY then
  409. begin
  410. consume(_FINALLY);
  411. p_finally_block:=statements_til_end;
  412. try_statement:=gennode(tryfinallyn,p_try_block,p_finally_block);
  413. end
  414. else
  415. begin
  416. consume(_EXCEPT);
  417. old_in_except_block:=in_except_block;
  418. in_except_block:=true;
  419. if token=_ON then
  420. { catch specific exceptions }
  421. begin
  422. repeat
  423. consume(_ON);
  424. e1:=expr;
  425. if token=COLON then
  426. begin
  427. consume(COLON);
  428. e2:=expr;
  429. { !!!!! }
  430. end
  431. else
  432. begin
  433. { !!!!! }
  434. end;
  435. consume(_DO);
  436. statement;
  437. if token<>SEMICOLON then
  438. break;
  439. emptystats;
  440. until false;
  441. if token=_ELSE then
  442. { catch the other exceptions }
  443. begin
  444. consume(_ELSE);
  445. p_default:=statements_til_end;
  446. end;
  447. end
  448. else
  449. { catch all exceptions }
  450. begin
  451. p_default:=statements_til_end;
  452. end;
  453. in_except_block:=old_in_except_block;
  454. try_statement:=genloopnode(tryexceptn,p_try_block,p_specific,p_default,false);
  455. end;
  456. end;
  457. function exit_statement : ptree;
  458. var
  459. p : ptree;
  460. begin
  461. consume(_EXIT);
  462. if token=LKLAMMER then
  463. begin
  464. consume(LKLAMMER);
  465. p:=expr;
  466. consume(RKLAMMER);
  467. if procinfo.retdef=pdef(voiddef) then
  468. Message(parser_e_void_function)
  469. else
  470. procinfo.funcret_is_valid:=true;
  471. end
  472. else
  473. p:=nil;
  474. exit_statement:=gensinglenode(exitn,p);
  475. end;
  476. {$ifdef i386}
  477. function _asm_statement : ptree;
  478. begin
  479. case aktasmmode of
  480. I386_ATT : _asm_statement:=ratti386.assemble;
  481. I386_INTEL : _asm_statement:=rai386.assemble;
  482. I386_DIRECT : _asm_statement:=radi386.assemble;
  483. else internalerror(30004);
  484. end;
  485. { Erst am Ende _ASM konsumieren, da der Scanner sonst die }
  486. { erste Assemblerstatement zu lesen versucht! }
  487. consume(_ASM);
  488. { (END is read) }
  489. if token=LECKKLAMMER then
  490. begin
  491. { it's possible to specify the modified registers }
  492. consume(LECKKLAMMER);
  493. if token<>RECKKLAMMER then
  494. repeat
  495. pattern:=upper(pattern);
  496. if pattern='EAX' then
  497. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  498. else if pattern='EBX' then
  499. usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  500. else if pattern='ECX' then
  501. usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  502. else if pattern='EDX' then
  503. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  504. else if pattern='ESI' then
  505. usedinproc:=usedinproc or ($80 shr byte(R_ESI))
  506. else if pattern='EDI' then
  507. usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  508. else consume(RECKKLAMMER);
  509. consume(CSTRING);
  510. if token=COMMA then consume(COMMA)
  511. else break;
  512. until false;
  513. consume(RECKKLAMMER);
  514. end
  515. else usedinproc:=$ff;
  516. end;
  517. {$endif}
  518. {$ifdef m68k}
  519. function _asm_statement : ptree;
  520. begin
  521. _asm_statement:= ra68k.assemble;
  522. { Erst am Ende _ASM konsumieren, da der Scanner sonst die }
  523. { erste Assemblerstatement zu lesen versucht! }
  524. consume(_ASM);
  525. { (END is read) }
  526. if token=LECKKLAMMER then
  527. begin
  528. { it's possible to specify the modified registers }
  529. { we only check the registers which are not reserved }
  530. { and which can be used. This is done for future }
  531. { optimizations. }
  532. consume(LECKKLAMMER);
  533. if token<>RECKKLAMMER then
  534. repeat
  535. pattern:=upper(pattern);
  536. if pattern='D0' then
  537. usedinproc:=usedinproc or ($800 shr word(R_D0))
  538. else if pattern='D1' then
  539. usedinproc:=usedinproc or ($800 shr word(R_D1))
  540. else if pattern='D6' then
  541. usedinproc:=usedinproc or ($800 shr word(R_D6))
  542. else if pattern='A0' then
  543. usedinproc:=usedinproc or ($800 shr word(R_A0))
  544. else if pattern='A1' then
  545. usedinproc:=usedinproc or ($800 shr word(R_A1))
  546. else consume(RECKKLAMMER);
  547. consume(CSTRING);
  548. if token=COMMA then consume(COMMA)
  549. else break;
  550. until false;
  551. consume(RECKKLAMMER);
  552. end
  553. else usedinproc:=$ffff;
  554. end;
  555. {$endif}
  556. function new_dispose_statement : ptree;
  557. var
  558. p,p2 : ptree;
  559. ht : ttoken;
  560. again : boolean; { dummy for do_proc_call }
  561. destrukname : stringid;
  562. sym : psym;
  563. classh : pobjectdef;
  564. pd,pd2 : pdef;
  565. store_valid : boolean;
  566. tt : ttreetyp;
  567. begin
  568. ht:=token;
  569. if token=_NEW then consume(_NEW)
  570. else consume(_DISPOSE);
  571. if ht=_NEW then
  572. tt:=hnewn
  573. else
  574. tt:=hdisposen;
  575. consume(LKLAMMER);
  576. p:=expr;
  577. { calc return type }
  578. cleartempgen;
  579. Store_valid := Must_be_valid;
  580. Must_be_valid := False;
  581. do_firstpass(p);
  582. Must_be_valid := Store_valid;
  583. {var o:Pobject;
  584. begin
  585. new(o,init); (*Also a valid new statement*)
  586. end;}
  587. if token=COMMA then
  588. begin
  589. { extended syntax of new and dispose }
  590. { function styled new is handled in factor }
  591. consume(COMMA);
  592. { destructors have no parameters }
  593. destrukname:=pattern;
  594. consume(ID);
  595. pd:=p^.resulttype;
  596. pd2:=pd;
  597. if (p^.resulttype = nil) or (pd^.deftype<>pointerdef) then
  598. begin
  599. Message(parser_e_pointer_type_expected);
  600. p:=factor(false);
  601. consume(RKLAMMER);
  602. new_dispose_statement:=genzeronode(errorn);
  603. exit;
  604. end;
  605. { first parameter must be an object or class }
  606. if ppointerdef(pd)^.definition^.deftype<>objectdef then
  607. begin
  608. Message(parser_e_pointer_to_class_expected);
  609. new_dispose_statement:=factor(false);
  610. consume_all_until(RKLAMMER);
  611. consume(RKLAMMER);
  612. exit;
  613. end;
  614. { check, if the first parameter is a pointer to a _class_ }
  615. classh:=pobjectdef(ppointerdef(pd)^.definition);
  616. if (classh^.options and oois_class)<>0 then
  617. begin
  618. Message(parser_e_no_new_or_dispose_for_classes);
  619. new_dispose_statement:=factor(false);
  620. { while token<>RKLAMMER do
  621. consume(token); }
  622. consume_all_until(RKLAMMER);
  623. consume(RKLAMMER);
  624. exit;
  625. end;
  626. { search cons-/destructor, also in parent classes }
  627. sym:=nil;
  628. while assigned(classh) do
  629. begin
  630. sym:=classh^.publicsyms^.search(pattern);
  631. srsymtable:=classh^.publicsyms;
  632. if assigned(sym) then
  633. break;
  634. classh:=classh^.childof;
  635. end;
  636. { the second parameter of new/dispose must be a call }
  637. { to a cons-/destructor }
  638. if (sym^.typ<>procsym) then
  639. begin
  640. Message(parser_e_expr_have_to_be_destructor_call);
  641. new_dispose_statement:=genzeronode(errorn);
  642. end
  643. else
  644. begin
  645. p2:=gensinglenode(tt,p);
  646. if ht=_NEW then
  647. begin
  648. { Constructors can take parameters.}
  649. p2^.resulttype:=ppointerdef(pd)^.definition;
  650. do_member_read(sym,p2,pd,again);
  651. end
  652. else
  653. { destructors can't.}
  654. p2:=genmethodcallnode(pprocsym(sym),srsymtable,p2);
  655. { we need the real called method }
  656. cleartempgen;
  657. do_firstpass(p2);
  658. if (ht=_NEW) and ((p2^.procdefinition^.options and poconstructor)=0) then
  659. Message(parser_e_expr_have_to_be_constructor_call);
  660. if (ht=_DISPOSE) and ((p2^.procdefinition^.options and podestructor)=0) then
  661. Message(parser_e_expr_have_to_be_destructor_call);
  662. if ht=_NEW then
  663. begin
  664. p2:=gennode(assignn,getcopy(p),gensinglenode(newn,p2));
  665. p2^.right^.resulttype:=pd2;
  666. end;
  667. new_dispose_statement:=p2;
  668. end;
  669. end
  670. else
  671. begin
  672. if (p^.resulttype=nil) or (p^.resulttype^.deftype<>pointerdef) then
  673. Begin
  674. Message(parser_e_pointer_type_expected);
  675. new_dispose_statement:=genzeronode(errorn);
  676. end
  677. else
  678. begin
  679. if (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) then
  680. Message(parser_w_use_extended_syntax_for_objects);
  681. case ht of
  682. _NEW : new_dispose_statement:=gensinglenode(simplenewn,p);
  683. _DISPOSE : new_dispose_statement:=gensinglenode(simpledisposen,p);
  684. end;
  685. end;
  686. end;
  687. consume(RKLAMMER);
  688. end;
  689. function statement_block : ptree;
  690. var
  691. first,last : ptree;
  692. begin
  693. first:=nil;
  694. consume(_BEGIN);
  695. while token<>_END do
  696. begin
  697. if first=nil then
  698. begin
  699. last:=gennode(statementn,nil,statement);
  700. first:=last;
  701. end
  702. else
  703. begin
  704. last^.left:=gennode(statementn,nil,statement);
  705. last:=last^.left;
  706. end;
  707. if token=_END then
  708. break
  709. else
  710. begin
  711. { if no semicolon, then error and go on }
  712. if token<>SEMICOLON then
  713. begin
  714. consume(SEMICOLON);
  715. { while token<>SEMICOLON do
  716. consume(token); }
  717. consume_all_until(SEMICOLON);
  718. end;
  719. consume(SEMICOLON);
  720. end;
  721. emptystats;
  722. end;
  723. consume(_END);
  724. last:=gensinglenode(blockn,first);
  725. set_file_line(first,last);
  726. statement_block:=last;
  727. end;
  728. function statement : ptree;
  729. var
  730. p : ptree;
  731. code : ptree;
  732. labelnr : plabel;
  733. {$ifdef UseTokenInfo}
  734. filepos : tfileposinfo;
  735. {$endif UseTokenInfo}
  736. label
  737. ready;
  738. begin
  739. {$ifdef UseTokenInfo}
  740. filepos:=tokeninfo^.fi;
  741. {$endif UseTokenInfo}
  742. case token of
  743. _GOTO : begin
  744. if not(cs_support_goto in aktswitches)then
  745. Message(sym_e_goto_and_label_not_supported);
  746. consume(_GOTO);
  747. if (token<>INTCONST) and (token<>ID) then
  748. begin
  749. Message(sym_e_label_not_found);
  750. code:=genzeronode(errorn);
  751. end
  752. else
  753. begin
  754. getsym(pattern,true);
  755. consume(token);
  756. if srsym^.typ<>labelsym then
  757. begin
  758. Message(sym_e_id_is_no_label_id);
  759. code:=genzeronode(errorn);
  760. end
  761. else
  762. code:=genlabelnode(goton,
  763. plabelsym(srsym)^.number);
  764. end;
  765. end;
  766. _BEGIN : code:=statement_block;
  767. _IF : code:=if_statement;
  768. _CASE : code:=case_statement;
  769. _REPEAT : code:=repeat_statement;
  770. _WHILE : code:=while_statement;
  771. _FOR : code:=for_statement;
  772. _NEW,_DISPOSE : code:=new_dispose_statement;
  773. _WITH : code:=with_statement;
  774. _TRY : code:=try_statement;
  775. _RAISE : code:=raise_statement;
  776. { semicolons,else until and end are ignored }
  777. SEMICOLON,
  778. _ELSE,
  779. _UNTIL,
  780. _END : code:=genzeronode(niln);
  781. _CONTINUE : begin
  782. consume(_CONTINUE);
  783. code:=genzeronode(continuen);
  784. end;
  785. _FAIL : begin
  786. { internalerror(100); }
  787. if (aktprocsym^.definition^.options and poconstructor)=0 then
  788. Message(parser_e_fail_only_in_constructor);
  789. consume(_FAIL);
  790. code:=genzeronode(failn);
  791. end;
  792. {
  793. _BREAK:
  794. begin
  795. consume(_BREAK);
  796. code:=genzeronode(breakn);
  797. end;
  798. }
  799. _EXIT : code:=exit_statement;
  800. _ASM : code:=_asm_statement;
  801. else
  802. begin
  803. if (token=INTCONST) or
  804. ((token=ID) and
  805. not((cs_delphi2_compatible in aktswitches) and
  806. (pattern='RESULT'))) then
  807. begin
  808. getsym(pattern,false);
  809. if assigned(srsym) and (srsym^.typ=labelsym) then
  810. begin
  811. consume(token);
  812. consume(COLON);
  813. if plabelsym(srsym)^.defined then
  814. Message(sym_e_label_already_defined);
  815. plabelsym(srsym)^.defined:=true;
  816. { statement modifies srsym }
  817. labelnr:=plabelsym(srsym)^.number;
  818. { the pointer to the following instruction }
  819. { isn't a very clean way }
  820. {$ifdef tp}
  821. code:=gensinglenode(labeln,statement);
  822. {$else}
  823. code:=gensinglenode(labeln,statement());
  824. {$endif}
  825. code^.labelnr:=labelnr;
  826. { sorry, but there is a jump the easiest way }
  827. goto ready;
  828. end;
  829. end;
  830. p:=expr;
  831. if not(p^.treetype in [calln,assignn,breakn,inlinen,
  832. continuen]) then
  833. Message(cg_e_illegal_expression);
  834. code:=p;
  835. end;
  836. end;
  837. ready:
  838. {$ifdef UseTokenInfo}
  839. set_tree_filepos(code,filepos);
  840. {$endif UseTokenInfo}
  841. statement:=code;
  842. end;
  843. function block(islibrary : boolean) : ptree;
  844. {$ifdef TEST_FUNCRET }
  845. var
  846. funcretsym : pfuncretsym;
  847. {$endif TEST_FUNCRET }
  848. begin
  849. {$ifdef TEST_FUNCRET }
  850. if procinfo.retdef<>pdef(voiddef) then
  851. begin
  852. { if the current is a function aktprocsym is non nil }
  853. { and there is a local symtable set }
  854. funcretsym:=new(pfuncretsym,init(aktprocsym^.name),@procinfo);
  855. { insert in local symtable }
  856. symtablestack^.insert(funcretsym);
  857. end;
  858. {$endif TEST_FUNCRET }
  859. read_declarations(islibrary);
  860. { temporary space is set, while the BEGIN of the procedure }
  861. if (symtablestack^.symtabletype=localsymtable) then
  862. procinfo.firsttemp := -symtablestack^.datasize
  863. else procinfo.firsttemp := 0;
  864. { space for the return value }
  865. { !!!!! this means that we can not set the return value
  866. in a subfunction !!!!! }
  867. { because we don't know yet where the address is }
  868. if procinfo.retdef<>pdef(voiddef) then
  869. begin
  870. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  871. { if (procinfo.retdef^.deftype=orddef) or
  872. (procinfo.retdef^.deftype=pointerdef) or
  873. (procinfo.retdef^.deftype=enumdef) or
  874. (procinfo.retdef^.deftype=procvardef) or
  875. (procinfo.retdef^.deftype=floatdef) or
  876. (
  877. (procinfo.retdef^.deftype=setdef) and
  878. (psetdef(procinfo.retdef)^.settype=smallset)
  879. ) then }
  880. begin
  881. {$ifdef TEST_FUNCRET }
  882. { the space has been set in the local symtable }
  883. procinfo.retoffset:=-funcretsym^.address;
  884. strdispose(funcretsym^._name);
  885. { lowercase name unreachable }
  886. { as it is handled differently }
  887. funcretsym^._name:=strpnew('func_result');
  888. {$else TEST_FUNCRET }
  889. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  890. procinfo.firsttemp:=procinfo.retoffset;
  891. {$endif TEST_FUNCRET }
  892. if (procinfo.flags and pi_operator)<>0 then
  893. {opsym^.address:=procinfo.call_offset; is wrong PM }
  894. opsym^.address:=-procinfo.retoffset;
  895. { eax is modified by a function }
  896. {$ifdef i386}
  897. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  898. {$endif}
  899. {$ifdef m68k}
  900. usedinproc:=usedinproc or ($800 shr word(R_D0))
  901. {$endif}
  902. end;
  903. end;
  904. {Unit initialization?.}
  905. if (lexlevel=1) then
  906. if (token=_END) then
  907. begin
  908. consume(_END);
  909. block:=nil;
  910. end
  911. else
  912. begin
  913. current_module^.flags:=current_module^.flags or
  914. uf_init;
  915. block:=statement_block;
  916. end
  917. else
  918. block:=statement_block;
  919. end;
  920. function assembler_block : ptree;
  921. begin
  922. read_declarations(false);
  923. { temporary space is set, while the BEGIN of the procedure }
  924. if symtablestack^.symtabletype=localsymtable then
  925. procinfo.firsttemp := -symtablestack^.datasize
  926. else procinfo.firsttemp := 0;
  927. { assembler code does not allocate }
  928. { space for the return value }
  929. if procinfo.retdef<>pdef(voiddef) then
  930. begin
  931. if ret_in_acc(procinfo.retdef) then
  932. begin
  933. { in assembler code the result should be directly in %eax
  934. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  935. procinfo.firsttemp:=procinfo.retoffset; }
  936. {$ifdef i386}
  937. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  938. {$endif}
  939. {$ifdef m68k}
  940. usedinproc:=usedinproc or ($800 shr word(R_D0))
  941. {$endif}
  942. end
  943. else
  944. { should we allow assembler functions of big elements ? }
  945. Message(parser_e_asm_incomp_with_function_return);
  946. end;
  947. { set the framepointer to esp for assembler functions }
  948. { but only if the are no local variables }
  949. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  950. (aktprocsym^.definition^.localst^.datasize=0) then
  951. begin
  952. {$ifdef i386}
  953. procinfo.framepointer:=R_ESP;
  954. {$endif}
  955. {$ifdef m68k}
  956. procinfo.framepointer:=R_SP;
  957. {$endif}
  958. { set the right value for parameters }
  959. dec(aktprocsym^.definition^.parast^.call_offset,4);
  960. dec(procinfo.call_offset,4);
  961. end;
  962. assembler_block:=_asm_statement;
  963. end;
  964. end.
  965. {
  966. $Log$
  967. Revision 1.7 1998-05-01 16:38:46 florian
  968. * handling of private and protected fixed
  969. + change_keywords_to_tp implemented to remove
  970. keywords which aren't supported by tp
  971. * break and continue are now symbols of the system unit
  972. + widestring, longstring and ansistring type released
  973. Revision 1.6 1998/04/30 15:59:42 pierre
  974. * GDB works again better :
  975. correct type info in one pass
  976. + UseTokenInfo for better source position
  977. * fixed one remaining bug in scanner for line counts
  978. * several little fixes
  979. Revision 1.5 1998/04/29 10:33:59 pierre
  980. + added some code for ansistring (not complete nor working yet)
  981. * corrected operator overloading
  982. * corrected nasm output
  983. + started inline procedures
  984. + added starstarn : use ** for exponentiation (^ gave problems)
  985. + started UseTokenInfo cond to get accurate positions
  986. Revision 1.4 1998/04/08 16:58:05 pierre
  987. * several bugfixes
  988. ADD ADC and AND are also sign extended
  989. nasm output OK (program still crashes at end
  990. and creates wrong assembler files !!)
  991. procsym types sym in tdef removed !!
  992. Revision 1.3 1998/03/28 23:09:56 florian
  993. * secondin bugfix (m68k and i386)
  994. * overflow checking bugfix (m68k and i386) -- pretty useless in
  995. secondadd, since everything is done using 32-bit
  996. * loading pointer to routines hopefully fixed (m68k)
  997. * flags problem with calls to RTL internal routines fixed (still strcmp
  998. to fix) (m68k)
  999. * #ELSE was still incorrect (didn't take care of the previous level)
  1000. * problem with filenames in the command line solved
  1001. * problem with mangledname solved
  1002. * linking name problem solved (was case insensitive)
  1003. * double id problem and potential crash solved
  1004. * stop after first error
  1005. * and=>test problem removed
  1006. * correct read for all float types
  1007. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  1008. * push/pop is now correct optimized (=> mov (%esp),reg)
  1009. Revision 1.2 1998/03/26 11:18:31 florian
  1010. - switch -Sa removed
  1011. - support of a:=b:=0 removed
  1012. Revision 1.1.1.1 1998/03/25 11:18:15 root
  1013. * Restored version
  1014. Revision 1.21 1998/03/10 16:27:42 pierre
  1015. * better line info in stabs debug
  1016. * symtabletype and lexlevel separated into two fields of tsymtable
  1017. + ifdef MAKELIB for direct library output, not complete
  1018. + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  1019. working
  1020. + ifdef TESTFUNCRET for setting func result in underfunction, not
  1021. working
  1022. Revision 1.20 1998/03/10 04:18:26 carl
  1023. * wrong units were being used with m68k target
  1024. Revision 1.19 1998/03/10 01:17:25 peter
  1025. * all files have the same header
  1026. * messages are fully implemented, EXTDEBUG uses Comment()
  1027. + AG... files for the Assembler generation
  1028. Revision 1.18 1998/03/06 00:52:46 peter
  1029. * replaced all old messages from errore.msg, only ExtDebug and some
  1030. Comment() calls are left
  1031. * fixed options.pas
  1032. Revision 1.17 1998/03/02 01:49:07 peter
  1033. * renamed target_DOS to target_GO32V1
  1034. + new verbose system, merged old errors and verbose units into one new
  1035. verbose.pas, so errors.pas is obsolete
  1036. Revision 1.16 1998/02/22 23:03:30 peter
  1037. * renamed msource->mainsource and name->unitname
  1038. * optimized filename handling, filename is not seperate anymore with
  1039. path+name+ext, this saves stackspace and a lot of fsplit()'s
  1040. * recompiling of some units in libraries fixed
  1041. * shared libraries are working again
  1042. + $LINKLIB <lib> to support automatic linking to libraries
  1043. + libraries are saved/read from the ppufile, also allows more libraries
  1044. per ppufile
  1045. Revision 1.15 1998/02/21 03:33:54 carl
  1046. + mit assembler syntax support
  1047. Revision 1.14 1998/02/13 10:35:29 daniel
  1048. * Made Motorola version compilable.
  1049. * Fixed optimizer
  1050. Revision 1.13 1998/02/12 11:50:30 daniel
  1051. Yes! Finally! After three retries, my patch!
  1052. Changes:
  1053. Complete rewrite of psub.pas.
  1054. Added support for DLL's.
  1055. Compiler requires less memory.
  1056. Platform units for each platform.
  1057. Revision 1.12 1998/02/11 21:56:39 florian
  1058. * bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089
  1059. Revision 1.11 1998/02/07 09:39:26 florian
  1060. * correct handling of in_main
  1061. + $D,$T,$X,$V like tp
  1062. Revision 1.10 1998/01/31 00:42:26 carl
  1063. +* Final bugfix #60 (working!) Type checking in case statements
  1064. Revision 1.7 1998/01/21 02:18:28 carl
  1065. * bugfix 79 (assembler_block now chooses the correct framepointer and
  1066. offset).
  1067. Revision 1.6 1998/01/16 22:34:43 michael
  1068. * Changed 'conversation' to 'conversion'. Waayyy too much chatting going on
  1069. in this compiler :)
  1070. Revision 1.5 1998/01/12 14:51:18 carl
  1071. - temporariliy removed case type checking until i know where the bug
  1072. comes from!
  1073. Revision 1.4 1998/01/11 19:23:49 carl
  1074. * bug fix number 60 (case statements type checking)
  1075. Revision 1.3 1998/01/11 10:54:25 florian
  1076. + generic library support
  1077. Revision 1.2 1998/01/09 09:10:02 michael
  1078. + Initial implementation, second try
  1079. }