pstatmnt.pas 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  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. strings,cobjects,globals,files,verbose,systems,
  31. symtable,aasm,pass_1,types,scanner,hcodegen,ppu
  32. ,pbase,pexpr,pdecl
  33. {$ifdef i386}
  34. ,i386,tgeni386
  35. {$ifndef NoRa386Int}
  36. ,ra386int
  37. {$endif NoRa386Int}
  38. {$ifndef NoRa386Att}
  39. ,ra386att
  40. {$endif NoRa386Att}
  41. {$ifndef NoRa386Dir}
  42. ,ra386dir
  43. {$endif NoRa386Dir}
  44. {$endif i386}
  45. {$ifdef m68k}
  46. ,m68k,tgen68k
  47. {$ifndef NoRa68kMot}
  48. ,ra68kmot
  49. {$endif NoRa68kMot}
  50. {$endif m68k}
  51. ;
  52. const
  53. statement_level : longint = 0;
  54. function statement : ptree;forward;
  55. function if_statement : ptree;
  56. var
  57. ex,if_a,else_a : ptree;
  58. begin
  59. consume(_IF);
  60. ex:=comp_expr(true);
  61. consume(_THEN);
  62. if token<>_ELSE then
  63. if_a:=statement
  64. else
  65. if_a:=nil;
  66. if token=_ELSE then
  67. begin
  68. consume(_ELSE);
  69. else_a:=statement;
  70. end
  71. else
  72. else_a:=nil;
  73. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  74. end;
  75. { creates a block (list) of statements, til the next END token }
  76. function statements_til_end : ptree;
  77. var
  78. first,last : ptree;
  79. begin
  80. first:=nil;
  81. while token<>_END do
  82. begin
  83. if first=nil then
  84. begin
  85. last:=gennode(statementn,nil,statement);
  86. first:=last;
  87. end
  88. else
  89. begin
  90. last^.left:=gennode(statementn,nil,statement);
  91. last:=last^.left;
  92. end;
  93. if token<>SEMICOLON then
  94. break
  95. else
  96. consume(SEMICOLON);
  97. while token=SEMICOLON do
  98. consume(SEMICOLON);
  99. end;
  100. consume(_END);
  101. statements_til_end:=gensinglenode(blockn,first);
  102. end;
  103. function case_statement : ptree;
  104. var
  105. { contains the label number of currently parsed case block }
  106. aktcaselabel : plabel;
  107. root : pcaserecord;
  108. { the typ of the case expression }
  109. casedef : pdef;
  110. procedure newcaselabel(l,h : longint);
  111. var
  112. hcaselabel : pcaserecord;
  113. procedure insertlabel(var p : pcaserecord);
  114. begin
  115. if p=nil then p:=hcaselabel
  116. else
  117. if (p^._low>hcaselabel^._low) and
  118. (p^._low>hcaselabel^._high) then
  119. insertlabel(p^.less)
  120. else if (p^._high<hcaselabel^._low) and
  121. (p^._high<hcaselabel^._high) then
  122. insertlabel(p^.greater)
  123. else Message(parser_e_double_caselabel);
  124. end;
  125. begin
  126. new(hcaselabel);
  127. hcaselabel^.less:=nil;
  128. hcaselabel^.greater:=nil;
  129. hcaselabel^.statement:=aktcaselabel;
  130. getlabel(hcaselabel^._at);
  131. hcaselabel^._low:=l;
  132. hcaselabel^._high:=h;
  133. insertlabel(root);
  134. end;
  135. var
  136. code,caseexpr,p,instruc,elseblock : ptree;
  137. hl1,hl2 : longint;
  138. ranges : boolean;
  139. begin
  140. consume(_CASE);
  141. caseexpr:=comp_expr(true);
  142. { determines result type }
  143. cleartempgen;
  144. do_firstpass(caseexpr);
  145. casedef:=caseexpr^.resulttype;
  146. if not(is_ordinal(casedef)) then
  147. Message(parser_e_ordinal_expected);
  148. consume(_OF);
  149. inc(statement_level);
  150. root:=nil;
  151. ranges:=false;
  152. instruc:=nil;
  153. repeat
  154. getlabel(aktcaselabel);
  155. {aktcaselabel^.is_used:=true; }
  156. { may be an instruction has more case labels }
  157. repeat
  158. p:=expr;
  159. cleartempgen;
  160. do_firstpass(p);
  161. if (p^.treetype=rangen) then
  162. begin
  163. { type checking for case statements }
  164. if not is_subequal(casedef, p^.left^.resulttype) then
  165. Message(parser_e_case_mismatch);
  166. { type checking for case statements }
  167. if not is_subequal(casedef, p^.right^.resulttype) then
  168. Message(parser_e_case_mismatch);
  169. hl1:=get_ordinal_value(p^.left);
  170. hl2:=get_ordinal_value(p^.right);
  171. testrange(casedef,hl1);
  172. testrange(casedef,hl2);
  173. newcaselabel(hl1,hl2);
  174. ranges:=true;
  175. end
  176. else
  177. begin
  178. { type checking for case statements }
  179. if not is_subequal(casedef, p^.resulttype) then
  180. Message(parser_e_case_mismatch);
  181. hl1:=get_ordinal_value(p);
  182. testrange(casedef,hl1);
  183. newcaselabel(hl1,hl1);
  184. end;
  185. disposetree(p);
  186. if token=COMMA then consume(COMMA)
  187. else break;
  188. until false;
  189. consume(COLON);
  190. { handles instruction block }
  191. p:=gensinglenode(labeln,statement);
  192. p^.labelnr:=aktcaselabel;
  193. { concats instruction }
  194. instruc:=gennode(statementn,instruc,p);
  195. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  196. consume(SEMICOLON);
  197. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  198. if (token=_ELSE) or (token=_OTHERWISE) then
  199. begin
  200. if token=_ELSE then consume(_ELSE)
  201. else consume(_OTHERWISE);
  202. elseblock:=statements_til_end;
  203. end
  204. else
  205. begin
  206. elseblock:=nil;
  207. consume(_END);
  208. end;
  209. dec(statement_level);
  210. code:=gencasenode(caseexpr,instruc,root);
  211. code^.elseblock:=elseblock;
  212. case_statement:=code;
  213. end;
  214. function repeat_statement : ptree;
  215. var
  216. first,last,p_e : ptree;
  217. begin
  218. consume(_REPEAT);
  219. first:=nil;
  220. inc(statement_level);
  221. while token<>_UNTIL do
  222. begin
  223. if first=nil then
  224. begin
  225. last:=gennode(statementn,nil,statement);
  226. first:=last;
  227. end
  228. else
  229. begin
  230. last^.left:=gennode(statementn,nil,statement);
  231. last:=last^.left;
  232. end;
  233. if token<>SEMICOLON then
  234. break;
  235. consume(SEMICOLON);
  236. while token=SEMICOLON do
  237. consume(SEMICOLON);
  238. end;
  239. consume(_UNTIL);
  240. dec(statement_level);
  241. first:=gensinglenode(blockn,first);
  242. p_e:=comp_expr(true);
  243. repeat_statement:=genloopnode(repeatn,p_e,first,nil,false);
  244. end;
  245. function while_statement : ptree;
  246. var
  247. p_e,p_a : ptree;
  248. begin
  249. consume(_WHILE);
  250. p_e:=comp_expr(true);
  251. consume(_DO);
  252. p_a:=statement;
  253. while_statement:=genloopnode(whilen,p_e,p_a,nil,false);
  254. end;
  255. function for_statement : ptree;
  256. var
  257. p_e,tovalue,p_a : ptree;
  258. backward : boolean;
  259. begin
  260. { parse loop header }
  261. consume(_FOR);
  262. p_e:=expr;
  263. if token=_DOWNTO then
  264. begin
  265. consume(_DOWNTO);
  266. backward:=true;
  267. end
  268. else
  269. begin
  270. consume(_TO);
  271. backward:=false;
  272. end;
  273. tovalue:=comp_expr(true);
  274. consume(_DO);
  275. { ... now the instruction }
  276. p_a:=statement;
  277. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  278. end;
  279. function _with_statement : ptree;
  280. var
  281. right,hp,p : ptree;
  282. i,levelcount : longint;
  283. withsymtable,symtab : psymtable;
  284. obj : pobjectdef;
  285. begin
  286. Must_be_valid:=false;
  287. p:=comp_expr(true);
  288. do_firstpass(p);
  289. right:=nil;
  290. case p^.resulttype^.deftype of
  291. objectdef : begin
  292. obj:=pobjectdef(p^.resulttype);
  293. { this creates the stack in the wrong order !!
  294. levelcount:=0;
  295. while assigned(obj) do
  296. begin
  297. symtab:=obj^.publicsyms;
  298. withsymtable:=new(psymtable,init(symtable.withsymtable));
  299. withsymtable^.root:=symtab^.root;
  300. withsymtable^.next:=symtablestack;
  301. symtablestack:=withsymtable;
  302. obj:=obj^.childof;
  303. inc(levelcount);
  304. end; }
  305. withsymtable:=new(psymtable,init(symtable.withsymtable));
  306. withsymtable^.root:=obj^.publicsyms^.root;
  307. symtab:=withsymtable;
  308. levelcount:=1;
  309. obj:=obj^.childof;
  310. while assigned(obj) do
  311. begin
  312. symtab^.next:=new(psymtable,init(symtable.withsymtable));
  313. symtab:=symtab^.next;
  314. symtab^.root:=obj^.publicsyms^.root;
  315. obj:=obj^.childof;
  316. inc(levelcount);
  317. end;
  318. symtab^.next:=symtablestack;
  319. symtablestack:=withsymtable;
  320. end;
  321. recorddef : begin
  322. symtab:=precdef(p^.resulttype)^.symtable;
  323. levelcount:=1;
  324. withsymtable:=new(psymtable,init(symtable.withsymtable));
  325. withsymtable^.root:=symtab^.root;
  326. withsymtable^.next:=symtablestack;
  327. symtablestack:=withsymtable;
  328. end;
  329. else
  330. begin
  331. Message(parser_e_false_with_expr);
  332. { try to recover from error }
  333. if token=COMMA then
  334. begin
  335. consume(COMMA);
  336. {$ifdef tp}
  337. hp:=_with_statement;
  338. {$else}
  339. hp:=_with_statement();
  340. {$endif}
  341. end
  342. else
  343. begin
  344. consume(_DO);
  345. { ignore all }
  346. if token<>SEMICOLON then
  347. statement;
  348. end;
  349. _with_statement:=nil;
  350. exit;
  351. end;
  352. end;
  353. if token=COMMA then
  354. begin
  355. consume(COMMA);
  356. {$ifdef tp}
  357. right:=_with_statement;
  358. {$else}
  359. right:=_with_statement();
  360. {$endif}
  361. end
  362. else
  363. begin
  364. consume(_DO);
  365. if token<>SEMICOLON then
  366. right:=statement
  367. else
  368. right:=nil;
  369. end;
  370. for i:=1 to levelcount do
  371. symtablestack:=symtablestack^.next;
  372. _with_statement:=genwithnode(withsymtable,p,right,levelcount);
  373. end;
  374. function with_statement : ptree;
  375. begin
  376. consume(_WITH);
  377. with_statement:=_with_statement;
  378. end;
  379. function raise_statement : ptree;
  380. var
  381. p1,p2 : ptree;
  382. begin
  383. p1:=nil;
  384. p2:=nil;
  385. consume(_RAISE);
  386. if token<>SEMICOLON then
  387. begin
  388. p1:=comp_expr(true);
  389. if (token=ID) and (pattern='AT') then
  390. begin
  391. consume(ID);
  392. p2:=comp_expr(true);
  393. end;
  394. end
  395. else
  396. begin
  397. if not(in_except_block) then
  398. Message(parser_e_no_reraise_possible);
  399. end;
  400. raise_statement:=gennode(raisen,p1,p2);
  401. end;
  402. function try_statement : ptree;
  403. var
  404. p_try_block,p_finally_block,first,last,
  405. p_default,p_specific : ptree;
  406. ot : pobjectdef;
  407. sym : pvarsym;
  408. old_in_except_block : boolean;
  409. exceptsymtable : psymtable;
  410. objname : stringid;
  411. begin
  412. procinfo.flags:=procinfo.flags or
  413. pi_uses_exceptions;
  414. p_default:=nil;
  415. p_specific:=nil;
  416. { read statements to try }
  417. consume(_TRY);
  418. first:=nil;
  419. inc(statement_level);
  420. while (token<>_FINALLY) and (token<>_EXCEPT) do
  421. begin
  422. if first=nil then
  423. begin
  424. last:=gennode(statementn,nil,statement);
  425. first:=last;
  426. end
  427. else
  428. begin
  429. last^.left:=gennode(statementn,nil,statement);
  430. last:=last^.left;
  431. end;
  432. if token<>SEMICOLON then
  433. break;
  434. consume(SEMICOLON);
  435. emptystats;
  436. end;
  437. p_try_block:=gensinglenode(blockn,first);
  438. if token=_FINALLY then
  439. begin
  440. consume(_FINALLY);
  441. p_finally_block:=statements_til_end;
  442. try_statement:=gennode(tryfinallyn,p_try_block,p_finally_block);
  443. dec(statement_level);
  444. end
  445. else
  446. begin
  447. consume(_EXCEPT);
  448. old_in_except_block:=in_except_block;
  449. in_except_block:=true;
  450. p_specific:=nil;
  451. if token=_ON then
  452. { catch specific exceptions }
  453. begin
  454. repeat
  455. consume(_ON);
  456. if token=ID then
  457. begin
  458. getsym(pattern,false);
  459. objname:=pattern;
  460. consume(ID);
  461. { is a explicit name for the exception given ? }
  462. if token=COLON then
  463. begin
  464. sym:=new(pvarsym,init(objname,nil));
  465. exceptsymtable:=new(psymtable,init(stt_exceptsymtable));
  466. exceptsymtable^.insert(sym);
  467. consume(COLON);
  468. getsym(pattern,false);
  469. consume(ID);
  470. if srsym^.typ=unitsym then
  471. begin
  472. consume(POINT);
  473. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  474. consume(ID);
  475. end;
  476. if (srsym^.typ=typesym) and
  477. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  478. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  479. ot:=pobjectdef(ptypesym(srsym)^.definition)
  480. else
  481. begin
  482. message(parser_e_class_type_expected);
  483. ot:=pobjectdef(generrordef);
  484. end;
  485. sym^.definition:=ot;
  486. { insert the exception symtable stack }
  487. exceptsymtable^.next:=symtablestack;
  488. symtablestack:=exceptsymtable;
  489. end
  490. else
  491. begin
  492. { only exception type }
  493. if srsym^.typ=unitsym then
  494. begin
  495. consume(POINT);
  496. getsymonlyin(punitsym(srsym)^.unitsymtable,objname);
  497. consume(ID);
  498. end;
  499. consume(ID);
  500. if (srsym^.typ=typesym) and
  501. (ptypesym(srsym)^.definition^.deftype=objectdef) and
  502. pobjectdef(ptypesym(srsym)^.definition)^.isclass then
  503. ot:=pobjectdef(ptypesym(srsym)^.definition)
  504. else
  505. begin
  506. message(parser_e_class_type_expected);
  507. ot:=pobjectdef(generrordef);
  508. end;
  509. exceptsymtable:=nil;
  510. end;
  511. end
  512. else
  513. consume(ID);
  514. consume(_DO);
  515. if p_specific=nil then
  516. begin
  517. last:=gennode(onn,nil,statement);
  518. p_specific:=last;
  519. end
  520. else
  521. begin
  522. last^.left:=gennode(onn,nil,statement);
  523. last:=last^.left;
  524. end;
  525. { set the informations }
  526. last^.excepttype:=ot;
  527. last^.exceptsymtable:=exceptsymtable;
  528. last^.disposetyp:=dt_onn;
  529. { remove exception symtable }
  530. if assigned(exceptsymtable) then
  531. dellexlevel;
  532. if token<>SEMICOLON then
  533. break;
  534. consume(SEMICOLON);
  535. emptystats;
  536. until (token=_END) or(token=_ELSE);
  537. if token=_ELSE then
  538. { catch the other exceptions }
  539. begin
  540. consume(_ELSE);
  541. p_default:=statements_til_end;
  542. end
  543. else
  544. consume(_END);
  545. end
  546. else
  547. { catch all exceptions }
  548. begin
  549. p_default:=statements_til_end;
  550. end;
  551. dec(statement_level);
  552. in_except_block:=old_in_except_block;
  553. try_statement:=genloopnode(tryexceptn,p_try_block,p_specific,p_default,false);
  554. end;
  555. end;
  556. function exit_statement : ptree;
  557. var
  558. p : ptree;
  559. begin
  560. consume(_EXIT);
  561. if token=LKLAMMER then
  562. begin
  563. consume(LKLAMMER);
  564. p:=comp_expr(true);
  565. consume(RKLAMMER);
  566. if procinfo.retdef=pdef(voiddef) then
  567. Message(parser_e_void_function)
  568. else
  569. procinfo.funcret_is_valid:=true;
  570. end
  571. else
  572. p:=nil;
  573. exit_statement:=gensinglenode(exitn,p);
  574. end;
  575. function _asm_statement : ptree;
  576. var
  577. asmstat : ptree;
  578. begin
  579. if (aktprocsym^.definition^.options and poinline)<>0 then
  580. Begin
  581. Message1(parser_w_not_supported_for_inline,'asm statement');
  582. Message(parser_w_inlining_disabled);
  583. aktprocsym^.definition^.options:= aktprocsym^.definition^.options and not poinline;
  584. End;
  585. case aktasmmode of
  586. {$ifdef i386}
  587. {$ifndef NoRA386Att}
  588. I386_ATT : asmstat:=ra386att.assemble;
  589. {$endif NoRA386Att}
  590. {$ifndef NoRA386Int}
  591. I386_INTEL : asmstat:=ra386int.assemble;
  592. {$endif NoRA386Int}
  593. {$ifndef NoRA386Dir}
  594. I386_DIRECT : asmstat:=ra386dir.assemble;
  595. {$endif NoRA386Dir}
  596. {$endif}
  597. {$ifdef m68k}
  598. {$ifndef NoRA68kMot}
  599. M68K_MOT : asmstat:=ra68kmot.assemble;
  600. {$endif NoRA68kMot}
  601. {$endif}
  602. else
  603. Message(parser_f_assembler_reader_not_supported);
  604. end;
  605. { Read first the _ASM statement }
  606. consume(_ASM);
  607. { END is read }
  608. if token=LECKKLAMMER then
  609. begin
  610. { it's possible to specify the modified registers }
  611. consume(LECKKLAMMER);
  612. asmstat^.object_preserved:=true;
  613. if token<>RECKKLAMMER then
  614. repeat
  615. { uppercase, because it's a CSTRING }
  616. uppervar(pattern);
  617. {$ifdef i386}
  618. if pattern='EAX' then
  619. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  620. else if pattern='EBX' then
  621. usedinproc:=usedinproc or ($80 shr byte(R_EBX))
  622. else if pattern='ECX' then
  623. usedinproc:=usedinproc or ($80 shr byte(R_ECX))
  624. else if pattern='EDX' then
  625. usedinproc:=usedinproc or ($80 shr byte(R_EDX))
  626. else if pattern='ESI' then
  627. begin
  628. usedinproc:=usedinproc or ($80 shr byte(R_ESI));
  629. asmstat^.object_preserved:=false;
  630. end
  631. else if pattern='EDI' then
  632. usedinproc:=usedinproc or ($80 shr byte(R_EDI))
  633. {$endif i386}
  634. {$ifdef m68k}
  635. if pattern='D0' then
  636. usedinproc:=usedinproc or ($800 shr word(R_D0))
  637. else if pattern='D1' then
  638. usedinproc:=usedinproc or ($800 shr word(R_D1))
  639. else if pattern='D6' then
  640. usedinproc:=usedinproc or ($800 shr word(R_D6))
  641. else if pattern='A0' then
  642. usedinproc:=usedinproc or ($800 shr word(R_A0))
  643. else if pattern='A1' then
  644. usedinproc:=usedinproc or ($800 shr word(R_A1))
  645. {$endif m68k}
  646. else consume(RECKKLAMMER);
  647. consume(CSTRING);
  648. if token=COMMA then consume(COMMA)
  649. else break;
  650. until false;
  651. consume(RECKKLAMMER);
  652. end
  653. else usedinproc:=$ff;
  654. _asm_statement:=asmstat;
  655. end;
  656. function new_dispose_statement : ptree;
  657. var
  658. p,p2 : ptree;
  659. ht : ttoken;
  660. again : boolean; { dummy for do_proc_call }
  661. destrukname : stringid;
  662. sym : psym;
  663. classh : pobjectdef;
  664. pd,pd2 : pdef;
  665. store_valid : boolean;
  666. tt : ttreetyp;
  667. begin
  668. ht:=token;
  669. if token=_NEW then consume(_NEW)
  670. else consume(_DISPOSE);
  671. if ht=_NEW then
  672. tt:=hnewn
  673. else
  674. tt:=hdisposen;
  675. consume(LKLAMMER);
  676. p:=comp_expr(true);
  677. { calc return type }
  678. cleartempgen;
  679. Store_valid := Must_be_valid;
  680. Must_be_valid := False;
  681. do_firstpass(p);
  682. Must_be_valid := Store_valid;
  683. {var o:Pobject;
  684. begin
  685. new(o,init); (*Also a valid new statement*)
  686. end;}
  687. if token=COMMA then
  688. begin
  689. { extended syntax of new and dispose }
  690. { function styled new is handled in factor }
  691. consume(COMMA);
  692. { destructors have no parameters }
  693. destrukname:=pattern;
  694. consume(ID);
  695. pd:=p^.resulttype;
  696. pd2:=pd;
  697. if (p^.resulttype = nil) or (pd^.deftype<>pointerdef) then
  698. begin
  699. Message(parser_e_pointer_type_expected);
  700. p:=factor(false);
  701. consume(RKLAMMER);
  702. new_dispose_statement:=genzeronode(errorn);
  703. exit;
  704. end;
  705. { first parameter must be an object or class }
  706. if ppointerdef(pd)^.definition^.deftype<>objectdef then
  707. begin
  708. Message(parser_e_pointer_to_class_expected);
  709. new_dispose_statement:=factor(false);
  710. consume_all_until(RKLAMMER);
  711. consume(RKLAMMER);
  712. exit;
  713. end;
  714. { check, if the first parameter is a pointer to a _class_ }
  715. classh:=pobjectdef(ppointerdef(pd)^.definition);
  716. if (classh^.options and oois_class)<>0 then
  717. begin
  718. Message(parser_e_no_new_or_dispose_for_classes);
  719. new_dispose_statement:=factor(false);
  720. { while token<>RKLAMMER do
  721. consume(token); }
  722. consume_all_until(RKLAMMER);
  723. consume(RKLAMMER);
  724. exit;
  725. end;
  726. { search cons-/destructor, also in parent classes }
  727. sym:=nil;
  728. while assigned(classh) do
  729. begin
  730. sym:=classh^.publicsyms^.search(pattern);
  731. srsymtable:=classh^.publicsyms;
  732. if assigned(sym) then
  733. break;
  734. classh:=classh^.childof;
  735. end;
  736. { the second parameter of new/dispose must be a call }
  737. { to a cons-/destructor }
  738. if (sym^.typ<>procsym) then
  739. begin
  740. Message(parser_e_expr_have_to_be_destructor_call);
  741. new_dispose_statement:=genzeronode(errorn);
  742. end
  743. else
  744. begin
  745. p2:=gensinglenode(tt,p);
  746. if ht=_NEW then
  747. begin
  748. { Constructors can take parameters.}
  749. p2^.resulttype:=ppointerdef(pd)^.definition;
  750. do_member_read(false,sym,p2,pd,again);
  751. end
  752. else
  753. { destructors can't.}
  754. p2:=genmethodcallnode(pprocsym(sym),srsymtable,p2);
  755. { we need the real called method }
  756. cleartempgen;
  757. do_firstpass(p2);
  758. if (ht=_NEW) and ((p2^.procdefinition^.options and poconstructor)=0) then
  759. Message(parser_e_expr_have_to_be_constructor_call);
  760. if (ht=_DISPOSE) and ((p2^.procdefinition^.options and podestructor)=0) then
  761. Message(parser_e_expr_have_to_be_destructor_call);
  762. if ht=_NEW then
  763. begin
  764. p2:=gennode(assignn,getcopy(p),gensinglenode(newn,p2));
  765. p2^.right^.resulttype:=pd2;
  766. end;
  767. new_dispose_statement:=p2;
  768. end;
  769. end
  770. else
  771. begin
  772. if (p^.resulttype=nil) or (p^.resulttype^.deftype<>pointerdef) then
  773. Begin
  774. Message(parser_e_pointer_type_expected);
  775. new_dispose_statement:=genzeronode(errorn);
  776. end
  777. else
  778. begin
  779. if (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) then
  780. Message(parser_w_use_extended_syntax_for_objects);
  781. case ht of
  782. _NEW : new_dispose_statement:=gensinglenode(simplenewn,p);
  783. _DISPOSE : new_dispose_statement:=gensinglenode(simpledisposen,p);
  784. end;
  785. end;
  786. end;
  787. consume(RKLAMMER);
  788. end;
  789. function statement_block(starttoken : ttoken) : ptree;
  790. var
  791. first,last : ptree;
  792. filepos : tfileposinfo;
  793. begin
  794. first:=nil;
  795. filepos:=tokenpos;
  796. consume(starttoken);
  797. inc(statement_level);
  798. while not(
  799. (token=_END) or
  800. ((starttoken=_INITIALIZATION) and (token=_FINALIZATION))
  801. ) do
  802. begin
  803. if first=nil then
  804. begin
  805. last:=gennode(statementn,nil,statement);
  806. first:=last;
  807. end
  808. else
  809. begin
  810. last^.left:=gennode(statementn,nil,statement);
  811. last:=last^.left;
  812. end;
  813. if (token=_END) or
  814. ((starttoken=_INITIALIZATION) and (token=_FINALIZATION)) then
  815. break
  816. else
  817. begin
  818. { if no semicolon, then error and go on }
  819. if token<>SEMICOLON then
  820. begin
  821. consume(SEMICOLON);
  822. { while token<>SEMICOLON do
  823. consume(token); }
  824. consume_all_until(SEMICOLON);
  825. end;
  826. consume(SEMICOLON);
  827. end;
  828. emptystats;
  829. end;
  830. { don't consume the finalization token, it is consumed when
  831. reading the finalization block !
  832. }
  833. if token=_END then
  834. consume(_END);
  835. dec(statement_level);
  836. last:=gensinglenode(blockn,first);
  837. set_tree_filepos(last,filepos);
  838. statement_block:=last;
  839. end;
  840. function statement : ptree;
  841. var
  842. p : ptree;
  843. code : ptree;
  844. labelnr : plabel;
  845. filepos : tfileposinfo;
  846. label
  847. ready;
  848. begin
  849. filepos:=tokenpos;
  850. case token of
  851. _GOTO : begin
  852. if not(cs_support_goto in aktmoduleswitches)then
  853. Message(sym_e_goto_and_label_not_supported);
  854. consume(_GOTO);
  855. if (token<>INTCONST) and (token<>ID) then
  856. begin
  857. Message(sym_e_label_not_found);
  858. code:=genzeronode(errorn);
  859. end
  860. else
  861. begin
  862. getsym(pattern,true);
  863. consume(token);
  864. if srsym^.typ<>labelsym then
  865. begin
  866. Message(sym_e_id_is_no_label_id);
  867. code:=genzeronode(errorn);
  868. end
  869. else
  870. code:=genlabelnode(goton,
  871. plabelsym(srsym)^.number);
  872. end;
  873. end;
  874. _BEGIN : code:=statement_block(_BEGIN);
  875. _IF : code:=if_statement;
  876. _CASE : code:=case_statement;
  877. _REPEAT : code:=repeat_statement;
  878. _WHILE : code:=while_statement;
  879. _FOR : code:=for_statement;
  880. _NEW,_DISPOSE : code:=new_dispose_statement;
  881. _WITH : code:=with_statement;
  882. _TRY : code:=try_statement;
  883. _RAISE : code:=raise_statement;
  884. { semicolons,else until and end are ignored }
  885. SEMICOLON,
  886. _ELSE,
  887. _UNTIL,
  888. _END:
  889. code:=genzeronode(niln);
  890. _CONTINUE:
  891. begin
  892. consume(_CONTINUE);
  893. code:=genzeronode(continuen);
  894. end;
  895. _FAIL : begin
  896. { internalerror(100); }
  897. if (aktprocsym^.definition^.options and poconstructor)=0 then
  898. Message(parser_e_fail_only_in_constructor);
  899. consume(_FAIL);
  900. code:=genzeronode(failn);
  901. end;
  902. {
  903. _BREAK:
  904. begin
  905. consume(_BREAK);
  906. code:=genzeronode(breakn);
  907. end;
  908. }
  909. _EXIT : code:=exit_statement;
  910. _ASM : begin
  911. code:=_asm_statement;
  912. end;
  913. else
  914. begin
  915. if (token=INTCONST) or
  916. ((token=ID) and
  917. not((cs_delphi2_compatible in aktmoduleswitches) and
  918. (pattern='RESULT'))) then
  919. begin
  920. getsym(pattern,true);
  921. lastsymknown:=true;
  922. lastsrsym:=srsym;
  923. { it is NOT necessarily the owner
  924. it can be a withsymtable !!! }
  925. lastsrsymtable:=srsymtable;
  926. if assigned(srsym) and (srsym^.typ=labelsym) then
  927. begin
  928. consume(token);
  929. consume(COLON);
  930. if plabelsym(srsym)^.defined then
  931. Message(sym_e_label_already_defined);
  932. plabelsym(srsym)^.defined:=true;
  933. { statement modifies srsym }
  934. labelnr:=plabelsym(srsym)^.number;
  935. lastsymknown:=false;
  936. { the pointer to the following instruction }
  937. { isn't a very clean way }
  938. {$ifdef tp}
  939. code:=gensinglenode(labeln,statement);
  940. {$else}
  941. code:=gensinglenode(labeln,statement());
  942. {$endif}
  943. code^.labelnr:=labelnr;
  944. { sorry, but there is a jump the easiest way }
  945. goto ready;
  946. end;
  947. end;
  948. p:=expr;
  949. if not(p^.treetype in [calln,assignn,breakn,inlinen,
  950. continuen]) then
  951. Message(cg_e_illegal_expression);
  952. { specify that we don't use the value returned by the call }
  953. { Question : can this be also improtant
  954. for inlinen ??
  955. it is used for :
  956. - dispose of temp stack space
  957. - dispose on FPU stack }
  958. if p^.treetype=calln then
  959. p^.return_value_used:=false;
  960. code:=p;
  961. end;
  962. end;
  963. ready:
  964. if assigned(code) then
  965. set_tree_filepos(code,filepos);
  966. statement:=code;
  967. end;
  968. function block(islibrary : boolean) : ptree;
  969. {$ifdef TEST_FUNCRET }
  970. var
  971. funcretsym : pfuncretsym;
  972. {$endif TEST_FUNCRET }
  973. begin
  974. {$ifdef TEST_FUNCRET }
  975. if procinfo.retdef<>pdef(voiddef) then
  976. begin
  977. { if the current is a function aktprocsym is non nil }
  978. { and there is a local symtable set }
  979. funcretsym:=new(pfuncretsym,init(aktprocsym^.name,@procinfo));
  980. { insert in local symtable }
  981. symtablestack^.insert(funcretsym);
  982. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  983. procinfo.retoffset:=-funcretsym^.address;
  984. procinfo.funcretsym:=funcretsym;
  985. end;
  986. {$endif TEST_FUNCRET }
  987. read_declarations(islibrary);
  988. { temporary space is set, while the BEGIN of the procedure }
  989. if (symtablestack^.symtabletype=localsymtable) then
  990. procinfo.firsttemp := -symtablestack^.datasize
  991. else procinfo.firsttemp := 0;
  992. { space for the return value }
  993. { !!!!! this means that we can not set the return value
  994. in a subfunction !!!!! }
  995. { because we don't know yet where the address is }
  996. if procinfo.retdef<>pdef(voiddef) then
  997. begin
  998. if ret_in_acc(procinfo.retdef) or (procinfo.retdef^.deftype=floatdef) then
  999. { if (procinfo.retdef^.deftype=orddef) or
  1000. (procinfo.retdef^.deftype=pointerdef) or
  1001. (procinfo.retdef^.deftype=enumdef) or
  1002. (procinfo.retdef^.deftype=procvardef) or
  1003. (procinfo.retdef^.deftype=floatdef) or
  1004. (
  1005. (procinfo.retdef^.deftype=setdef) and
  1006. (psetdef(procinfo.retdef)^.settype=smallset)
  1007. ) then }
  1008. begin
  1009. {$ifdef TEST_FUNCRET }
  1010. { the space has been set in the local symtable }
  1011. procinfo.retoffset:=-funcretsym^.address;
  1012. {$else TEST_FUNCRET }
  1013. { align func result at 4 byte }
  1014. procinfo.retoffset:=
  1015. -((-procinfo.firsttemp+(procinfo.retdef^.size+3)) div 4)*4;
  1016. procinfo.firsttemp:=procinfo.retoffset;
  1017. {$endif TEST_FUNCRET }
  1018. if (procinfo.flags and pi_operator)<>0 then
  1019. {opsym^.address:=procinfo.call_offset; is wrong PM }
  1020. opsym^.address:=-procinfo.retoffset;
  1021. { eax is modified by a function }
  1022. {$ifdef i386}
  1023. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1024. {$endif}
  1025. {$ifdef m68k}
  1026. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1027. {$endif}
  1028. end;
  1029. end;
  1030. {Unit initialization?.}
  1031. if (lexlevel=1) and (current_module^.is_unit) then
  1032. if (token=_END) then
  1033. begin
  1034. consume(_END);
  1035. block:=nil;
  1036. end
  1037. else
  1038. begin
  1039. if token=_INITIALIZATION then
  1040. begin
  1041. current_module^.flags:=current_module^.flags or uf_init;
  1042. block:=statement_block(_INITIALIZATION);
  1043. end
  1044. else if (token=_FINALIZATION) then
  1045. begin
  1046. if (current_module^.flags and uf_finalize)<>0 then
  1047. block:=statement_block(_FINALIZATION)
  1048. else
  1049. begin
  1050. block:=nil;
  1051. exit;
  1052. end;
  1053. end
  1054. else
  1055. begin
  1056. current_module^.flags:=current_module^.flags or uf_init;
  1057. block:=statement_block(_BEGIN);
  1058. end;
  1059. end
  1060. else
  1061. block:=statement_block(_BEGIN);
  1062. end;
  1063. function assembler_block : ptree;
  1064. begin
  1065. read_declarations(false);
  1066. { temporary space is set, while the BEGIN of the procedure }
  1067. if symtablestack^.symtabletype=localsymtable then
  1068. procinfo.firsttemp := -symtablestack^.datasize
  1069. else procinfo.firsttemp := 0;
  1070. { assembler code does not allocate }
  1071. { space for the return value }
  1072. if procinfo.retdef<>pdef(voiddef) then
  1073. begin
  1074. if ret_in_acc(procinfo.retdef) then
  1075. begin
  1076. { in assembler code the result should be directly in %eax
  1077. procinfo.retoffset:=procinfo.firsttemp-procinfo.retdef^.size;
  1078. procinfo.firsttemp:=procinfo.retoffset; }
  1079. {$ifdef i386}
  1080. usedinproc:=usedinproc or ($80 shr byte(R_EAX))
  1081. {$endif}
  1082. {$ifdef m68k}
  1083. usedinproc:=usedinproc or ($800 shr word(R_D0))
  1084. {$endif}
  1085. end
  1086. else if not is_fpu(procinfo.retdef) then
  1087. { should we allow assembler functions of big elements ? }
  1088. Message(parser_e_asm_incomp_with_function_return);
  1089. end;
  1090. { set the framepointer to esp for assembler functions }
  1091. { but only if the are no local variables }
  1092. { added no parameter also (PM) }
  1093. if ((aktprocsym^.definition^.options and poassembler)<>0) and
  1094. (aktprocsym^.definition^.localst^.datasize=0) and
  1095. (aktprocsym^.definition^.parast^.datasize=0) then
  1096. begin
  1097. {$ifdef i386}
  1098. procinfo.framepointer:=R_ESP;
  1099. {$endif}
  1100. {$ifdef m68k}
  1101. procinfo.framepointer:=R_SP;
  1102. {$endif}
  1103. { set the right value for parameters }
  1104. dec(aktprocsym^.definition^.parast^.call_offset,sizeof(pointer));
  1105. dec(procinfo.call_offset,sizeof(pointer));
  1106. end;
  1107. assembler_block:=_asm_statement;
  1108. { becuase the END is already read we need to get the
  1109. last_endtoken_filepos here (PFV) }
  1110. last_endtoken_filepos:=tokenpos;
  1111. end;
  1112. end.
  1113. {
  1114. $Log$
  1115. Revision 1.35 1998-08-20 09:26:42 pierre
  1116. + funcret setting in underproc testing
  1117. compile with _dTEST_FUNCRET
  1118. Revision 1.34 1998/08/17 10:10:09 peter
  1119. - removed OLDPPU
  1120. Revision 1.33 1998/08/12 19:39:30 peter
  1121. * fixed some crashes
  1122. Revision 1.32 1998/08/10 14:50:17 peter
  1123. + localswitches, moduleswitches, globalswitches splitting
  1124. Revision 1.31 1998/08/02 16:41:59 florian
  1125. * on o : tobject do should also work now, the exceptsymtable shouldn't be
  1126. disposed by dellexlevel
  1127. Revision 1.30 1998/07/30 16:07:10 florian
  1128. * try ... expect <statement> end; works now
  1129. Revision 1.29 1998/07/30 13:30:37 florian
  1130. * final implemenation of exception support, maybe it needs
  1131. some fixes :)
  1132. Revision 1.28 1998/07/30 11:18:18 florian
  1133. + first implementation of try ... except on .. do end;
  1134. * limitiation of 65535 bytes parameters for cdecl removed
  1135. Revision 1.27 1998/07/28 21:52:55 florian
  1136. + implementation of raise and try..finally
  1137. + some misc. exception stuff
  1138. Revision 1.26 1998/07/27 21:57:14 florian
  1139. * fix to allow tv like stream registration:
  1140. @tmenu.load doesn't work if load had parameters or if load was only
  1141. declared in an anchestor class of tmenu
  1142. Revision 1.25 1998/07/14 21:46:53 peter
  1143. * updated messages file
  1144. Revision 1.24 1998/07/10 10:48:42 peter
  1145. * fixed realnumber scanning
  1146. * [] after asmblock was not uppercased anymore
  1147. Revision 1.23 1998/06/25 08:48:18 florian
  1148. * first version of rtti support
  1149. Revision 1.22 1998/06/24 14:48:36 peter
  1150. * ifdef newppu -> ifndef oldppu
  1151. Revision 1.21 1998/06/24 14:06:34 peter
  1152. * fixed the name changes
  1153. Revision 1.20 1998/06/23 14:00:16 peter
  1154. * renamed RA* units
  1155. Revision 1.19 1998/06/08 22:59:50 peter
  1156. * smartlinking works for win32
  1157. * some defines to exclude some compiler parts
  1158. Revision 1.18 1998/06/05 14:37:35 pierre
  1159. * fixes for inline for operators
  1160. * inline procedure more correctly restricted
  1161. Revision 1.17 1998/06/04 09:55:43 pierre
  1162. * demangled name of procsym reworked to become independant of the mangling scheme
  1163. Revision 1.16 1998/06/02 17:03:04 pierre
  1164. * with node corrected for objects
  1165. * small bugs for SUPPORT_MMX fixed
  1166. Revision 1.15 1998/05/30 14:31:06 peter
  1167. + $ASMMODE
  1168. Revision 1.14 1998/05/29 09:58:14 pierre
  1169. * OPR_REGISTER for 1 arg was missing in ratti386.pas
  1170. (probably a merging problem)
  1171. * errors at start of line were lost
  1172. Revision 1.13 1998/05/28 17:26:50 peter
  1173. * fixed -R switch, it didn't work after my previous akt/init patch
  1174. * fixed bugs 110,130,136
  1175. Revision 1.12 1998/05/21 19:33:33 peter
  1176. + better procedure directive handling and only one table
  1177. Revision 1.11 1998/05/20 09:42:35 pierre
  1178. + UseTokenInfo now default
  1179. * unit in interface uses and implementation uses gives error now
  1180. * only one error for unknown symbol (uses lastsymknown boolean)
  1181. the problem came from the label code !
  1182. + first inlined procedures and function work
  1183. (warning there might be allowed cases were the result is still wrong !!)
  1184. * UseBrower updated gives a global list of all position of all used symbols
  1185. with switch -gb
  1186. Revision 1.10 1998/05/11 13:07:56 peter
  1187. + $ifdef NEWPPU for the new ppuformat
  1188. + $define GDB not longer required
  1189. * removed all warnings and stripped some log comments
  1190. * no findfirst/findnext anymore to remove smartlink *.o files
  1191. Revision 1.9 1998/05/06 08:38:46 pierre
  1192. * better position info with UseTokenInfo
  1193. UseTokenInfo greatly simplified
  1194. + added check for changed tree after first time firstpass
  1195. (if we could remove all the cases were it happen
  1196. we could skip all firstpass if firstpasscount > 1)
  1197. Only with ExtDebug
  1198. Revision 1.8 1998/05/05 12:05:42 florian
  1199. * problems with properties fixed
  1200. * crash fixed: i:=l when i and l are undefined, was a problem with
  1201. implementation of private/protected
  1202. Revision 1.7 1998/05/01 16:38:46 florian
  1203. * handling of private and protected fixed
  1204. + change_keywords_to_tp implemented to remove
  1205. keywords which aren't supported by tp
  1206. * break and continue are now symbols of the system unit
  1207. + widestring, longstring and ansistring type released
  1208. Revision 1.6 1998/04/30 15:59:42 pierre
  1209. * GDB works again better :
  1210. correct type info in one pass
  1211. + UseTokenInfo for better source position
  1212. * fixed one remaining bug in scanner for line counts
  1213. * several little fixes
  1214. Revision 1.5 1998/04/29 10:33:59 pierre
  1215. + added some code for ansistring (not complete nor working yet)
  1216. * corrected operator overloading
  1217. * corrected nasm output
  1218. + started inline procedures
  1219. + added starstarn : use ** for exponentiation (^ gave problems)
  1220. + started UseTokenInfo cond to get accurate positions
  1221. Revision 1.4 1998/04/08 16:58:05 pierre
  1222. * several bugfixes
  1223. ADD ADC and AND are also sign extended
  1224. nasm output OK (program still crashes at end
  1225. and creates wrong assembler files !!)
  1226. procsym types sym in tdef removed !!
  1227. }