pexpr.pas 84 KB

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