pexpr.pas 84 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Florian Klaempfl
  4. Does parsing of expression for Free Pascal
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pexpr;
  19. interface
  20. uses symtable,tree;
  21. { reads a whole expression }
  22. function expr : ptree;
  23. { reads an expression without assignements and .. }
  24. function comp_expr(accept_equal : boolean):Ptree;
  25. { reads a single factor }
  26. function factor(getaddr : boolean) : ptree;
  27. { the ID token has to be consumed before calling this function }
  28. procedure do_member_read(getaddr : boolean;const sym : psym;var p1 : ptree;
  29. var pd : pdef;var again : boolean);
  30. function get_intconst:longint;
  31. function get_stringconst:string;
  32. implementation
  33. uses
  34. globtype,systems,tokens,
  35. cobjects,globals,scanner,
  36. symconst,aasm,
  37. {$ifdef newcg}
  38. cgbase,
  39. {$else}
  40. hcodegen,
  41. {$endif}
  42. types,verbose,strings,
  43. {$ifndef newcg}
  44. tccal,
  45. {$endif newcg}
  46. pass_1,
  47. { parser specific stuff }
  48. pbase,ptype,
  49. { processor specific stuff }
  50. cpubase,cpuinfo;
  51. const
  52. allow_type : boolean = true;
  53. got_addrn : boolean = false;
  54. function parse_paras(__colon,in_prop_paras : boolean) : ptree;
  55. var
  56. p1,p2 : ptree;
  57. end_of_paras : ttoken;
  58. begin
  59. if in_prop_paras then
  60. end_of_paras:=_RECKKLAMMER
  61. else
  62. end_of_paras:=_RKLAMMER;
  63. if token=end_of_paras then
  64. begin
  65. parse_paras:=nil;
  66. exit;
  67. end;
  68. p2:=nil;
  69. inc(parsing_para_level);
  70. while true do
  71. begin
  72. p1:=comp_expr(true);
  73. p2:=gencallparanode(p1,p2);
  74. { it's for the str(l:5,s); }
  75. if __colon and (token=_COLON) then
  76. begin
  77. consume(_COLON);
  78. p1:=comp_expr(true);
  79. p2:=gencallparanode(p1,p2);
  80. p2^.is_colon_para:=true;
  81. if token=_COLON then
  82. begin
  83. consume(_COLON);
  84. p1:=comp_expr(true);
  85. p2:=gencallparanode(p1,p2);
  86. p2^.is_colon_para:=true;
  87. end
  88. end;
  89. if token=_COMMA then
  90. consume(_COMMA)
  91. else
  92. break;
  93. end;
  94. dec(parsing_para_level);
  95. parse_paras:=p2;
  96. end;
  97. procedure check_tp_procvar(var p : ptree);
  98. var
  99. p1 : ptree;
  100. Store_valid : boolean;
  101. begin
  102. if (m_tp_procvar in aktmodeswitches) and
  103. (not got_addrn) and
  104. (not in_args) and
  105. (p^.treetype=loadn) then
  106. begin
  107. { support if procvar then for tp7 and many other expression like this }
  108. Store_valid:=Must_be_valid;
  109. Must_be_valid:=false;
  110. do_firstpass(p);
  111. Must_be_valid:=Store_valid;
  112. if not(getprocvar) and (p^.resulttype^.deftype=procvardef) then
  113. begin
  114. p1:=gencallnode(nil,nil);
  115. p1^.right:=p;
  116. p1^.resulttype:=pprocvardef(p^.resulttype)^.retdef;
  117. firstpass(p1);
  118. p:=p1;
  119. end;
  120. end;
  121. end;
  122. function statement_syssym(l : longint;var pd : pdef) : ptree;
  123. var
  124. p1,p2,paras : ptree;
  125. prev_in_args : boolean;
  126. Store_valid : boolean;
  127. begin
  128. prev_in_args:=in_args;
  129. Store_valid:=Must_be_valid;
  130. case l of
  131. in_ord_x :
  132. begin
  133. consume(_LKLAMMER);
  134. in_args:=true;
  135. Must_be_valid:=true;
  136. p1:=comp_expr(true);
  137. consume(_RKLAMMER);
  138. do_firstpass(p1);
  139. p1:=geninlinenode(in_ord_x,false,p1);
  140. do_firstpass(p1);
  141. statement_syssym := p1;
  142. pd:=p1^.resulttype;
  143. end;
  144. in_break :
  145. begin
  146. statement_syssym:=genzeronode(breakn);
  147. pd:=voiddef;
  148. end;
  149. in_continue :
  150. begin
  151. statement_syssym:=genzeronode(continuen);
  152. pd:=voiddef;
  153. end;
  154. in_typeof_x :
  155. begin
  156. consume(_LKLAMMER);
  157. in_args:=true;
  158. {allow_type:=true;}
  159. p1:=comp_expr(true);
  160. {allow_type:=false;}
  161. consume(_RKLAMMER);
  162. pd:=voidpointerdef;
  163. if p1^.treetype=typen then
  164. begin
  165. if (p1^.typenodetype=nil) then
  166. begin
  167. Message(type_e_mismatch);
  168. statement_syssym:=genzeronode(errorn);
  169. end
  170. else
  171. if p1^.typenodetype^.deftype=objectdef then
  172. begin
  173. { we can use resulttype in pass_2 (PM) }
  174. p1^.resulttype:=p1^.typenodetype;
  175. statement_syssym:=geninlinenode(in_typeof_x,false,p1);
  176. end
  177. else
  178. begin
  179. Message(type_e_mismatch);
  180. disposetree(p1);
  181. statement_syssym:=genzeronode(errorn);
  182. end;
  183. end
  184. else { not a type node }
  185. begin
  186. Must_be_valid:=false;
  187. do_firstpass(p1);
  188. if (p1^.resulttype=nil) then
  189. begin
  190. Message(type_e_mismatch);
  191. disposetree(p1);
  192. statement_syssym:=genzeronode(errorn)
  193. end
  194. else
  195. if p1^.resulttype^.deftype=objectdef then
  196. statement_syssym:=geninlinenode(in_typeof_x,false,p1)
  197. else
  198. begin
  199. Message(type_e_mismatch);
  200. statement_syssym:=genzeronode(errorn);
  201. disposetree(p1);
  202. end;
  203. end;
  204. end;
  205. in_sizeof_x :
  206. begin
  207. consume(_LKLAMMER);
  208. in_args:=true;
  209. {allow_type:=true;}
  210. p1:=comp_expr(true);
  211. {allow_type:=false; }
  212. consume(_RKLAMMER);
  213. pd:=s32bitdef;
  214. if p1^.treetype=typen then
  215. begin
  216. statement_syssym:=genordinalconstnode(p1^.typenodetype^.size,pd);
  217. { p1 not needed !}
  218. disposetree(p1);
  219. end
  220. else
  221. begin
  222. Must_be_valid:=false;
  223. do_firstpass(p1);
  224. if ((p1^.resulttype^.deftype=objectdef) and
  225. (oo_has_constructor in pobjectdef(p1^.resulttype)^.objectoptions)) or
  226. is_open_array(p1^.resulttype) or
  227. is_open_string(p1^.resulttype) then
  228. statement_syssym:=geninlinenode(in_sizeof_x,false,p1)
  229. else
  230. begin
  231. statement_syssym:=genordinalconstnode(p1^.resulttype^.size,pd);
  232. { p1 not needed !}
  233. disposetree(p1);
  234. end;
  235. end;
  236. end;
  237. in_assigned_x :
  238. begin
  239. consume(_LKLAMMER);
  240. in_args:=true;
  241. p1:=comp_expr(true);
  242. Must_be_valid:=true;
  243. do_firstpass(p1);
  244. if not codegenerror then
  245. begin
  246. case p1^.resulttype^.deftype of
  247. pointerdef,
  248. procvardef,
  249. classrefdef : ;
  250. objectdef :
  251. if not(pobjectdef(p1^.resulttype)^.is_class) then
  252. Message(parser_e_illegal_parameter_list);
  253. else
  254. Message(parser_e_illegal_parameter_list);
  255. end;
  256. end;
  257. p2:=gencallparanode(p1,nil);
  258. p2:=geninlinenode(in_assigned_x,false,p2);
  259. consume(_RKLAMMER);
  260. pd:=booldef;
  261. statement_syssym:=p2;
  262. end;
  263. in_ofs_x :
  264. begin
  265. consume(_LKLAMMER);
  266. in_args:=true;
  267. p1:=comp_expr(true);
  268. p1:=gensinglenode(addrn,p1);
  269. Must_be_valid:=false;
  270. do_firstpass(p1);
  271. { Ofs() returns a longint, not a pointer }
  272. p1^.resulttype:=u32bitdef;
  273. pd:=p1^.resulttype;
  274. consume(_RKLAMMER);
  275. statement_syssym:=p1;
  276. end;
  277. in_addr_x :
  278. begin
  279. consume(_LKLAMMER);
  280. in_args:=true;
  281. p1:=comp_expr(true);
  282. p1:=gensinglenode(addrn,p1);
  283. Must_be_valid:=false;
  284. do_firstpass(p1);
  285. pd:=p1^.resulttype;
  286. consume(_RKLAMMER);
  287. statement_syssym:=p1;
  288. end;
  289. in_seg_x :
  290. begin
  291. consume(_LKLAMMER);
  292. in_args:=true;
  293. p1:=comp_expr(true);
  294. do_firstpass(p1);
  295. if p1^.location.loc<>LOC_REFERENCE then
  296. Message(cg_e_illegal_expression);
  297. p1:=genordinalconstnode(0,s32bitdef);
  298. Must_be_valid:=false;
  299. pd:=s32bitdef;
  300. consume(_RKLAMMER);
  301. statement_syssym:=p1;
  302. end;
  303. in_high_x,
  304. in_low_x :
  305. begin
  306. consume(_LKLAMMER);
  307. in_args:=true;
  308. {allow_type:=true;}
  309. p1:=comp_expr(true);
  310. {allow_type:=false;}
  311. do_firstpass(p1);
  312. if p1^.treetype=typen then
  313. p1^.resulttype:=p1^.typenodetype;
  314. Must_be_valid:=false;
  315. p2:=geninlinenode(l,false,p1);
  316. consume(_RKLAMMER);
  317. pd:=s32bitdef;
  318. statement_syssym:=p2;
  319. end;
  320. in_succ_x,
  321. in_pred_x :
  322. begin
  323. consume(_LKLAMMER);
  324. in_args:=true;
  325. p1:=comp_expr(true);
  326. do_firstpass(p1);
  327. Must_be_valid:=false;
  328. p2:=geninlinenode(l,false,p1);
  329. consume(_RKLAMMER);
  330. pd:=p1^.resulttype;
  331. statement_syssym:=p2;
  332. end;
  333. in_inc_x,
  334. in_dec_x :
  335. begin
  336. consume(_LKLAMMER);
  337. in_args:=true;
  338. p1:=comp_expr(true);
  339. Must_be_valid:=false;
  340. if token=_COMMA then
  341. begin
  342. consume(_COMMA);
  343. p2:=gencallparanode(comp_expr(true),nil);
  344. end
  345. else
  346. p2:=nil;
  347. p2:=gencallparanode(p1,p2);
  348. statement_syssym:=geninlinenode(l,false,p2);
  349. consume(_RKLAMMER);
  350. pd:=voiddef;
  351. end;
  352. in_concat_x :
  353. begin
  354. consume(_LKLAMMER);
  355. in_args:=true;
  356. p2:=nil;
  357. while true do
  358. begin
  359. p1:=comp_expr(true);
  360. Must_be_valid:=true;
  361. do_firstpass(p1);
  362. if not((p1^.resulttype^.deftype=stringdef) or
  363. ((p1^.resulttype^.deftype=orddef) and
  364. (porddef(p1^.resulttype)^.typ=uchar))) then
  365. Message(parser_e_illegal_parameter_list);
  366. if p2<>nil then
  367. p2:=gennode(addn,p2,p1)
  368. else
  369. p2:=p1;
  370. if token=_COMMA then
  371. consume(_COMMA)
  372. else
  373. break;
  374. end;
  375. consume(_RKLAMMER);
  376. pd:=cshortstringdef;
  377. statement_syssym:=p2;
  378. end;
  379. in_read_x,
  380. in_readln_x :
  381. begin
  382. if token=_LKLAMMER then
  383. begin
  384. consume(_LKLAMMER);
  385. in_args:=true;
  386. Must_be_valid:=false;
  387. paras:=parse_paras(false,false);
  388. consume(_RKLAMMER);
  389. end
  390. else
  391. paras:=nil;
  392. pd:=voiddef;
  393. p1:=geninlinenode(l,false,paras);
  394. do_firstpass(p1);
  395. statement_syssym := p1;
  396. end;
  397. in_write_x,
  398. in_writeln_x :
  399. begin
  400. if token=_LKLAMMER then
  401. begin
  402. consume(_LKLAMMER);
  403. in_args:=true;
  404. Must_be_valid:=true;
  405. paras:=parse_paras(true,false);
  406. consume(_RKLAMMER);
  407. end
  408. else
  409. paras:=nil;
  410. pd:=voiddef;
  411. p1 := geninlinenode(l,false,paras);
  412. do_firstpass(p1);
  413. statement_syssym := p1;
  414. end;
  415. in_str_x_string :
  416. begin
  417. consume(_LKLAMMER);
  418. in_args:=true;
  419. paras:=parse_paras(true,false);
  420. consume(_RKLAMMER);
  421. p1 := geninlinenode(l,false,paras);
  422. do_firstpass(p1);
  423. statement_syssym := p1;
  424. pd:=voiddef;
  425. end;
  426. in_val_x:
  427. Begin
  428. consume(_LKLAMMER);
  429. in_args := true;
  430. p1:= gencallparanode(comp_expr(true), nil);
  431. Must_be_valid := False;
  432. consume(_COMMA);
  433. p2 := gencallparanode(comp_expr(true),p1);
  434. if (token = _COMMA) then
  435. Begin
  436. consume(_COMMA);
  437. p2 := gencallparanode(comp_expr(true),p2)
  438. End;
  439. consume(_RKLAMMER);
  440. p2 := geninlinenode(l,false,p2);
  441. do_firstpass(p2);
  442. statement_syssym := p2;
  443. pd := voiddef;
  444. End;
  445. in_include_x_y,
  446. in_exclude_x_y :
  447. begin
  448. consume(_LKLAMMER);
  449. in_args:=true;
  450. p1:=comp_expr(true);
  451. Must_be_valid:=false;
  452. consume(_COMMA);
  453. p2:=comp_expr(true);
  454. statement_syssym:=geninlinenode(l,false,gencallparanode(p1,gencallparanode(p2,nil)));
  455. consume(_RKLAMMER);
  456. pd:=voiddef;
  457. end;
  458. in_assert_x_y :
  459. begin
  460. consume(_LKLAMMER);
  461. in_args:=true;
  462. p1:=comp_expr(true);
  463. if token=_COMMA then
  464. begin
  465. consume(_COMMA);
  466. p2:=comp_expr(true);
  467. end
  468. else
  469. begin
  470. { then insert an empty string }
  471. p2:=genstringconstnode('');
  472. end;
  473. statement_syssym:=geninlinenode(l,false,gencallparanode(p1,gencallparanode(p2,nil)));
  474. consume(_RKLAMMER);
  475. pd:=voiddef;
  476. end;
  477. else
  478. internalerror(15);
  479. end;
  480. in_args:=prev_in_args;
  481. Must_be_valid:=Store_valid;
  482. end;
  483. { reads the parameter for a subroutine call }
  484. procedure do_proc_call(getaddr : boolean;var again : boolean;var p1:Ptree;var pd:Pdef);
  485. var
  486. prev_in_args : boolean;
  487. prevafterassn : boolean;
  488. Store_valid : boolean;
  489. begin
  490. prev_in_args:=in_args;
  491. prevafterassn:=afterassignment;
  492. afterassignment:=false;
  493. { want we only determine the address of }
  494. { a subroutine ? }
  495. if not(getaddr) then
  496. begin
  497. if token=_LKLAMMER then
  498. begin
  499. consume(_LKLAMMER);
  500. in_args:=true;
  501. p1^.left:=parse_paras(false,false);
  502. consume(_RKLAMMER);
  503. end
  504. else p1^.left:=nil;
  505. { do firstpass because we need the }
  506. { result type }
  507. Store_valid:=Must_be_valid;
  508. Must_be_valid:=false;
  509. do_firstpass(p1);
  510. Must_be_valid:=Store_valid;
  511. end
  512. else
  513. begin
  514. { address operator @: }
  515. p1^.left:=nil;
  516. { forget pd }
  517. pd:=nil;
  518. if (p1^.symtableproc^.symtabletype=withsymtable) and
  519. (p1^.symtableproc^.defowner^.deftype=objectdef) then
  520. begin
  521. p1^.methodpointer:=getcopy(pwithsymtable(p1^.symtableproc)^.withrefnode);
  522. end
  523. else if not(assigned(p1^.methodpointer)) then
  524. begin
  525. { we must provide a method pointer, if it isn't given, }
  526. { it is self }
  527. if assigned(procinfo) then
  528. begin
  529. p1^.methodpointer:=genselfnode(procinfo^._class);
  530. p1^.methodpointer^.resulttype:=procinfo^._class;
  531. end
  532. else
  533. begin
  534. p1^.methodpointer:=genselfnode(nil);
  535. p1^.methodpointer^.resulttype:=nil;
  536. end;
  537. end;
  538. { no postfix operators }
  539. again:=false;
  540. end;
  541. pd:=p1^.resulttype;
  542. in_args:=prev_in_args;
  543. afterassignment:=prevafterassn;
  544. end;
  545. procedure handle_procvar(pv : pprocvardef;var p2 : ptree);
  546. procedure doconv(procvar : pprocvardef;var t : ptree);
  547. var
  548. hp : ptree;
  549. begin
  550. hp:=nil;
  551. if (proc_to_procvar_equal(pprocsym(t^.symtableentry)^.definition,procvar)) then
  552. begin
  553. if (po_methodpointer in procvar^.procoptions) then
  554. hp:=genloadmethodcallnode(pprocsym(t^.symtableprocentry),t^.symtable,getcopy(t^.methodpointer))
  555. else
  556. hp:=genloadcallnode(pprocsym(t^.symtableprocentry),t^.symtable);
  557. end;
  558. if assigned(hp) then
  559. begin
  560. disposetree(t);
  561. t:=hp;
  562. end;
  563. end;
  564. begin
  565. if (p2^.treetype=calln) then
  566. doconv(pv,p2)
  567. else
  568. if (p2^.treetype=typeconvn) and
  569. (p2^.left^.treetype=calln) then
  570. doconv(pv,p2^.left);
  571. end;
  572. { the following procedure handles the access to a property symbol }
  573. procedure handle_propertysym(sym : psym;st : psymtable;var p1 : ptree;
  574. var pd : pdef);
  575. var
  576. paras : ptree;
  577. p2 : ptree;
  578. plist : ppropsymlist;
  579. begin
  580. paras:=nil;
  581. { property parameters? read them only if the property really }
  582. { has parameters }
  583. if ppo_hasparameters in ppropertysym(sym)^.propoptions then
  584. begin
  585. if token=_LECKKLAMMER then
  586. begin
  587. consume(_LECKKLAMMER);
  588. paras:=parse_paras(false,true);
  589. consume(_RECKKLAMMER);
  590. end;
  591. { indexed property }
  592. if (ppo_indexed in ppropertysym(sym)^.propoptions) then
  593. begin
  594. p2:=genordinalconstnode(ppropertysym(sym)^.index,ppropertysym(sym)^.indexdef);
  595. paras:=gencallparanode(p2,paras);
  596. end;
  597. end;
  598. { we need only a write property if a := follows }
  599. { if not(afterassignment) and not(in_args) then }
  600. if token=_ASSIGNMENT then
  601. begin
  602. { write property: }
  603. { no result }
  604. pd:=voiddef;
  605. if assigned(ppropertysym(sym)^.writeaccesssym) then
  606. begin
  607. case ppropertysym(sym)^.writeaccesssym^.sym^.typ of
  608. procsym :
  609. begin
  610. { generate the method call }
  611. p1:=genmethodcallnode(pprocsym(ppropertysym(sym)^.writeaccesssym^.sym),st,p1);
  612. { we know the procedure to call, so
  613. force the usage of that procedure }
  614. p1^.procdefinition:=pprocdef(ppropertysym(sym)^.writeaccessdef);
  615. p1^.left:=paras;
  616. consume(_ASSIGNMENT);
  617. { read the expression }
  618. getprocvar:=ppropertysym(sym)^.proptype^.deftype=procvardef;
  619. p2:=comp_expr(true);
  620. if getprocvar then
  621. handle_procvar(pprocvardef(ppropertysym(sym)^.proptype),p2);
  622. p1^.left:=gencallparanode(p2,p1^.left);
  623. p1^.isproperty:=true;
  624. getprocvar:=false;
  625. end;
  626. varsym :
  627. begin
  628. if assigned(paras) then
  629. message(parser_e_no_paras_allowed);
  630. { subscribed access? }
  631. plist:=ppropertysym(sym)^.writeaccesssym;
  632. while assigned(plist) do
  633. begin
  634. if p1=nil then
  635. p1:=genloadnode(pvarsym(plist^.sym),st)
  636. else
  637. p1:=gensubscriptnode(pvarsym(plist^.sym),p1);
  638. plist:=plist^.next;
  639. end;
  640. p1^.isproperty:=true;
  641. consume(_ASSIGNMENT);
  642. { read the expression }
  643. p2:=comp_expr(true);
  644. p1:=gennode(assignn,p1,p2);
  645. end
  646. else
  647. begin
  648. p1:=genzeronode(errorn);
  649. Message(parser_e_no_procedure_to_access_property);
  650. end;
  651. end;
  652. end
  653. else
  654. begin
  655. p1:=genzeronode(errorn);
  656. Message(parser_e_no_procedure_to_access_property);
  657. end;
  658. end
  659. else
  660. begin
  661. { read property: }
  662. pd:=ppropertysym(sym)^.proptype;
  663. if assigned(ppropertysym(sym)^.readaccesssym) then
  664. begin
  665. case ppropertysym(sym)^.readaccesssym^.sym^.typ of
  666. varsym :
  667. begin
  668. if assigned(paras) then
  669. message(parser_e_no_paras_allowed);
  670. { subscribed access? }
  671. plist:=ppropertysym(sym)^.readaccesssym;
  672. while assigned(plist) do
  673. begin
  674. if p1=nil then
  675. p1:=genloadnode(pvarsym(plist^.sym),st)
  676. else
  677. p1:=gensubscriptnode(pvarsym(plist^.sym),p1);
  678. plist:=plist^.next;
  679. end;
  680. p1^.isproperty:=true;
  681. end;
  682. procsym :
  683. begin
  684. { generate the method call }
  685. p1:=genmethodcallnode(pprocsym(ppropertysym(sym)^.readaccesssym^.sym),st,p1);
  686. { we know the procedure to call, so
  687. force the usage of that procedure }
  688. p1^.procdefinition:=pprocdef(ppropertysym(sym)^.readaccessdef);
  689. { insert paras }
  690. p1^.left:=paras;
  691. p1^.isproperty:=true;
  692. end
  693. else
  694. begin
  695. p1:=genzeronode(errorn);
  696. Message(type_e_mismatch);
  697. end;
  698. end;
  699. end
  700. else
  701. begin
  702. { error, no function to read property }
  703. p1:=genzeronode(errorn);
  704. Message(parser_e_no_procedure_to_access_property);
  705. end;
  706. end;
  707. end;
  708. { the ID token has to be consumed before calling this function }
  709. procedure do_member_read(getaddr : boolean;const sym : psym;var p1 : ptree;
  710. var pd : pdef;var again : boolean);
  711. var
  712. static_name : string;
  713. isclassref : boolean;
  714. begin
  715. if sym=nil then
  716. begin
  717. { pattern is still valid unless
  718. there is another ID just after the ID of sym }
  719. Message1(sym_e_id_no_member,pattern);
  720. disposetree(p1);
  721. p1:=genzeronode(errorn);
  722. { try to clean up }
  723. pd:=generrordef;
  724. again:=false;
  725. end
  726. else
  727. begin
  728. isclassref:=pd^.deftype=classrefdef;
  729. { check protected and private members }
  730. { please leave this code as it is, }
  731. { it has now the same behaviaor as TP/Delphi }
  732. if (sp_private in sym^.symoptions) and
  733. (pobjectdef(pd)^.owner^.symtabletype=unitsymtable) then
  734. Message(parser_e_cant_access_private_member);
  735. if (sp_protected in sym^.symoptions) and
  736. (pobjectdef(pd)^.owner^.symtabletype=unitsymtable) then
  737. begin
  738. if assigned(aktprocsym^.definition^._class) then
  739. begin
  740. if not aktprocsym^.definition^._class^.is_related(pobjectdef(sym^.owner^.defowner)) then
  741. Message(parser_e_cant_access_protected_member);
  742. end
  743. else
  744. Message(parser_e_cant_access_protected_member);
  745. end;
  746. { we assume, that only procsyms and varsyms are in an object }
  747. { symbol table, for classes, properties are allowed }
  748. case sym^.typ of
  749. procsym:
  750. begin
  751. p1:=genmethodcallnode(pprocsym(sym),srsymtable,p1);
  752. do_proc_call(getaddr or
  753. (getprocvar and
  754. ((block_type=bt_const) or
  755. ((m_tp_procvar in aktmodeswitches) and
  756. proc_to_procvar_equal(pprocsym(sym)^.definition,getprocvardef)
  757. )
  758. )
  759. ),again,p1,pd);
  760. if (block_type=bt_const) and
  761. getprocvar then
  762. handle_procvar(getprocvardef,p1);
  763. { now we know the real method e.g. we can check for a class method }
  764. if isclassref and
  765. assigned(p1^.procdefinition) and
  766. not(po_classmethod in p1^.procdefinition^.procoptions) and
  767. not(p1^.procdefinition^.proctypeoption=potype_constructor) then
  768. Message(parser_e_only_class_methods_via_class_ref);
  769. end;
  770. varsym:
  771. begin
  772. if isclassref then
  773. Message(parser_e_only_class_methods_via_class_ref);
  774. if (sp_static in sym^.symoptions) then
  775. begin
  776. { static_name:=lower(srsymtable^.name^)+'_'+sym^.name;
  777. this is wrong for static field in with symtable (PM) }
  778. static_name:=lower(srsym^.owner^.name^)+'_'+sym^.name;
  779. getsym(static_name,true);
  780. disposetree(p1);
  781. p1:=genloadnode(pvarsym(srsym),srsymtable);
  782. end
  783. else
  784. p1:=gensubscriptnode(pvarsym(sym),p1);
  785. pd:=pvarsym(sym)^.definition;
  786. end;
  787. propertysym:
  788. begin
  789. if isclassref then
  790. Message(parser_e_only_class_methods_via_class_ref);
  791. handle_propertysym(sym,srsymtable,p1,pd);
  792. end;
  793. else internalerror(16);
  794. end;
  795. end;
  796. end;
  797. {****************************************************************************
  798. Factor
  799. ****************************************************************************}
  800. function factor(getaddr : boolean) : ptree;
  801. var
  802. l : longint;
  803. oldp1,
  804. p1,p2,p3 : ptree;
  805. code : integer;
  806. pd,pd2 : pdef;
  807. possible_error,
  808. unit_specific,
  809. again : boolean;
  810. sym : pvarsym;
  811. classh : pobjectdef;
  812. d : bestreal;
  813. static_name : string;
  814. propsym : ppropertysym;
  815. filepos : tfileposinfo;
  816. {---------------------------------------------
  817. Is_func_ret
  818. ---------------------------------------------}
  819. function is_func_ret(sym : psym) : boolean;
  820. var
  821. p : pprocinfo;
  822. storesymtablestack : psymtable;
  823. begin
  824. is_func_ret:=false;
  825. if not assigned(procinfo) or
  826. ((sym^.typ<>funcretsym) and ((procinfo^.flags and pi_operator)=0)) then
  827. exit;
  828. p:=procinfo;
  829. while assigned(p) do
  830. begin
  831. { is this an access to a function result? Accessing _RESULT is
  832. always allowed and funcretn is generated }
  833. if assigned(p^.funcretsym) and
  834. ((pfuncretsym(sym)=p^.resultfuncretsym) or
  835. ((pfuncretsym(sym)=p^.funcretsym) or
  836. ((pvarsym(sym)=opsym) and ((p^.flags and pi_operator)<>0))) and
  837. (p^.retdef<>pdef(voiddef)) and
  838. (token<>_LKLAMMER) and
  839. (not ((m_tp in aktmodeswitches) and (afterassignment or in_args)))
  840. ) then
  841. begin
  842. if ((pvarsym(sym)=opsym) and
  843. ((p^.flags and pi_operator)<>0)) then
  844. inc(opsym^.refs);
  845. p1:=genzeronode(funcretn);
  846. pd:=p^.retdef;
  847. p1^.funcretprocinfo:=p;
  848. p1^.retdef:=pd;
  849. is_func_ret:=true;
  850. if p^.funcret_state=vs_declared then
  851. begin
  852. p^.funcret_state:=vs_declared_and_first_found;
  853. p1^.is_first_funcret:=true;
  854. end;
  855. exit;
  856. end;
  857. p:=p^.parent;
  858. end;
  859. { we must use the function call }
  860. if (sym^.typ=funcretsym) then
  861. begin
  862. storesymtablestack:=symtablestack;
  863. symtablestack:=srsymtable^.next;
  864. getsym(sym^.name,true);
  865. if srsym^.typ<>procsym then
  866. Message(cg_e_illegal_expression);
  867. symtablestack:=storesymtablestack;
  868. end;
  869. end;
  870. {---------------------------------------------
  871. Factor_read_id
  872. ---------------------------------------------}
  873. procedure factor_read_id;
  874. var
  875. pc : pchar;
  876. len : longint;
  877. begin
  878. { allow post fix operators }
  879. again:=true;
  880. begin
  881. if lastsymknown then
  882. begin
  883. srsym:=lastsrsym;
  884. srsymtable:=lastsrsymtable;
  885. lastsymknown:=false;
  886. end
  887. else
  888. getsym(pattern,true);
  889. consume(_ID);
  890. if not is_func_ret(srsym) then
  891. { else it's a normal symbol }
  892. begin
  893. { is it defined like UNIT.SYMBOL ? }
  894. if srsym^.typ=unitsym then
  895. begin
  896. consume(_POINT);
  897. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  898. unit_specific:=true;
  899. consume(_ID);
  900. end
  901. else
  902. unit_specific:=false;
  903. if not assigned(srsym) then
  904. Begin
  905. p1:=genzeronode(errorn);
  906. { try to clean up }
  907. pd:=generrordef;
  908. end
  909. else
  910. Begin
  911. { check semantics of private }
  912. if (srsym^.typ in [propertysym,procsym,varsym]) and
  913. (srsymtable^.symtabletype=objectsymtable) then
  914. begin
  915. if (sp_private in srsym^.symoptions) and
  916. (pobjectdef(srsym^.owner^.defowner)^.owner^.symtabletype=unitsymtable) then
  917. Message(parser_e_cant_access_private_member);
  918. end;
  919. case srsym^.typ of
  920. absolutesym : begin
  921. p1:=genloadnode(pvarsym(srsym),srsymtable);
  922. pd:=pabsolutesym(srsym)^.definition;
  923. end;
  924. varsym : begin
  925. { are we in a class method ? }
  926. if (srsymtable^.symtabletype=objectsymtable) and
  927. assigned(aktprocsym) and
  928. (po_classmethod in aktprocsym^.definition^.procoptions) then
  929. Message(parser_e_only_class_methods);
  930. if (sp_static in srsym^.symoptions) then
  931. begin
  932. static_name:=lower(srsym^.owner^.name^)+'_'+srsym^.name;
  933. getsym(static_name,true);
  934. end;
  935. p1:=genloadnode(pvarsym(srsym),srsymtable);
  936. if pvarsym(srsym)^.varstate=vs_declared then
  937. begin
  938. p1^.is_first := true;
  939. { set special between first loaded until checked in firstpass }
  940. pvarsym(srsym)^.varstate:=vs_declared_and_first_found;
  941. end;
  942. pd:=pvarsym(srsym)^.definition;
  943. end;
  944. typedconstsym : begin
  945. p1:=gentypedconstloadnode(ptypedconstsym(srsym),srsymtable);
  946. pd:=ptypedconstsym(srsym)^.definition;
  947. end;
  948. syssym : p1:=statement_syssym(psyssym(srsym)^.number,pd);
  949. typesym : begin
  950. pd:=ptypesym(srsym)^.definition;
  951. if not assigned(pd) then
  952. begin
  953. pd:=generrordef;
  954. again:=false;
  955. end
  956. else
  957. begin
  958. { if we read a type declaration }
  959. { we have to return the type and }
  960. { nothing else }
  961. if block_type=bt_type then
  962. begin
  963. { we don't need sym reference when it's in the
  964. current unit or system unit, because those
  965. units are always loaded (PFV) }
  966. if not(assigned(pd^.owner)) or
  967. (pd^.owner^.unitid=0) or
  968. (pd^.owner^.unitid=1) then
  969. p1:=gentypenode(pd,nil)
  970. else
  971. p1:=gentypenode(pd,ptypesym(srsym));
  972. { here we can also set resulttype !! }
  973. p1^.resulttype:=pd;
  974. pd:=voiddef;
  975. end
  976. else { not type block }
  977. begin
  978. if token=_LKLAMMER then
  979. begin
  980. consume(_LKLAMMER);
  981. p1:=comp_expr(true);
  982. consume(_RKLAMMER);
  983. p1:=gentypeconvnode(p1,pd);
  984. p1^.explizit:=true;
  985. end
  986. else { not LKLAMMER}
  987. if (token=_POINT) and
  988. (pd^.deftype=objectdef) and
  989. not(pobjectdef(pd)^.is_class) then
  990. begin
  991. consume(_POINT);
  992. if assigned(procinfo) and
  993. assigned(procinfo^._class) and
  994. not(getaddr) then
  995. begin
  996. if procinfo^._class^.is_related(pobjectdef(pd)) then
  997. begin
  998. p1:=gentypenode(pd,ptypesym(srsym));
  999. p1^.resulttype:=pd;
  1000. { search also in inherited methods }
  1001. repeat
  1002. srsymtable:=pobjectdef(pd)^.symtable;
  1003. sym:=pvarsym(srsymtable^.search(pattern));
  1004. if assigned(sym) then
  1005. break;
  1006. pd:=pobjectdef(pd)^.childof;
  1007. until not assigned(pd);
  1008. consume(_ID);
  1009. do_member_read(false,sym,p1,pd,again);
  1010. end
  1011. else
  1012. begin
  1013. Message(parser_e_no_super_class);
  1014. pd:=generrordef;
  1015. again:=false;
  1016. end;
  1017. end
  1018. else
  1019. begin
  1020. { allows @TObject.Load }
  1021. { also allows static methods and variables }
  1022. p1:=genzeronode(typen);
  1023. p1^.resulttype:=pd;
  1024. { TP allows also @TMenu.Load if Load is only }
  1025. { defined in an anchestor class }
  1026. sym:=pvarsym(search_class_member(pobjectdef(pd),pattern));
  1027. if not assigned(sym) then
  1028. Message1(sym_e_id_no_member,pattern)
  1029. else if not(getaddr) and not(sp_static in sym^.symoptions) then
  1030. Message(sym_e_only_static_in_static)
  1031. else
  1032. begin
  1033. consume(_ID);
  1034. do_member_read(getaddr,sym,p1,pd,again);
  1035. end;
  1036. end;
  1037. end
  1038. else
  1039. begin
  1040. { class reference ? }
  1041. if (pd^.deftype=objectdef)
  1042. and pobjectdef(pd)^.is_class then
  1043. begin
  1044. p1:=gentypenode(pd,nil);
  1045. p1^.resulttype:=pd;
  1046. pd:=new(pclassrefdef,init(pd));
  1047. p1:=gensinglenode(loadvmtn,p1);
  1048. p1^.resulttype:=pd;
  1049. end
  1050. else
  1051. begin
  1052. { generate a type node }
  1053. { (for typeof etc) }
  1054. if allow_type then
  1055. begin
  1056. p1:=gentypenode(pd,nil);
  1057. { here we must use typenodetype explicitly !! PM
  1058. p1^.resulttype:=pd; }
  1059. pd:=voiddef;
  1060. end
  1061. else
  1062. Message(parser_e_no_type_not_allowed_here);
  1063. end;
  1064. end;
  1065. end;
  1066. end;
  1067. end;
  1068. enumsym : begin
  1069. p1:=genenumnode(penumsym(srsym));
  1070. pd:=p1^.resulttype;
  1071. end;
  1072. constsym : begin
  1073. case pconstsym(srsym)^.consttype of
  1074. constint :
  1075. p1:=genordinalconstnode(pconstsym(srsym)^.value,s32bitdef);
  1076. conststring :
  1077. begin
  1078. len:=pconstsym(srsym)^.len;
  1079. if not(cs_ansistrings in aktlocalswitches) and (len>255) then
  1080. len:=255;
  1081. getmem(pc,len+1);
  1082. move(pchar(pconstsym(srsym)^.value)^,pc^,len);
  1083. pc[len]:=#0;
  1084. p1:=genpcharconstnode(pc,len);
  1085. end;
  1086. constchar :
  1087. p1:=genordinalconstnode(pconstsym(srsym)^.value,cchardef);
  1088. constreal :
  1089. p1:=genrealconstnode(pbestreal(pconstsym(srsym)^.value)^,bestrealdef^);
  1090. constbool :
  1091. p1:=genordinalconstnode(pconstsym(srsym)^.value,booldef);
  1092. constset :
  1093. p1:=gensetconstnode(pconstset(pconstsym(srsym)^.value),
  1094. psetdef(pconstsym(srsym)^.definition));
  1095. constord :
  1096. p1:=genordinalconstnode(pconstsym(srsym)^.value,
  1097. pconstsym(srsym)^.definition);
  1098. constpointer :
  1099. p1:=genpointerconstnode(pconstsym(srsym)^.value,
  1100. pconstsym(srsym)^.definition);
  1101. constnil :
  1102. p1:=genzeronode(niln);
  1103. constresourcestring:
  1104. begin
  1105. p1:=genloadnode(pvarsym(srsym),srsymtable);
  1106. p1^.resulttype:=cansistringdef;
  1107. end;
  1108. end;
  1109. pd:=p1^.resulttype;
  1110. end;
  1111. procsym : begin
  1112. { are we in a class method ? }
  1113. possible_error:=(srsymtable^.symtabletype=objectsymtable) and
  1114. assigned(aktprocsym) and
  1115. (po_classmethod in aktprocsym^.definition^.procoptions);
  1116. p1:=gencallnode(pprocsym(srsym),srsymtable);
  1117. p1^.unit_specific:=unit_specific;
  1118. do_proc_call(getaddr or
  1119. (getprocvar and
  1120. ((block_type=bt_const) or
  1121. ((m_tp_procvar in aktmodeswitches) and
  1122. proc_to_procvar_equal(pprocsym(srsym)^.definition,getprocvardef)
  1123. )
  1124. )
  1125. ),again,p1,pd);
  1126. if (block_type=bt_const) and
  1127. getprocvar then
  1128. handle_procvar(getprocvardef,p1);
  1129. if possible_error and
  1130. not(po_classmethod in p1^.procdefinition^.procoptions) then
  1131. Message(parser_e_only_class_methods);
  1132. end;
  1133. propertysym : begin
  1134. { access to property in a method }
  1135. { are we in a class method ? }
  1136. if (srsymtable^.symtabletype=objectsymtable) and
  1137. assigned(aktprocsym) and
  1138. (po_classmethod in aktprocsym^.definition^.procoptions) then
  1139. Message(parser_e_only_class_methods);
  1140. { no method pointer }
  1141. p1:=nil;
  1142. handle_propertysym(srsym,srsymtable,p1,pd);
  1143. end;
  1144. errorsym : begin
  1145. p1:=genzeronode(errorn);
  1146. p1^.resulttype:=generrordef;
  1147. pd:=generrordef;
  1148. if token=_LKLAMMER then
  1149. begin
  1150. consume(_LKLAMMER);
  1151. parse_paras(false,false);
  1152. consume(_RKLAMMER);
  1153. end;
  1154. end;
  1155. else
  1156. begin
  1157. p1:=genzeronode(errorn);
  1158. pd:=generrordef;
  1159. Message(cg_e_illegal_expression);
  1160. end;
  1161. end; { end case }
  1162. end;
  1163. end;
  1164. end;
  1165. end;
  1166. {---------------------------------------------
  1167. Factor_Read_Set
  1168. ---------------------------------------------}
  1169. { Read a set between [] }
  1170. function factor_read_set:ptree;
  1171. var
  1172. p1,
  1173. lastp,
  1174. buildp : ptree;
  1175. begin
  1176. buildp:=nil;
  1177. { be sure that a least one arrayconstructn is used, also for an
  1178. empty [] }
  1179. if token=_RECKKLAMMER then
  1180. buildp:=gennode(arrayconstructn,nil,buildp)
  1181. else
  1182. begin
  1183. while true do
  1184. begin
  1185. p1:=comp_expr(true);
  1186. if token=_POINTPOINT then
  1187. begin
  1188. consume(_POINTPOINT);
  1189. p2:=comp_expr(true);
  1190. p1:=gennode(arrayconstructrangen,p1,p2);
  1191. end;
  1192. { insert at the end of the tree, to get the correct order }
  1193. if not assigned(buildp) then
  1194. begin
  1195. buildp:=gennode(arrayconstructn,p1,nil);
  1196. lastp:=buildp;
  1197. end
  1198. else
  1199. begin
  1200. lastp^.right:=gennode(arrayconstructn,p1,nil);
  1201. lastp:=lastp^.right;
  1202. end;
  1203. { there could be more elements }
  1204. if token=_COMMA then
  1205. consume(_COMMA)
  1206. else
  1207. break;
  1208. end;
  1209. end;
  1210. factor_read_set:=buildp;
  1211. end;
  1212. {---------------------------------------------
  1213. Helpers
  1214. ---------------------------------------------}
  1215. procedure check_tokenpos;
  1216. begin
  1217. if (p1<>oldp1) then
  1218. begin
  1219. if assigned(p1) then
  1220. set_tree_filepos(p1,filepos);
  1221. oldp1:=p1;
  1222. filepos:=tokenpos;
  1223. end;
  1224. end;
  1225. {---------------------------------------------
  1226. PostFixOperators
  1227. ---------------------------------------------}
  1228. procedure postfixoperators;
  1229. var
  1230. store_static : boolean;
  1231. { p1 and p2 must contain valid value_str }
  1232. begin
  1233. check_tokenpos;
  1234. while again do
  1235. begin
  1236. { prevent crashes with unknown types }
  1237. if not assigned(pd) then
  1238. begin
  1239. { try to recover }
  1240. repeat
  1241. case token of
  1242. _CARET:
  1243. consume(_CARET);
  1244. _POINT:
  1245. begin
  1246. consume(_POINT);
  1247. consume(_ID);
  1248. end;
  1249. _LECKKLAMMER:
  1250. begin
  1251. repeat
  1252. consume(token);
  1253. until token in [_RECKKLAMMER,_SEMICOLON];
  1254. end;
  1255. else
  1256. break;
  1257. end;
  1258. until false;
  1259. exit;
  1260. end;
  1261. { handle token }
  1262. case token of
  1263. _CARET:
  1264. begin
  1265. consume(_CARET);
  1266. if (pd^.deftype<>pointerdef) then
  1267. begin
  1268. { ^ as binary operator is a problem!!!! (FK) }
  1269. again:=false;
  1270. Message(cg_e_invalid_qualifier);
  1271. disposetree(p1);
  1272. p1:=genzeronode(errorn);
  1273. end
  1274. else
  1275. begin
  1276. p1:=gensinglenode(derefn,p1);
  1277. pd:=ppointerdef(pd)^.definition;
  1278. end;
  1279. end;
  1280. _LECKKLAMMER:
  1281. begin
  1282. if (pd^.deftype=objectdef) and pobjectdef(pd)^.is_class then
  1283. begin
  1284. { default property }
  1285. propsym:=search_default_property(pobjectdef(pd));
  1286. if not(assigned(propsym)) then
  1287. begin
  1288. disposetree(p1);
  1289. p1:=genzeronode(errorn);
  1290. again:=false;
  1291. message(parser_e_no_default_property_available);
  1292. end
  1293. else
  1294. handle_propertysym(propsym,propsym^.owner,p1,pd);
  1295. end
  1296. else
  1297. begin
  1298. consume(_LECKKLAMMER);
  1299. repeat
  1300. case pd^.deftype of
  1301. pointerdef:
  1302. begin
  1303. p2:=comp_expr(true);
  1304. p1:=gennode(vecn,p1,p2);
  1305. pd:=ppointerdef(pd)^.definition;
  1306. end;
  1307. stringdef : begin
  1308. p2:=comp_expr(true);
  1309. p1:=gennode(vecn,p1,p2);
  1310. pd:=cchardef
  1311. end;
  1312. arraydef : begin
  1313. p2:=comp_expr(true);
  1314. { support SEG:OFS for go32v2 Mem[] }
  1315. if (target_info.target=target_i386_go32v2) and
  1316. (p1^.treetype=loadn) and
  1317. assigned(p1^.symtableentry) and
  1318. assigned(p1^.symtableentry^.owner^.name) and
  1319. (p1^.symtableentry^.owner^.name^='SYSTEM') and
  1320. ((p1^.symtableentry^.name='MEM') or
  1321. (p1^.symtableentry^.name='MEMW') or
  1322. (p1^.symtableentry^.name='MEML')) then
  1323. begin
  1324. if (token=_COLON) then
  1325. begin
  1326. consume(_COLON);
  1327. p3:=gennode(muln,genordinalconstnode($10,s32bitdef),p2);
  1328. p2:=comp_expr(true);
  1329. p2:=gennode(addn,p2,p3);
  1330. p1:=gennode(vecn,p1,p2);
  1331. p1^.memseg:=true;
  1332. p1^.memindex:=true;
  1333. end
  1334. else
  1335. begin
  1336. p1:=gennode(vecn,p1,p2);
  1337. p1^.memindex:=true;
  1338. end;
  1339. end
  1340. else
  1341. p1:=gennode(vecn,p1,p2);
  1342. pd:=parraydef(pd)^.definition;
  1343. end;
  1344. else
  1345. begin
  1346. Message(cg_e_invalid_qualifier);
  1347. disposetree(p1);
  1348. p1:=genzeronode(errorn);
  1349. again:=false;
  1350. end;
  1351. end;
  1352. if token=_COMMA then
  1353. consume(_COMMA)
  1354. else
  1355. break;
  1356. until false;
  1357. consume(_RECKKLAMMER);
  1358. end;
  1359. end;
  1360. _POINT : begin
  1361. consume(_POINT);
  1362. if (pd^.deftype=pointerdef) and
  1363. (m_autoderef in aktmodeswitches) then
  1364. begin
  1365. p1:=gensinglenode(derefn,p1);
  1366. pd:=ppointerdef(pd)^.definition;
  1367. end;
  1368. case pd^.deftype of
  1369. recorddef:
  1370. begin
  1371. sym:=pvarsym(precorddef(pd)^.symtable^.search(pattern));
  1372. if sym=nil then
  1373. begin
  1374. Message1(sym_e_illegal_field,pattern);
  1375. disposetree(p1);
  1376. p1:=genzeronode(errorn);
  1377. end
  1378. else
  1379. begin
  1380. p1:=gensubscriptnode(sym,p1);
  1381. pd:=sym^.definition;
  1382. end;
  1383. consume(_ID);
  1384. end;
  1385. classrefdef:
  1386. begin
  1387. classh:=pobjectdef(pclassrefdef(pd)^.definition);
  1388. sym:=nil;
  1389. while assigned(classh) do
  1390. begin
  1391. sym:=pvarsym(classh^.symtable^.search(pattern));
  1392. srsymtable:=classh^.symtable;
  1393. if assigned(sym) then
  1394. break;
  1395. classh:=classh^.childof;
  1396. end;
  1397. consume(_ID);
  1398. do_member_read(getaddr,sym,p1,pd,again);
  1399. end;
  1400. objectdef:
  1401. begin
  1402. classh:=pobjectdef(pd);
  1403. sym:=nil;
  1404. store_static:=allow_only_static;
  1405. allow_only_static:=false;
  1406. while assigned(classh) do
  1407. begin
  1408. sym:=pvarsym(classh^.symtable^.search(pattern));
  1409. srsymtable:=classh^.symtable;
  1410. if assigned(sym) then
  1411. break;
  1412. classh:=classh^.childof;
  1413. end;
  1414. allow_only_static:=store_static;
  1415. consume(_ID);
  1416. do_member_read(getaddr,sym,p1,pd,again);
  1417. end;
  1418. pointerdef:
  1419. begin
  1420. Message(cg_e_invalid_qualifier);
  1421. if ppointerdef(pd)^.definition^.deftype in [recorddef,objectdef,classrefdef] then
  1422. Message(parser_h_maybe_deref_caret_missing);
  1423. end;
  1424. else
  1425. begin
  1426. Message(cg_e_invalid_qualifier);
  1427. disposetree(p1);
  1428. p1:=genzeronode(errorn);
  1429. end;
  1430. end;
  1431. end;
  1432. else
  1433. begin
  1434. { is this a procedure variable ? }
  1435. if assigned(pd) then
  1436. begin
  1437. if (pd^.deftype=procvardef) then
  1438. begin
  1439. if getprocvar and is_equal(pd,getprocvardef) then
  1440. again:=false
  1441. else
  1442. if (token=_LKLAMMER) or
  1443. ((pprocvardef(pd)^.para^.empty) and
  1444. (not((token in [_ASSIGNMENT,_UNEQUAL,_EQUAL]))) and
  1445. (not afterassignment) and
  1446. (not in_args)) then
  1447. begin
  1448. { do this in a strange way }
  1449. { it's not a clean solution }
  1450. p2:=p1;
  1451. p1:=gencallnode(nil,nil);
  1452. p1^.right:=p2;
  1453. p1^.unit_specific:=unit_specific;
  1454. p1^.symtableprocentry:=pprocsym(sym);
  1455. if token=_LKLAMMER then
  1456. begin
  1457. consume(_LKLAMMER);
  1458. p1^.left:=parse_paras(false,false);
  1459. consume(_RKLAMMER);
  1460. end;
  1461. pd:=pprocvardef(pd)^.retdef;
  1462. { proc():= is never possible }
  1463. if token=_ASSIGNMENT then
  1464. begin
  1465. Message(cg_e_illegal_expression);
  1466. p1:=genzeronode(errorn);
  1467. again:=false;
  1468. end;
  1469. p1^.resulttype:=pd;
  1470. end
  1471. else
  1472. again:=false;
  1473. p1^.resulttype:=pd;
  1474. end
  1475. else
  1476. again:=false;
  1477. end
  1478. else
  1479. again:=false;
  1480. end;
  1481. end;
  1482. check_tokenpos;
  1483. end; { while again }
  1484. end;
  1485. {---------------------------------------------
  1486. Factor (Main)
  1487. ---------------------------------------------}
  1488. begin
  1489. oldp1:=nil;
  1490. p1:=nil;
  1491. filepos:=tokenpos;
  1492. if token=_ID then
  1493. begin
  1494. factor_read_id;
  1495. { handle post fix operators }
  1496. postfixoperators;
  1497. end
  1498. else
  1499. case token of
  1500. _NEW : begin
  1501. consume(_NEW);
  1502. consume(_LKLAMMER);
  1503. {allow_type:=true;}
  1504. p1:=factor(false);
  1505. {allow_type:=false;}
  1506. if p1^.treetype<>typen then
  1507. begin
  1508. Message(type_e_type_id_expected);
  1509. disposetree(p1);
  1510. pd:=generrordef;
  1511. end
  1512. else
  1513. pd:=p1^.typenodetype;
  1514. pd2:=pd;
  1515. if (pd^.deftype<>pointerdef) then
  1516. Message1(type_e_pointer_type_expected,pd^.typename)
  1517. else
  1518. if token=_RKLAMMER then
  1519. begin
  1520. if (ppointerdef(pd)^.definition^.deftype=objectdef) and
  1521. (oo_has_vmt in pobjectdef(ppointerdef(pd)^.definition)^.objectoptions) then
  1522. Message(parser_w_use_extended_syntax_for_objects);
  1523. p1:=gensinglenode(newn,nil);
  1524. p1^.resulttype:=pd2;
  1525. consume(_RKLAMMER);
  1526. end
  1527. else
  1528. begin
  1529. disposetree(p1);
  1530. p1:=genzeronode(hnewn);
  1531. p1^.resulttype:=ppointerdef(pd)^.definition;
  1532. consume(_COMMA);
  1533. afterassignment:=false;
  1534. { determines the current object defintion }
  1535. classh:=pobjectdef(ppointerdef(pd)^.definition);
  1536. if classh^.deftype<>objectdef then
  1537. Message(parser_e_pointer_to_class_expected)
  1538. else
  1539. begin
  1540. { check for an abstract class }
  1541. if (oo_has_abstract in classh^.objectoptions) then
  1542. Message(sym_e_no_instance_of_abstract_object);
  1543. { search the constructor also in the symbol tables of
  1544. the parents }
  1545. sym:=nil;
  1546. while assigned(classh) do
  1547. begin
  1548. sym:=pvarsym(classh^.symtable^.search(pattern));
  1549. srsymtable:=classh^.symtable;
  1550. if assigned(sym) then
  1551. break;
  1552. classh:=classh^.childof;
  1553. end;
  1554. consume(_ID);
  1555. do_member_read(false,sym,p1,pd,again);
  1556. if (p1^.treetype<>calln) or
  1557. (assigned(p1^.procdefinition) and
  1558. (p1^.procdefinition^.proctypeoption<>potype_constructor)) then
  1559. Message(parser_e_expr_have_to_be_constructor_call);
  1560. end;
  1561. p1:=gensinglenode(newn,p1);
  1562. { set the resulttype }
  1563. p1^.resulttype:=pd2;
  1564. consume(_RKLAMMER);
  1565. end;
  1566. postfixoperators;
  1567. end;
  1568. _SELF : begin
  1569. again:=true;
  1570. consume(_SELF);
  1571. if not assigned(procinfo^._class) then
  1572. begin
  1573. p1:=genzeronode(errorn);
  1574. pd:=generrordef;
  1575. again:=false;
  1576. Message(parser_e_self_not_in_method);
  1577. end
  1578. else
  1579. begin
  1580. if (po_classmethod in aktprocsym^.definition^.procoptions) then
  1581. begin
  1582. { self in class methods is a class reference type }
  1583. pd:=new(pclassrefdef,init(procinfo^._class));
  1584. p1:=genselfnode(pd);
  1585. p1^.resulttype:=pd;
  1586. end
  1587. else
  1588. begin
  1589. p1:=genselfnode(procinfo^._class);
  1590. p1^.resulttype:=procinfo^._class;
  1591. end;
  1592. pd:=p1^.resulttype;
  1593. postfixoperators;
  1594. end;
  1595. end;
  1596. _INHERITED : begin
  1597. again:=true;
  1598. consume(_INHERITED);
  1599. if assigned(procinfo^._class) then
  1600. begin
  1601. classh:=procinfo^._class^.childof;
  1602. while assigned(classh) do
  1603. begin
  1604. srsymtable:=pobjectdef(classh)^.symtable;
  1605. sym:=pvarsym(srsymtable^.search(pattern));
  1606. if assigned(sym) then
  1607. begin
  1608. { only for procsyms we need to set the type (PFV) }
  1609. if sym^.typ=procsym then
  1610. begin
  1611. p1:=genzeronode(typen);
  1612. p1^.resulttype:=classh;
  1613. pd:=p1^.resulttype;
  1614. end
  1615. else
  1616. p1:=nil;
  1617. consume(_ID);
  1618. do_member_read(false,sym,p1,pd,again);
  1619. break;
  1620. end;
  1621. classh:=classh^.childof;
  1622. end;
  1623. if classh=nil then
  1624. begin
  1625. Message1(sym_e_id_no_member,pattern);
  1626. again:=false;
  1627. pd:=generrordef;
  1628. p1:=genzeronode(errorn);
  1629. end;
  1630. end
  1631. else
  1632. begin
  1633. Message(parser_e_generic_methods_only_in_methods);
  1634. again:=false;
  1635. pd:=generrordef;
  1636. p1:=genzeronode(errorn);
  1637. end;
  1638. postfixoperators;
  1639. end;
  1640. _INTCONST : begin
  1641. valint(pattern,l,code);
  1642. if code<>0 then
  1643. begin
  1644. val(pattern,d,code);
  1645. if code<>0 then
  1646. begin
  1647. Message(cg_e_invalid_integer);
  1648. consume(_INTCONST);
  1649. l:=1;
  1650. p1:=genordinalconstnode(l,s32bitdef);
  1651. end
  1652. else
  1653. begin
  1654. consume(_INTCONST);
  1655. p1:=genrealconstnode(d,bestrealdef^);
  1656. end;
  1657. end
  1658. else
  1659. begin
  1660. consume(_INTCONST);
  1661. p1:=genordinalconstnode(l,s32bitdef);
  1662. end;
  1663. end;
  1664. _REALNUMBER : begin
  1665. val(pattern,d,code);
  1666. if code<>0 then
  1667. begin
  1668. Message(parser_e_error_in_real);
  1669. d:=1.0;
  1670. end;
  1671. consume(_REALNUMBER);
  1672. p1:=genrealconstnode(d,bestrealdef^);
  1673. end;
  1674. _STRING : begin
  1675. pd:=string_dec;
  1676. { STRING can be also a type cast }
  1677. if token=_LKLAMMER then
  1678. begin
  1679. consume(_LKLAMMER);
  1680. p1:=comp_expr(true);
  1681. consume(_RKLAMMER);
  1682. p1:=gentypeconvnode(p1,pd);
  1683. p1^.explizit:=true;
  1684. { handle postfix operators here e.g. string(a)[10] }
  1685. again:=true;
  1686. postfixoperators;
  1687. end
  1688. else
  1689. p1:=gentypenode(pd,nil);
  1690. end;
  1691. _FILE : begin
  1692. pd:=cfiledef;
  1693. consume(_FILE);
  1694. { FILE can be also a type cast }
  1695. if token=_LKLAMMER then
  1696. begin
  1697. consume(_LKLAMMER);
  1698. p1:=comp_expr(true);
  1699. consume(_RKLAMMER);
  1700. p1:=gentypeconvnode(p1,pd);
  1701. p1^.explizit:=true;
  1702. { handle postfix operators here e.g. string(a)[10] }
  1703. again:=true;
  1704. postfixoperators;
  1705. end
  1706. else
  1707. p1:=gentypenode(pd,nil);
  1708. end;
  1709. _CSTRING : begin
  1710. p1:=genstringconstnode(pattern);
  1711. consume(_CSTRING);
  1712. end;
  1713. _CCHAR : begin
  1714. p1:=genordinalconstnode(ord(pattern[1]),cchardef);
  1715. consume(_CCHAR);
  1716. end;
  1717. _KLAMMERAFFE : begin
  1718. consume(_KLAMMERAFFE);
  1719. got_addrn:=true;
  1720. { support both @<x> and @(<x>) }
  1721. if token=_LKLAMMER then
  1722. begin
  1723. consume(_LKLAMMER);
  1724. p1:=factor(true);
  1725. consume(_RKLAMMER);
  1726. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1727. begin
  1728. { we need the resulttype }
  1729. { of the expression in pd }
  1730. do_firstpass(p1);
  1731. pd:=p1^.resulttype;
  1732. again:=true;
  1733. postfixoperators;
  1734. end;
  1735. end
  1736. else
  1737. p1:=factor(true);
  1738. got_addrn:=false;
  1739. p1:=gensinglenode(addrn,p1);
  1740. end;
  1741. _LKLAMMER : begin
  1742. consume(_LKLAMMER);
  1743. p1:=comp_expr(true);
  1744. consume(_RKLAMMER);
  1745. { it's not a good solution }
  1746. { but (a+b)^ makes some problems }
  1747. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1748. begin
  1749. { we need the resulttype }
  1750. { of the expression in pd }
  1751. do_firstpass(p1);
  1752. pd:=p1^.resulttype;
  1753. again:=true;
  1754. postfixoperators;
  1755. end;
  1756. end;
  1757. _LECKKLAMMER : begin
  1758. consume(_LECKKLAMMER);
  1759. p1:=factor_read_set;
  1760. consume(_RECKKLAMMER);
  1761. end;
  1762. _PLUS : begin
  1763. consume(_PLUS);
  1764. p1:=factor(false);
  1765. end;
  1766. _MINUS : begin
  1767. consume(_MINUS);
  1768. p1:=factor(false);
  1769. p1:=gensinglenode(umminusn,p1);
  1770. end;
  1771. _NOT : begin
  1772. consume(_NOT);
  1773. p1:=factor(false);
  1774. p1:=gensinglenode(notn,p1);
  1775. end;
  1776. _TRUE : begin
  1777. consume(_TRUE);
  1778. p1:=genordinalconstnode(1,booldef);
  1779. end;
  1780. _FALSE : begin
  1781. consume(_FALSE);
  1782. p1:=genordinalconstnode(0,booldef);
  1783. end;
  1784. _NIL : begin
  1785. consume(_NIL);
  1786. p1:=genzeronode(niln);
  1787. end;
  1788. else
  1789. begin
  1790. p1:=genzeronode(errorn);
  1791. consume(token);
  1792. Message(cg_e_illegal_expression);
  1793. end;
  1794. end;
  1795. { generate error node if no node is created }
  1796. if not assigned(p1) then
  1797. p1:=genzeronode(errorn);
  1798. { tp7 procvar handling, but not if the next token
  1799. will be a := }
  1800. if (m_tp_procvar in aktmodeswitches) and
  1801. (token<>_ASSIGNMENT) then
  1802. check_tp_procvar(p1);
  1803. factor:=p1;
  1804. check_tokenpos;
  1805. end;
  1806. {****************************************************************************
  1807. Sub_Expr
  1808. ****************************************************************************}
  1809. type
  1810. Toperator_precedence=(opcompare,opaddition,opmultiply);
  1811. Ttok2nodeRec=record
  1812. tok : ttoken;
  1813. nod : ttreetyp;
  1814. end;
  1815. const
  1816. tok2nodes=23;
  1817. tok2node:array[1..tok2nodes] of ttok2noderec=(
  1818. (tok:_PLUS ;nod:addn),
  1819. (tok:_MINUS ;nod:subn),
  1820. (tok:_STAR ;nod:muln),
  1821. (tok:_SLASH ;nod:slashn),
  1822. (tok:_EQUAL ;nod:equaln),
  1823. (tok:_GT ;nod:gtn),
  1824. (tok:_LT ;nod:ltn),
  1825. (tok:_GTE ;nod:gten),
  1826. (tok:_LTE ;nod:lten),
  1827. (tok:_SYMDIF ;nod:symdifn),
  1828. (tok:_STARSTAR;nod:starstarn),
  1829. (tok:_OP_AS ;nod:asn),
  1830. (tok:_OP_IN ;nod:inn),
  1831. (tok:_OP_IS ;nod:isn),
  1832. (tok:_OP_OR ;nod:orn),
  1833. (tok:_OP_AND ;nod:andn),
  1834. (tok:_OP_DIV ;nod:divn),
  1835. (tok:_OP_MOD ;nod:modn),
  1836. (tok:_OP_SHL ;nod:shln),
  1837. (tok:_OP_SHR ;nod:shrn),
  1838. (tok:_OP_XOR ;nod:xorn),
  1839. (tok:_CARET ;nod:caretn),
  1840. (tok:_UNEQUAL ;nod:unequaln)
  1841. );
  1842. { Warning these stay be ordered !! }
  1843. operator_levels:array[Toperator_precedence] of set of Ttoken=
  1844. ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_OP_IN,_OP_IS],
  1845. [_PLUS,_MINUS,_OP_OR,_OP_XOR],
  1846. [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,
  1847. _OP_AS,_OP_AND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR]);
  1848. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):Ptree;
  1849. {Reads a subexpression while the operators are of the current precedence
  1850. level, or any higher level. Replaces the old term, simpl_expr and
  1851. simpl2_expr.}
  1852. var
  1853. low,high,mid : longint;
  1854. p1,p2 : Ptree;
  1855. oldt : Ttoken;
  1856. filepos : tfileposinfo;
  1857. begin
  1858. if pred_level=opmultiply then
  1859. p1:=factor(false)
  1860. else
  1861. p1:=sub_expr(succ(pred_level),true);
  1862. repeat
  1863. if (token in operator_levels[pred_level]) and
  1864. ((token<>_EQUAL) or accept_equal) then
  1865. begin
  1866. oldt:=token;
  1867. filepos:=tokenpos;
  1868. consume(token);
  1869. if pred_level=opmultiply then
  1870. p2:=factor(false)
  1871. else
  1872. p2:=sub_expr(succ(pred_level),true);
  1873. low:=1;
  1874. high:=tok2nodes;
  1875. while (low<high) do
  1876. begin
  1877. mid:=(low+high+1) shr 1;
  1878. if oldt<tok2node[mid].tok then
  1879. high:=mid-1
  1880. else
  1881. low:=mid;
  1882. end;
  1883. if tok2node[high].tok=oldt then
  1884. p1:=gennode(tok2node[high].nod,p1,p2)
  1885. else
  1886. p1:=gennode(nothingn,p1,p2);
  1887. set_tree_filepos(p1,filepos);
  1888. end
  1889. else
  1890. break;
  1891. until false;
  1892. sub_expr:=p1;
  1893. end;
  1894. function comp_expr(accept_equal : boolean):Ptree;
  1895. var
  1896. oldafterassignment : boolean;
  1897. p1 : ptree;
  1898. begin
  1899. oldafterassignment:=afterassignment;
  1900. afterassignment:=true;
  1901. p1:=sub_expr(opcompare,accept_equal);
  1902. afterassignment:=oldafterassignment;
  1903. comp_expr:=p1;
  1904. end;
  1905. function expr : ptree;
  1906. var
  1907. p1,p2 : ptree;
  1908. oldafterassignment : boolean;
  1909. oldp1 : ptree;
  1910. filepos : tfileposinfo;
  1911. begin
  1912. oldafterassignment:=afterassignment;
  1913. p1:=sub_expr(opcompare,true);
  1914. filepos:=tokenpos;
  1915. if (m_tp_procvar in aktmodeswitches) and
  1916. (token<>_ASSIGNMENT) then
  1917. check_tp_procvar(p1);
  1918. if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  1919. afterassignment:=true;
  1920. oldp1:=p1;
  1921. case token of
  1922. _POINTPOINT : begin
  1923. consume(_POINTPOINT);
  1924. p2:=sub_expr(opcompare,true);
  1925. p1:=gennode(rangen,p1,p2);
  1926. end;
  1927. _ASSIGNMENT : begin
  1928. consume(_ASSIGNMENT);
  1929. { avoid a firstpass of a procedure if
  1930. it must be assigned to a procvar }
  1931. { should be recursive for a:=b:=c !!! }
  1932. if (p1^.resulttype<>nil) and (p1^.resulttype^.deftype=procvardef) then
  1933. begin
  1934. getprocvar:=true;
  1935. getprocvardef:=pprocvardef(p1^.resulttype);
  1936. end;
  1937. p2:=sub_expr(opcompare,true);
  1938. if getprocvar then
  1939. handle_procvar(getprocvardef,p2);
  1940. getprocvar:=false;
  1941. p1:=gennode(assignn,p1,p2);
  1942. end;
  1943. { this is the code for C like assignements }
  1944. { from an improvement of Peter Schaefer }
  1945. _PLUSASN : begin
  1946. consume(_PLUSASN );
  1947. p2:=sub_expr(opcompare,true);
  1948. p1:=gennode(assignn,p1,gennode(addn,getcopy(p1),p2));
  1949. { was first
  1950. p1:=gennode(assignn,p1,gennode(addn,p1,p2));
  1951. but disposetree assumes that we have a real
  1952. *** tree *** }
  1953. end;
  1954. _MINUSASN : begin
  1955. consume(_MINUSASN );
  1956. p2:=sub_expr(opcompare,true);
  1957. p1:=gennode(assignn,p1,gennode(subn,getcopy(p1),p2));
  1958. end;
  1959. _STARASN : begin
  1960. consume(_STARASN );
  1961. p2:=sub_expr(opcompare,true);
  1962. p1:=gennode(assignn,p1,gennode(muln,getcopy(p1),p2));
  1963. end;
  1964. _SLASHASN : begin
  1965. consume(_SLASHASN );
  1966. p2:=sub_expr(opcompare,true);
  1967. p1:=gennode(assignn,p1,gennode(slashn,getcopy(p1),p2));
  1968. end;
  1969. end;
  1970. afterassignment:=oldafterassignment;
  1971. if p1<>oldp1 then
  1972. set_tree_filepos(p1,filepos);
  1973. expr:=p1;
  1974. end;
  1975. function get_intconst:longint;
  1976. {Reads an expression, tries to evalute it and check if it is an integer
  1977. constant. Then the constant is returned.}
  1978. var
  1979. p:Ptree;
  1980. begin
  1981. p:=comp_expr(true);
  1982. do_firstpass(p);
  1983. if not codegenerror then
  1984. begin
  1985. if (p^.treetype<>ordconstn) and
  1986. (p^.resulttype^.deftype=orddef) and
  1987. not(Porddef(p^.resulttype)^.typ in [uvoid,uchar,bool8bit,bool16bit,bool32bit]) then
  1988. Message(cg_e_illegal_expression)
  1989. else
  1990. get_intconst:=p^.value;
  1991. end;
  1992. disposetree(p);
  1993. end;
  1994. function get_stringconst:string;
  1995. {Reads an expression, tries to evaluate it and checks if it is a string
  1996. constant. Then the constant is returned.}
  1997. var
  1998. p:Ptree;
  1999. begin
  2000. get_stringconst:='';
  2001. p:=comp_expr(true);
  2002. do_firstpass(p);
  2003. if p^.treetype<>stringconstn then
  2004. begin
  2005. if (p^.treetype=ordconstn) and is_char(p^.resulttype) then
  2006. get_stringconst:=char(p^.value)
  2007. else
  2008. Message(cg_e_illegal_expression);
  2009. end
  2010. else
  2011. get_stringconst:=strpas(p^.value_str);
  2012. disposetree(p);
  2013. end;
  2014. end.
  2015. {
  2016. $Log$
  2017. Revision 1.160 1999-11-17 17:05:01 pierre
  2018. * Notes/hints changes
  2019. Revision 1.159 1999/11/15 17:52:59 pierre
  2020. + one field added for ttoken record for operator
  2021. linking the id to the corresponding operator token that
  2022. can now now all be overloaded
  2023. * overloaded operators are resetted to nil in InitSymtable
  2024. (bug when trying to compile a uint that overloads operators twice)
  2025. Revision 1.158 1999/11/14 15:57:35 peter
  2026. * fixed crash with an errordef
  2027. Revision 1.157 1999/11/08 14:02:16 florian
  2028. * problem with "index X"-properties solved
  2029. * typed constants of class references are now allowed
  2030. Revision 1.156 1999/11/07 23:21:30 florian
  2031. * previous fix for 517 was imcomplete: there was a problem if the property
  2032. had only an index
  2033. Revision 1.155 1999/11/07 23:16:49 florian
  2034. * finally bug 517 solved ...
  2035. Revision 1.154 1999/11/06 14:34:21 peter
  2036. * truncated log to 20 revs
  2037. Revision 1.153 1999/11/05 00:10:30 peter
  2038. * fixed inherited with properties
  2039. Revision 1.152 1999/10/27 16:06:19 peter
  2040. * check for object in extended new
  2041. Revision 1.151 1999/10/26 12:30:44 peter
  2042. * const parameter is now checked
  2043. * better and generic check if a node can be used for assigning
  2044. * export fixes
  2045. * procvar equal works now (it never had worked at least from 0.99.8)
  2046. * defcoll changed to linkedlist with pparaitem so it can easily be
  2047. walked both directions
  2048. Revision 1.150 1999/10/22 14:37:30 peter
  2049. * error when properties are passed to var parameters
  2050. Revision 1.149 1999/10/22 10:39:34 peter
  2051. * split type reading from pdecl to ptype unit
  2052. * parameter_dec routine is now used for procedure and procvars
  2053. Revision 1.148 1999/10/14 14:57:52 florian
  2054. - removed the hcodegen use in the new cg, use cgbase instead
  2055. Revision 1.147 1999/09/28 11:03:54 peter
  2056. * fixed result access in 'if result = XXX then'
  2057. * fixed const cr=chr(13)
  2058. Revision 1.146 1999/09/27 23:44:54 peter
  2059. * procinfo is now a pointer
  2060. * support for result setting in sub procedure
  2061. Revision 1.145 1999/09/27 11:59:42 peter
  2062. * fix for pointer reading in const with @type.method
  2063. Revision 1.144 1999/09/26 21:30:19 peter
  2064. + constant pointer support which can happend with typecasting like
  2065. const p=pointer(1)
  2066. * better procvar parsing in typed consts
  2067. Revision 1.143 1999/09/15 20:35:41 florian
  2068. * small fix to operator overloading when in MMX mode
  2069. + the compiler uses now fldz and fld1 if possible
  2070. + some fixes to floating point registers
  2071. + some math. functions (arctan, ln, sin, cos, sqrt, sqr, pi) are now inlined
  2072. * .... ???
  2073. Revision 1.142 1999/09/13 16:26:32 peter
  2074. * fix crash with empty object as childs
  2075. Revision 1.141 1999/09/11 19:47:26 florian
  2076. * bug fix for @tobject.method, fixes bug 557, 605 and 606
  2077. Revision 1.140 1999/09/11 09:08:33 florian
  2078. * fixed bug 596
  2079. * fixed some problems with procedure variables and procedures of object,
  2080. especially in TP mode. Procedure of object doesn't apply only to classes,
  2081. it is also allowed for objects !!
  2082. Revision 1.139 1999/09/10 18:48:07 florian
  2083. * some bug fixes (e.g. must_be_valid and procinfo^.funcret_is_valid)
  2084. * most things for stored properties fixed
  2085. Revision 1.138 1999/09/07 08:01:20 peter
  2086. * @(<x>) support
  2087. Revision 1.137 1999/09/01 22:08:58 peter
  2088. * fixed crash with assigned()
  2089. Revision 1.136 1999/08/15 22:47:45 peter
  2090. * fixed property writeaccess which was buggy after my previous
  2091. subscribed property access
  2092. Revision 1.135 1999/08/14 00:38:56 peter
  2093. * hack to support property with record fields
  2094. Revision 1.134 1999/08/09 22:16:29 peter
  2095. * fixed crash after wrong para's with class contrustor
  2096. }