pstatmnt.pas 40 KB

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