pstatmnt.pas 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  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(anwein,nil,statement);
  83. first:=last;
  84. end
  85. else
  86. begin
  87. last^.left:=gennode(anwein,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(anwein,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(anwein,nil,statement);
  220. first:=last;
  221. end
  222. else
  223. begin
  224. last^.left:=gennode(anwein,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(anwein,nil,statement);
  395. first:=last;
  396. end
  397. else
  398. begin
  399. last^.left:=gennode(anwein,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(anwein,nil,statement);
  700. first:=last;
  701. end
  702. else
  703. begin
  704. last^.left:=gennode(anwein,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. label
  734. ready;
  735. begin
  736. case token of
  737. _GOTO : begin
  738. if not(cs_support_goto in aktswitches)then
  739. Message(sym_e_goto_and_label_not_supported);
  740. consume(_GOTO);
  741. if (token<>INTCONST) and (token<>ID) then
  742. begin
  743. Message(sym_e_label_not_found);
  744. code:=genzeronode(errorn);
  745. end
  746. else
  747. begin
  748. getsym(pattern,true);
  749. consume(token);
  750. if srsym^.typ<>labelsym then
  751. begin
  752. Message(sym_e_id_is_no_label_id);
  753. code:=genzeronode(errorn);
  754. end
  755. else
  756. code:=genlabelnode(goton,
  757. plabelsym(srsym)^.number);
  758. end;
  759. end;
  760. _BEGIN : code:=statement_block;
  761. _IF : code:=if_statement;
  762. _CASE : code:=case_statement;
  763. _REPEAT : code:=repeat_statement;
  764. _WHILE : code:=while_statement;
  765. _FOR : code:=for_statement;
  766. _NEW,_DISPOSE : code:=new_dispose_statement;
  767. _WITH : code:=with_statement;
  768. _TRY : code:=try_statement;
  769. _RAISE : code:=raise_statement;
  770. { semicolons,else until and end are ignored }
  771. SEMICOLON,
  772. _ELSE,
  773. _UNTIL,
  774. _END : code:=genzeronode(niln);
  775. _CONTINUE : begin
  776. consume(_CONTINUE);
  777. code:=genzeronode(continuen);
  778. end;
  779. _FAIL : begin
  780. { internalerror(100); }
  781. if (aktprocsym^.definition^.options and poconstructor)=0 then
  782. Message(parser_e_fail_only_in_constructor);
  783. consume(_FAIL);
  784. code:=genzeronode(failn);
  785. end;
  786. _BREAK:
  787. begin
  788. consume(_BREAK);
  789. code:=genzeronode(breakn);
  790. end;
  791. _EXIT : code:=exit_statement;
  792. _ASM : code:=_asm_statement;
  793. else
  794. begin
  795. if (token=INTCONST) or
  796. ((token=ID) and
  797. not((cs_delphi2_compatible in aktswitches) and
  798. (pattern='RESULT'))) then
  799. begin
  800. getsym(pattern,false);
  801. if assigned(srsym) and (srsym^.typ=labelsym) then
  802. begin
  803. consume(token);
  804. consume(COLON);
  805. if plabelsym(srsym)^.defined then
  806. Message(sym_e_label_already_defined);
  807. plabelsym(srsym)^.defined:=true;
  808. { statement modifies srsym }
  809. labelnr:=plabelsym(srsym)^.number;
  810. { the pointer to the following instruction }
  811. { isn't a very clean way }
  812. {$ifdef tp}
  813. code:=gensinglenode(labeln,statement);
  814. {$else}
  815. code:=gensinglenode(labeln,statement());
  816. {$endif}
  817. code^.labelnr:=labelnr;
  818. { sorry, but there is a jump the easiest way }
  819. goto ready;
  820. end;
  821. end;
  822. p:=expr;
  823. if (p^.treetype<>calln) and
  824. (p^.treetype<>assignn) and
  825. (p^.treetype<>inlinen) then
  826. Message(cg_e_illegal_expression);
  827. code:=p;
  828. end;
  829. end;
  830. ready:
  831. statement:=code;
  832. end;
  833. function block(islibrary : boolean) : ptree;
  834. {$ifdef TEST_FUNCRET }
  835. var
  836. funcretsym : pfuncretsym;
  837. {$endif TEST_FUNCRET }
  838. begin
  839. {$ifdef TEST_FUNCRET }
  840. if procinfo.retdef<>pdef(voiddef) then
  841. begin
  842. { if the current is a function aktprocsym is non nil }
  843. { and there is a local symtable set }
  844. funcretsym:=new(pfuncretsym,init(aktprocsym^.name),@procinfo);
  845. { insert in local symtable }
  846. symtablestack^.insert(funcretsym);
  847. end;
  848. {$endif TEST_FUNCRET }
  849. read_declarations(islibrary);
  850. { temporary space is set, while the BEGIN of the procedure }
  851. if (symtablestack^.symtabletype=localsymtable) then
  852. procinfo.firsttemp := -symtablestack^.datasize
  853. else procinfo.firsttemp := 0;
  854. { space for the return value }
  855. { !!!!! this means that we can not set the return value
  856. in a subfunction !!!!! }
  857. { because we don't know yet where the address is }
  858. if procinfo.retdef<>pdef(voiddef) then
  859. begin
  860. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  861. { if (procinfo.retdef^.deftype=orddef) or
  862. (procinfo.retdef^.deftype=pointerdef) or
  863. (procinfo.retdef^.deftype=enumdef) or
  864. (procinfo.retdef^.deftype=procvardef) or
  865. (procinfo.retdef^.deftype=floatdef) or
  866. (
  867. (procinfo.retdef^.deftype=setdef) and
  868. (psetdef(procinfo.retdef)^.settype=smallset)
  869. ) then }
  870. begin
  871. {$ifdef TEST_FUNCRET }
  872. { the space has been set in the local symtable }
  873. procinfo.retoffset:=-funcretsym^.address;
  874. strdispose(funcretsym^._name);
  875. { lowercase name unreachable }
  876. { as it is handled differently }
  877. funcretsym^._name:=strpnew('func_result');
  878. {$else TEST_FUNCRET }
  879. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  880. procinfo.firsttemp:=procinfo.retoffset;
  881. {$endif TEST_FUNCRET }
  882. if (procinfo.flags and pooperator)<>0 then
  883. {opsym^.address:=procinfo.call_offset; is wrong PM }
  884. opsym^.address:=procinfo.retoffset;
  885. { eax is modified by a function }
  886. {$ifdef i386}
  887. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  888. {$endif}
  889. {$ifdef m68k}
  890. usedinproc:=usedinproc or ($800 shr word(R_D0))
  891. {$endif}
  892. end;
  893. end;
  894. {Unit initialization?.}
  895. if (lexlevel=1) then
  896. if (token=_END) then
  897. begin
  898. consume(_END);
  899. block:=nil;
  900. end
  901. else
  902. begin
  903. current_module^.flags:=current_module^.flags or
  904. uf_init;
  905. block:=statement_block;
  906. end
  907. else
  908. block:=statement_block;
  909. end;
  910. function assembler_block : ptree;
  911. begin
  912. read_declarations(false);
  913. { temporary space is set, while the BEGIN of the procedure }
  914. if symtablestack^.symtabletype=localsymtable then
  915. procinfo.firsttemp := -symtablestack^.datasize
  916. else procinfo.firsttemp := 0;
  917. { assembler code does not allocate }
  918. { space for the return value }
  919. if procinfo.retdef<>pdef(voiddef) then
  920. begin
  921. if ret_in_acc(procinfo.retdef) then
  922. begin
  923. { in assembler code the result should be directly in %eax
  924. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  925. procinfo.firsttemp:=procinfo.retoffset; }
  926. {$ifdef i386}
  927. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  928. {$endif}
  929. {$ifdef m68k}
  930. usedinproc:=usedinproc or ($800 shr word(R_D0))
  931. {$endif}
  932. end
  933. else
  934. { should we allow assembler functions of big elements ? }
  935. Message(parser_e_asm_incomp_with_function_return);
  936. end;
  937. { set the framepointer to esp for assembler functions }
  938. { but only if the are no local variables }
  939. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  940. (aktprocsym^.definition^.localst^.datasize=0) then
  941. begin
  942. {$ifdef i386}
  943. procinfo.framepointer:=R_ESP;
  944. {$endif}
  945. {$ifdef m68k}
  946. procinfo.framepointer:=R_SP;
  947. {$endif}
  948. { set the right value for parameters }
  949. dec(aktprocsym^.definition^.parast^.call_offset,4);
  950. dec(procinfo.call_offset,4);
  951. end;
  952. assembler_block:=_asm_statement;
  953. end;
  954. end.
  955. {
  956. $Log$
  957. Revision 1.4 1998-04-08 16:58:05 pierre
  958. * several bugfixes
  959. ADD ADC and AND are also sign extended
  960. nasm output OK (program still crashes at end
  961. and creates wrong assembler files !!)
  962. procsym types sym in tdef removed !!
  963. Revision 1.3 1998/03/28 23:09:56 florian
  964. * secondin bugfix (m68k and i386)
  965. * overflow checking bugfix (m68k and i386) -- pretty useless in
  966. secondadd, since everything is done using 32-bit
  967. * loading pointer to routines hopefully fixed (m68k)
  968. * flags problem with calls to RTL internal routines fixed (still strcmp
  969. to fix) (m68k)
  970. * #ELSE was still incorrect (didn't take care of the previous level)
  971. * problem with filenames in the command line solved
  972. * problem with mangledname solved
  973. * linking name problem solved (was case insensitive)
  974. * double id problem and potential crash solved
  975. * stop after first error
  976. * and=>test problem removed
  977. * correct read for all float types
  978. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  979. * push/pop is now correct optimized (=> mov (%esp),reg)
  980. Revision 1.2 1998/03/26 11:18:31 florian
  981. - switch -Sa removed
  982. - support of a:=b:=0 removed
  983. Revision 1.1.1.1 1998/03/25 11:18:15 root
  984. * Restored version
  985. Revision 1.21 1998/03/10 16:27:42 pierre
  986. * better line info in stabs debug
  987. * symtabletype and lexlevel separated into two fields of tsymtable
  988. + ifdef MAKELIB for direct library output, not complete
  989. + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  990. working
  991. + ifdef TESTFUNCRET for setting func result in underfunction, not
  992. working
  993. Revision 1.20 1998/03/10 04:18:26 carl
  994. * wrong units were being used with m68k target
  995. Revision 1.19 1998/03/10 01:17:25 peter
  996. * all files have the same header
  997. * messages are fully implemented, EXTDEBUG uses Comment()
  998. + AG... files for the Assembler generation
  999. Revision 1.18 1998/03/06 00:52:46 peter
  1000. * replaced all old messages from errore.msg, only ExtDebug and some
  1001. Comment() calls are left
  1002. * fixed options.pas
  1003. Revision 1.17 1998/03/02 01:49:07 peter
  1004. * renamed target_DOS to target_GO32V1
  1005. + new verbose system, merged old errors and verbose units into one new
  1006. verbose.pas, so errors.pas is obsolete
  1007. Revision 1.16 1998/02/22 23:03:30 peter
  1008. * renamed msource->mainsource and name->unitname
  1009. * optimized filename handling, filename is not seperate anymore with
  1010. path+name+ext, this saves stackspace and a lot of fsplit()'s
  1011. * recompiling of some units in libraries fixed
  1012. * shared libraries are working again
  1013. + $LINKLIB <lib> to support automatic linking to libraries
  1014. + libraries are saved/read from the ppufile, also allows more libraries
  1015. per ppufile
  1016. Revision 1.15 1998/02/21 03:33:54 carl
  1017. + mit assembler syntax support
  1018. Revision 1.14 1998/02/13 10:35:29 daniel
  1019. * Made Motorola version compilable.
  1020. * Fixed optimizer
  1021. Revision 1.13 1998/02/12 11:50:30 daniel
  1022. Yes! Finally! After three retries, my patch!
  1023. Changes:
  1024. Complete rewrite of psub.pas.
  1025. Added support for DLL's.
  1026. Compiler requires less memory.
  1027. Platform units for each platform.
  1028. Revision 1.12 1998/02/11 21:56:39 florian
  1029. * bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089
  1030. Revision 1.11 1998/02/07 09:39:26 florian
  1031. * correct handling of in_main
  1032. + $D,$T,$X,$V like tp
  1033. Revision 1.10 1998/01/31 00:42:26 carl
  1034. +* Final bugfix #60 (working!) Type checking in case statements
  1035. Revision 1.7 1998/01/21 02:18:28 carl
  1036. * bugfix 79 (assembler_block now chooses the correct framepointer and
  1037. offset).
  1038. Revision 1.6 1998/01/16 22:34:43 michael
  1039. * Changed 'conversation' to 'conversion'. Waayyy too much chatting going on
  1040. in this compiler :)
  1041. Revision 1.5 1998/01/12 14:51:18 carl
  1042. - temporariliy removed case type checking until i know where the bug
  1043. comes from!
  1044. Revision 1.4 1998/01/11 19:23:49 carl
  1045. * bug fix number 60 (case statements type checking)
  1046. Revision 1.3 1998/01/11 10:54:25 florian
  1047. + generic library support
  1048. Revision 1.2 1998/01/09 09:10:02 michael
  1049. + Initial implementation, second try
  1050. }