pstatmnt.pas 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462
  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,ngenutil,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,ptype,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,false);
  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,false);
  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. else
  156. begin
  157. if is_char(casedef) and is_widechar(p.resultdef) then
  158. begin
  159. if (p.nodetype=ordconstn) then
  160. begin
  161. p:=ctypeconvnode.create(p,cansichartype);
  162. do_typecheckpass(p);
  163. end
  164. else if (p.nodetype=rangen) then
  165. begin
  166. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cansichartype);
  167. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cansichartype);
  168. do_typecheckpass(trangenode(p).left);
  169. do_typecheckpass(trangenode(p).right);
  170. end;
  171. end;
  172. end;
  173. hl1:=0;
  174. hl2:=0;
  175. sl1:=nil;
  176. sl2:=nil;
  177. if (p.nodetype=rangen) then
  178. begin
  179. { type check for string case statements }
  180. if caseofstring and
  181. is_conststring_or_constcharnode(trangenode(p).left) and
  182. is_conststring_or_constcharnode(trangenode(p).right) then
  183. begin
  184. { we need stringconstnodes, even if expression contains single chars }
  185. sl1 := get_string_value(trangenode(p).left, tstringdef(casedef));
  186. sl2 := get_string_value(trangenode(p).right, tstringdef(casedef));
  187. if sl1.fullcompare(sl2) > 0 then
  188. CGMessage(parser_e_case_lower_less_than_upper_bound);
  189. end
  190. { type checking for ordinal case statements }
  191. else if (not caseofstring) and
  192. is_subequal(casedef, trangenode(p).left.resultdef) and
  193. is_subequal(casedef, trangenode(p).right.resultdef) then
  194. begin
  195. hl1:=get_ordinal_value(trangenode(p).left);
  196. hl2:=get_ordinal_value(trangenode(p).right);
  197. if hl1>hl2 then
  198. CGMessage(parser_e_case_lower_less_than_upper_bound);
  199. if not casedeferror then
  200. begin
  201. testrange(casedef,hl1,false,false);
  202. testrange(casedef,hl2,false,false);
  203. end;
  204. end
  205. else
  206. CGMessage(parser_e_case_mismatch);
  207. if caseofstring then
  208. casenode.addlabel(blockid,sl1,sl2)
  209. else
  210. casenode.addlabel(blockid,hl1,hl2);
  211. end
  212. else
  213. begin
  214. { type check for string case statements }
  215. if (caseofstring and (not is_conststring_or_constcharnode(p))) or
  216. { type checking for ordinal case statements }
  217. ((not caseofstring) and (not is_subequal(casedef, p.resultdef))) then
  218. CGMessage(parser_e_case_mismatch);
  219. if caseofstring then
  220. begin
  221. sl1:=get_string_value(p, tstringdef(casedef));
  222. casenode.addlabel(blockid,sl1,sl1);
  223. end
  224. else
  225. begin
  226. hl1:=get_ordinal_value(p);
  227. if not casedeferror then
  228. testrange(casedef,hl1,false,false);
  229. casenode.addlabel(blockid,hl1,hl1);
  230. end;
  231. end;
  232. p.free;
  233. sl1.free;
  234. sl2.free;
  235. if token=_COMMA then
  236. consume(_COMMA)
  237. else
  238. break;
  239. until false;
  240. consume(_COLON);
  241. { add instruction block }
  242. casenode.addblock(blockid,statement);
  243. { next block }
  244. inc(blockid);
  245. if not(token in [_ELSE,_OTHERWISE,_END]) then
  246. consume(_SEMICOLON);
  247. until (token in [_ELSE,_OTHERWISE,_END]);
  248. if (token in [_ELSE,_OTHERWISE]) then
  249. begin
  250. if not try_to_consume(_ELSE) then
  251. consume(_OTHERWISE);
  252. casenode.addelseblock(statements_til_end);
  253. end
  254. else
  255. consume(_END);
  256. result:=casenode;
  257. end;
  258. function repeat_statement : tnode;
  259. var
  260. first,last,p_e : tnode;
  261. begin
  262. consume(_REPEAT);
  263. first:=nil;
  264. while token<>_UNTIL do
  265. begin
  266. if first=nil then
  267. begin
  268. last:=cstatementnode.create(statement,nil);
  269. first:=last;
  270. end
  271. else
  272. begin
  273. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  274. last:=tstatementnode(last).right;
  275. end;
  276. if not try_to_consume(_SEMICOLON) then
  277. break;
  278. consume_emptystats;
  279. end;
  280. consume(_UNTIL);
  281. first:=cblocknode.create(first);
  282. p_e:=comp_expr(true,false);
  283. result:=cwhilerepeatnode.create(p_e,first,false,true);
  284. end;
  285. function while_statement : tnode;
  286. var
  287. p_e,p_a : tnode;
  288. begin
  289. consume(_WHILE);
  290. p_e:=comp_expr(true,false);
  291. consume(_DO);
  292. p_a:=statement;
  293. result:=cwhilerepeatnode.create(p_e,p_a,true,false);
  294. end;
  295. { a helper function which is used both by "with" and "for-in loop" nodes }
  296. function skip_nodes_before_load(p: tnode): tnode;
  297. begin
  298. { ignore nodes that don't add instructions in the tree }
  299. while assigned(p) and
  300. { equal type conversions }
  301. (
  302. (p.nodetype=typeconvn) and
  303. (ttypeconvnode(p).convtype=tc_equal)
  304. ) or
  305. { constant array index }
  306. (
  307. (p.nodetype=vecn) and
  308. (tvecnode(p).right.nodetype=ordconstn)
  309. ) do
  310. p:=tunarynode(p).left;
  311. result:=p;
  312. end;
  313. function for_statement : tnode;
  314. procedure check_range(hp:tnode; fordef: tdef);
  315. begin
  316. if (hp.nodetype=ordconstn) and
  317. (fordef.typ<>errordef) then
  318. testrange(fordef,tordconstnode(hp).value,false,true);
  319. end;
  320. function for_loop_create(hloopvar: tnode): tnode;
  321. var
  322. hp,
  323. hblock,
  324. hto,hfrom : tnode;
  325. backward : boolean;
  326. loopvarsym : tabstractvarsym;
  327. begin
  328. { Check loop variable }
  329. loopvarsym:=nil;
  330. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  331. if not(is_ordinal(hloopvar.resultdef))
  332. {$ifndef cpu64bitaddr}
  333. or is_64bitint(hloopvar.resultdef)
  334. {$endif not cpu64bitaddr}
  335. then
  336. MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
  337. hp:=hloopvar;
  338. while assigned(hp) and
  339. (
  340. { record/object fields and array elements are allowed }
  341. { in tp7 mode only }
  342. (
  343. (m_tp7 in current_settings.modeswitches) and
  344. (
  345. ((hp.nodetype=subscriptn) and
  346. ((tsubscriptnode(hp).left.resultdef.typ=recorddef) or
  347. is_object(tsubscriptnode(hp).left.resultdef))
  348. ) or
  349. { constant array index }
  350. (
  351. (hp.nodetype=vecn) and
  352. is_constintnode(tvecnode(hp).right)
  353. )
  354. )
  355. ) or
  356. { equal typeconversions }
  357. (
  358. (hp.nodetype=typeconvn) and
  359. (ttypeconvnode(hp).convtype=tc_equal)
  360. )
  361. ) do
  362. begin
  363. { Use the recordfield for loopvarsym }
  364. if not assigned(loopvarsym) and
  365. (hp.nodetype=subscriptn) then
  366. loopvarsym:=tsubscriptnode(hp).vs;
  367. hp:=tunarynode(hp).left;
  368. end;
  369. if assigned(hp) and
  370. (hp.nodetype=loadn) then
  371. begin
  372. case tloadnode(hp).symtableentry.typ of
  373. staticvarsym,
  374. localvarsym,
  375. paravarsym :
  376. begin
  377. { we need a simple loadn:
  378. 1. The load must be in a global symtable or
  379. in the same level as the para of the current proc.
  380. 2. value variables (no const,out or var)
  381. 3. No threadvar, readonly or typedconst
  382. }
  383. if (
  384. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  385. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  386. ) and
  387. (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_value) and
  388. ([vo_is_thread_var,vo_is_typed_const] * tabstractvarsym(tloadnode(hp).symtableentry).varoptions=[]) then
  389. begin
  390. { Assigning for-loop variable is only allowed in tp7 and macpas }
  391. if ([m_tp7,m_mac] * current_settings.modeswitches = []) then
  392. begin
  393. if not assigned(loopvarsym) then
  394. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  395. include(loopvarsym.varoptions,vo_is_loop_counter);
  396. end;
  397. end
  398. else
  399. begin
  400. { Typed const is allowed in tp7 }
  401. if not(m_tp7 in current_settings.modeswitches) or
  402. not(vo_is_typed_const in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
  403. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  404. end;
  405. end;
  406. else
  407. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  408. end;
  409. end
  410. else
  411. MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
  412. hfrom:=comp_expr(true,false);
  413. if try_to_consume(_DOWNTO) then
  414. backward:=true
  415. else
  416. begin
  417. consume(_TO);
  418. backward:=false;
  419. end;
  420. hto:=comp_expr(true,false);
  421. consume(_DO);
  422. { Check if the constants fit in the range }
  423. check_range(hfrom,hloopvar.resultdef);
  424. check_range(hto,hloopvar.resultdef);
  425. { first set the varstate for from and to, so
  426. uses of loopvar in those expressions will also
  427. trigger a warning when it is not used yet. This
  428. needs to be done before the instruction block is
  429. parsed to have a valid hloopvar }
  430. typecheckpass(hfrom);
  431. set_varstate(hfrom,vs_read,[vsf_must_be_valid]);
  432. typecheckpass(hto);
  433. set_varstate(hto,vs_read,[vsf_must_be_valid]);
  434. typecheckpass(hloopvar);
  435. { in two steps, because vs_readwritten may turn on vsf_must_be_valid }
  436. { for some subnodes }
  437. set_varstate(hloopvar,vs_written,[]);
  438. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  439. { ... now the instruction block }
  440. hblock:=statement;
  441. { variable is not used for loop counter anymore }
  442. if assigned(loopvarsym) then
  443. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  444. result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
  445. end;
  446. function for_in_loop_create(hloopvar: tnode): tnode;
  447. var
  448. expr,hloopbody,hp: tnode;
  449. loopvarsym: tabstractvarsym;
  450. begin
  451. hp:=skip_nodes_before_load(hloopvar);
  452. if assigned(hp)and(hp.nodetype=loadn) then
  453. begin
  454. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  455. include(loopvarsym.varoptions,vo_is_loop_counter);
  456. end
  457. else
  458. loopvarsym:=nil;
  459. expr:=comp_expr(true,false);
  460. consume(_DO);
  461. set_varstate(hloopvar,vs_written,[]);
  462. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  463. hloopbody:=statement;
  464. if assigned(loopvarsym) then
  465. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  466. result:=create_for_in_loop(hloopvar,hloopbody,expr);
  467. expr.free;
  468. end;
  469. var
  470. hloopvar: tnode;
  471. begin
  472. { parse loop header }
  473. consume(_FOR);
  474. hloopvar:=factor(false,false);
  475. valid_for_loopvar(hloopvar,true);
  476. if try_to_consume(_ASSIGNMENT) then
  477. result:=for_loop_create(hloopvar)
  478. else if try_to_consume(_IN) then
  479. result:=for_in_loop_create(hloopvar)
  480. else
  481. consume(_ASSIGNMENT); // fail
  482. end;
  483. function _with_statement : tnode;
  484. var
  485. p : tnode;
  486. i : longint;
  487. st : TSymtable;
  488. newblock : tblocknode;
  489. newstatement : tstatementnode;
  490. calltempnode,
  491. tempnode : ttempcreatenode;
  492. valuenode,
  493. hp,
  494. refnode : tnode;
  495. hdef : tdef;
  496. helperdef : tobjectdef;
  497. hasimplicitderef : boolean;
  498. withsymtablelist : TFPObjectList;
  499. procedure pushobjchild(withdef,obj:tobjectdef);
  500. var
  501. parenthelperdef : tobjectdef;
  502. begin
  503. if not assigned(obj) then
  504. exit;
  505. pushobjchild(withdef,obj.childof);
  506. { we need to look for helpers that were defined for the parent
  507. class as well }
  508. search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
  509. { push the symtables of the helper's parents in reverse order }
  510. if assigned(parenthelperdef) then
  511. pushobjchild(withdef,parenthelperdef.childof);
  512. { keep the original tobjectdef as owner, because that is used for
  513. visibility of the symtable }
  514. st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
  515. symtablestack.push(st);
  516. withsymtablelist.add(st);
  517. { push the symtable of the helper }
  518. if assigned(parenthelperdef) then
  519. begin
  520. st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
  521. symtablestack.push(st);
  522. withsymtablelist.add(st);
  523. end;
  524. end;
  525. begin
  526. p:=comp_expr(true,false);
  527. do_typecheckpass(p);
  528. if (p.nodetype=vecn) and
  529. (nf_memseg in p.flags) then
  530. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  531. { "with procvar" can never mean anything, so always try
  532. to call it in case it returns a record/object/... }
  533. maybe_call_procvar(p,false);
  534. if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) or
  535. ((p.resultdef.typ=undefineddef) and (df_generic in current_procinfo.procdef.defoptions)) then
  536. begin
  537. newblock:=nil;
  538. valuenode:=nil;
  539. tempnode:=nil;
  540. hp:=skip_nodes_before_load(p);
  541. if (hp.nodetype=loadn) and
  542. (
  543. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  544. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  545. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  546. ) and
  547. { MacPas objects are mapped to classes, and the MacPas compilers
  548. interpret with-statements with MacPas objects the same way
  549. as records (the object referenced by the with-statement
  550. must remain constant)
  551. }
  552. not(is_class(hp.resultdef) and
  553. (m_mac in current_settings.modeswitches)) then
  554. begin
  555. { simple load, we can reference direct }
  556. refnode:=p;
  557. end
  558. else
  559. begin
  560. calltempnode:=nil;
  561. { complex load, load in temp first }
  562. newblock:=internalstatements(newstatement);
  563. { when we can't take the address of p, load it in a temp }
  564. { since we may need its address later on }
  565. if not valid_for_addr(p,false) then
  566. begin
  567. calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
  568. addstatement(newstatement,calltempnode);
  569. addstatement(newstatement,cassignmentnode.create(
  570. ctemprefnode.create(calltempnode),
  571. p));
  572. p:=ctemprefnode.create(calltempnode);
  573. typecheckpass(p);
  574. end;
  575. { several object types have implicit dereferencing }
  576. { is_implicit_pointer_object_type() returns true for records
  577. on the JVM target because they are implemented as classes
  578. there, but we definitely have to take their address here
  579. since otherwise a deep copy is made and changes are made to
  580. this copy rather than to the original one }
  581. hasimplicitderef:=
  582. (is_implicit_pointer_object_type(p.resultdef) or
  583. (p.resultdef.typ=classrefdef)) and
  584. not((target_info.system in systems_jvm) and
  585. ((p.resultdef.typ=recorddef) or
  586. is_object(p.resultdef)));
  587. if hasimplicitderef then
  588. hdef:=p.resultdef
  589. else
  590. hdef:=tpointerdef.create(p.resultdef);
  591. { load address of the value in a temp }
  592. tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
  593. typecheckpass(tnode(tempnode));
  594. valuenode:=p;
  595. refnode:=ctemprefnode.create(tempnode);
  596. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  597. { add address call for valuenode and deref for refnode if this
  598. is not done implicitly }
  599. if not hasimplicitderef then
  600. begin
  601. valuenode:=caddrnode.create_internal_nomark(valuenode);
  602. include(valuenode.flags,nf_typedaddr);
  603. refnode:=cderefnode.create(refnode);
  604. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  605. end;
  606. addstatement(newstatement,tempnode);
  607. addstatement(newstatement,cassignmentnode.create(
  608. ctemprefnode.create(tempnode),
  609. valuenode));
  610. typecheckpass(refnode);
  611. end;
  612. { Note: the symtable of the helper is pushed after the following
  613. "case", the symtables of the helper's parents are passed in
  614. the "case" branches }
  615. withsymtablelist:=TFPObjectList.create(true);
  616. case p.resultdef.typ of
  617. objectdef :
  618. begin
  619. { do we have a helper for this type? }
  620. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  621. { push symtables of all parents in reverse order }
  622. pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
  623. { push symtables of all parents of the helper in reverse order }
  624. if assigned(helperdef) then
  625. pushobjchild(helperdef,helperdef.childof);
  626. { push object symtable }
  627. st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
  628. symtablestack.push(st);
  629. withsymtablelist.add(st);
  630. end;
  631. classrefdef :
  632. begin
  633. { do we have a helper for this type? }
  634. search_last_objectpascal_helper(tobjectdef(tclassrefdef(p.resultdef).pointeddef),current_structdef,helperdef);
  635. { push symtables of all parents in reverse order }
  636. pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
  637. { push symtables of all parents of the helper in reverse order }
  638. if assigned(helperdef) then
  639. pushobjchild(helperdef,helperdef.childof);
  640. { push object symtable }
  641. st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
  642. symtablestack.push(st);
  643. withsymtablelist.add(st);
  644. end;
  645. recorddef :
  646. begin
  647. { do we have a helper for this type? }
  648. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  649. { push symtables of all parents of the helper in reverse order }
  650. if assigned(helperdef) then
  651. pushobjchild(helperdef,helperdef.childof);
  652. { push record symtable }
  653. st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
  654. symtablestack.push(st);
  655. withsymtablelist.add(st);
  656. end;
  657. undefineddef :
  658. begin
  659. if not(df_generic in current_procinfo.procdef.defoptions) then
  660. internalerror(2012122802);
  661. helperdef:=nil;
  662. { push record symtable }
  663. st:=twithsymtable.create(p.resultdef,nil,refnode);
  664. symtablestack.push(st);
  665. withsymtablelist.add(st);
  666. end;
  667. else
  668. internalerror(200601271);
  669. end;
  670. { push helper symtable }
  671. if assigned(helperdef) then
  672. begin
  673. st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
  674. symtablestack.push(st);
  675. withsymtablelist.add(st);
  676. end;
  677. if try_to_consume(_COMMA) then
  678. p:=_with_statement()
  679. else
  680. begin
  681. consume(_DO);
  682. if token<>_SEMICOLON then
  683. p:=statement
  684. else
  685. p:=cnothingnode.create;
  686. end;
  687. { remove symtables in reverse order from the stack }
  688. for i:=withsymtablelist.count-1 downto 0 do
  689. symtablestack.pop(TSymtable(withsymtablelist[i]));
  690. withsymtablelist.free;
  691. // p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refnode);
  692. { Finalize complex withnode with destroy of temp }
  693. if assigned(newblock) then
  694. begin
  695. addstatement(newstatement,p);
  696. if assigned(tempnode) then
  697. addstatement(newstatement,ctempdeletenode.create(tempnode));
  698. if assigned(calltempnode) then
  699. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  700. p:=newblock;
  701. end;
  702. result:=p;
  703. end
  704. else
  705. begin
  706. p.free;
  707. Message1(parser_e_false_with_expr,p.resultdef.GetTypeName);
  708. { try to recover from error }
  709. if try_to_consume(_COMMA) then
  710. begin
  711. hp:=_with_statement();
  712. if (hp=nil) then; { remove warning about unused }
  713. end
  714. else
  715. begin
  716. consume(_DO);
  717. { ignore all }
  718. if token<>_SEMICOLON then
  719. statement;
  720. end;
  721. result:=nil;
  722. end;
  723. end;
  724. function with_statement : tnode;
  725. begin
  726. consume(_WITH);
  727. with_statement:=_with_statement();
  728. end;
  729. function raise_statement : tnode;
  730. var
  731. p,pobj,paddr,pframe : tnode;
  732. begin
  733. pobj:=nil;
  734. paddr:=nil;
  735. pframe:=nil;
  736. consume(_RAISE);
  737. if not(token in endtokens) then
  738. begin
  739. { object }
  740. pobj:=comp_expr(true,false);
  741. if try_to_consume(_AT) then
  742. begin
  743. paddr:=comp_expr(true,false);
  744. if try_to_consume(_COMMA) then
  745. pframe:=comp_expr(true,false);
  746. end;
  747. end
  748. else
  749. begin
  750. if (block_type<>bt_except) then
  751. Message(parser_e_no_reraise_possible);
  752. end;
  753. p:=craisenode.create(pobj,paddr,pframe);
  754. raise_statement:=p;
  755. end;
  756. function try_statement : tnode;
  757. procedure check_type_valid(var def: tdef);
  758. begin
  759. if not (is_class(def) or is_javaclass(def) or
  760. { skip showing error message the second time }
  761. (def.typ=errordef)) then
  762. begin
  763. Message1(type_e_class_type_expected,def.typename);
  764. def:=generrordef;
  765. end;
  766. end;
  767. var
  768. p_try_block,p_finally_block,first,last,
  769. p_default,p_specific,hp : tnode;
  770. ot : tDef;
  771. sym : tlocalvarsym;
  772. old_block_type : tblock_type;
  773. excepTSymtable : TSymtable;
  774. objname,objrealname : TIDString;
  775. srsym : tsym;
  776. srsymtable : TSymtable;
  777. t:ttoken;
  778. unit_found:boolean;
  779. oldcurrent_exceptblock: integer;
  780. begin
  781. p_default:=nil;
  782. p_specific:=nil;
  783. { read statements to try }
  784. consume(_TRY);
  785. first:=nil;
  786. inc(exceptblockcounter);
  787. oldcurrent_exceptblock := current_exceptblock;
  788. current_exceptblock := exceptblockcounter;
  789. old_block_type := block_type;
  790. block_type := bt_body;
  791. while (token<>_FINALLY) and (token<>_EXCEPT) do
  792. begin
  793. if first=nil then
  794. begin
  795. last:=cstatementnode.create(statement,nil);
  796. first:=last;
  797. end
  798. else
  799. begin
  800. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  801. last:=tstatementnode(last).right;
  802. end;
  803. if not try_to_consume(_SEMICOLON) then
  804. break;
  805. consume_emptystats;
  806. end;
  807. p_try_block:=cblocknode.create(first);
  808. if try_to_consume(_FINALLY) then
  809. begin
  810. inc(exceptblockcounter);
  811. current_exceptblock := exceptblockcounter;
  812. p_finally_block:=statements_til_end;
  813. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  814. end
  815. else
  816. begin
  817. consume(_EXCEPT);
  818. block_type:=bt_except;
  819. inc(exceptblockcounter);
  820. current_exceptblock := exceptblockcounter;
  821. ot:=generrordef;
  822. p_specific:=nil;
  823. if (idtoken=_ON) then
  824. { catch specific exceptions }
  825. begin
  826. repeat
  827. consume(_ON);
  828. if token=_ID then
  829. begin
  830. objname:=pattern;
  831. objrealname:=orgpattern;
  832. { can't use consume_sym here, because we need already
  833. to check for the colon }
  834. searchsym(objname,srsym,srsymtable);
  835. consume(_ID);
  836. { is a explicit name for the exception given ? }
  837. if try_to_consume(_COLON) then
  838. begin
  839. single_type(ot,[]);
  840. check_type_valid(ot);
  841. sym:=tlocalvarsym.create(objrealname,vs_value,ot,[]);
  842. end
  843. else
  844. begin
  845. { check if type is valid, must be done here because
  846. with "e: Exception" the e is not necessary }
  847. { support unit.identifier }
  848. unit_found:=try_consume_unitsym(srsym,srsymtable,t,false);
  849. if srsym=nil then
  850. begin
  851. identifier_not_found(orgpattern);
  852. srsym:=generrorsym;
  853. end;
  854. if unit_found then
  855. consume(t);
  856. { check if type is valid, must be done here because
  857. with "e: Exception" the e is not necessary }
  858. if (srsym.typ=typesym) then
  859. begin
  860. ot:=ttypesym(srsym).typedef;
  861. parse_nested_types(ot,false,nil);
  862. check_type_valid(ot);
  863. end
  864. else
  865. begin
  866. Message(type_e_type_id_expected);
  867. ot:=generrordef;
  868. end;
  869. { create dummy symbol so we don't need a special
  870. case in ncgflw, and so that we always know the
  871. type }
  872. sym:=tlocalvarsym.create('$exceptsym',vs_value,ot,[]);
  873. end;
  874. excepTSymtable:=tstt_excepTSymtable.create;
  875. excepTSymtable.insert(sym);
  876. symtablestack.push(excepTSymtable);
  877. end
  878. else
  879. consume(_ID);
  880. consume(_DO);
  881. hp:=connode.create(nil,statement);
  882. if ot.typ=errordef then
  883. begin
  884. hp.free;
  885. hp:=cerrornode.create;
  886. end;
  887. if p_specific=nil then
  888. begin
  889. last:=hp;
  890. p_specific:=last;
  891. end
  892. else
  893. begin
  894. tonnode(last).left:=hp;
  895. last:=tonnode(last).left;
  896. end;
  897. { set the informations }
  898. { only if the creation of the onnode was succesful, it's possible }
  899. { that last and hp are errornodes (JM) }
  900. if last.nodetype = onn then
  901. begin
  902. tonnode(last).excepttype:=tobjectdef(ot);
  903. tonnode(last).excepTSymtable:=excepTSymtable;
  904. end;
  905. { remove exception symtable }
  906. if assigned(excepTSymtable) then
  907. begin
  908. symtablestack.pop(excepTSymtable);
  909. if last.nodetype <> onn then
  910. excepTSymtable.free;
  911. end;
  912. if not try_to_consume(_SEMICOLON) then
  913. break;
  914. consume_emptystats;
  915. until (token in [_END,_ELSE]);
  916. if try_to_consume(_ELSE) then
  917. begin
  918. { catch the other exceptions }
  919. p_default:=statements_til_end;
  920. end
  921. else
  922. consume(_END);
  923. end
  924. else
  925. begin
  926. { catch all exceptions }
  927. p_default:=statements_til_end;
  928. end;
  929. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  930. end;
  931. block_type:=old_block_type;
  932. current_exceptblock := oldcurrent_exceptblock;
  933. end;
  934. function _asm_statement : tnode;
  935. var
  936. asmstat : tasmnode;
  937. Marker : tai;
  938. reg : tregister;
  939. asmreader : tbaseasmreader;
  940. entrypos : tfileposinfo;
  941. begin
  942. Inside_asm_statement:=true;
  943. if assigned(asmmodeinfos[current_settings.asmmode]) then
  944. begin
  945. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  946. entrypos:=current_filepos;
  947. asmstat:=casmnode.create(asmreader.assemble as TAsmList);
  948. asmstat.fileinfo:=entrypos;
  949. asmreader.free;
  950. end
  951. else
  952. Message(parser_f_assembler_reader_not_supported);
  953. { Mark procedure that it has assembler blocks }
  954. include(current_procinfo.flags,pi_has_assembler_block);
  955. { Read first the _ASM statement }
  956. consume(_ASM);
  957. { END is read, got a list of changed registers? }
  958. if try_to_consume(_LECKKLAMMER) then
  959. begin
  960. {$ifdef cpunofpu}
  961. asmstat.used_regs_fpu:=[0..first_int_imreg-1];
  962. {$else cpunofpu}
  963. asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
  964. {$endif cpunofpu}
  965. if token<>_RECKKLAMMER then
  966. begin
  967. if po_assembler in current_procinfo.procdef.procoptions then
  968. Message(parser_w_register_list_ignored);
  969. repeat
  970. { it's possible to specify the modified registers }
  971. reg:=std_regnum_search(lower(cstringpattern));
  972. if reg<>NR_NO then
  973. begin
  974. if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then
  975. include(asmstat.used_regs_int,getsupreg(reg));
  976. end
  977. else
  978. Message(asmr_e_invalid_register);
  979. consume(_CSTRING);
  980. if not try_to_consume(_COMMA) then
  981. break;
  982. until false;
  983. end;
  984. consume(_RECKKLAMMER);
  985. end
  986. else
  987. begin
  988. asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
  989. asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
  990. end;
  991. { mark the start and the end of the assembler block
  992. this is needed for the optimizer }
  993. If Assigned(AsmStat.p_asm) Then
  994. Begin
  995. Marker := Tai_Marker.Create(mark_AsmBlockStart);
  996. AsmStat.p_asm.Insert(Marker);
  997. Marker := Tai_Marker.Create(mark_AsmBlockEnd);
  998. AsmStat.p_asm.Concat(Marker);
  999. End;
  1000. Inside_asm_statement:=false;
  1001. _asm_statement:=asmstat;
  1002. end;
  1003. function statement : tnode;
  1004. var
  1005. p,
  1006. code : tnode;
  1007. filepos : tfileposinfo;
  1008. srsym : tsym;
  1009. srsymtable : TSymtable;
  1010. s : TIDString;
  1011. begin
  1012. filepos:=current_tokenpos;
  1013. case token of
  1014. _GOTO :
  1015. begin
  1016. if not(cs_support_goto in current_settings.moduleswitches) then
  1017. Message(sym_e_goto_and_label_not_supported);
  1018. consume(_GOTO);
  1019. if (token<>_INTCONST) and (token<>_ID) then
  1020. begin
  1021. Message(sym_e_label_not_found);
  1022. code:=cerrornode.create;
  1023. end
  1024. else
  1025. begin
  1026. if token=_ID then
  1027. consume_sym(srsym,srsymtable)
  1028. else
  1029. begin
  1030. if token<>_INTCONST then
  1031. internalerror(201008021);
  1032. { strip leading 0's in iso mode }
  1033. if m_iso in current_settings.modeswitches then
  1034. while pattern[1]='0' do
  1035. delete(pattern,1,1);
  1036. searchsym(pattern,srsym,srsymtable);
  1037. if srsym=nil then
  1038. begin
  1039. identifier_not_found(pattern);
  1040. srsym:=generrorsym;
  1041. srsymtable:=nil;
  1042. end;
  1043. consume(token);
  1044. end;
  1045. if srsym.typ<>labelsym then
  1046. begin
  1047. Message(sym_e_id_is_no_label_id);
  1048. code:=cerrornode.create;
  1049. end
  1050. else
  1051. begin
  1052. { goto outside the current scope? }
  1053. if srsym.owner<>current_procinfo.procdef.localst then
  1054. begin
  1055. { allowed? }
  1056. if not(m_non_local_goto in current_settings.modeswitches) then
  1057. Message(parser_e_goto_outside_proc);
  1058. include(current_procinfo.flags,pi_has_global_goto);
  1059. end;
  1060. code:=cgotonode.create(tlabelsym(srsym));
  1061. tgotonode(code).labelsym:=tlabelsym(srsym);
  1062. { set flag that this label is used }
  1063. tlabelsym(srsym).used:=true;
  1064. end;
  1065. end;
  1066. end;
  1067. _BEGIN :
  1068. code:=statement_block(_BEGIN);
  1069. _IF :
  1070. code:=if_statement;
  1071. _CASE :
  1072. code:=case_statement;
  1073. _REPEAT :
  1074. code:=repeat_statement;
  1075. _WHILE :
  1076. code:=while_statement;
  1077. _FOR :
  1078. code:=for_statement;
  1079. _WITH :
  1080. code:=with_statement;
  1081. _TRY :
  1082. code:=try_statement;
  1083. _RAISE :
  1084. code:=raise_statement;
  1085. { semicolons,else until and end are ignored }
  1086. _SEMICOLON,
  1087. _ELSE,
  1088. _UNTIL,
  1089. _END:
  1090. code:=cnothingnode.create;
  1091. _FAIL :
  1092. begin
  1093. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  1094. Message(parser_e_fail_only_in_constructor);
  1095. consume(_FAIL);
  1096. code:=cnodeutils.call_fail_node;
  1097. end;
  1098. _ASM :
  1099. begin
  1100. if parse_generic then
  1101. Message(parser_e_no_assembler_in_generic);
  1102. code:=_asm_statement;
  1103. end;
  1104. _EOF :
  1105. Message(scan_f_end_of_file);
  1106. else
  1107. begin
  1108. { don't typecheck yet, because that will also simplify, which may
  1109. result in not detecting certain kinds of syntax errors --
  1110. see mantis #15594 }
  1111. p:=expr(false);
  1112. { save the pattern here for latter usage, the label could be "000",
  1113. even if we read an expression, the pattern is still valid if it's really
  1114. a label (FK)
  1115. if you want to mess here, take care of
  1116. tests/webtbs/tw3546.pp
  1117. }
  1118. s:=pattern;
  1119. { When a colon follows a intconst then transform it into a label }
  1120. if (p.nodetype=ordconstn) and
  1121. try_to_consume(_COLON) then
  1122. begin
  1123. { in iso mode, 0003: is equal to 3: }
  1124. if m_iso in current_settings.modeswitches then
  1125. searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
  1126. else
  1127. searchsym(s,srsym,srsymtable);
  1128. p.free;
  1129. if assigned(srsym) and
  1130. (srsym.typ=labelsym) then
  1131. begin
  1132. if tlabelsym(srsym).defined then
  1133. Message(sym_e_label_already_defined);
  1134. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1135. begin
  1136. tlabelsym(srsym).nonlocal:=true;
  1137. exclude(current_procinfo.procdef.procoptions,po_inline);
  1138. end;
  1139. if tlabelsym(srsym).nonlocal and
  1140. (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1141. Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
  1142. tlabelsym(srsym).defined:=true;
  1143. p:=clabelnode.create(nil,tlabelsym(srsym));
  1144. tlabelsym(srsym).code:=p;
  1145. end
  1146. else
  1147. begin
  1148. Message1(sym_e_label_used_and_not_defined,s);
  1149. p:=cnothingnode.create;
  1150. end;
  1151. end;
  1152. if p.nodetype=labeln then
  1153. begin
  1154. { the pointer to the following instruction }
  1155. { isn't a very clean way }
  1156. if token in endtokens then
  1157. tlabelnode(p).left:=cnothingnode.create
  1158. else
  1159. tlabelnode(p).left:=statement();
  1160. { be sure to have left also typecheckpass }
  1161. typecheckpass(tlabelnode(p).left);
  1162. end
  1163. else
  1164. { change a load of a procvar to a call. this is also
  1165. supported in fpc mode }
  1166. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1167. maybe_call_procvar(p,false);
  1168. { blockn support because a read/write is changed into a blocknode
  1169. with a separate statement for each read/write operation (JM)
  1170. the same is true for val() if the third parameter is not 32 bit
  1171. goto nodes are created by the compiler for non local exit statements, so
  1172. include them as well
  1173. }
  1174. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1175. continuen,labeln,blockn,exitn,goton]) or
  1176. ((p.nodetype=inlinen) and
  1177. not is_void(p.resultdef)) or
  1178. ((p.nodetype=calln) and
  1179. (assigned(tcallnode(p).procdefinition)) and
  1180. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1181. Message(parser_e_illegal_expression);
  1182. if not assigned(p.resultdef) then
  1183. do_typecheckpass(p);
  1184. { Specify that we don't use the value returned by the call.
  1185. This is used for :
  1186. - dispose of temp stack space
  1187. - dispose on FPU stack
  1188. - extended syntax checking }
  1189. if (p.nodetype=calln) then
  1190. begin
  1191. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1192. { in $x- state, the function result must not be ignored }
  1193. if not(cs_extsyntax in current_settings.moduleswitches) and
  1194. not(is_void(p.resultdef)) and
  1195. { can be nil in case there was an error in the expression }
  1196. assigned(tcallnode(p).procdefinition) and
  1197. { allow constructor calls to drop the result if they are
  1198. called as instance methods instead of class methods }
  1199. not(
  1200. (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
  1201. is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and
  1202. assigned(tcallnode(p).methodpointer) and
  1203. (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef)
  1204. ) then
  1205. Message(parser_e_illegal_expression);
  1206. end;
  1207. code:=p;
  1208. end;
  1209. end;
  1210. if assigned(code) then
  1211. begin
  1212. typecheckpass(code);
  1213. code.fileinfo:=filepos;
  1214. end;
  1215. statement:=code;
  1216. end;
  1217. function statement_block(starttoken : ttoken) : tnode;
  1218. var
  1219. first,last : tnode;
  1220. filepos : tfileposinfo;
  1221. begin
  1222. first:=nil;
  1223. filepos:=current_tokenpos;
  1224. consume(starttoken);
  1225. while not(token in [_END,_FINALIZATION]) do
  1226. begin
  1227. if first=nil then
  1228. begin
  1229. last:=cstatementnode.create(statement,nil);
  1230. first:=last;
  1231. end
  1232. else
  1233. begin
  1234. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1235. last:=tstatementnode(last).right;
  1236. end;
  1237. if (token in [_END,_FINALIZATION]) then
  1238. break
  1239. else
  1240. begin
  1241. { if no semicolon, then error and go on }
  1242. if token<>_SEMICOLON then
  1243. begin
  1244. consume(_SEMICOLON);
  1245. consume_all_until(_SEMICOLON);
  1246. end;
  1247. consume(_SEMICOLON);
  1248. end;
  1249. consume_emptystats;
  1250. end;
  1251. { don't consume the finalization token, it is consumed when
  1252. reading the finalization block, but allow it only after
  1253. an initalization ! }
  1254. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1255. consume(_END);
  1256. last:=cblocknode.create(first);
  1257. last.fileinfo:=filepos;
  1258. statement_block:=last;
  1259. end;
  1260. function assembler_block : tnode;
  1261. var
  1262. p : tnode;
  1263. {$ifndef arm}
  1264. locals : longint;
  1265. {$endif arm}
  1266. srsym : tsym;
  1267. begin
  1268. if parse_generic then
  1269. message(parser_e_no_assembler_in_generic);
  1270. { Rename the funcret so that recursive calls are possible }
  1271. if not is_void(current_procinfo.procdef.returndef) then
  1272. begin
  1273. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1274. if assigned(srsym) then
  1275. srsym.realname:='$hiddenresult';
  1276. end;
  1277. { delphi uses register calling for assembler methods }
  1278. if (m_delphi in current_settings.modeswitches) and
  1279. (po_assembler in current_procinfo.procdef.procoptions) and
  1280. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1281. current_procinfo.procdef.proccalloption:=pocall_register;
  1282. { force the asm statement }
  1283. if token<>_ASM then
  1284. consume(_ASM);
  1285. include(current_procinfo.flags,pi_is_assembler);
  1286. p:=_asm_statement;
  1287. {$if not(defined(sparc)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1288. if (po_assembler in current_procinfo.procdef.procoptions) then
  1289. begin
  1290. { set the framepointer to esp for assembler functions when the
  1291. following conditions are met:
  1292. - if the are no local variables and parameters (except the allocated result)
  1293. - no reference to the result variable (refcount<=1)
  1294. - result is not stored as parameter
  1295. - target processor has optional frame pointer save
  1296. (vm, i386, vm only currently)
  1297. }
  1298. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1299. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1300. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1301. if (locals=0) and
  1302. not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1303. (not assigned(current_procinfo.procdef.funcretsym) or
  1304. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1305. not (df_generic in current_procinfo.procdef.defoptions) and
  1306. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1307. begin
  1308. { Only need to set the framepointer, the locals will
  1309. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1310. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1311. end;
  1312. end;
  1313. {$endif not(defined(sparc)) and not(defined(arm)) and not(defined(avr))}
  1314. { Flag the result as assigned when it is returned in a
  1315. register.
  1316. }
  1317. if assigned(current_procinfo.procdef.funcretsym) and
  1318. not (df_generic in current_procinfo.procdef.defoptions) and
  1319. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1320. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1321. { because the END is already read we need to get the
  1322. last_endtoken_filepos here (PFV) }
  1323. last_endtoken_filepos:=current_tokenpos;
  1324. assembler_block:=p;
  1325. end;
  1326. end.