pexpr.pas 84 KB

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