pstatmnt.pas 48 KB

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