pstatmnt.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  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;
  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. if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) then
  478. begin
  479. newblock:=nil;
  480. valuenode:=nil;
  481. tempnode:=nil;
  482. { ignore nodes that don't add instructions in the tree }
  483. hp:=p;
  484. while { equal type conversions }
  485. (
  486. (hp.nodetype=typeconvn) and
  487. (ttypeconvnode(hp).convtype=tc_equal)
  488. ) or
  489. { constant array index }
  490. (
  491. (hp.nodetype=vecn) and
  492. (tvecnode(hp).right.nodetype=ordconstn)
  493. ) do
  494. hp:=tunarynode(hp).left;
  495. if (hp.nodetype=loadn) and
  496. (
  497. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  498. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  499. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  500. ) and
  501. { MacPas objects are mapped to classes, and the MacPas compilers
  502. interpret with-statements with MacPas objects the same way
  503. as records (the object referenced by the with-statement
  504. must remain constant)
  505. }
  506. not(is_class(hp.resultdef) and
  507. (m_mac in current_settings.modeswitches)) then
  508. begin
  509. { simple load, we can reference direct }
  510. refnode:=p;
  511. end
  512. else
  513. begin
  514. calltempnode:=nil;
  515. { complex load, load in temp first }
  516. newblock:=internalstatements(newstatement);
  517. { when we can't take the address of p, load it in a temp }
  518. { since we may need its address later on }
  519. if not valid_for_addr(p,false) then
  520. begin
  521. calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
  522. addstatement(newstatement,calltempnode);
  523. addstatement(newstatement,cassignmentnode.create(
  524. ctemprefnode.create(calltempnode),
  525. p));
  526. p:=ctemprefnode.create(calltempnode);
  527. typecheckpass(p);
  528. end;
  529. { classes and interfaces have implicit dereferencing }
  530. hasimplicitderef:=is_class_or_interface_or_dispinterface_or_objc(p.resultdef) or
  531. (p.resultdef.typ = classrefdef);
  532. if hasimplicitderef then
  533. hdef:=p.resultdef
  534. else
  535. hdef:=tpointerdef.create(p.resultdef);
  536. { load address of the value in a temp }
  537. tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
  538. typecheckpass(tnode(tempnode));
  539. valuenode:=p;
  540. refnode:=ctemprefnode.create(tempnode);
  541. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  542. { add address call for valuenode and deref for refnode if this
  543. is not done implicitly }
  544. if not hasimplicitderef then
  545. begin
  546. valuenode:=caddrnode.create_internal_nomark(valuenode);
  547. refnode:=cderefnode.create(refnode);
  548. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  549. end;
  550. addstatement(newstatement,tempnode);
  551. addstatement(newstatement,cassignmentnode.create(
  552. ctemprefnode.create(tempnode),
  553. valuenode));
  554. typecheckpass(refnode);
  555. end;
  556. withsymtablelist:=TFPObjectList.create(true);
  557. case p.resultdef.typ of
  558. objectdef :
  559. begin
  560. { push symtables of all parents in reverse order }
  561. pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
  562. { push object symtable }
  563. st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
  564. symtablestack.push(st);
  565. withsymtablelist.add(st);
  566. end;
  567. classrefdef :
  568. begin
  569. { push symtables of all parents in reverse order }
  570. pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
  571. { push object symtable }
  572. st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
  573. symtablestack.push(st);
  574. withsymtablelist.add(st);
  575. end;
  576. recorddef :
  577. begin
  578. st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
  579. symtablestack.push(st);
  580. withsymtablelist.add(st);
  581. end;
  582. else
  583. internalerror(200601271);
  584. end;
  585. if try_to_consume(_COMMA) then
  586. p:=_with_statement()
  587. else
  588. begin
  589. consume(_DO);
  590. if token<>_SEMICOLON then
  591. p:=statement
  592. else
  593. p:=cnothingnode.create;
  594. end;
  595. { remove symtables in reverse order from the stack }
  596. for i:=withsymtablelist.count-1 downto 0 do
  597. symtablestack.pop(TSymtable(withsymtablelist[i]));
  598. withsymtablelist.free;
  599. // p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refnode);
  600. { Finalize complex withnode with destroy of temp }
  601. if assigned(newblock) then
  602. begin
  603. addstatement(newstatement,p);
  604. if assigned(tempnode) then
  605. addstatement(newstatement,ctempdeletenode.create(tempnode));
  606. if assigned(calltempnode) then
  607. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  608. p:=newblock;
  609. end;
  610. result:=p;
  611. end
  612. else
  613. begin
  614. p.free;
  615. Message(parser_e_false_with_expr);
  616. { try to recover from error }
  617. if try_to_consume(_COMMA) then
  618. begin
  619. hp:=_with_statement();
  620. if (hp=nil) then; { remove warning about unused }
  621. end
  622. else
  623. begin
  624. consume(_DO);
  625. { ignore all }
  626. if token<>_SEMICOLON then
  627. statement;
  628. end;
  629. result:=nil;
  630. end;
  631. end;
  632. function with_statement : tnode;
  633. begin
  634. consume(_WITH);
  635. with_statement:=_with_statement();
  636. end;
  637. function raise_statement : tnode;
  638. var
  639. p,pobj,paddr,pframe : tnode;
  640. begin
  641. pobj:=nil;
  642. paddr:=nil;
  643. pframe:=nil;
  644. consume(_RAISE);
  645. if not(token in endtokens) then
  646. begin
  647. { object }
  648. pobj:=comp_expr(true);
  649. if try_to_consume(_AT) then
  650. begin
  651. paddr:=comp_expr(true);
  652. if try_to_consume(_COMMA) then
  653. pframe:=comp_expr(true);
  654. end;
  655. end
  656. else
  657. begin
  658. if (block_type<>bt_except) then
  659. Message(parser_e_no_reraise_possible);
  660. end;
  661. p:=craisenode.create(pobj,paddr,pframe);
  662. raise_statement:=p;
  663. end;
  664. function try_statement : tnode;
  665. var
  666. p_try_block,p_finally_block,first,last,
  667. p_default,p_specific,hp : tnode;
  668. ot : tDef;
  669. sym : tlocalvarsym;
  670. old_block_type : tblock_type;
  671. excepTSymtable : TSymtable;
  672. objname,objrealname : TIDString;
  673. srsym : tsym;
  674. srsymtable : TSymtable;
  675. oldcurrent_exceptblock: integer;
  676. begin
  677. include(current_procinfo.flags,pi_uses_exceptions);
  678. p_default:=nil;
  679. p_specific:=nil;
  680. { read statements to try }
  681. consume(_TRY);
  682. first:=nil;
  683. inc(exceptblockcounter);
  684. oldcurrent_exceptblock := current_exceptblock;
  685. current_exceptblock := exceptblockcounter;
  686. while (token<>_FINALLY) and (token<>_EXCEPT) do
  687. begin
  688. if first=nil then
  689. begin
  690. last:=cstatementnode.create(statement,nil);
  691. first:=last;
  692. end
  693. else
  694. begin
  695. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  696. last:=tstatementnode(last).right;
  697. end;
  698. if not try_to_consume(_SEMICOLON) then
  699. break;
  700. consume_emptystats;
  701. end;
  702. p_try_block:=cblocknode.create(first);
  703. if try_to_consume(_FINALLY) then
  704. begin
  705. inc(exceptblockcounter);
  706. current_exceptblock := exceptblockcounter;
  707. p_finally_block:=statements_til_end;
  708. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  709. end
  710. else
  711. begin
  712. consume(_EXCEPT);
  713. old_block_type:=block_type;
  714. block_type:=bt_except;
  715. inc(exceptblockcounter);
  716. current_exceptblock := exceptblockcounter;
  717. ot:=generrordef;
  718. p_specific:=nil;
  719. if (idtoken=_ON) then
  720. { catch specific exceptions }
  721. begin
  722. repeat
  723. consume(_ON);
  724. if token=_ID then
  725. begin
  726. objname:=pattern;
  727. objrealname:=orgpattern;
  728. { can't use consume_sym here, because we need already
  729. to check for the colon }
  730. searchsym(objname,srsym,srsymtable);
  731. consume(_ID);
  732. { is a explicit name for the exception given ? }
  733. if try_to_consume(_COLON) then
  734. begin
  735. consume_sym(srsym,srsymtable);
  736. if (srsym.typ=typesym) and
  737. is_class(ttypesym(srsym).typedef) then
  738. begin
  739. ot:=ttypesym(srsym).typedef;
  740. sym:=tlocalvarsym.create(objrealname,vs_value,ot,[]);
  741. end
  742. else
  743. begin
  744. sym:=tlocalvarsym.create(objrealname,vs_value,generrordef,[]);
  745. if (srsym.typ=typesym) then
  746. Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
  747. else
  748. Message1(type_e_class_type_expected,ot.typename);
  749. end;
  750. excepTSymtable:=tstt_excepTSymtable.create;
  751. excepTSymtable.insert(sym);
  752. symtablestack.push(excepTSymtable);
  753. end
  754. else
  755. begin
  756. { check if type is valid, must be done here because
  757. with "e: Exception" the e is not necessary }
  758. if srsym=nil then
  759. begin
  760. identifier_not_found(objrealname);
  761. srsym:=generrorsym;
  762. end;
  763. { support unit.identifier }
  764. if srsym.typ=unitsym then
  765. begin
  766. consume(_POINT);
  767. searchsym_in_module(tunitsym(srsym).module,pattern,srsym,srsymtable);
  768. if srsym=nil then
  769. begin
  770. identifier_not_found(orgpattern);
  771. srsym:=generrorsym;
  772. end;
  773. consume(_ID);
  774. end;
  775. { check if type is valid, must be done here because
  776. with "e: Exception" the e is not necessary }
  777. if (srsym.typ=typesym) and
  778. is_class(ttypesym(srsym).typedef) then
  779. ot:=ttypesym(srsym).typedef
  780. else
  781. begin
  782. ot:=generrordef;
  783. if (srsym.typ=typesym) then
  784. Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
  785. else
  786. Message1(type_e_class_type_expected,ot.typename);
  787. end;
  788. excepTSymtable:=nil;
  789. end;
  790. end
  791. else
  792. consume(_ID);
  793. consume(_DO);
  794. hp:=connode.create(nil,statement);
  795. if ot.typ=errordef then
  796. begin
  797. hp.free;
  798. hp:=cerrornode.create;
  799. end;
  800. if p_specific=nil then
  801. begin
  802. last:=hp;
  803. p_specific:=last;
  804. end
  805. else
  806. begin
  807. tonnode(last).left:=hp;
  808. last:=tonnode(last).left;
  809. end;
  810. { set the informations }
  811. { only if the creation of the onnode was succesful, it's possible }
  812. { that last and hp are errornodes (JM) }
  813. if last.nodetype = onn then
  814. begin
  815. tonnode(last).excepttype:=tobjectdef(ot);
  816. tonnode(last).excepTSymtable:=excepTSymtable;
  817. end;
  818. { remove exception symtable }
  819. if assigned(excepTSymtable) then
  820. begin
  821. symtablestack.pop(excepTSymtable);
  822. if last.nodetype <> onn then
  823. excepTSymtable.free;
  824. end;
  825. if not try_to_consume(_SEMICOLON) then
  826. break;
  827. consume_emptystats;
  828. until (token in [_END,_ELSE]);
  829. if try_to_consume(_ELSE) then
  830. begin
  831. { catch the other exceptions }
  832. p_default:=statements_til_end;
  833. end
  834. else
  835. consume(_END);
  836. end
  837. else
  838. begin
  839. { catch all exceptions }
  840. p_default:=statements_til_end;
  841. end;
  842. block_type:=old_block_type;
  843. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  844. end;
  845. current_exceptblock := oldcurrent_exceptblock;
  846. end;
  847. function _asm_statement : tnode;
  848. var
  849. asmstat : tasmnode;
  850. Marker : tai;
  851. reg : tregister;
  852. asmreader : tbaseasmreader;
  853. begin
  854. Inside_asm_statement:=true;
  855. if assigned(asmmodeinfos[current_settings.asmmode]) then
  856. begin
  857. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  858. asmstat:=casmnode.create(asmreader.assemble as TAsmList);
  859. asmreader.free;
  860. end
  861. else
  862. Message(parser_f_assembler_reader_not_supported);
  863. { Mark procedure that it has assembler blocks }
  864. include(current_procinfo.flags,pi_has_assembler_block);
  865. { Read first the _ASM statement }
  866. consume(_ASM);
  867. { END is read, got a list of changed registers? }
  868. if try_to_consume(_LECKKLAMMER) then
  869. begin
  870. {$ifdef cpunofpu}
  871. asmstat.used_regs_fpu:=[0..first_int_imreg-1];
  872. {$else cpunofpu}
  873. asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
  874. {$endif cpunofpu}
  875. if token<>_RECKKLAMMER then
  876. begin
  877. if po_assembler in current_procinfo.procdef.procoptions then
  878. Message(parser_w_register_list_ignored);
  879. repeat
  880. { it's possible to specify the modified registers }
  881. reg:=std_regnum_search(lower(cstringpattern));
  882. if reg<>NR_NO then
  883. begin
  884. if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then
  885. include(asmstat.used_regs_int,getsupreg(reg));
  886. end
  887. else
  888. Message(asmr_e_invalid_register);
  889. consume(_CSTRING);
  890. if not try_to_consume(_COMMA) then
  891. break;
  892. until false;
  893. end;
  894. consume(_RECKKLAMMER);
  895. end
  896. else
  897. begin
  898. asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
  899. asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
  900. end;
  901. { mark the start and the end of the assembler block
  902. this is needed for the optimizer }
  903. If Assigned(AsmStat.p_asm) Then
  904. Begin
  905. Marker := Tai_Marker.Create(mark_AsmBlockStart);
  906. AsmStat.p_asm.Insert(Marker);
  907. Marker := Tai_Marker.Create(mark_AsmBlockEnd);
  908. AsmStat.p_asm.Concat(Marker);
  909. End;
  910. Inside_asm_statement:=false;
  911. _asm_statement:=asmstat;
  912. end;
  913. function statement : tnode;
  914. var
  915. p : tnode;
  916. code : tnode;
  917. filepos : tfileposinfo;
  918. srsym : tsym;
  919. srsymtable : TSymtable;
  920. s : TIDString;
  921. begin
  922. filepos:=current_tokenpos;
  923. case token of
  924. _GOTO :
  925. begin
  926. if not(cs_support_goto in current_settings.moduleswitches)then
  927. Message(sym_e_goto_and_label_not_supported);
  928. consume(_GOTO);
  929. if (token<>_INTCONST) and (token<>_ID) then
  930. begin
  931. Message(sym_e_label_not_found);
  932. code:=cerrornode.create;
  933. end
  934. else
  935. begin
  936. if token=_ID then
  937. consume_sym(srsym,srsymtable)
  938. else
  939. begin
  940. searchsym(pattern,srsym,srsymtable);
  941. if srsym=nil then
  942. begin
  943. identifier_not_found(pattern);
  944. srsym:=generrorsym;
  945. srsymtable:=nil;
  946. end;
  947. consume(token);
  948. end;
  949. if srsym.typ<>labelsym then
  950. begin
  951. Message(sym_e_id_is_no_label_id);
  952. code:=cerrornode.create;
  953. end
  954. else
  955. begin
  956. { goto is only allowed to labels within the current scope }
  957. if srsym.owner<>current_procinfo.procdef.localst then
  958. CGMessage(parser_e_goto_outside_proc);
  959. code:=cgotonode.create(tlabelsym(srsym));
  960. tgotonode(code).labelsym:=tlabelsym(srsym);
  961. { set flag that this label is used }
  962. tlabelsym(srsym).used:=true;
  963. end;
  964. end;
  965. end;
  966. _BEGIN :
  967. code:=statement_block(_BEGIN);
  968. _IF :
  969. code:=if_statement;
  970. _CASE :
  971. code:=case_statement;
  972. _REPEAT :
  973. code:=repeat_statement;
  974. _WHILE :
  975. code:=while_statement;
  976. _FOR :
  977. code:=for_statement;
  978. _WITH :
  979. code:=with_statement;
  980. _TRY :
  981. code:=try_statement;
  982. _RAISE :
  983. code:=raise_statement;
  984. { semicolons,else until and end are ignored }
  985. _SEMICOLON,
  986. _ELSE,
  987. _UNTIL,
  988. _END:
  989. code:=cnothingnode.create;
  990. _FAIL :
  991. begin
  992. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  993. Message(parser_e_fail_only_in_constructor);
  994. consume(_FAIL);
  995. code:=call_fail_node;
  996. end;
  997. _ASM :
  998. code:=_asm_statement;
  999. _EOF :
  1000. Message(scan_f_end_of_file);
  1001. else
  1002. begin
  1003. p:=expr;
  1004. { save the pattern here for latter usage, the label could be "000",
  1005. even if we read an expression, the pattern is still valid if it's really
  1006. a label (FK)
  1007. if you want to mess here, take care of
  1008. tests/webtbs/tw3546.pp
  1009. }
  1010. s:=pattern;
  1011. { When a colon follows a intconst then transform it into a label }
  1012. if (p.nodetype=ordconstn) and
  1013. try_to_consume(_COLON) then
  1014. begin
  1015. p.free;
  1016. searchsym(s,srsym,srsymtable);
  1017. if assigned(srsym) and
  1018. (srsym.typ=labelsym) then
  1019. begin
  1020. if tlabelsym(srsym).defined then
  1021. Message(sym_e_label_already_defined);
  1022. tlabelsym(srsym).defined:=true;
  1023. p:=clabelnode.create(nil,tlabelsym(srsym));
  1024. tlabelsym(srsym).code:=p;
  1025. end
  1026. else
  1027. begin
  1028. Message1(sym_e_label_used_and_not_defined,s);
  1029. p:=cnothingnode.create;
  1030. end;
  1031. end;
  1032. if p.nodetype=labeln then
  1033. begin
  1034. { the pointer to the following instruction }
  1035. { isn't a very clean way }
  1036. if token in endtokens then
  1037. tlabelnode(p).left:=cnothingnode.create
  1038. else
  1039. tlabelnode(p).left:=statement();
  1040. { be sure to have left also typecheckpass }
  1041. typecheckpass(tlabelnode(p).left);
  1042. end
  1043. else
  1044. { change a load of a procvar to a call. this is also
  1045. supported in fpc mode }
  1046. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1047. maybe_call_procvar(p,false);
  1048. { blockn support because a read/write is changed into a blocknode }
  1049. { with a separate statement for each read/write operation (JM) }
  1050. { the same is true for val() if the third parameter is not 32 bit }
  1051. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1052. continuen,labeln,blockn,exitn]) or
  1053. ((p.nodetype=inlinen) and
  1054. not is_void(p.resultdef)) or
  1055. ((p.nodetype=calln) and
  1056. (assigned(tcallnode(p).procdefinition)) and
  1057. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1058. Message(parser_e_illegal_expression);
  1059. { Specify that we don't use the value returned by the call.
  1060. This is used for :
  1061. - dispose of temp stack space
  1062. - dispose on FPU stack }
  1063. if (p.nodetype=calln) then
  1064. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1065. code:=p;
  1066. end;
  1067. end;
  1068. if assigned(code) then
  1069. begin
  1070. typecheckpass(code);
  1071. code.fileinfo:=filepos;
  1072. end;
  1073. statement:=code;
  1074. end;
  1075. function statement_block(starttoken : ttoken) : tnode;
  1076. var
  1077. first,last : tnode;
  1078. filepos : tfileposinfo;
  1079. begin
  1080. first:=nil;
  1081. filepos:=current_tokenpos;
  1082. consume(starttoken);
  1083. while not(token in [_END,_FINALIZATION]) do
  1084. begin
  1085. if first=nil then
  1086. begin
  1087. last:=cstatementnode.create(statement,nil);
  1088. first:=last;
  1089. end
  1090. else
  1091. begin
  1092. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1093. last:=tstatementnode(last).right;
  1094. end;
  1095. if (token in [_END,_FINALIZATION]) then
  1096. break
  1097. else
  1098. begin
  1099. { if no semicolon, then error and go on }
  1100. if token<>_SEMICOLON then
  1101. begin
  1102. consume(_SEMICOLON);
  1103. consume_all_until(_SEMICOLON);
  1104. end;
  1105. consume(_SEMICOLON);
  1106. end;
  1107. consume_emptystats;
  1108. end;
  1109. { don't consume the finalization token, it is consumed when
  1110. reading the finalization block, but allow it only after
  1111. an initalization ! }
  1112. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1113. consume(_END);
  1114. last:=cblocknode.create(first);
  1115. last.fileinfo:=filepos;
  1116. statement_block:=last;
  1117. end;
  1118. function assembler_block : tnode;
  1119. var
  1120. p : tnode;
  1121. {$ifndef arm}
  1122. locals : longint;
  1123. {$endif arm}
  1124. srsym : tsym;
  1125. begin
  1126. { Rename the funcret so that recursive calls are possible }
  1127. if not is_void(current_procinfo.procdef.returndef) then
  1128. begin
  1129. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1130. if assigned(srsym) then
  1131. srsym.realname:='$hiddenresult';
  1132. end;
  1133. { delphi uses register calling for assembler methods }
  1134. if (m_delphi in current_settings.modeswitches) and
  1135. (po_assembler in current_procinfo.procdef.procoptions) and
  1136. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1137. current_procinfo.procdef.proccalloption:=pocall_register;
  1138. { force the asm statement }
  1139. if token<>_ASM then
  1140. consume(_ASM);
  1141. include(current_procinfo.flags,pi_is_assembler);
  1142. p:=_asm_statement;
  1143. {$ifndef sparc}
  1144. {$ifndef arm}
  1145. if (po_assembler in current_procinfo.procdef.procoptions) then
  1146. begin
  1147. { set the framepointer to esp for assembler functions when the
  1148. following conditions are met:
  1149. - if the are no local variables and parameters (except the allocated result)
  1150. - no reference to the result variable (refcount<=1)
  1151. - result is not stored as parameter
  1152. - target processor has optional frame pointer save
  1153. (vm, i386, vm only currently)
  1154. }
  1155. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1156. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1157. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1158. if (locals=0) and
  1159. (current_procinfo.procdef.owner.symtabletype<>ObjectSymtable) and
  1160. (not assigned(current_procinfo.procdef.funcretsym) or
  1161. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1162. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
  1163. begin
  1164. { Only need to set the framepointer, the locals will
  1165. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1166. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1167. end;
  1168. end;
  1169. {$endif arm}
  1170. {$endif sparc}
  1171. { Flag the result as assigned when it is returned in a
  1172. register.
  1173. }
  1174. if assigned(current_procinfo.procdef.funcretsym) and
  1175. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
  1176. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1177. { because the END is already read we need to get the
  1178. last_endtoken_filepos here (PFV) }
  1179. last_endtoken_filepos:=current_tokenpos;
  1180. assembler_block:=p;
  1181. end;
  1182. end.