pstatmnt.pas 38 KB

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