pstatmnt.pas 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. tokens,node;
  23. function statement_block(starttoken : ttoken) : tnode;
  24. { reads an assembler block }
  25. function assembler_block : tnode;
  26. implementation
  27. uses
  28. { common }
  29. cutils,
  30. { global }
  31. globtype,globals,verbose,
  32. systems,
  33. { aasm }
  34. cpubase,aasmbase,aasmtai,
  35. { symtable }
  36. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  37. paramgr,symutil,
  38. { pass 1 }
  39. pass_1,htypechk,
  40. nutils,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  41. { parser }
  42. scanner,
  43. pbase,pexpr,
  44. { codegen }
  45. procinfo,cgbase,
  46. { assembler reader }
  47. rabase
  48. ;
  49. function statement : tnode;forward;
  50. function if_statement : tnode;
  51. var
  52. ex,if_a,else_a : tnode;
  53. begin
  54. consume(_IF);
  55. ex:=comp_expr(true);
  56. consume(_THEN);
  57. if token<>_ELSE then
  58. if_a:=statement
  59. else
  60. if_a:=nil;
  61. if try_to_consume(_ELSE) then
  62. else_a:=statement
  63. else
  64. else_a:=nil;
  65. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  66. end;
  67. { creates a block (list) of statements, til the next END token }
  68. function statements_til_end : tnode;
  69. var
  70. first,last : tstatementnode;
  71. begin
  72. first:=nil;
  73. while token<>_END do
  74. begin
  75. if first=nil then
  76. begin
  77. last:=cstatementnode.create(statement,nil);
  78. first:=last;
  79. end
  80. else
  81. begin
  82. last.right:=cstatementnode.create(statement,nil);
  83. last:=tstatementnode(last.right);
  84. end;
  85. if not try_to_consume(_SEMICOLON) then
  86. break;
  87. consume_emptystats;
  88. end;
  89. consume(_END);
  90. statements_til_end:=cblocknode.create(first);
  91. end;
  92. function case_statement : tnode;
  93. var
  94. { contains the label number of currently parsed case block }
  95. aktcaselabel : tasmlabel;
  96. firstlabel : boolean;
  97. root : pcaserecord;
  98. { the typ of the case expression }
  99. casedef : tdef;
  100. procedure newcaselabel(l,h : TConstExprInt;first:boolean);
  101. var
  102. hcaselabel : pcaserecord;
  103. procedure insertlabel(var p : pcaserecord);
  104. begin
  105. if p=nil then p:=hcaselabel
  106. else
  107. if (p^._low>hcaselabel^._low) and
  108. (p^._low>hcaselabel^._high) then
  109. if (hcaselabel^.statement = p^.statement) and
  110. (p^._low = hcaselabel^._high + 1) then
  111. begin
  112. p^._low := hcaselabel^._low;
  113. dispose(hcaselabel);
  114. end
  115. else
  116. insertlabel(p^.less)
  117. else
  118. if (p^._high<hcaselabel^._low) and
  119. (p^._high<hcaselabel^._high) then
  120. if (hcaselabel^.statement = p^.statement) and
  121. (p^._high+1 = hcaselabel^._low) then
  122. begin
  123. p^._high := hcaselabel^._high;
  124. dispose(hcaselabel);
  125. end
  126. else
  127. insertlabel(p^.greater)
  128. else Message(parser_e_double_caselabel);
  129. end;
  130. begin
  131. new(hcaselabel);
  132. hcaselabel^.less:=nil;
  133. hcaselabel^.greater:=nil;
  134. hcaselabel^.statement:=aktcaselabel;
  135. hcaselabel^.firstlabel:=first;
  136. objectlibrary.getlabel(hcaselabel^._at);
  137. hcaselabel^._low:=l;
  138. hcaselabel^._high:=h;
  139. insertlabel(root);
  140. end;
  141. var
  142. code,caseexpr,p,instruc,elseblock : tnode;
  143. hl1,hl2 : TConstExprInt;
  144. casedeferror : boolean;
  145. begin
  146. consume(_CASE);
  147. caseexpr:=comp_expr(true);
  148. { determines result type }
  149. do_resulttypepass(caseexpr);
  150. set_varstate(caseexpr,vs_used,true);
  151. casedeferror:=false;
  152. casedef:=caseexpr.resulttype.def;
  153. if (not assigned(casedef)) or
  154. not(is_ordinal(casedef)) then
  155. begin
  156. CGMessage(type_e_ordinal_expr_expected);
  157. { create a correct tree }
  158. caseexpr.free;
  159. caseexpr:=cordconstnode.create(0,u32inttype,false);
  160. { set error flag so no rangechecks are done }
  161. casedeferror:=true;
  162. end;
  163. consume(_OF);
  164. root:=nil;
  165. instruc:=nil;
  166. repeat
  167. objectlibrary.getlabel(aktcaselabel);
  168. firstlabel:=true;
  169. { maybe an instruction has more case labels }
  170. repeat
  171. p:=expr;
  172. if is_widechar(casedef) then
  173. begin
  174. if (p.nodetype=rangen) then
  175. begin
  176. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  177. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  178. do_resulttypepass(trangenode(p).left);
  179. do_resulttypepass(trangenode(p).right);
  180. end
  181. else
  182. begin
  183. p:=ctypeconvnode.create(p,cwidechartype);
  184. do_resulttypepass(p);
  185. end;
  186. end;
  187. hl1:=0;
  188. hl2:=0;
  189. if (p.nodetype=rangen) then
  190. begin
  191. { type checking for case statements }
  192. if is_subequal(casedef, trangenode(p).left.resulttype.def) and
  193. is_subequal(casedef, trangenode(p).right.resulttype.def) then
  194. begin
  195. hl1:=get_ordinal_value(trangenode(p).left);
  196. hl2:=get_ordinal_value(trangenode(p).right);
  197. if hl1>hl2 then
  198. CGMessage(parser_e_case_lower_less_than_upper_bound);
  199. if not casedeferror then
  200. begin
  201. testrange(casedef,hl1,false);
  202. testrange(casedef,hl2,false);
  203. end;
  204. end
  205. else
  206. CGMessage(parser_e_case_mismatch);
  207. newcaselabel(hl1,hl2,firstlabel);
  208. end
  209. else
  210. begin
  211. { type checking for case statements }
  212. if not is_subequal(casedef, p.resulttype.def) then
  213. CGMessage(parser_e_case_mismatch);
  214. hl1:=get_ordinal_value(p);
  215. if not casedeferror then
  216. testrange(casedef,hl1,false);
  217. newcaselabel(hl1,hl1,firstlabel);
  218. end;
  219. p.free;
  220. if token=_COMMA then
  221. consume(_COMMA)
  222. else
  223. break;
  224. firstlabel:=false;
  225. until false;
  226. consume(_COLON);
  227. { handles instruction block }
  228. p:=clabelnode.createcase(aktcaselabel,statement);
  229. { concats instruction }
  230. instruc:=cstatementnode.create(p,instruc);
  231. if not(token in [_ELSE,_OTHERWISE,_END]) then
  232. consume(_SEMICOLON);
  233. until (token in [_ELSE,_OTHERWISE,_END]);
  234. if (token in [_ELSE,_OTHERWISE]) then
  235. begin
  236. if not try_to_consume(_ELSE) then
  237. consume(_OTHERWISE);
  238. elseblock:=statements_til_end;
  239. end
  240. else
  241. begin
  242. elseblock:=nil;
  243. consume(_END);
  244. end;
  245. code:=ccasenode.create(caseexpr,instruc,root);
  246. tcasenode(code).elseblock:=elseblock;
  247. case_statement:=code;
  248. end;
  249. function repeat_statement : tnode;
  250. var
  251. first,last,p_e : tnode;
  252. begin
  253. consume(_REPEAT);
  254. first:=nil;
  255. while token<>_UNTIL do
  256. begin
  257. if first=nil then
  258. begin
  259. last:=cstatementnode.create(statement,nil);
  260. first:=last;
  261. end
  262. else
  263. begin
  264. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  265. last:=tstatementnode(last).right;
  266. end;
  267. if not try_to_consume(_SEMICOLON) then
  268. break;
  269. consume_emptystats;
  270. end;
  271. consume(_UNTIL);
  272. first:=cblocknode.create(first);
  273. p_e:=comp_expr(true);
  274. repeat_statement:=genloopnode(whilerepeatn,p_e,first,nil,true);
  275. end;
  276. function while_statement : tnode;
  277. var
  278. p_e,p_a : tnode;
  279. begin
  280. consume(_WHILE);
  281. p_e:=comp_expr(true);
  282. consume(_DO);
  283. p_a:=statement;
  284. while_statement:=genloopnode(whilerepeatn,p_e,p_a,nil,false);
  285. end;
  286. function for_statement : tnode;
  287. var
  288. p_e,tovalue,p_a : tnode;
  289. backward : boolean;
  290. loopvarsym : tvarsym;
  291. hp : tnode;
  292. begin
  293. { parse loop header }
  294. consume(_FOR);
  295. p_e:=expr;
  296. { Check loop variable }
  297. hp:=nil;
  298. loopvarsym:=nil;
  299. if (p_e.nodetype=assignn) then
  300. begin
  301. hp:=tassignmentnode(p_e).left;
  302. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  303. if not(is_ordinal(hp.resulttype.def))
  304. {$ifndef cpu64bit}
  305. or is_64bitint(hp.resulttype.def)
  306. {$endif cpu64bit}
  307. then
  308. MessagePos(hp.fileinfo,type_e_ordinal_expr_expected);
  309. while assigned(hp) and
  310. (
  311. { record/object fields are allowed }
  312. (
  313. (hp.nodetype=subscriptn) and
  314. ((tsubscriptnode(hp).left.resulttype.def.deftype=recorddef) or
  315. is_object(tsubscriptnode(hp).left.resulttype.def))
  316. ) or
  317. { constant array index }
  318. (
  319. (hp.nodetype=vecn) and
  320. is_constintnode(tvecnode(hp).right)
  321. ) or
  322. { equal typeconversions }
  323. (
  324. (hp.nodetype=typeconvn) and
  325. (ttypeconvnode(hp).convtype=tc_equal)
  326. )
  327. ) do
  328. begin
  329. { Use the recordfield for loopvarsym }
  330. if not assigned(loopvarsym) and
  331. (hp.nodetype=subscriptn) then
  332. loopvarsym:=tsubscriptnode(hp).vs;
  333. hp:=tunarynode(hp).left;
  334. end;
  335. if assigned(hp) and
  336. (hp.nodetype=loadn) then
  337. begin
  338. case tloadnode(hp).symtableentry.typ of
  339. varsym :
  340. begin
  341. { we need a simple loadn and the load must be in a global symtable or
  342. in the same level as the para of the current proc }
  343. if (
  344. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  345. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  346. ) and
  347. not(
  348. (tloadnode(hp).symtableentry.typ=varsym) and
  349. ((tvarsym(tloadnode(hp).symtableentry).varspez in [vs_var,vs_out]) or
  350. (vo_is_thread_var in tvarsym(tloadnode(hp).symtableentry).varoptions))
  351. ) then
  352. begin
  353. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_used;
  354. { Assigning for-loop variable is only allowed in tp7 }
  355. if not(m_tp7 in aktmodeswitches) then
  356. begin
  357. if not assigned(loopvarsym) then
  358. loopvarsym:=tvarsym(tloadnode(hp).symtableentry);
  359. include(loopvarsym.varoptions,vo_is_loop_counter);
  360. end;
  361. end
  362. else
  363. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  364. end;
  365. typedconstsym :
  366. begin
  367. { Bad programming, only allowed in tp7 mode }
  368. if not(m_tp7 in aktmodeswitches) then
  369. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  370. end;
  371. else
  372. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  373. end;
  374. end
  375. else
  376. MessagePos(tassignmentnode(p_e).left.fileinfo,type_e_illegal_count_var);
  377. end
  378. else
  379. Message(parser_e_illegal_expression);
  380. if token=_DOWNTO then
  381. begin
  382. consume(_DOWNTO);
  383. backward:=true;
  384. end
  385. else
  386. begin
  387. consume(_TO);
  388. backward:=false;
  389. end;
  390. tovalue:=comp_expr(true);
  391. consume(_DO);
  392. { ... now the instruction block }
  393. p_a:=statement;
  394. { variable is not used a loop counter anymore }
  395. if assigned(loopvarsym) then
  396. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  397. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  398. end;
  399. function _with_statement : tnode;
  400. var
  401. right,p : tnode;
  402. i,levelcount : longint;
  403. withsymtable,symtab : tsymtable;
  404. obj : tobjectdef;
  405. hp : tnode;
  406. newblock : tblocknode;
  407. newstatement : tstatementnode;
  408. calltempp,
  409. loadp : ttempcreatenode;
  410. refp : tnode;
  411. htype : ttype;
  412. hasimplicitderef : boolean;
  413. begin
  414. p:=comp_expr(true);
  415. do_resulttypepass(p);
  416. set_varstate(p,vs_used,false);
  417. right:=nil;
  418. if (not codegenerror) and
  419. (p.resulttype.def.deftype in [objectdef,recorddef]) then
  420. begin
  421. newblock:=nil;
  422. { ignore nodes that don't add instructions in the tree }
  423. hp:=p;
  424. while { equal type conversions }
  425. (
  426. (hp.nodetype=typeconvn) and
  427. (ttypeconvnode(hp).convtype=tc_equal)
  428. ) or
  429. { constant array index }
  430. (
  431. (hp.nodetype=vecn) and
  432. (tvecnode(hp).right.nodetype=ordconstn)
  433. ) do
  434. hp:=tunarynode(hp).left;
  435. if (hp.nodetype=loadn) and
  436. (
  437. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  438. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  439. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  440. ) then
  441. begin
  442. { simple load, we can reference direct }
  443. loadp:=nil;
  444. refp:=p;
  445. end
  446. else
  447. begin
  448. calltempp:=nil;
  449. { complex load, load in temp first }
  450. newblock:=internalstatements(newstatement);
  451. { when right is a call then load it first in a temp }
  452. if p.nodetype=calln then
  453. begin
  454. calltempp:=ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent);
  455. addstatement(newstatement,calltempp);
  456. addstatement(newstatement,cassignmentnode.create(
  457. ctemprefnode.create(calltempp),
  458. p));
  459. p:=ctemprefnode.create(calltempp);
  460. resulttypepass(p);
  461. end;
  462. { classes and interfaces have implicit dereferencing }
  463. hasimplicitderef:=is_class_or_interface(p.resulttype.def);
  464. if hasimplicitderef then
  465. htype:=p.resulttype
  466. else
  467. htype.setdef(tpointerdef.create(p.resulttype));
  468. {$ifdef WITHNODEDEBUG}
  469. { we can't generate debuginfo for a withnode stored in a }
  470. { register }
  471. if (cs_debuginfo in aktmoduleswitches) then
  472. loadp:=ctempcreatenode.create(htype,sizeof(aint),tt_persistent)
  473. else
  474. {$endif WITHNODEDEBUG}
  475. loadp:=ctempcreatenode.create_reg(htype,sizeof(aint),tt_persistent);
  476. resulttypepass(loadp);
  477. if hasimplicitderef then
  478. begin
  479. hp:=p;
  480. refp:=ctemprefnode.create(loadp);
  481. end
  482. else
  483. begin
  484. hp:=caddrnode.create(p);
  485. refp:=cderefnode.create(ctemprefnode.create(loadp));
  486. end;
  487. addstatement(newstatement,loadp);
  488. addstatement(newstatement,cassignmentnode.create(
  489. ctemprefnode.create(loadp),
  490. hp));
  491. resulttypepass(refp);
  492. end;
  493. case p.resulttype.def.deftype of
  494. objectdef :
  495. begin
  496. obj:=tobjectdef(p.resulttype.def);
  497. withsymtable:=twithsymtable.Create(obj,obj.symtable.symsearch,refp);
  498. { include also all parent symtables }
  499. levelcount:=1;
  500. obj:=obj.childof;
  501. symtab:=withsymtable;
  502. while assigned(obj) do
  503. begin
  504. { keep the original tobjectdef as owner, because that is used for
  505. visibility of the symtable }
  506. symtab.next:=twithsymtable.create(tobjectdef(p.resulttype.def),obj.symtable.symsearch,refp.getcopy);
  507. symtab:=symtab.next;
  508. obj:=obj.childof;
  509. inc(levelcount);
  510. end;
  511. symtab.next:=symtablestack;
  512. symtablestack:=withsymtable;
  513. end;
  514. recorddef :
  515. begin
  516. symtab:=trecorddef(p.resulttype.def).symtable;
  517. levelcount:=1;
  518. withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch,refp);
  519. withsymtable.next:=symtablestack;
  520. symtablestack:=withsymtable;
  521. end;
  522. end;
  523. if try_to_consume(_COMMA) then
  524. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif}
  525. else
  526. begin
  527. consume(_DO);
  528. if token<>_SEMICOLON then
  529. right:=statement
  530. else
  531. right:=cerrornode.create;
  532. end;
  533. { remove symtables from the stack }
  534. for i:=1 to levelcount do
  535. symtablestack:=symtablestack.next;
  536. p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refp);
  537. { Finalize complex withnode with destroy of temp }
  538. if assigned(newblock) then
  539. begin
  540. addstatement(newstatement,p);
  541. addstatement(newstatement,ctempdeletenode.create(loadp));
  542. if assigned(calltempp) then
  543. addstatement(newstatement,ctempdeletenode.create(calltempp));
  544. p:=newblock;
  545. end;
  546. _with_statement:=p;
  547. end
  548. else
  549. begin
  550. p.free;
  551. Message(parser_e_false_with_expr);
  552. { try to recover from error }
  553. if try_to_consume(_COMMA) then
  554. begin
  555. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  556. if (hp=nil) then; { remove warning about unused }
  557. end
  558. else
  559. begin
  560. consume(_DO);
  561. { ignore all }
  562. if token<>_SEMICOLON then
  563. statement;
  564. end;
  565. _with_statement:=nil;
  566. end;
  567. end;
  568. function with_statement : tnode;
  569. begin
  570. consume(_WITH);
  571. with_statement:=_with_statement;
  572. end;
  573. function raise_statement : tnode;
  574. var
  575. p,pobj,paddr,pframe : tnode;
  576. begin
  577. pobj:=nil;
  578. paddr:=nil;
  579. pframe:=nil;
  580. consume(_RAISE);
  581. if not(token in endtokens) then
  582. begin
  583. { object }
  584. pobj:=comp_expr(true);
  585. if try_to_consume(_AT) then
  586. begin
  587. paddr:=comp_expr(true);
  588. if try_to_consume(_COMMA) then
  589. pframe:=comp_expr(true);
  590. end;
  591. end
  592. else
  593. begin
  594. if (block_type<>bt_except) then
  595. Message(parser_e_no_reraise_possible);
  596. end;
  597. p:=craisenode.create(pobj,paddr,pframe);
  598. raise_statement:=p;
  599. end;
  600. function try_statement : tnode;
  601. var
  602. p_try_block,p_finally_block,first,last,
  603. p_default,p_specific,hp : tnode;
  604. ot : ttype;
  605. sym : tvarsym;
  606. old_block_type : tblock_type;
  607. exceptsymtable : tsymtable;
  608. objname,objrealname : stringid;
  609. srsym : tsym;
  610. srsymtable : tsymtable;
  611. oldaktexceptblock: integer;
  612. begin
  613. include(current_procinfo.flags,pi_uses_exceptions);
  614. p_default:=nil;
  615. p_specific:=nil;
  616. { read statements to try }
  617. consume(_TRY);
  618. first:=nil;
  619. inc(exceptblockcounter);
  620. oldaktexceptblock := aktexceptblock;
  621. aktexceptblock := exceptblockcounter;
  622. while (token<>_FINALLY) and (token<>_EXCEPT) do
  623. begin
  624. if first=nil then
  625. begin
  626. last:=cstatementnode.create(statement,nil);
  627. first:=last;
  628. end
  629. else
  630. begin
  631. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  632. last:=tstatementnode(last).right;
  633. end;
  634. if not try_to_consume(_SEMICOLON) then
  635. break;
  636. consume_emptystats;
  637. end;
  638. p_try_block:=cblocknode.create(first);
  639. if try_to_consume(_FINALLY) then
  640. begin
  641. inc(exceptblockcounter);
  642. aktexceptblock := exceptblockcounter;
  643. p_finally_block:=statements_til_end;
  644. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  645. end
  646. else
  647. begin
  648. consume(_EXCEPT);
  649. old_block_type:=block_type;
  650. block_type:=bt_except;
  651. inc(exceptblockcounter);
  652. aktexceptblock := exceptblockcounter;
  653. ot:=generrortype;
  654. p_specific:=nil;
  655. if (idtoken=_ON) then
  656. { catch specific exceptions }
  657. begin
  658. repeat
  659. consume(_ID);
  660. if token=_ID then
  661. begin
  662. objname:=pattern;
  663. objrealname:=orgpattern;
  664. { can't use consume_sym here, because we need already
  665. to check for the colon }
  666. searchsym(objname,srsym,srsymtable);
  667. consume(_ID);
  668. { is a explicit name for the exception given ? }
  669. if try_to_consume(_COLON) then
  670. begin
  671. consume_sym(srsym,srsymtable);
  672. if (srsym.typ=typesym) and
  673. is_class(ttypesym(srsym).restype.def) then
  674. begin
  675. ot:=ttypesym(srsym).restype;
  676. sym:=tvarsym.create(objrealname,vs_value,ot);
  677. end
  678. else
  679. begin
  680. sym:=tvarsym.create(objrealname,vs_value,generrortype);
  681. if (srsym.typ=typesym) then
  682. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  683. else
  684. Message1(type_e_class_type_expected,ot.def.typename);
  685. end;
  686. exceptsymtable:=tstt_exceptsymtable.create;
  687. exceptsymtable.insert(sym);
  688. { insert the exception symtable stack }
  689. exceptsymtable.next:=symtablestack;
  690. symtablestack:=exceptsymtable;
  691. end
  692. else
  693. begin
  694. { check if type is valid, must be done here because
  695. with "e: Exception" the e is not necessary }
  696. if srsym=nil then
  697. begin
  698. identifier_not_found(objrealname);
  699. srsym:=generrorsym;
  700. end;
  701. { support unit.identifier }
  702. if srsym.typ=unitsym then
  703. begin
  704. consume(_POINT);
  705. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  706. if srsym=nil then
  707. begin
  708. identifier_not_found(orgpattern);
  709. srsym:=generrorsym;
  710. end;
  711. consume(_ID);
  712. end;
  713. { check if type is valid, must be done here because
  714. with "e: Exception" the e is not necessary }
  715. if (srsym.typ=typesym) and
  716. is_class(ttypesym(srsym).restype.def) then
  717. ot:=ttypesym(srsym).restype
  718. else
  719. begin
  720. ot:=generrortype;
  721. if (srsym.typ=typesym) then
  722. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  723. else
  724. Message1(type_e_class_type_expected,ot.def.typename);
  725. end;
  726. exceptsymtable:=nil;
  727. end;
  728. end
  729. else
  730. consume(_ID);
  731. consume(_DO);
  732. hp:=connode.create(nil,statement);
  733. if ot.def.deftype=errordef then
  734. begin
  735. hp.free;
  736. hp:=cerrornode.create;
  737. end;
  738. if p_specific=nil then
  739. begin
  740. last:=hp;
  741. p_specific:=last;
  742. end
  743. else
  744. begin
  745. tonnode(last).left:=hp;
  746. last:=tonnode(last).left;
  747. end;
  748. { set the informations }
  749. { only if the creation of the onnode was succesful, it's possible }
  750. { that last and hp are errornodes (JM) }
  751. if last.nodetype = onn then
  752. begin
  753. tonnode(last).excepttype:=tobjectdef(ot.def);
  754. tonnode(last).exceptsymtable:=exceptsymtable;
  755. end;
  756. { remove exception symtable }
  757. if assigned(exceptsymtable) then
  758. begin
  759. symtablestack:=symtablestack.next;
  760. if last.nodetype <> onn then
  761. exceptsymtable.free;
  762. end;
  763. if not try_to_consume(_SEMICOLON) then
  764. break;
  765. consume_emptystats;
  766. until (token in [_END,_ELSE]);
  767. if try_to_consume(_ELSE) then
  768. begin
  769. { catch the other exceptions }
  770. p_default:=statements_til_end;
  771. end
  772. else
  773. consume(_END);
  774. end
  775. else
  776. begin
  777. { catch all exceptions }
  778. p_default:=statements_til_end;
  779. end;
  780. block_type:=old_block_type;
  781. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  782. end;
  783. aktexceptblock := oldaktexceptblock;
  784. end;
  785. function _asm_statement : tnode;
  786. var
  787. asmstat : tasmnode;
  788. Marker : tai;
  789. reg : tregister;
  790. asmreader : tbaseasmreader;
  791. begin
  792. Inside_asm_statement:=true;
  793. if assigned(asmmodeinfos[aktasmmode]) then
  794. begin
  795. asmreader:=asmmodeinfos[aktasmmode]^.casmreader.create;
  796. asmstat:=casmnode.create(asmreader.assemble as taasmoutput);
  797. asmreader.free;
  798. end
  799. else
  800. Message(parser_f_assembler_reader_not_supported);
  801. { Mark procedure that it has assembler blocks }
  802. include(current_procinfo.flags,pi_has_assembler_block);
  803. { Read first the _ASM statement }
  804. consume(_ASM);
  805. { END is read, got a list of changed registers? }
  806. if try_to_consume(_LECKKLAMMER) then
  807. begin
  808. asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
  809. if token<>_RECKKLAMMER then
  810. begin
  811. repeat
  812. { it's possible to specify the modified registers }
  813. reg:=std_regnum_search(lower(pattern));
  814. if reg<>NR_NO then
  815. begin
  816. if getregtype(reg)=R_INTREGISTER then
  817. include(asmstat.used_regs_int,getsupreg(reg));
  818. end
  819. else
  820. Message(asmr_e_invalid_register);
  821. consume(_CSTRING);
  822. if not try_to_consume(_COMMA) then
  823. break;
  824. until false;
  825. end;
  826. consume(_RECKKLAMMER);
  827. end
  828. else
  829. begin
  830. asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
  831. asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
  832. end;
  833. { mark the start and the end of the assembler block
  834. this is needed for the optimizer }
  835. If Assigned(AsmStat.p_asm) Then
  836. Begin
  837. Marker := Tai_Marker.Create(AsmBlockStart);
  838. AsmStat.p_asm.Insert(Marker);
  839. Marker := Tai_Marker.Create(AsmBlockEnd);
  840. AsmStat.p_asm.Concat(Marker);
  841. End;
  842. Inside_asm_statement:=false;
  843. _asm_statement:=asmstat;
  844. end;
  845. function statement : tnode;
  846. var
  847. p : tnode;
  848. code : tnode;
  849. filepos : tfileposinfo;
  850. srsym : tsym;
  851. srsymtable : tsymtable;
  852. s : stringid;
  853. begin
  854. filepos:=akttokenpos;
  855. case token of
  856. _GOTO :
  857. begin
  858. if not(cs_support_goto in aktmoduleswitches)then
  859. Message(sym_e_goto_and_label_not_supported);
  860. consume(_GOTO);
  861. if (token<>_INTCONST) and (token<>_ID) then
  862. begin
  863. Message(sym_e_label_not_found);
  864. code:=cerrornode.create;
  865. end
  866. else
  867. begin
  868. if token=_ID then
  869. consume_sym(srsym,srsymtable)
  870. else
  871. begin
  872. searchsym(pattern,srsym,srsymtable);
  873. if srsym=nil then
  874. begin
  875. identifier_not_found(pattern);
  876. srsym:=generrorsym;
  877. srsymtable:=nil;
  878. end;
  879. consume(token);
  880. end;
  881. if srsym.typ<>labelsym then
  882. begin
  883. Message(sym_e_id_is_no_label_id);
  884. code:=cerrornode.create;
  885. end
  886. else
  887. begin
  888. { goto is only allowed to labels within the current scope }
  889. if srsym.owner<>current_procinfo.procdef.localst then
  890. CGMessage(parser_e_goto_outside_proc);
  891. code:=cgotonode.create(tlabelsym(srsym));
  892. tgotonode(code).labsym:=tlabelsym(srsym);
  893. { set flag that this label is used }
  894. tlabelsym(srsym).used:=true;
  895. end;
  896. end;
  897. end;
  898. _BEGIN :
  899. code:=statement_block(_BEGIN);
  900. _IF :
  901. code:=if_statement;
  902. _CASE :
  903. code:=case_statement;
  904. _REPEAT :
  905. code:=repeat_statement;
  906. _WHILE :
  907. code:=while_statement;
  908. _FOR :
  909. code:=for_statement;
  910. _WITH :
  911. code:=with_statement;
  912. _TRY :
  913. code:=try_statement;
  914. _RAISE :
  915. code:=raise_statement;
  916. { semicolons,else until and end are ignored }
  917. _SEMICOLON,
  918. _ELSE,
  919. _UNTIL,
  920. _END:
  921. code:=cnothingnode.create;
  922. _FAIL :
  923. begin
  924. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  925. Message(parser_e_fail_only_in_constructor);
  926. consume(_FAIL);
  927. code:=call_fail_node;
  928. end;
  929. _ASM :
  930. code:=_asm_statement;
  931. _EOF :
  932. Message(scan_f_end_of_file);
  933. else
  934. begin
  935. p:=expr;
  936. { When a colon follows a intconst then transform it into a label }
  937. if (p.nodetype=ordconstn) and
  938. try_to_consume(_COLON) then
  939. begin
  940. s:=tostr(tordconstnode(p).value);
  941. p.free;
  942. searchsym(s,srsym,srsymtable);
  943. if assigned(srsym) and
  944. (srsym.typ=labelsym) then
  945. begin
  946. if tlabelsym(srsym).defined then
  947. Message(sym_e_label_already_defined);
  948. tlabelsym(srsym).defined:=true;
  949. p:=clabelnode.create(tlabelsym(srsym),nil);
  950. end
  951. else
  952. begin
  953. Message1(sym_e_label_used_and_not_defined,s);
  954. p:=cnothingnode.create;
  955. end;
  956. end;
  957. if p.nodetype=labeln then
  958. begin
  959. { the pointer to the following instruction }
  960. { isn't a very clean way }
  961. if token in endtokens then
  962. tlabelnode(p).left:=cnothingnode.create
  963. else
  964. tlabelnode(p).left:=statement{$ifdef FPCPROCVAR}(){$endif};
  965. { be sure to have left also resulttypepass }
  966. resulttypepass(tlabelnode(p).left);
  967. end
  968. else
  969. { change a load of a procvar to a call. this is also
  970. supported in fpc mode }
  971. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  972. maybe_call_procvar(p,false);
  973. { blockn support because a read/write is changed into a blocknode }
  974. { with a separate statement for each read/write operation (JM) }
  975. { the same is true for val() if the third parameter is not 32 bit }
  976. if not(p.nodetype in [nothingn,calln,ifn,assignn,breakn,inlinen,
  977. continuen,labeln,blockn,exitn]) then
  978. Message(parser_e_illegal_expression);
  979. { Specify that we don't use the value returned by the call.
  980. This is used for :
  981. - dispose of temp stack space
  982. - dispose on FPU stack }
  983. if (p.nodetype=calln) then
  984. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  985. code:=p;
  986. end;
  987. end;
  988. if assigned(code) then
  989. code.set_tree_filepos(filepos);
  990. statement:=code;
  991. end;
  992. function statement_block(starttoken : ttoken) : tnode;
  993. var
  994. first,last : tnode;
  995. filepos : tfileposinfo;
  996. begin
  997. first:=nil;
  998. filepos:=akttokenpos;
  999. consume(starttoken);
  1000. while not(token in [_END,_FINALIZATION]) do
  1001. begin
  1002. if first=nil then
  1003. begin
  1004. last:=cstatementnode.create(statement,nil);
  1005. first:=last;
  1006. end
  1007. else
  1008. begin
  1009. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1010. last:=tstatementnode(last).right;
  1011. end;
  1012. if (token in [_END,_FINALIZATION]) then
  1013. break
  1014. else
  1015. begin
  1016. { if no semicolon, then error and go on }
  1017. if token<>_SEMICOLON then
  1018. begin
  1019. consume(_SEMICOLON);
  1020. consume_all_until(_SEMICOLON);
  1021. end;
  1022. consume(_SEMICOLON);
  1023. end;
  1024. consume_emptystats;
  1025. end;
  1026. { don't consume the finalization token, it is consumed when
  1027. reading the finalization block, but allow it only after
  1028. an initalization ! }
  1029. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1030. consume(_END);
  1031. last:=cblocknode.create(first);
  1032. last.set_tree_filepos(filepos);
  1033. statement_block:=last;
  1034. end;
  1035. function assembler_block : tnode;
  1036. var
  1037. p : tnode;
  1038. locals : longint;
  1039. begin
  1040. { Rename the funcret so that recursive calls are possible }
  1041. if not is_void(current_procinfo.procdef.rettype.def) then
  1042. symtablestack.rename(current_procinfo.procdef.resultname,'$hiddenresult');
  1043. { delphi uses register calling for assembler methods }
  1044. if (m_delphi in aktmodeswitches) and
  1045. (po_assembler in current_procinfo.procdef.procoptions) and
  1046. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1047. current_procinfo.procdef.proccalloption:=pocall_register;
  1048. { force the asm statement }
  1049. if token<>_ASM then
  1050. consume(_ASM);
  1051. include(current_procinfo.flags,pi_is_assembler);
  1052. p:=_asm_statement;
  1053. {$ifndef sparc}
  1054. {$ifndef arm}
  1055. if (po_assembler in current_procinfo.procdef.procoptions) then
  1056. begin
  1057. { set the framepointer to esp for assembler functions when the
  1058. following conditions are met:
  1059. - if the are no local variables and parameters (except the allocated result)
  1060. - no reference to the result variable (refcount<=1)
  1061. - result is not stored as parameter
  1062. - target processor has optional frame pointer save
  1063. (vm, i386, vm only currently)
  1064. }
  1065. locals:=0;
  1066. current_procinfo.procdef.localst.foreach_static({$ifdef FPCPROCVAR}@{$endif}count_locals,@locals);
  1067. current_procinfo.procdef.parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}count_locals,@locals);
  1068. if (locals=0) and
  1069. (current_procinfo.procdef.owner.symtabletype<>objectsymtable) and
  1070. (not assigned(current_procinfo.procdef.funcretsym) or
  1071. (tvarsym(current_procinfo.procdef.funcretsym).refcount<=1)) and
  1072. not(paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) then
  1073. begin
  1074. { Only need to set the framepointer, the locals will
  1075. be inserted with the correct reference in tcgasmnode.pass_2 }
  1076. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1077. end;
  1078. end;
  1079. {$endif arm}
  1080. {$endif sparc}
  1081. { Flag the result as assigned when it is returned in a
  1082. register.
  1083. }
  1084. if assigned(current_procinfo.procdef.funcretsym) and
  1085. (not paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) then
  1086. tvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_assigned;
  1087. { because the END is already read we need to get the
  1088. last_endtoken_filepos here (PFV) }
  1089. last_endtoken_filepos:=akttokenpos;
  1090. assembler_block:=p;
  1091. end;
  1092. end.
  1093. {
  1094. $Log$
  1095. Revision 1.141 2004-09-27 15:15:52 peter
  1096. * register loopvarsym for fields instead of record variable
  1097. * don't allow class fields as loop var
  1098. Revision 1.140 2004/09/26 17:45:30 peter
  1099. * simple regvar support, not yet finished
  1100. Revision 1.139 2004/09/21 17:25:12 peter
  1101. * paraloc branch merged
  1102. Revision 1.138 2004/09/21 16:00:50 peter
  1103. * no difference for withnode when debuginfo is generated
  1104. Revision 1.137 2004/09/13 20:28:27 peter
  1105. * for loop variable assignment is not allowed anymore
  1106. Revision 1.136.4.1 2004/09/21 16:01:54 peter
  1107. * withnode debug disabled
  1108. Revision 1.136 2004/06/20 08:55:30 florian
  1109. * logs truncated
  1110. Revision 1.135 2004/06/16 20:07:09 florian
  1111. * dwarf branch merged
  1112. Revision 1.134 2004/05/23 18:28:41 peter
  1113. * methodpointer is loaded into a temp when it was a calln
  1114. Revision 1.133 2004/05/23 11:39:38 peter
  1115. * give error when goto jumps to label outside current proc scope
  1116. Revision 1.132.2.2 2004/05/01 16:02:09 peter
  1117. * POINTER_SIZE replaced with sizeof(aint)
  1118. * aint,aword,tconst*int moved to globtype
  1119. Revision 1.132.2.1 2004/04/28 19:55:52 peter
  1120. * new warning for ordinal-pointer when size is different
  1121. * fixed some cg_e_ messages to the correct section type_e_ or parser_e_
  1122. }