pexpr.pas 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222
  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. if ((pvarsym(sym)=opsym) and
  846. ((p^.flags and pi_operator)<>0)) then
  847. inc(opsym^.refs);
  848. p1:=genzeronode(funcretn);
  849. pd:=p^.retdef;
  850. p1^.funcretprocinfo:=p;
  851. p1^.retdef:=pd;
  852. is_func_ret:=true;
  853. exit;
  854. end;
  855. p:=p^.parent;
  856. end;
  857. { we must use the function call }
  858. if(sym^.typ=funcretsym) then
  859. begin
  860. storesymtablestack:=symtablestack;
  861. symtablestack:=srsymtable^.next;
  862. getsym(sym^.name,true);
  863. if srsym^.typ<>procsym then
  864. Message(cg_e_illegal_expression);
  865. symtablestack:=storesymtablestack;
  866. end;
  867. end;
  868. {---------------------------------------------
  869. Factor_read_id
  870. ---------------------------------------------}
  871. procedure factor_read_id;
  872. var
  873. pc : pchar;
  874. len : longint;
  875. begin
  876. { allow post fix operators }
  877. again:=true;
  878. begin
  879. if lastsymknown then
  880. begin
  881. srsym:=lastsrsym;
  882. srsymtable:=lastsrsymtable;
  883. lastsymknown:=false;
  884. end
  885. else
  886. getsym(pattern,true);
  887. consume(_ID);
  888. if not is_func_ret(srsym) then
  889. { else it's a normal symbol }
  890. begin
  891. { is it defined like UNIT.SYMBOL ? }
  892. if srsym^.typ=unitsym then
  893. begin
  894. consume(_POINT);
  895. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  896. unit_specific:=true;
  897. consume(_ID);
  898. end
  899. else
  900. unit_specific:=false;
  901. if not assigned(srsym) then
  902. Begin
  903. p1:=genzeronode(errorn);
  904. { try to clean up }
  905. pd:=generrordef;
  906. end
  907. else
  908. Begin
  909. { check semantics of private }
  910. if (srsym^.typ in [propertysym,procsym,varsym]) and
  911. (srsymtable^.symtabletype=objectsymtable) then
  912. begin
  913. if (sp_private in srsym^.symoptions) and
  914. (pobjectdef(srsym^.owner^.defowner)^.owner^.symtabletype=unitsymtable) then
  915. Message(parser_e_cant_access_private_member);
  916. end;
  917. case srsym^.typ of
  918. absolutesym : begin
  919. p1:=genloadnode(pvarsym(srsym),srsymtable);
  920. pd:=pabsolutesym(srsym)^.definition;
  921. end;
  922. varsym : begin
  923. { are we in a class method ? }
  924. if (srsymtable^.symtabletype=objectsymtable) and
  925. assigned(aktprocsym) and
  926. (po_classmethod in aktprocsym^.definition^.procoptions) then
  927. Message(parser_e_only_class_methods);
  928. if (sp_static in srsym^.symoptions) then
  929. begin
  930. static_name:=lower(srsym^.owner^.name^)+'_'+srsym^.name;
  931. getsym(static_name,true);
  932. end;
  933. p1:=genloadnode(pvarsym(srsym),srsymtable);
  934. if pvarsym(srsym)^.varstate=vs_declared then
  935. begin
  936. p1^.is_first := true;
  937. { set special between first loaded until checked in firstpass }
  938. pvarsym(srsym)^.varstate:=vs_declared2;
  939. end;
  940. pd:=pvarsym(srsym)^.definition;
  941. end;
  942. typedconstsym : begin
  943. p1:=gentypedconstloadnode(ptypedconstsym(srsym),srsymtable);
  944. pd:=ptypedconstsym(srsym)^.definition;
  945. end;
  946. syssym : p1:=statement_syssym(psyssym(srsym)^.number,pd);
  947. typesym : begin
  948. pd:=ptypesym(srsym)^.definition;
  949. if not assigned(pd) then
  950. begin
  951. pd:=generrordef;
  952. again:=false;
  953. end
  954. else
  955. begin
  956. { if we read a type declaration }
  957. { we have to return the type and }
  958. { nothing else }
  959. if block_type=bt_type then
  960. begin
  961. { we don't need sym reference when it's in the
  962. current unit or system unit, because those
  963. units are always loaded (PFV) }
  964. if not(assigned(pd^.owner)) or
  965. (pd^.owner^.unitid=0) or
  966. (pd^.owner^.unitid=1) then
  967. p1:=gentypenode(pd,nil)
  968. else
  969. p1:=gentypenode(pd,ptypesym(srsym));
  970. { here we can also set resulttype !! }
  971. p1^.resulttype:=pd;
  972. pd:=voiddef;
  973. end
  974. else { not type block }
  975. begin
  976. if token=_LKLAMMER then
  977. begin
  978. consume(_LKLAMMER);
  979. p1:=comp_expr(true);
  980. consume(_RKLAMMER);
  981. p1:=gentypeconvnode(p1,pd);
  982. p1^.explizit:=true;
  983. end
  984. else { not LKLAMMER}
  985. if (token=_POINT) and
  986. (pd^.deftype=objectdef) and
  987. not(pobjectdef(pd)^.is_class) then
  988. begin
  989. consume(_POINT);
  990. if assigned(procinfo) and
  991. assigned(procinfo^._class) and
  992. not(getaddr) then
  993. begin
  994. if procinfo^._class^.is_related(pobjectdef(pd)) then
  995. begin
  996. p1:=gentypenode(pd,ptypesym(srsym));
  997. p1^.resulttype:=pd;
  998. { search also in inherited methods }
  999. repeat
  1000. srsymtable:=pobjectdef(pd)^.symtable;
  1001. sym:=pvarsym(srsymtable^.search(pattern));
  1002. if assigned(sym) then
  1003. break;
  1004. pd:=pobjectdef(pd)^.childof;
  1005. until not assigned(pd);
  1006. consume(_ID);
  1007. do_member_read(false,sym,p1,pd,again);
  1008. end
  1009. else
  1010. begin
  1011. Message(parser_e_no_super_class);
  1012. pd:=generrordef;
  1013. again:=false;
  1014. end;
  1015. end
  1016. else
  1017. begin
  1018. { allows @TObject.Load }
  1019. { also allows static methods and variables }
  1020. p1:=genzeronode(typen);
  1021. p1^.resulttype:=pd;
  1022. { TP allows also @TMenu.Load if Load is only }
  1023. { defined in an anchestor class }
  1024. sym:=pvarsym(search_class_member(pobjectdef(pd),pattern));
  1025. if not assigned(sym) then
  1026. Message1(sym_e_id_no_member,pattern)
  1027. else if not(getaddr) and not(sp_static in sym^.symoptions) then
  1028. Message(sym_e_only_static_in_static)
  1029. else
  1030. begin
  1031. consume(_ID);
  1032. do_member_read(getaddr,sym,p1,pd,again);
  1033. end;
  1034. end;
  1035. end
  1036. else
  1037. begin
  1038. { class reference ? }
  1039. if (pd^.deftype=objectdef)
  1040. and pobjectdef(pd)^.is_class then
  1041. begin
  1042. p1:=gentypenode(pd,nil);
  1043. p1^.resulttype:=pd;
  1044. pd:=new(pclassrefdef,init(pd));
  1045. p1:=gensinglenode(loadvmtn,p1);
  1046. p1^.resulttype:=pd;
  1047. end
  1048. else
  1049. begin
  1050. { generate a type node }
  1051. { (for typeof etc) }
  1052. if allow_type then
  1053. begin
  1054. p1:=gentypenode(pd,nil);
  1055. { here we must use typenodetype explicitly !! PM
  1056. p1^.resulttype:=pd; }
  1057. pd:=voiddef;
  1058. end
  1059. else
  1060. Message(parser_e_no_type_not_allowed_here);
  1061. end;
  1062. end;
  1063. end;
  1064. end;
  1065. end;
  1066. enumsym : begin
  1067. p1:=genenumnode(penumsym(srsym));
  1068. pd:=p1^.resulttype;
  1069. end;
  1070. constsym : begin
  1071. case pconstsym(srsym)^.consttype of
  1072. constint :
  1073. p1:=genordinalconstnode(pconstsym(srsym)^.value,s32bitdef);
  1074. conststring :
  1075. begin
  1076. len:=pconstsym(srsym)^.len;
  1077. if not(cs_ansistrings in aktlocalswitches) and (len>255) then
  1078. len:=255;
  1079. getmem(pc,len+1);
  1080. move(pchar(pconstsym(srsym)^.value)^,pc^,len);
  1081. pc[len]:=#0;
  1082. p1:=genpcharconstnode(pc,len);
  1083. end;
  1084. constchar :
  1085. p1:=genordinalconstnode(pconstsym(srsym)^.value,cchardef);
  1086. constreal :
  1087. p1:=genrealconstnode(pbestreal(pconstsym(srsym)^.value)^,bestrealdef^);
  1088. constbool :
  1089. p1:=genordinalconstnode(pconstsym(srsym)^.value,booldef);
  1090. constset :
  1091. p1:=gensetconstnode(pconstset(pconstsym(srsym)^.value),
  1092. psetdef(pconstsym(srsym)^.definition));
  1093. constord :
  1094. p1:=genordinalconstnode(pconstsym(srsym)^.value,
  1095. pconstsym(srsym)^.definition);
  1096. constpointer :
  1097. p1:=genpointerconstnode(pconstsym(srsym)^.value,
  1098. pconstsym(srsym)^.definition);
  1099. constnil :
  1100. p1:=genzeronode(niln);
  1101. constresourcestring:
  1102. begin
  1103. p1:=genloadnode(pvarsym(srsym),srsymtable);
  1104. p1^.resulttype:=cansistringdef;
  1105. end;
  1106. end;
  1107. pd:=p1^.resulttype;
  1108. end;
  1109. procsym : begin
  1110. { are we in a class method ? }
  1111. possible_error:=(srsymtable^.symtabletype=objectsymtable) and
  1112. assigned(aktprocsym) and
  1113. (po_classmethod in aktprocsym^.definition^.procoptions);
  1114. p1:=gencallnode(pprocsym(srsym),srsymtable);
  1115. p1^.unit_specific:=unit_specific;
  1116. do_proc_call(getaddr or
  1117. (getprocvar and
  1118. ((block_type=bt_const) or
  1119. ((m_tp_procvar in aktmodeswitches) and
  1120. proc_to_procvar_equal(pprocsym(srsym)^.definition,getprocvardef)
  1121. )
  1122. )
  1123. ),again,p1,pd);
  1124. if (block_type=bt_const) and
  1125. getprocvar then
  1126. handle_procvar(getprocvardef,p1);
  1127. if possible_error and
  1128. not(po_classmethod in p1^.procdefinition^.procoptions) then
  1129. Message(parser_e_only_class_methods);
  1130. end;
  1131. propertysym : begin
  1132. { access to property in a method }
  1133. { are we in a class method ? }
  1134. if (srsymtable^.symtabletype=objectsymtable) and
  1135. assigned(aktprocsym) and
  1136. (po_classmethod in aktprocsym^.definition^.procoptions) then
  1137. Message(parser_e_only_class_methods);
  1138. { no method pointer }
  1139. p1:=nil;
  1140. handle_propertysym(srsym,srsymtable,p1,pd);
  1141. end;
  1142. errorsym : begin
  1143. p1:=genzeronode(errorn);
  1144. p1^.resulttype:=generrordef;
  1145. pd:=generrordef;
  1146. if token=_LKLAMMER then
  1147. begin
  1148. consume(_LKLAMMER);
  1149. parse_paras(false,false);
  1150. consume(_RKLAMMER);
  1151. end;
  1152. end;
  1153. else
  1154. begin
  1155. p1:=genzeronode(errorn);
  1156. pd:=generrordef;
  1157. Message(cg_e_illegal_expression);
  1158. end;
  1159. end; { end case }
  1160. end;
  1161. end;
  1162. end;
  1163. end;
  1164. {---------------------------------------------
  1165. Factor_Read_Set
  1166. ---------------------------------------------}
  1167. { Read a set between [] }
  1168. function factor_read_set:ptree;
  1169. var
  1170. p1,
  1171. lastp,
  1172. buildp : ptree;
  1173. begin
  1174. buildp:=nil;
  1175. { be sure that a least one arrayconstructn is used, also for an
  1176. empty [] }
  1177. if token=_RECKKLAMMER then
  1178. buildp:=gennode(arrayconstructn,nil,buildp)
  1179. else
  1180. begin
  1181. while true do
  1182. begin
  1183. p1:=comp_expr(true);
  1184. if token=_POINTPOINT then
  1185. begin
  1186. consume(_POINTPOINT);
  1187. p2:=comp_expr(true);
  1188. p1:=gennode(arrayconstructrangen,p1,p2);
  1189. end;
  1190. { insert at the end of the tree, to get the correct order }
  1191. if not assigned(buildp) then
  1192. begin
  1193. buildp:=gennode(arrayconstructn,p1,nil);
  1194. lastp:=buildp;
  1195. end
  1196. else
  1197. begin
  1198. lastp^.right:=gennode(arrayconstructn,p1,nil);
  1199. lastp:=lastp^.right;
  1200. end;
  1201. { there could be more elements }
  1202. if token=_COMMA then
  1203. consume(_COMMA)
  1204. else
  1205. break;
  1206. end;
  1207. end;
  1208. factor_read_set:=buildp;
  1209. end;
  1210. {---------------------------------------------
  1211. Helpers
  1212. ---------------------------------------------}
  1213. procedure check_tokenpos;
  1214. begin
  1215. if (p1<>oldp1) then
  1216. begin
  1217. if assigned(p1) then
  1218. set_tree_filepos(p1,filepos);
  1219. oldp1:=p1;
  1220. filepos:=tokenpos;
  1221. end;
  1222. end;
  1223. {---------------------------------------------
  1224. PostFixOperators
  1225. ---------------------------------------------}
  1226. procedure postfixoperators;
  1227. var
  1228. store_static : boolean;
  1229. { p1 and p2 must contain valid value_str }
  1230. begin
  1231. check_tokenpos;
  1232. while again do
  1233. begin
  1234. { prevent crashes with unknown types }
  1235. if not assigned(pd) then
  1236. begin
  1237. { try to recover }
  1238. repeat
  1239. case token of
  1240. _CARET:
  1241. consume(_CARET);
  1242. _POINT:
  1243. begin
  1244. consume(_POINT);
  1245. consume(_ID);
  1246. end;
  1247. _LECKKLAMMER:
  1248. begin
  1249. repeat
  1250. consume(token);
  1251. until token in [_RECKKLAMMER,_SEMICOLON];
  1252. end;
  1253. else
  1254. break;
  1255. end;
  1256. until false;
  1257. exit;
  1258. end;
  1259. { handle token }
  1260. case token of
  1261. _CARET:
  1262. begin
  1263. consume(_CARET);
  1264. if (pd^.deftype<>pointerdef) then
  1265. begin
  1266. { ^ as binary operator is a problem!!!! (FK) }
  1267. again:=false;
  1268. Message(cg_e_invalid_qualifier);
  1269. disposetree(p1);
  1270. p1:=genzeronode(errorn);
  1271. end
  1272. else
  1273. begin
  1274. p1:=gensinglenode(derefn,p1);
  1275. pd:=ppointerdef(pd)^.definition;
  1276. end;
  1277. end;
  1278. _LECKKLAMMER:
  1279. begin
  1280. if (pd^.deftype=objectdef) and pobjectdef(pd)^.is_class then
  1281. begin
  1282. { default property }
  1283. propsym:=search_default_property(pobjectdef(pd));
  1284. if not(assigned(propsym)) then
  1285. begin
  1286. disposetree(p1);
  1287. p1:=genzeronode(errorn);
  1288. again:=false;
  1289. message(parser_e_no_default_property_available);
  1290. end
  1291. else
  1292. handle_propertysym(propsym,propsym^.owner,p1,pd);
  1293. end
  1294. else
  1295. begin
  1296. consume(_LECKKLAMMER);
  1297. repeat
  1298. case pd^.deftype of
  1299. pointerdef:
  1300. begin
  1301. p2:=comp_expr(true);
  1302. p1:=gennode(vecn,p1,p2);
  1303. pd:=ppointerdef(pd)^.definition;
  1304. end;
  1305. stringdef : begin
  1306. p2:=comp_expr(true);
  1307. p1:=gennode(vecn,p1,p2);
  1308. pd:=cchardef
  1309. end;
  1310. arraydef : begin
  1311. p2:=comp_expr(true);
  1312. { support SEG:OFS for go32v2 Mem[] }
  1313. if (target_info.target=target_i386_go32v2) and
  1314. (p1^.treetype=loadn) and
  1315. assigned(p1^.symtableentry) and
  1316. assigned(p1^.symtableentry^.owner^.name) and
  1317. (p1^.symtableentry^.owner^.name^='SYSTEM') and
  1318. ((p1^.symtableentry^.name='MEM') or
  1319. (p1^.symtableentry^.name='MEMW') or
  1320. (p1^.symtableentry^.name='MEML')) then
  1321. begin
  1322. if (token=_COLON) then
  1323. begin
  1324. consume(_COLON);
  1325. p3:=gennode(muln,genordinalconstnode($10,s32bitdef),p2);
  1326. p2:=comp_expr(true);
  1327. p2:=gennode(addn,p2,p3);
  1328. p1:=gennode(vecn,p1,p2);
  1329. p1^.memseg:=true;
  1330. p1^.memindex:=true;
  1331. end
  1332. else
  1333. begin
  1334. p1:=gennode(vecn,p1,p2);
  1335. p1^.memindex:=true;
  1336. end;
  1337. end
  1338. else
  1339. p1:=gennode(vecn,p1,p2);
  1340. pd:=parraydef(pd)^.definition;
  1341. end;
  1342. else
  1343. begin
  1344. Message(cg_e_invalid_qualifier);
  1345. disposetree(p1);
  1346. p1:=genzeronode(errorn);
  1347. again:=false;
  1348. end;
  1349. end;
  1350. if token=_COMMA then
  1351. consume(_COMMA)
  1352. else
  1353. break;
  1354. until false;
  1355. consume(_RECKKLAMMER);
  1356. end;
  1357. end;
  1358. _POINT : begin
  1359. consume(_POINT);
  1360. if (pd^.deftype=pointerdef) and
  1361. (m_autoderef in aktmodeswitches) then
  1362. begin
  1363. p1:=gensinglenode(derefn,p1);
  1364. pd:=ppointerdef(pd)^.definition;
  1365. end;
  1366. case pd^.deftype of
  1367. recorddef:
  1368. begin
  1369. sym:=pvarsym(precorddef(pd)^.symtable^.search(pattern));
  1370. if sym=nil then
  1371. begin
  1372. Message1(sym_e_illegal_field,pattern);
  1373. disposetree(p1);
  1374. p1:=genzeronode(errorn);
  1375. end
  1376. else
  1377. begin
  1378. p1:=gensubscriptnode(sym,p1);
  1379. pd:=sym^.definition;
  1380. end;
  1381. consume(_ID);
  1382. end;
  1383. classrefdef:
  1384. begin
  1385. classh:=pobjectdef(pclassrefdef(pd)^.definition);
  1386. sym:=nil;
  1387. while assigned(classh) do
  1388. begin
  1389. sym:=pvarsym(classh^.symtable^.search(pattern));
  1390. srsymtable:=classh^.symtable;
  1391. if assigned(sym) then
  1392. break;
  1393. classh:=classh^.childof;
  1394. end;
  1395. consume(_ID);
  1396. do_member_read(getaddr,sym,p1,pd,again);
  1397. end;
  1398. objectdef:
  1399. begin
  1400. classh:=pobjectdef(pd);
  1401. sym:=nil;
  1402. store_static:=allow_only_static;
  1403. allow_only_static:=false;
  1404. while assigned(classh) do
  1405. begin
  1406. sym:=pvarsym(classh^.symtable^.search(pattern));
  1407. srsymtable:=classh^.symtable;
  1408. if assigned(sym) then
  1409. break;
  1410. classh:=classh^.childof;
  1411. end;
  1412. allow_only_static:=store_static;
  1413. consume(_ID);
  1414. do_member_read(getaddr,sym,p1,pd,again);
  1415. end;
  1416. pointerdef:
  1417. begin
  1418. Message(cg_e_invalid_qualifier);
  1419. if ppointerdef(pd)^.definition^.deftype in [recorddef,objectdef,classrefdef] then
  1420. Message(parser_h_maybe_deref_caret_missing);
  1421. end;
  1422. else
  1423. begin
  1424. Message(cg_e_invalid_qualifier);
  1425. disposetree(p1);
  1426. p1:=genzeronode(errorn);
  1427. end;
  1428. end;
  1429. end;
  1430. else
  1431. begin
  1432. { is this a procedure variable ? }
  1433. if assigned(pd) then
  1434. begin
  1435. if (pd^.deftype=procvardef) then
  1436. begin
  1437. if getprocvar and is_equal(pd,getprocvardef) then
  1438. again:=false
  1439. else
  1440. if (token=_LKLAMMER) or
  1441. ((pprocvardef(pd)^.para^.empty) and
  1442. (not((token in [_ASSIGNMENT,_UNEQUAL,_EQUAL]))) and
  1443. (not afterassignment) and
  1444. (not in_args)) then
  1445. begin
  1446. { do this in a strange way }
  1447. { it's not a clean solution }
  1448. p2:=p1;
  1449. p1:=gencallnode(nil,nil);
  1450. p1^.right:=p2;
  1451. p1^.unit_specific:=unit_specific;
  1452. p1^.symtableprocentry:=pprocsym(sym);
  1453. if token=_LKLAMMER then
  1454. begin
  1455. consume(_LKLAMMER);
  1456. p1^.left:=parse_paras(false,false);
  1457. consume(_RKLAMMER);
  1458. end;
  1459. pd:=pprocvardef(pd)^.retdef;
  1460. { proc():= is never possible }
  1461. if token=_ASSIGNMENT then
  1462. begin
  1463. Message(cg_e_illegal_expression);
  1464. p1:=genzeronode(errorn);
  1465. again:=false;
  1466. end;
  1467. p1^.resulttype:=pd;
  1468. end
  1469. else
  1470. again:=false;
  1471. p1^.resulttype:=pd;
  1472. end
  1473. else
  1474. again:=false;
  1475. end
  1476. else
  1477. again:=false;
  1478. end;
  1479. end;
  1480. check_tokenpos;
  1481. end; { while again }
  1482. end;
  1483. {---------------------------------------------
  1484. Factor (Main)
  1485. ---------------------------------------------}
  1486. begin
  1487. oldp1:=nil;
  1488. p1:=nil;
  1489. filepos:=tokenpos;
  1490. if token=_ID then
  1491. begin
  1492. factor_read_id;
  1493. { handle post fix operators }
  1494. postfixoperators;
  1495. end
  1496. else
  1497. case token of
  1498. _NEW : begin
  1499. consume(_NEW);
  1500. consume(_LKLAMMER);
  1501. {allow_type:=true;}
  1502. p1:=factor(false);
  1503. {allow_type:=false;}
  1504. if p1^.treetype<>typen then
  1505. begin
  1506. Message(type_e_type_id_expected);
  1507. disposetree(p1);
  1508. pd:=generrordef;
  1509. end
  1510. else
  1511. pd:=p1^.typenodetype;
  1512. pd2:=pd;
  1513. if (pd^.deftype<>pointerdef) then
  1514. Message1(type_e_pointer_type_expected,pd^.typename)
  1515. else
  1516. if token=_RKLAMMER then
  1517. begin
  1518. if (ppointerdef(pd)^.definition^.deftype=objectdef) and
  1519. (oo_has_vmt in pobjectdef(ppointerdef(pd)^.definition)^.objectoptions) then
  1520. Message(parser_w_use_extended_syntax_for_objects);
  1521. p1:=gensinglenode(newn,nil);
  1522. p1^.resulttype:=pd2;
  1523. consume(_RKLAMMER);
  1524. end
  1525. else
  1526. begin
  1527. disposetree(p1);
  1528. p1:=genzeronode(hnewn);
  1529. p1^.resulttype:=ppointerdef(pd)^.definition;
  1530. consume(_COMMA);
  1531. afterassignment:=false;
  1532. { determines the current object defintion }
  1533. classh:=pobjectdef(ppointerdef(pd)^.definition);
  1534. if classh^.deftype<>objectdef then
  1535. Message(parser_e_pointer_to_class_expected)
  1536. else
  1537. begin
  1538. { check for an abstract class }
  1539. if (oo_has_abstract in classh^.objectoptions) then
  1540. Message(sym_e_no_instance_of_abstract_object);
  1541. { search the constructor also in the symbol tables of
  1542. the parents }
  1543. sym:=nil;
  1544. while assigned(classh) do
  1545. begin
  1546. sym:=pvarsym(classh^.symtable^.search(pattern));
  1547. srsymtable:=classh^.symtable;
  1548. if assigned(sym) then
  1549. break;
  1550. classh:=classh^.childof;
  1551. end;
  1552. consume(_ID);
  1553. do_member_read(false,sym,p1,pd,again);
  1554. if (p1^.treetype<>calln) or
  1555. (assigned(p1^.procdefinition) and
  1556. (p1^.procdefinition^.proctypeoption<>potype_constructor)) then
  1557. Message(parser_e_expr_have_to_be_constructor_call);
  1558. end;
  1559. p1:=gensinglenode(newn,p1);
  1560. { set the resulttype }
  1561. p1^.resulttype:=pd2;
  1562. consume(_RKLAMMER);
  1563. end;
  1564. postfixoperators;
  1565. end;
  1566. _SELF : begin
  1567. again:=true;
  1568. consume(_SELF);
  1569. if not assigned(procinfo^._class) then
  1570. begin
  1571. p1:=genzeronode(errorn);
  1572. pd:=generrordef;
  1573. again:=false;
  1574. Message(parser_e_self_not_in_method);
  1575. end
  1576. else
  1577. begin
  1578. if (po_classmethod in aktprocsym^.definition^.procoptions) then
  1579. begin
  1580. { self in class methods is a class reference type }
  1581. pd:=new(pclassrefdef,init(procinfo^._class));
  1582. p1:=genselfnode(pd);
  1583. p1^.resulttype:=pd;
  1584. end
  1585. else
  1586. begin
  1587. p1:=genselfnode(procinfo^._class);
  1588. p1^.resulttype:=procinfo^._class;
  1589. end;
  1590. pd:=p1^.resulttype;
  1591. postfixoperators;
  1592. end;
  1593. end;
  1594. _INHERITED : begin
  1595. again:=true;
  1596. consume(_INHERITED);
  1597. if assigned(procinfo^._class) then
  1598. begin
  1599. classh:=procinfo^._class^.childof;
  1600. while assigned(classh) do
  1601. begin
  1602. srsymtable:=pobjectdef(classh)^.symtable;
  1603. sym:=pvarsym(srsymtable^.search(pattern));
  1604. if assigned(sym) then
  1605. begin
  1606. { only for procsyms we need to set the type (PFV) }
  1607. if sym^.typ=procsym then
  1608. begin
  1609. p1:=genzeronode(typen);
  1610. p1^.resulttype:=classh;
  1611. pd:=p1^.resulttype;
  1612. end
  1613. else
  1614. p1:=nil;
  1615. consume(_ID);
  1616. do_member_read(false,sym,p1,pd,again);
  1617. break;
  1618. end;
  1619. classh:=classh^.childof;
  1620. end;
  1621. if classh=nil then
  1622. begin
  1623. Message1(sym_e_id_no_member,pattern);
  1624. again:=false;
  1625. pd:=generrordef;
  1626. p1:=genzeronode(errorn);
  1627. end;
  1628. end
  1629. else
  1630. begin
  1631. Message(parser_e_generic_methods_only_in_methods);
  1632. again:=false;
  1633. pd:=generrordef;
  1634. p1:=genzeronode(errorn);
  1635. end;
  1636. postfixoperators;
  1637. end;
  1638. _INTCONST : begin
  1639. valint(pattern,l,code);
  1640. if code<>0 then
  1641. begin
  1642. val(pattern,d,code);
  1643. if code<>0 then
  1644. begin
  1645. Message(cg_e_invalid_integer);
  1646. consume(_INTCONST);
  1647. l:=1;
  1648. p1:=genordinalconstnode(l,s32bitdef);
  1649. end
  1650. else
  1651. begin
  1652. consume(_INTCONST);
  1653. p1:=genrealconstnode(d,bestrealdef^);
  1654. end;
  1655. end
  1656. else
  1657. begin
  1658. consume(_INTCONST);
  1659. p1:=genordinalconstnode(l,s32bitdef);
  1660. end;
  1661. end;
  1662. _REALNUMBER : begin
  1663. val(pattern,d,code);
  1664. if code<>0 then
  1665. begin
  1666. Message(parser_e_error_in_real);
  1667. d:=1.0;
  1668. end;
  1669. consume(_REALNUMBER);
  1670. p1:=genrealconstnode(d,bestrealdef^);
  1671. end;
  1672. _STRING : begin
  1673. pd:=string_dec;
  1674. { STRING can be also a type cast }
  1675. if token=_LKLAMMER then
  1676. begin
  1677. consume(_LKLAMMER);
  1678. p1:=comp_expr(true);
  1679. consume(_RKLAMMER);
  1680. p1:=gentypeconvnode(p1,pd);
  1681. p1^.explizit:=true;
  1682. { handle postfix operators here e.g. string(a)[10] }
  1683. again:=true;
  1684. postfixoperators;
  1685. end
  1686. else
  1687. p1:=gentypenode(pd,nil);
  1688. end;
  1689. _FILE : begin
  1690. pd:=cfiledef;
  1691. consume(_FILE);
  1692. { FILE can be also a type cast }
  1693. if token=_LKLAMMER then
  1694. begin
  1695. consume(_LKLAMMER);
  1696. p1:=comp_expr(true);
  1697. consume(_RKLAMMER);
  1698. p1:=gentypeconvnode(p1,pd);
  1699. p1^.explizit:=true;
  1700. { handle postfix operators here e.g. string(a)[10] }
  1701. again:=true;
  1702. postfixoperators;
  1703. end
  1704. else
  1705. p1:=gentypenode(pd,nil);
  1706. end;
  1707. _CSTRING : begin
  1708. p1:=genstringconstnode(pattern);
  1709. consume(_CSTRING);
  1710. end;
  1711. _CCHAR : begin
  1712. p1:=genordinalconstnode(ord(pattern[1]),cchardef);
  1713. consume(_CCHAR);
  1714. end;
  1715. _KLAMMERAFFE : begin
  1716. consume(_KLAMMERAFFE);
  1717. got_addrn:=true;
  1718. { support both @<x> and @(<x>) }
  1719. if token=_LKLAMMER then
  1720. begin
  1721. consume(_LKLAMMER);
  1722. p1:=factor(true);
  1723. consume(_RKLAMMER);
  1724. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1725. begin
  1726. { we need the resulttype }
  1727. { of the expression in pd }
  1728. do_firstpass(p1);
  1729. pd:=p1^.resulttype;
  1730. again:=true;
  1731. postfixoperators;
  1732. end;
  1733. end
  1734. else
  1735. p1:=factor(true);
  1736. got_addrn:=false;
  1737. p1:=gensinglenode(addrn,p1);
  1738. end;
  1739. _LKLAMMER : begin
  1740. consume(_LKLAMMER);
  1741. p1:=comp_expr(true);
  1742. consume(_RKLAMMER);
  1743. { it's not a good solution }
  1744. { but (a+b)^ makes some problems }
  1745. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1746. begin
  1747. { we need the resulttype }
  1748. { of the expression in pd }
  1749. do_firstpass(p1);
  1750. pd:=p1^.resulttype;
  1751. again:=true;
  1752. postfixoperators;
  1753. end;
  1754. end;
  1755. _LECKKLAMMER : begin
  1756. consume(_LECKKLAMMER);
  1757. p1:=factor_read_set;
  1758. consume(_RECKKLAMMER);
  1759. end;
  1760. _PLUS : begin
  1761. consume(_PLUS);
  1762. p1:=factor(false);
  1763. end;
  1764. _MINUS : begin
  1765. consume(_MINUS);
  1766. p1:=factor(false);
  1767. p1:=gensinglenode(umminusn,p1);
  1768. end;
  1769. _NOT : begin
  1770. consume(_NOT);
  1771. p1:=factor(false);
  1772. p1:=gensinglenode(notn,p1);
  1773. end;
  1774. _TRUE : begin
  1775. consume(_TRUE);
  1776. p1:=genordinalconstnode(1,booldef);
  1777. end;
  1778. _FALSE : begin
  1779. consume(_FALSE);
  1780. p1:=genordinalconstnode(0,booldef);
  1781. end;
  1782. _NIL : begin
  1783. consume(_NIL);
  1784. p1:=genzeronode(niln);
  1785. end;
  1786. else
  1787. begin
  1788. p1:=genzeronode(errorn);
  1789. consume(token);
  1790. Message(cg_e_illegal_expression);
  1791. end;
  1792. end;
  1793. { generate error node if no node is created }
  1794. if not assigned(p1) then
  1795. p1:=genzeronode(errorn);
  1796. { tp7 procvar handling, but not if the next token
  1797. will be a := }
  1798. if (m_tp_procvar in aktmodeswitches) and
  1799. (token<>_ASSIGNMENT) then
  1800. check_tp_procvar(p1);
  1801. factor:=p1;
  1802. check_tokenpos;
  1803. end;
  1804. {****************************************************************************
  1805. Sub_Expr
  1806. ****************************************************************************}
  1807. type
  1808. Toperator_precedence=(opcompare,opaddition,opmultiply);
  1809. Ttok2nodeRec=record
  1810. tok : ttoken;
  1811. nod : ttreetyp;
  1812. end;
  1813. const
  1814. tok2nodes=23;
  1815. tok2node:array[1..tok2nodes] of ttok2noderec=(
  1816. (tok:_PLUS ;nod:addn),
  1817. (tok:_MINUS ;nod:subn),
  1818. (tok:_STAR ;nod:muln),
  1819. (tok:_SLASH ;nod:slashn),
  1820. (tok:_EQUAL ;nod:equaln),
  1821. (tok:_GT ;nod:gtn),
  1822. (tok:_LT ;nod:ltn),
  1823. (tok:_GTE ;nod:gten),
  1824. (tok:_LTE ;nod:lten),
  1825. (tok:_SYMDIF ;nod:symdifn),
  1826. (tok:_STARSTAR;nod:starstarn),
  1827. (tok:_OP_AS ;nod:asn),
  1828. (tok:_OP_IN ;nod:inn),
  1829. (tok:_OP_IS ;nod:isn),
  1830. (tok:_OP_OR ;nod:orn),
  1831. (tok:_OP_AND ;nod:andn),
  1832. (tok:_OP_DIV ;nod:divn),
  1833. (tok:_OP_MOD ;nod:modn),
  1834. (tok:_OP_SHL ;nod:shln),
  1835. (tok:_OP_SHR ;nod:shrn),
  1836. (tok:_OP_XOR ;nod:xorn),
  1837. (tok:_CARET ;nod:caretn),
  1838. (tok:_UNEQUAL ;nod:unequaln)
  1839. );
  1840. { Warning these stay be ordered !! }
  1841. operator_levels:array[Toperator_precedence] of set of Ttoken=
  1842. ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_OP_IN,_OP_IS],
  1843. [_PLUS,_MINUS,_OP_OR,_OP_XOR],
  1844. [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,
  1845. _OP_AS,_OP_AND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR]);
  1846. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):Ptree;
  1847. {Reads a subexpression while the operators are of the current precedence
  1848. level, or any higher level. Replaces the old term, simpl_expr and
  1849. simpl2_expr.}
  1850. var
  1851. low,high,mid : longint;
  1852. p1,p2 : Ptree;
  1853. oldt : Ttoken;
  1854. filepos : tfileposinfo;
  1855. begin
  1856. if pred_level=opmultiply then
  1857. p1:=factor(false)
  1858. else
  1859. p1:=sub_expr(succ(pred_level),true);
  1860. repeat
  1861. if (token in operator_levels[pred_level]) and
  1862. ((token<>_EQUAL) or accept_equal) then
  1863. begin
  1864. oldt:=token;
  1865. filepos:=tokenpos;
  1866. consume(token);
  1867. if pred_level=opmultiply then
  1868. p2:=factor(false)
  1869. else
  1870. p2:=sub_expr(succ(pred_level),true);
  1871. low:=1;
  1872. high:=tok2nodes;
  1873. while (low<high) do
  1874. begin
  1875. mid:=(low+high+1) shr 1;
  1876. if oldt<tok2node[mid].tok then
  1877. high:=mid-1
  1878. else
  1879. low:=mid;
  1880. end;
  1881. if tok2node[high].tok=oldt then
  1882. p1:=gennode(tok2node[high].nod,p1,p2)
  1883. else
  1884. p1:=gennode(nothingn,p1,p2);
  1885. set_tree_filepos(p1,filepos);
  1886. end
  1887. else
  1888. break;
  1889. until false;
  1890. sub_expr:=p1;
  1891. end;
  1892. function comp_expr(accept_equal : boolean):Ptree;
  1893. var
  1894. oldafterassignment : boolean;
  1895. p1 : ptree;
  1896. begin
  1897. oldafterassignment:=afterassignment;
  1898. afterassignment:=true;
  1899. p1:=sub_expr(opcompare,accept_equal);
  1900. afterassignment:=oldafterassignment;
  1901. comp_expr:=p1;
  1902. end;
  1903. function expr : ptree;
  1904. var
  1905. p1,p2 : ptree;
  1906. oldafterassignment : boolean;
  1907. oldp1 : ptree;
  1908. filepos : tfileposinfo;
  1909. begin
  1910. oldafterassignment:=afterassignment;
  1911. p1:=sub_expr(opcompare,true);
  1912. filepos:=tokenpos;
  1913. if (m_tp_procvar in aktmodeswitches) and
  1914. (token<>_ASSIGNMENT) then
  1915. check_tp_procvar(p1);
  1916. if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  1917. afterassignment:=true;
  1918. oldp1:=p1;
  1919. case token of
  1920. _POINTPOINT : begin
  1921. consume(_POINTPOINT);
  1922. p2:=sub_expr(opcompare,true);
  1923. p1:=gennode(rangen,p1,p2);
  1924. end;
  1925. _ASSIGNMENT : begin
  1926. consume(_ASSIGNMENT);
  1927. { avoid a firstpass of a procedure if
  1928. it must be assigned to a procvar }
  1929. { should be recursive for a:=b:=c !!! }
  1930. if (p1^.resulttype<>nil) and (p1^.resulttype^.deftype=procvardef) then
  1931. begin
  1932. getprocvar:=true;
  1933. getprocvardef:=pprocvardef(p1^.resulttype);
  1934. end;
  1935. p2:=sub_expr(opcompare,true);
  1936. if getprocvar then
  1937. handle_procvar(getprocvardef,p2);
  1938. getprocvar:=false;
  1939. p1:=gennode(assignn,p1,p2);
  1940. end;
  1941. { this is the code for C like assignements }
  1942. { from an improvement of Peter Schaefer }
  1943. _PLUSASN : begin
  1944. consume(_PLUSASN );
  1945. p2:=sub_expr(opcompare,true);
  1946. p1:=gennode(assignn,p1,gennode(addn,getcopy(p1),p2));
  1947. { was first
  1948. p1:=gennode(assignn,p1,gennode(addn,p1,p2));
  1949. but disposetree assumes that we have a real
  1950. *** tree *** }
  1951. end;
  1952. _MINUSASN : begin
  1953. consume(_MINUSASN );
  1954. p2:=sub_expr(opcompare,true);
  1955. p1:=gennode(assignn,p1,gennode(subn,getcopy(p1),p2));
  1956. end;
  1957. _STARASN : begin
  1958. consume(_STARASN );
  1959. p2:=sub_expr(opcompare,true);
  1960. p1:=gennode(assignn,p1,gennode(muln,getcopy(p1),p2));
  1961. end;
  1962. _SLASHASN : begin
  1963. consume(_SLASHASN );
  1964. p2:=sub_expr(opcompare,true);
  1965. p1:=gennode(assignn,p1,gennode(slashn,getcopy(p1),p2));
  1966. end;
  1967. end;
  1968. afterassignment:=oldafterassignment;
  1969. if p1<>oldp1 then
  1970. set_tree_filepos(p1,filepos);
  1971. expr:=p1;
  1972. end;
  1973. function get_intconst:longint;
  1974. {Reads an expression, tries to evalute it and check if it is an integer
  1975. constant. Then the constant is returned.}
  1976. var
  1977. p:Ptree;
  1978. begin
  1979. p:=comp_expr(true);
  1980. do_firstpass(p);
  1981. if not codegenerror then
  1982. begin
  1983. if (p^.treetype<>ordconstn) and
  1984. (p^.resulttype^.deftype=orddef) and
  1985. not(Porddef(p^.resulttype)^.typ in [uvoid,uchar,bool8bit,bool16bit,bool32bit]) then
  1986. Message(cg_e_illegal_expression)
  1987. else
  1988. get_intconst:=p^.value;
  1989. end;
  1990. disposetree(p);
  1991. end;
  1992. function get_stringconst:string;
  1993. {Reads an expression, tries to evaluate it and checks if it is a string
  1994. constant. Then the constant is returned.}
  1995. var
  1996. p:Ptree;
  1997. begin
  1998. get_stringconst:='';
  1999. p:=comp_expr(true);
  2000. do_firstpass(p);
  2001. if p^.treetype<>stringconstn then
  2002. begin
  2003. if (p^.treetype=ordconstn) and is_char(p^.resulttype) then
  2004. get_stringconst:=char(p^.value)
  2005. else
  2006. Message(cg_e_illegal_expression);
  2007. end
  2008. else
  2009. get_stringconst:=strpas(p^.value_str);
  2010. disposetree(p);
  2011. end;
  2012. end.
  2013. {
  2014. $Log$
  2015. Revision 1.159 1999-11-15 17:52:59 pierre
  2016. + one field added for ttoken record for operator
  2017. linking the id to the corresponding operator token that
  2018. can now now all be overloaded
  2019. * overloaded operators are resetted to nil in InitSymtable
  2020. (bug when trying to compile a uint that overloads operators twice)
  2021. Revision 1.158 1999/11/14 15:57:35 peter
  2022. * fixed crash with an errordef
  2023. Revision 1.157 1999/11/08 14:02:16 florian
  2024. * problem with "index X"-properties solved
  2025. * typed constants of class references are now allowed
  2026. Revision 1.156 1999/11/07 23:21:30 florian
  2027. * previous fix for 517 was imcomplete: there was a problem if the property
  2028. had only an index
  2029. Revision 1.155 1999/11/07 23:16:49 florian
  2030. * finally bug 517 solved ...
  2031. Revision 1.154 1999/11/06 14:34:21 peter
  2032. * truncated log to 20 revs
  2033. Revision 1.153 1999/11/05 00:10:30 peter
  2034. * fixed inherited with properties
  2035. Revision 1.152 1999/10/27 16:06:19 peter
  2036. * check for object in extended new
  2037. Revision 1.151 1999/10/26 12:30:44 peter
  2038. * const parameter is now checked
  2039. * better and generic check if a node can be used for assigning
  2040. * export fixes
  2041. * procvar equal works now (it never had worked at least from 0.99.8)
  2042. * defcoll changed to linkedlist with pparaitem so it can easily be
  2043. walked both directions
  2044. Revision 1.150 1999/10/22 14:37:30 peter
  2045. * error when properties are passed to var parameters
  2046. Revision 1.149 1999/10/22 10:39:34 peter
  2047. * split type reading from pdecl to ptype unit
  2048. * parameter_dec routine is now used for procedure and procvars
  2049. Revision 1.148 1999/10/14 14:57:52 florian
  2050. - removed the hcodegen use in the new cg, use cgbase instead
  2051. Revision 1.147 1999/09/28 11:03:54 peter
  2052. * fixed result access in 'if result = XXX then'
  2053. * fixed const cr=chr(13)
  2054. Revision 1.146 1999/09/27 23:44:54 peter
  2055. * procinfo is now a pointer
  2056. * support for result setting in sub procedure
  2057. Revision 1.145 1999/09/27 11:59:42 peter
  2058. * fix for pointer reading in const with @type.method
  2059. Revision 1.144 1999/09/26 21:30:19 peter
  2060. + constant pointer support which can happend with typecasting like
  2061. const p=pointer(1)
  2062. * better procvar parsing in typed consts
  2063. Revision 1.143 1999/09/15 20:35:41 florian
  2064. * small fix to operator overloading when in MMX mode
  2065. + the compiler uses now fldz and fld1 if possible
  2066. + some fixes to floating point registers
  2067. + some math. functions (arctan, ln, sin, cos, sqrt, sqr, pi) are now inlined
  2068. * .... ???
  2069. Revision 1.142 1999/09/13 16:26:32 peter
  2070. * fix crash with empty object as childs
  2071. Revision 1.141 1999/09/11 19:47:26 florian
  2072. * bug fix for @tobject.method, fixes bug 557, 605 and 606
  2073. Revision 1.140 1999/09/11 09:08:33 florian
  2074. * fixed bug 596
  2075. * fixed some problems with procedure variables and procedures of object,
  2076. especially in TP mode. Procedure of object doesn't apply only to classes,
  2077. it is also allowed for objects !!
  2078. Revision 1.139 1999/09/10 18:48:07 florian
  2079. * some bug fixes (e.g. must_be_valid and procinfo^.funcret_is_valid)
  2080. * most things for stored properties fixed
  2081. Revision 1.138 1999/09/07 08:01:20 peter
  2082. * @(<x>) support
  2083. Revision 1.137 1999/09/01 22:08:58 peter
  2084. * fixed crash with assigned()
  2085. Revision 1.136 1999/08/15 22:47:45 peter
  2086. * fixed property writeaccess which was buggy after my previous
  2087. subscribed property access
  2088. Revision 1.135 1999/08/14 00:38:56 peter
  2089. * hack to support property with record fields
  2090. Revision 1.134 1999/08/09 22:16:29 peter
  2091. * fixed crash after wrong para's with class contrustor
  2092. }