pexpr.pas 84 KB

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