pstatmnt.pas 44 KB

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