pstatmnt.pas 43 KB

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