pstatmnt.pas 46 KB

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