pstatmnt.pas 47 KB

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