pstatmnt.pas 47 KB

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