pexpr.pas 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652
  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. hcodegen,types,verbose,strings,
  38. {$ifndef newcg}
  39. tccal,
  40. {$endif newcg}
  41. pass_1,
  42. { parser specific stuff }
  43. pbase,pdecl,
  44. { processor specific stuff }
  45. cpubase,cpuinfo;
  46. const
  47. allow_type : boolean = true;
  48. got_addrn : boolean = false;
  49. function parse_paras(__colon,in_prop_paras : boolean) : ptree;
  50. var
  51. p1,p2 : ptree;
  52. end_of_paras : ttoken;
  53. begin
  54. if in_prop_paras then
  55. end_of_paras:=_RECKKLAMMER
  56. else
  57. end_of_paras:=_RKLAMMER;
  58. if token=end_of_paras then
  59. begin
  60. parse_paras:=nil;
  61. exit;
  62. end;
  63. p2:=nil;
  64. inc(parsing_para_level);
  65. while true do
  66. begin
  67. p1:=comp_expr(true);
  68. p2:=gencallparanode(p1,p2);
  69. { it's for the str(l:5,s); }
  70. if __colon and (token=_COLON) then
  71. begin
  72. consume(_COLON);
  73. p1:=comp_expr(true);
  74. p2:=gencallparanode(p1,p2);
  75. p2^.is_colon_para:=true;
  76. if token=_COLON then
  77. begin
  78. consume(_COLON);
  79. p1:=comp_expr(true);
  80. p2:=gencallparanode(p1,p2);
  81. p2^.is_colon_para:=true;
  82. end
  83. end;
  84. if token=_COMMA then
  85. consume(_COMMA)
  86. else
  87. break;
  88. end;
  89. dec(parsing_para_level);
  90. parse_paras:=p2;
  91. end;
  92. procedure check_tp_procvar(var p : ptree);
  93. var
  94. p1 : ptree;
  95. Store_valid : boolean;
  96. begin
  97. if (m_tp_procvar in aktmodeswitches) and
  98. (not got_addrn) and
  99. (not in_args) and
  100. (p^.treetype=loadn) then
  101. begin
  102. { support if procvar then for tp7 and many other expression like this }
  103. Store_valid:=Must_be_valid;
  104. Must_be_valid:=false;
  105. do_firstpass(p);
  106. Must_be_valid:=Store_valid;
  107. if not(getprocvar) and (p^.resulttype^.deftype=procvardef) then
  108. begin
  109. p1:=gencallnode(nil,nil);
  110. p1^.right:=p;
  111. p1^.resulttype:=pprocvardef(p^.resulttype)^.retdef;
  112. firstpass(p1);
  113. p:=p1;
  114. end;
  115. end;
  116. end;
  117. function statement_syssym(l : longint;var pd : pdef) : ptree;
  118. var
  119. p1,p2,paras : ptree;
  120. prev_in_args : boolean;
  121. Store_valid : boolean;
  122. begin
  123. prev_in_args:=in_args;
  124. Store_valid:=Must_be_valid;
  125. case l of
  126. in_ord_x :
  127. begin
  128. consume(_LKLAMMER);
  129. in_args:=true;
  130. Must_be_valid:=true;
  131. p1:=comp_expr(true);
  132. consume(_RKLAMMER);
  133. do_firstpass(p1);
  134. p1:=geninlinenode(in_ord_x,false,p1);
  135. do_firstpass(p1);
  136. statement_syssym := p1;
  137. pd:=p1^.resulttype;
  138. end;
  139. in_break :
  140. begin
  141. statement_syssym:=genzeronode(breakn);
  142. pd:=voiddef;
  143. end;
  144. in_continue :
  145. begin
  146. statement_syssym:=genzeronode(continuen);
  147. pd:=voiddef;
  148. end;
  149. in_typeof_x :
  150. begin
  151. consume(_LKLAMMER);
  152. in_args:=true;
  153. {allow_type:=true;}
  154. p1:=comp_expr(true);
  155. {allow_type:=false;}
  156. consume(_RKLAMMER);
  157. pd:=voidpointerdef;
  158. if p1^.treetype=typen then
  159. begin
  160. if (p1^.typenodetype=nil) then
  161. begin
  162. Message(type_e_mismatch);
  163. statement_syssym:=genzeronode(errorn);
  164. end
  165. else
  166. if p1^.typenodetype^.deftype=objectdef then
  167. begin
  168. { we can use resulttype in pass_2 (PM) }
  169. p1^.resulttype:=p1^.typenodetype;
  170. statement_syssym:=geninlinenode(in_typeof_x,false,p1);
  171. end
  172. else
  173. begin
  174. Message(type_e_mismatch);
  175. disposetree(p1);
  176. statement_syssym:=genzeronode(errorn);
  177. end;
  178. end
  179. else { not a type node }
  180. begin
  181. Must_be_valid:=false;
  182. do_firstpass(p1);
  183. if (p1^.resulttype=nil) then
  184. begin
  185. Message(type_e_mismatch);
  186. disposetree(p1);
  187. statement_syssym:=genzeronode(errorn)
  188. end
  189. else
  190. if p1^.resulttype^.deftype=objectdef then
  191. statement_syssym:=geninlinenode(in_typeof_x,false,p1)
  192. else
  193. begin
  194. Message(type_e_mismatch);
  195. statement_syssym:=genzeronode(errorn);
  196. disposetree(p1);
  197. end;
  198. end;
  199. end;
  200. in_sizeof_x :
  201. begin
  202. consume(_LKLAMMER);
  203. in_args:=true;
  204. {allow_type:=true;}
  205. p1:=comp_expr(true);
  206. {allow_type:=false; }
  207. consume(_RKLAMMER);
  208. pd:=s32bitdef;
  209. if p1^.treetype=typen then
  210. begin
  211. statement_syssym:=genordinalconstnode(p1^.typenodetype^.size,pd);
  212. { p1 not needed !}
  213. disposetree(p1);
  214. end
  215. else
  216. begin
  217. Must_be_valid:=false;
  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. Must_be_valid:=true;
  238. do_firstpass(p1);
  239. if not codegenerror then
  240. begin
  241. case p1^.resulttype^.deftype of
  242. pointerdef,
  243. procvardef,
  244. classrefdef : ;
  245. objectdef :
  246. if not(pobjectdef(p1^.resulttype)^.is_class) then
  247. Message(parser_e_illegal_parameter_list);
  248. else
  249. Message(parser_e_illegal_parameter_list);
  250. end;
  251. end;
  252. p2:=gencallparanode(p1,nil);
  253. p2:=geninlinenode(in_assigned_x,false,p2);
  254. consume(_RKLAMMER);
  255. pd:=booldef;
  256. statement_syssym:=p2;
  257. end;
  258. in_ofs_x :
  259. begin
  260. consume(_LKLAMMER);
  261. in_args:=true;
  262. p1:=comp_expr(true);
  263. p1:=gensinglenode(addrn,p1);
  264. Must_be_valid:=false;
  265. do_firstpass(p1);
  266. { Ofs() returns a longint, not a pointer }
  267. p1^.resulttype:=u32bitdef;
  268. pd:=p1^.resulttype;
  269. consume(_RKLAMMER);
  270. statement_syssym:=p1;
  271. end;
  272. in_addr_x :
  273. begin
  274. consume(_LKLAMMER);
  275. in_args:=true;
  276. p1:=comp_expr(true);
  277. p1:=gensinglenode(addrn,p1);
  278. Must_be_valid:=false;
  279. do_firstpass(p1);
  280. pd:=p1^.resulttype;
  281. consume(_RKLAMMER);
  282. statement_syssym:=p1;
  283. end;
  284. in_seg_x :
  285. begin
  286. consume(_LKLAMMER);
  287. in_args:=true;
  288. p1:=comp_expr(true);
  289. do_firstpass(p1);
  290. if p1^.location.loc<>LOC_REFERENCE then
  291. Message(cg_e_illegal_expression);
  292. p1:=genordinalconstnode(0,s32bitdef);
  293. Must_be_valid:=false;
  294. pd:=s32bitdef;
  295. consume(_RKLAMMER);
  296. statement_syssym:=p1;
  297. end;
  298. in_high_x,
  299. in_low_x :
  300. begin
  301. consume(_LKLAMMER);
  302. in_args:=true;
  303. {allow_type:=true;}
  304. p1:=comp_expr(true);
  305. {allow_type:=false;}
  306. do_firstpass(p1);
  307. if p1^.treetype=typen then
  308. p1^.resulttype:=p1^.typenodetype;
  309. Must_be_valid:=false;
  310. p2:=geninlinenode(l,false,p1);
  311. consume(_RKLAMMER);
  312. pd:=s32bitdef;
  313. statement_syssym:=p2;
  314. end;
  315. in_succ_x,
  316. in_pred_x :
  317. begin
  318. consume(_LKLAMMER);
  319. in_args:=true;
  320. p1:=comp_expr(true);
  321. do_firstpass(p1);
  322. Must_be_valid:=false;
  323. p2:=geninlinenode(l,false,p1);
  324. consume(_RKLAMMER);
  325. pd:=p1^.resulttype;
  326. statement_syssym:=p2;
  327. end;
  328. in_inc_x,
  329. in_dec_x :
  330. begin
  331. consume(_LKLAMMER);
  332. in_args:=true;
  333. p1:=comp_expr(true);
  334. Must_be_valid:=false;
  335. if token=_COMMA then
  336. begin
  337. consume(_COMMA);
  338. p2:=gencallparanode(comp_expr(true),nil);
  339. end
  340. else
  341. p2:=nil;
  342. p2:=gencallparanode(p1,p2);
  343. statement_syssym:=geninlinenode(l,false,p2);
  344. consume(_RKLAMMER);
  345. pd:=voiddef;
  346. end;
  347. in_concat_x :
  348. begin
  349. consume(_LKLAMMER);
  350. in_args:=true;
  351. p2:=nil;
  352. while true do
  353. begin
  354. p1:=comp_expr(true);
  355. Must_be_valid:=true;
  356. do_firstpass(p1);
  357. if not((p1^.resulttype^.deftype=stringdef) or
  358. ((p1^.resulttype^.deftype=orddef) and
  359. (porddef(p1^.resulttype)^.typ=uchar))) then
  360. Message(parser_e_illegal_parameter_list);
  361. if p2<>nil then
  362. p2:=gennode(addn,p2,p1)
  363. else
  364. p2:=p1;
  365. if token=_COMMA then
  366. consume(_COMMA)
  367. else
  368. break;
  369. end;
  370. consume(_RKLAMMER);
  371. pd:=cshortstringdef;
  372. statement_syssym:=p2;
  373. end;
  374. in_read_x,
  375. in_readln_x :
  376. begin
  377. if token=_LKLAMMER then
  378. begin
  379. consume(_LKLAMMER);
  380. in_args:=true;
  381. Must_be_valid:=false;
  382. paras:=parse_paras(false,false);
  383. consume(_RKLAMMER);
  384. end
  385. else
  386. paras:=nil;
  387. pd:=voiddef;
  388. p1:=geninlinenode(l,false,paras);
  389. do_firstpass(p1);
  390. statement_syssym := p1;
  391. end;
  392. in_write_x,
  393. in_writeln_x :
  394. begin
  395. if token=_LKLAMMER then
  396. begin
  397. consume(_LKLAMMER);
  398. in_args:=true;
  399. Must_be_valid:=true;
  400. paras:=parse_paras(true,false);
  401. consume(_RKLAMMER);
  402. end
  403. else
  404. paras:=nil;
  405. pd:=voiddef;
  406. p1 := geninlinenode(l,false,paras);
  407. do_firstpass(p1);
  408. statement_syssym := p1;
  409. end;
  410. in_str_x_string :
  411. begin
  412. consume(_LKLAMMER);
  413. in_args:=true;
  414. paras:=parse_paras(true,false);
  415. consume(_RKLAMMER);
  416. p1 := geninlinenode(l,false,paras);
  417. do_firstpass(p1);
  418. statement_syssym := p1;
  419. pd:=voiddef;
  420. end;
  421. in_val_x:
  422. Begin
  423. consume(_LKLAMMER);
  424. in_args := true;
  425. p1:= gencallparanode(comp_expr(true), nil);
  426. Must_be_valid := False;
  427. consume(_COMMA);
  428. p2 := gencallparanode(comp_expr(true),p1);
  429. if (token = _COMMA) then
  430. Begin
  431. consume(_COMMA);
  432. p2 := gencallparanode(comp_expr(true),p2)
  433. End;
  434. consume(_RKLAMMER);
  435. p2 := geninlinenode(l,false,p2);
  436. do_firstpass(p2);
  437. statement_syssym := p2;
  438. pd := voiddef;
  439. End;
  440. in_include_x_y,
  441. in_exclude_x_y :
  442. begin
  443. consume(_LKLAMMER);
  444. in_args:=true;
  445. p1:=comp_expr(true);
  446. Must_be_valid:=false;
  447. consume(_COMMA);
  448. p2:=comp_expr(true);
  449. statement_syssym:=geninlinenode(l,false,gencallparanode(p1,gencallparanode(p2,nil)));
  450. consume(_RKLAMMER);
  451. pd:=voiddef;
  452. end;
  453. in_assert_x_y :
  454. begin
  455. consume(_LKLAMMER);
  456. in_args:=true;
  457. p1:=comp_expr(true);
  458. if token=_COMMA then
  459. begin
  460. consume(_COMMA);
  461. p2:=comp_expr(true);
  462. end
  463. else
  464. begin
  465. { then insert an empty string }
  466. p2:=genstringconstnode('');
  467. end;
  468. statement_syssym:=geninlinenode(l,false,gencallparanode(p1,gencallparanode(p2,nil)));
  469. consume(_RKLAMMER);
  470. pd:=voiddef;
  471. end;
  472. else
  473. internalerror(15);
  474. end;
  475. in_args:=prev_in_args;
  476. Must_be_valid:=Store_valid;
  477. end;
  478. { reads the parameter for a subroutine call }
  479. procedure do_proc_call(getaddr : boolean;var again : boolean;var p1:Ptree;var pd:Pdef);
  480. var
  481. prev_in_args : boolean;
  482. prevafterassn : boolean;
  483. Store_valid : boolean;
  484. begin
  485. prev_in_args:=in_args;
  486. prevafterassn:=afterassignment;
  487. afterassignment:=false;
  488. { want we only determine the address of }
  489. { a subroutine ? }
  490. if not(getaddr) then
  491. begin
  492. if token=_LKLAMMER then
  493. begin
  494. consume(_LKLAMMER);
  495. in_args:=true;
  496. p1^.left:=parse_paras(false,false);
  497. consume(_RKLAMMER);
  498. end
  499. else p1^.left:=nil;
  500. { do firstpass because we need the }
  501. { result type }
  502. Store_valid:=Must_be_valid;
  503. Must_be_valid:=false;
  504. do_firstpass(p1);
  505. Must_be_valid:=Store_valid;
  506. end
  507. else
  508. begin
  509. { address operator @: }
  510. p1^.left:=nil;
  511. { forget pd }
  512. pd:=nil;
  513. if (p1^.symtableproc^.symtabletype=withsymtable) and
  514. (p1^.symtableproc^.defowner^.deftype=objectdef) then
  515. begin
  516. p1^.methodpointer:=getcopy(pwithsymtable(p1^.symtableproc)^.withrefnode);
  517. end
  518. else if not(assigned(p1^.methodpointer)) then
  519. begin
  520. { we must provide a method pointer, if it isn't given, }
  521. { it is self }
  522. p1^.methodpointer:=genselfnode(procinfo._class);
  523. p1^.methodpointer^.resulttype:=procinfo._class;
  524. end;
  525. { no postfix operators }
  526. again:=false;
  527. end;
  528. pd:=p1^.resulttype;
  529. in_args:=prev_in_args;
  530. afterassignment:=prevafterassn;
  531. end;
  532. procedure handle_procvar(procvar : pprocvardef;var t : ptree);
  533. var
  534. hp : ptree;
  535. begin
  536. hp:=nil;
  537. if (proc_to_procvar_equal(pprocsym(t^.symtableentry)^.definition,procvar)) then
  538. begin
  539. if (po_methodpointer in procvar^.procoptions) then
  540. hp:=genloadmethodcallnode(pprocsym(t^.symtableprocentry),t^.symtable,getcopy(t^.methodpointer))
  541. else
  542. hp:=genloadcallnode(pprocsym(t^.symtableprocentry),t^.symtable);
  543. end;
  544. if assigned(hp) then
  545. begin
  546. disposetree(t);
  547. t:=hp;
  548. end;
  549. end;
  550. { the following procedure handles the access to a property symbol }
  551. procedure handle_propertysym(sym : psym;st : psymtable;var p1 : ptree;
  552. var pd : pdef);
  553. var
  554. paras : ptree;
  555. p2 : ptree;
  556. plist : ppropsymlist;
  557. begin
  558. paras:=nil;
  559. { property parameters? }
  560. if token=_LECKKLAMMER then
  561. begin
  562. consume(_LECKKLAMMER);
  563. paras:=parse_paras(false,true);
  564. consume(_RECKKLAMMER);
  565. end;
  566. { indexed property }
  567. if (ppo_indexed in ppropertysym(sym)^.propoptions) then
  568. begin
  569. p2:=genordinalconstnode(ppropertysym(sym)^.index,s32bitdef);
  570. paras:=gencallparanode(p2,paras);
  571. end;
  572. { we need only a write property if a := follows }
  573. { if not(afterassignment) and not(in_args) then }
  574. if token=_ASSIGNMENT then
  575. begin
  576. { write property: }
  577. { no result }
  578. pd:=voiddef;
  579. if assigned(ppropertysym(sym)^.writeaccesssym) then
  580. begin
  581. case ppropertysym(sym)^.writeaccesssym^.sym^.typ of
  582. procsym :
  583. begin
  584. { generate the method call }
  585. p1:=genmethodcallnode(pprocsym(ppropertysym(sym)^.writeaccesssym^.sym),st,p1);
  586. { we know the procedure to call, so
  587. force the usage of that procedure }
  588. p1^.procdefinition:=pprocdef(ppropertysym(sym)^.writeaccessdef);
  589. p1^.left:=paras;
  590. consume(_ASSIGNMENT);
  591. { read the expression }
  592. getprocvar:=ppropertysym(sym)^.proptype^.deftype=procvardef;
  593. p2:=comp_expr(true);
  594. if getprocvar then
  595. begin
  596. if (p2^.treetype=calln) then
  597. handle_procvar(pprocvardef(ppropertysym(sym)^.proptype),p2)
  598. else
  599. if (p2^.treetype=typeconvn) and
  600. (p2^.left^.treetype=calln) then
  601. handle_procvar(pprocvardef(ppropertysym(sym)^.proptype),p2^.left);
  602. end;
  603. p1^.left:=gencallparanode(p2,p1^.left);
  604. getprocvar:=false;
  605. end;
  606. varsym :
  607. begin
  608. if assigned(paras) then
  609. message(parser_e_no_paras_allowed);
  610. { subscribed access? }
  611. plist:=ppropertysym(sym)^.writeaccesssym;
  612. while assigned(plist) do
  613. begin
  614. if p1=nil then
  615. p1:=genloadnode(pvarsym(plist^.sym),st)
  616. else
  617. p1:=gensubscriptnode(pvarsym(plist^.sym),p1);
  618. plist:=plist^.next;
  619. end;
  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;
  642. if assigned(ppropertysym(sym)^.readaccesssym) then
  643. begin
  644. case ppropertysym(sym)^.readaccesssym^.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)^.readaccesssym;
  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. end;
  660. procsym :
  661. begin
  662. { generate the method call }
  663. p1:=genmethodcallnode(pprocsym(ppropertysym(sym)^.readaccesssym^.sym),st,p1);
  664. { we know the procedure to call, so
  665. force the usage of that procedure }
  666. p1^.procdefinition:=pprocdef(ppropertysym(sym)^.readaccessdef);
  667. { insert paras }
  668. p1^.left:=paras;
  669. end
  670. else
  671. begin
  672. p1:=genzeronode(errorn);
  673. Message(type_e_mismatch);
  674. end;
  675. end;
  676. end
  677. else
  678. begin
  679. { error, no function to read property }
  680. p1:=genzeronode(errorn);
  681. Message(parser_e_no_procedure_to_access_property);
  682. end;
  683. end;
  684. end;
  685. { the ID token has to be consumed before calling this function }
  686. procedure do_member_read(getaddr : boolean;const sym : psym;var p1 : ptree;
  687. var pd : pdef;var again : boolean);
  688. var
  689. static_name : string;
  690. isclassref : boolean;
  691. begin
  692. if sym=nil then
  693. begin
  694. { pattern is still valid unless
  695. there is another ID just after the ID of sym }
  696. Message1(sym_e_id_no_member,pattern);
  697. disposetree(p1);
  698. p1:=genzeronode(errorn);
  699. { try to clean up }
  700. pd:=generrordef;
  701. again:=false;
  702. end
  703. else
  704. begin
  705. isclassref:=pd^.deftype=classrefdef;
  706. { check protected and private members }
  707. { please leave this code as it is, }
  708. { it has now the same behaviaor as TP/Delphi }
  709. if (sp_private in sym^.symoptions) and
  710. (pobjectdef(pd)^.owner^.symtabletype=unitsymtable) then
  711. Message(parser_e_cant_access_private_member);
  712. if (sp_protected in sym^.symoptions) and
  713. (pobjectdef(pd)^.owner^.symtabletype=unitsymtable) then
  714. begin
  715. if assigned(aktprocsym^.definition^._class) then
  716. begin
  717. if not aktprocsym^.definition^._class^.is_related(pobjectdef(sym^.owner^.defowner)) then
  718. Message(parser_e_cant_access_protected_member);
  719. end
  720. else
  721. Message(parser_e_cant_access_protected_member);
  722. end;
  723. { we assume, that only procsyms and varsyms are in an object }
  724. { symbol table, for classes, properties are allowed }
  725. case sym^.typ of
  726. procsym:
  727. begin
  728. p1:=genmethodcallnode(pprocsym(sym),srsymtable,p1);
  729. do_proc_call(getaddr or
  730. (getprocvar and
  731. (m_tp_procvar in aktmodeswitches) and
  732. proc_to_procvar_equal(pprocsym(sym)^.definition,getprocvardef))
  733. ,again,p1,pd);
  734. { now we know the real method e.g. we can check for a class method }
  735. if isclassref and
  736. assigned(p1^.procdefinition) and
  737. not(po_classmethod in p1^.procdefinition^.procoptions) and
  738. not(p1^.procdefinition^.proctypeoption=potype_constructor) then
  739. Message(parser_e_only_class_methods_via_class_ref);
  740. end;
  741. varsym:
  742. begin
  743. if isclassref then
  744. Message(parser_e_only_class_methods_via_class_ref);
  745. if (sp_static in sym^.symoptions) then
  746. begin
  747. { static_name:=lower(srsymtable^.name^)+'_'+sym^.name;
  748. this is wrong for static field in with symtable (PM) }
  749. static_name:=lower(srsym^.owner^.name^)+'_'+sym^.name;
  750. getsym(static_name,true);
  751. disposetree(p1);
  752. p1:=genloadnode(pvarsym(srsym),srsymtable);
  753. end
  754. else
  755. p1:=gensubscriptnode(pvarsym(sym),p1);
  756. pd:=pvarsym(sym)^.definition;
  757. end;
  758. propertysym:
  759. begin
  760. if isclassref then
  761. Message(parser_e_only_class_methods_via_class_ref);
  762. handle_propertysym(sym,srsymtable,p1,pd);
  763. end;
  764. else internalerror(16);
  765. end;
  766. end;
  767. end;
  768. {****************************************************************************
  769. Factor
  770. ****************************************************************************}
  771. function factor(getaddr : boolean) : ptree;
  772. var
  773. l : longint;
  774. oldp1,
  775. p1,p2,p3 : ptree;
  776. code : integer;
  777. pd,pd2 : pdef;
  778. possible_error,
  779. unit_specific,
  780. again : boolean;
  781. sym : pvarsym;
  782. classh : pobjectdef;
  783. d : bestreal;
  784. static_name : string;
  785. propsym : ppropertysym;
  786. filepos : tfileposinfo;
  787. {---------------------------------------------
  788. Is_func_ret
  789. ---------------------------------------------}
  790. function is_func_ret(sym : psym) : boolean;
  791. var
  792. p : pprocinfo;
  793. storesymtablestack : psymtable;
  794. begin
  795. is_func_ret:=false;
  796. if (sym^.typ<>funcretsym) and ((procinfo.flags and pi_operator)=0) then
  797. exit;
  798. p:=@procinfo;
  799. while system.assigned(p) do
  800. begin
  801. { is this an access to a function result ? }
  802. if assigned(p^.funcretsym) and
  803. ((pfuncretsym(sym)=p^.funcretsym) or
  804. ((pvarsym(sym)=opsym) and
  805. ((p^.flags and pi_operator)<>0))) and
  806. (p^.retdef<>pdef(voiddef)) and
  807. (token<>_LKLAMMER) and
  808. (not ((m_tp in aktmodeswitches) and
  809. (afterassignment or in_args))) then
  810. begin
  811. if ((pvarsym(sym)=opsym) and
  812. ((p^.flags and pi_operator)<>0)) then
  813. inc(opsym^.refs);
  814. if ((pvarsym(sym)=opsym) and
  815. ((p^.flags and pi_operator)<>0)) then
  816. inc(opsym^.refs);
  817. p1:=genzeronode(funcretn);
  818. pd:=p^.retdef;
  819. p1^.funcretprocinfo:=p;
  820. p1^.retdef:=pd;
  821. is_func_ret:=true;
  822. exit;
  823. end;
  824. p:=p^.parent;
  825. end;
  826. { we must use the function call }
  827. if(sym^.typ=funcretsym) then
  828. begin
  829. storesymtablestack:=symtablestack;
  830. symtablestack:=srsymtable^.next;
  831. getsym(sym^.name,true);
  832. if srsym^.typ<>procsym then
  833. Message(cg_e_illegal_expression);
  834. symtablestack:=storesymtablestack;
  835. end;
  836. end;
  837. {---------------------------------------------
  838. Factor_read_id
  839. ---------------------------------------------}
  840. procedure factor_read_id;
  841. var
  842. pc : pchar;
  843. len : longint;
  844. begin
  845. { allow post fix operators }
  846. again:=true;
  847. if (m_result in aktmodeswitches) and
  848. (idtoken=_RESULT) and
  849. assigned(aktprocsym) and
  850. (procinfo.retdef<>pdef(voiddef)) then
  851. begin
  852. consume(_ID);
  853. p1:=genzeronode(funcretn);
  854. pd:=procinfo.retdef;
  855. p1^.funcretprocinfo:=pointer(@procinfo);
  856. p1^.retdef:=pd;
  857. end
  858. else
  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)^.definition;
  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_declared2;
  920. end;
  921. pd:=pvarsym(srsym)^.definition;
  922. end;
  923. typedconstsym : begin
  924. p1:=gentypedconstloadnode(ptypedconstsym(srsym),srsymtable);
  925. pd:=ptypedconstsym(srsym)^.definition;
  926. end;
  927. syssym : p1:=statement_syssym(psyssym(srsym)^.number,pd);
  928. typesym : begin
  929. pd:=ptypesym(srsym)^.definition;
  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 (pd^.owner^.unitid=0) or
  946. (pd^.owner^.unitid=1) then
  947. p1:=gentypenode(pd,nil)
  948. else
  949. p1:=gentypenode(pd,ptypesym(srsym));
  950. { here we can also set resulttype !! }
  951. p1^.resulttype:=pd;
  952. pd:=voiddef;
  953. end
  954. else { not type block }
  955. begin
  956. if token=_LKLAMMER then
  957. begin
  958. consume(_LKLAMMER);
  959. p1:=comp_expr(true);
  960. consume(_RKLAMMER);
  961. p1:=gentypeconvnode(p1,pd);
  962. p1^.explizit:=true;
  963. end
  964. else { not LKLAMMER}
  965. if (token=_POINT) and
  966. (pd^.deftype=objectdef) and
  967. not(pobjectdef(pd)^.is_class) then
  968. begin
  969. consume(_POINT);
  970. if assigned(procinfo._class) then
  971. begin
  972. if procinfo._class^.is_related(pobjectdef(pd)) then
  973. begin
  974. p1:=gentypenode(pd,ptypesym(srsym));
  975. p1^.resulttype:=pd;
  976. srsymtable:=pobjectdef(pd)^.symtable;
  977. sym:=pvarsym(srsymtable^.search(pattern));
  978. { search also in inherited methods }
  979. while sym=nil do
  980. begin
  981. pd:=pobjectdef(pd)^.childof;
  982. srsymtable:=pobjectdef(pd)^.symtable;
  983. sym:=pvarsym(srsymtable^.search(pattern));
  984. end;
  985. consume(_ID);
  986. do_member_read(false,sym,p1,pd,again);
  987. end
  988. else
  989. begin
  990. Message(parser_e_no_super_class);
  991. pd:=generrordef;
  992. again:=false;
  993. end;
  994. end
  995. else
  996. begin
  997. { allows @TObject.Load }
  998. { also allows static methods and variables }
  999. p1:=genzeronode(typen);
  1000. p1^.resulttype:=pd;
  1001. { srsymtable:=pobjectdef(pd)^.symtable;
  1002. sym:=pvarsym(srsymtable^.search(pattern)); }
  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)^.consttype 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)^.definition));
  1074. constord :
  1075. p1:=genordinalconstnode(pconstsym(srsym)^.value,
  1076. pconstsym(srsym)^.definition);
  1077. constnil :
  1078. p1:=genzeronode(niln);
  1079. constresourcestring:
  1080. begin
  1081. p1:=genloadnode(pvarsym(srsym),srsymtable);
  1082. p1^.resulttype:=cansistringdef;
  1083. end;
  1084. end;
  1085. pd:=p1^.resulttype;
  1086. end;
  1087. procsym : begin
  1088. { are we in a class method ? }
  1089. possible_error:=(srsymtable^.symtabletype=objectsymtable) and
  1090. assigned(aktprocsym) and
  1091. (po_classmethod in aktprocsym^.definition^.procoptions);
  1092. p1:=gencallnode(pprocsym(srsym),srsymtable);
  1093. p1^.unit_specific:=unit_specific;
  1094. do_proc_call(getaddr or
  1095. (getprocvar and
  1096. (m_tp_procvar in aktmodeswitches) and
  1097. proc_to_procvar_equal(pprocsym(srsym)^.definition,getprocvardef)),
  1098. again,p1,pd);
  1099. if possible_error and
  1100. not(po_classmethod in p1^.procdefinition^.procoptions) then
  1101. Message(parser_e_only_class_methods);
  1102. end;
  1103. propertysym : begin
  1104. { access to property in a method }
  1105. { are we in a class method ? }
  1106. if (srsymtable^.symtabletype=objectsymtable) and
  1107. assigned(aktprocsym) and
  1108. (po_classmethod in aktprocsym^.definition^.procoptions) then
  1109. Message(parser_e_only_class_methods);
  1110. { no method pointer }
  1111. p1:=nil;
  1112. handle_propertysym(srsym,srsymtable,p1,pd);
  1113. end;
  1114. errorsym : begin
  1115. p1:=genzeronode(errorn);
  1116. p1^.resulttype:=generrordef;
  1117. pd:=generrordef;
  1118. if token=_LKLAMMER then
  1119. begin
  1120. consume(_LKLAMMER);
  1121. parse_paras(false,false);
  1122. consume(_RKLAMMER);
  1123. end;
  1124. end;
  1125. else
  1126. begin
  1127. p1:=genzeronode(errorn);
  1128. pd:=generrordef;
  1129. Message(cg_e_illegal_expression);
  1130. end;
  1131. end; { end case }
  1132. end;
  1133. end;
  1134. end;
  1135. end;
  1136. {---------------------------------------------
  1137. Factor_Read_Set
  1138. ---------------------------------------------}
  1139. { Read a set between [] }
  1140. function factor_read_set:ptree;
  1141. var
  1142. p1,
  1143. lastp,
  1144. buildp : ptree;
  1145. begin
  1146. buildp:=nil;
  1147. { be sure that a least one arrayconstructn is used, also for an
  1148. empty [] }
  1149. if token=_RECKKLAMMER then
  1150. buildp:=gennode(arrayconstructn,nil,buildp)
  1151. else
  1152. begin
  1153. while true do
  1154. begin
  1155. p1:=comp_expr(true);
  1156. if token=_POINTPOINT then
  1157. begin
  1158. consume(_POINTPOINT);
  1159. p2:=comp_expr(true);
  1160. p1:=gennode(arrayconstructrangen,p1,p2);
  1161. end;
  1162. { insert at the end of the tree, to get the correct order }
  1163. if not assigned(buildp) then
  1164. begin
  1165. buildp:=gennode(arrayconstructn,p1,nil);
  1166. lastp:=buildp;
  1167. end
  1168. else
  1169. begin
  1170. lastp^.right:=gennode(arrayconstructn,p1,nil);
  1171. lastp:=lastp^.right;
  1172. end;
  1173. { there could be more elements }
  1174. if token=_COMMA then
  1175. consume(_COMMA)
  1176. else
  1177. break;
  1178. end;
  1179. end;
  1180. factor_read_set:=buildp;
  1181. end;
  1182. {---------------------------------------------
  1183. Helpers
  1184. ---------------------------------------------}
  1185. procedure check_tokenpos;
  1186. begin
  1187. if (p1<>oldp1) then
  1188. begin
  1189. if assigned(p1) then
  1190. set_tree_filepos(p1,filepos);
  1191. oldp1:=p1;
  1192. filepos:=tokenpos;
  1193. end;
  1194. end;
  1195. {---------------------------------------------
  1196. PostFixOperators
  1197. ---------------------------------------------}
  1198. procedure postfixoperators;
  1199. var
  1200. store_static : boolean;
  1201. { p1 and p2 must contain valid value_str }
  1202. begin
  1203. check_tokenpos;
  1204. while again do
  1205. begin
  1206. { prevent crashes with unknown types }
  1207. if not assigned(pd) then
  1208. begin
  1209. { try to recover }
  1210. repeat
  1211. case token of
  1212. _CARET:
  1213. consume(_CARET);
  1214. _POINT:
  1215. begin
  1216. consume(_POINT);
  1217. consume(_ID);
  1218. end;
  1219. _LECKKLAMMER:
  1220. begin
  1221. repeat
  1222. consume(token);
  1223. until token in [_RECKKLAMMER,_SEMICOLON];
  1224. end;
  1225. else
  1226. break;
  1227. end;
  1228. until false;
  1229. exit;
  1230. end;
  1231. { handle token }
  1232. case token of
  1233. _CARET:
  1234. begin
  1235. consume(_CARET);
  1236. if (pd^.deftype<>pointerdef) then
  1237. begin
  1238. { ^ as binary operator is a problem!!!! (FK) }
  1239. again:=false;
  1240. Message(cg_e_invalid_qualifier);
  1241. disposetree(p1);
  1242. p1:=genzeronode(errorn);
  1243. end
  1244. else
  1245. begin
  1246. p1:=gensinglenode(derefn,p1);
  1247. pd:=ppointerdef(pd)^.definition;
  1248. end;
  1249. end;
  1250. _LECKKLAMMER:
  1251. begin
  1252. if (pd^.deftype=objectdef) and pobjectdef(pd)^.is_class then
  1253. begin
  1254. { default property }
  1255. propsym:=search_default_property(pobjectdef(pd));
  1256. if not(assigned(propsym)) then
  1257. begin
  1258. disposetree(p1);
  1259. p1:=genzeronode(errorn);
  1260. again:=false;
  1261. message(parser_e_no_default_property_available);
  1262. end
  1263. else
  1264. handle_propertysym(propsym,propsym^.owner,p1,pd);
  1265. end
  1266. else
  1267. begin
  1268. consume(_LECKKLAMMER);
  1269. repeat
  1270. case pd^.deftype of
  1271. pointerdef:
  1272. begin
  1273. p2:=comp_expr(true);
  1274. p1:=gennode(vecn,p1,p2);
  1275. pd:=ppointerdef(pd)^.definition;
  1276. end;
  1277. stringdef : begin
  1278. p2:=comp_expr(true);
  1279. p1:=gennode(vecn,p1,p2);
  1280. pd:=cchardef
  1281. end;
  1282. arraydef : begin
  1283. p2:=comp_expr(true);
  1284. { support SEG:OFS for go32v2 Mem[] }
  1285. if (target_info.target=target_i386_go32v2) and
  1286. (p1^.treetype=loadn) and
  1287. assigned(p1^.symtableentry) and
  1288. assigned(p1^.symtableentry^.owner^.name) and
  1289. (p1^.symtableentry^.owner^.name^='SYSTEM') and
  1290. ((p1^.symtableentry^.name='MEM') or
  1291. (p1^.symtableentry^.name='MEMW') or
  1292. (p1^.symtableentry^.name='MEML')) then
  1293. begin
  1294. if (token=_COLON) then
  1295. begin
  1296. consume(_COLON);
  1297. p3:=gennode(muln,genordinalconstnode($10,s32bitdef),p2);
  1298. p2:=comp_expr(true);
  1299. p2:=gennode(addn,p2,p3);
  1300. p1:=gennode(vecn,p1,p2);
  1301. p1^.memseg:=true;
  1302. p1^.memindex:=true;
  1303. end
  1304. else
  1305. begin
  1306. p1:=gennode(vecn,p1,p2);
  1307. p1^.memindex:=true;
  1308. end;
  1309. end
  1310. else
  1311. p1:=gennode(vecn,p1,p2);
  1312. pd:=parraydef(pd)^.definition;
  1313. end;
  1314. else
  1315. begin
  1316. Message(cg_e_invalid_qualifier);
  1317. disposetree(p1);
  1318. p1:=genzeronode(errorn);
  1319. again:=false;
  1320. end;
  1321. end;
  1322. if token=_COMMA then
  1323. consume(_COMMA)
  1324. else
  1325. break;
  1326. until false;
  1327. consume(_RECKKLAMMER);
  1328. end;
  1329. end;
  1330. _POINT : begin
  1331. consume(_POINT);
  1332. if (pd^.deftype=pointerdef) and
  1333. (m_autoderef in aktmodeswitches) then
  1334. begin
  1335. p1:=gensinglenode(derefn,p1);
  1336. pd:=ppointerdef(pd)^.definition;
  1337. end;
  1338. case pd^.deftype of
  1339. recorddef:
  1340. begin
  1341. sym:=pvarsym(precorddef(pd)^.symtable^.search(pattern));
  1342. if sym=nil then
  1343. begin
  1344. Message1(sym_e_illegal_field,pattern);
  1345. disposetree(p1);
  1346. p1:=genzeronode(errorn);
  1347. end
  1348. else
  1349. begin
  1350. p1:=gensubscriptnode(sym,p1);
  1351. pd:=sym^.definition;
  1352. end;
  1353. consume(_ID);
  1354. end;
  1355. classrefdef:
  1356. begin
  1357. classh:=pobjectdef(pclassrefdef(pd)^.definition);
  1358. sym:=nil;
  1359. while assigned(classh) do
  1360. begin
  1361. sym:=pvarsym(classh^.symtable^.search(pattern));
  1362. srsymtable:=classh^.symtable;
  1363. if assigned(sym) then
  1364. break;
  1365. classh:=classh^.childof;
  1366. end;
  1367. consume(_ID);
  1368. do_member_read(getaddr,sym,p1,pd,again);
  1369. end;
  1370. objectdef:
  1371. begin
  1372. classh:=pobjectdef(pd);
  1373. sym:=nil;
  1374. store_static:=allow_only_static;
  1375. allow_only_static:=false;
  1376. while assigned(classh) do
  1377. begin
  1378. sym:=pvarsym(classh^.symtable^.search(pattern));
  1379. srsymtable:=classh^.symtable;
  1380. if assigned(sym) then
  1381. break;
  1382. classh:=classh^.childof;
  1383. end;
  1384. allow_only_static:=store_static;
  1385. consume(_ID);
  1386. do_member_read(getaddr,sym,p1,pd,again);
  1387. end;
  1388. pointerdef:
  1389. begin
  1390. Message(cg_e_invalid_qualifier);
  1391. if ppointerdef(pd)^.definition^.deftype in [recorddef,objectdef,classrefdef] then
  1392. Message(parser_h_maybe_deref_caret_missing);
  1393. end;
  1394. else
  1395. begin
  1396. Message(cg_e_invalid_qualifier);
  1397. disposetree(p1);
  1398. p1:=genzeronode(errorn);
  1399. end;
  1400. end;
  1401. end;
  1402. else
  1403. begin
  1404. { is this a procedure variable ? }
  1405. if assigned(pd) then
  1406. begin
  1407. if (pd^.deftype=procvardef) then
  1408. begin
  1409. if getprocvar and is_equal(pd,getprocvardef) then
  1410. again:=false
  1411. else
  1412. if (token=_LKLAMMER) or
  1413. ((pprocvardef(pd)^.para1=nil) and
  1414. (not((token in [_ASSIGNMENT,_UNEQUAL,_EQUAL]))) and
  1415. (not afterassignment) and
  1416. (not in_args)) then
  1417. begin
  1418. { do this in a strange way }
  1419. { it's not a clean solution }
  1420. p2:=p1;
  1421. p1:=gencallnode(nil,nil);
  1422. p1^.right:=p2;
  1423. p1^.unit_specific:=unit_specific;
  1424. p1^.symtableprocentry:=pprocsym(sym);
  1425. if token=_LKLAMMER then
  1426. begin
  1427. consume(_LKLAMMER);
  1428. p1^.left:=parse_paras(false,false);
  1429. consume(_RKLAMMER);
  1430. end;
  1431. pd:=pprocvardef(pd)^.retdef;
  1432. { proc():= is never possible }
  1433. if token=_ASSIGNMENT then
  1434. begin
  1435. Message(cg_e_illegal_expression);
  1436. p1:=genzeronode(errorn);
  1437. again:=false;
  1438. end;
  1439. p1^.resulttype:=pd;
  1440. end
  1441. else
  1442. again:=false;
  1443. p1^.resulttype:=pd;
  1444. end
  1445. else
  1446. again:=false;
  1447. end
  1448. else
  1449. again:=false;
  1450. end;
  1451. end;
  1452. check_tokenpos;
  1453. end; { while again }
  1454. end;
  1455. {---------------------------------------------
  1456. Factor (Main)
  1457. ---------------------------------------------}
  1458. begin
  1459. oldp1:=nil;
  1460. p1:=nil;
  1461. filepos:=tokenpos;
  1462. if token=_ID then
  1463. begin
  1464. factor_read_id;
  1465. { handle post fix operators }
  1466. postfixoperators;
  1467. end
  1468. else
  1469. case token of
  1470. _NEW : begin
  1471. consume(_NEW);
  1472. consume(_LKLAMMER);
  1473. {allow_type:=true;}
  1474. p1:=factor(false);
  1475. {allow_type:=false;}
  1476. if p1^.treetype<>typen then
  1477. begin
  1478. Message(type_e_type_id_expected);
  1479. disposetree(p1);
  1480. pd:=generrordef;
  1481. end
  1482. else
  1483. pd:=p1^.typenodetype;
  1484. pd2:=pd;
  1485. if (pd^.deftype<>pointerdef) then
  1486. Message1(type_e_pointer_type_expected,pd^.typename)
  1487. else if {(ppointerdef(pd)^.definition^.deftype<>objectdef)}
  1488. token=_RKLAMMER then
  1489. begin
  1490. if (ppointerdef(pd)^.definition^.deftype=objectdef) and
  1491. (oo_has_vmt in pobjectdef(ppointerdef(pd)^.definition)^.objectoptions) then
  1492. Message(parser_w_use_extended_syntax_for_objects);
  1493. p1:=gensinglenode(newn,nil);
  1494. p1^.resulttype:=pd2;
  1495. consume(_RKLAMMER);
  1496. (*Message(parser_e_pointer_to_class_expected);
  1497. { if an error occurs, read til the end of
  1498. the new statement }
  1499. p1:=genzeronode(errorn);
  1500. l:=1;
  1501. while true do
  1502. begin
  1503. case token of
  1504. _LKLAMMER : inc(l);
  1505. _RKLAMMER : dec(l);
  1506. end;
  1507. consume(token);
  1508. if l=0 then
  1509. break;
  1510. end;*)
  1511. end
  1512. else
  1513. begin
  1514. disposetree(p1);
  1515. p1:=genzeronode(hnewn);
  1516. p1^.resulttype:=ppointerdef(pd)^.definition;
  1517. consume(_COMMA);
  1518. afterassignment:=false;
  1519. { determines the current object defintion }
  1520. classh:=pobjectdef(ppointerdef(pd)^.definition);
  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. { no constructor found }
  1527. sym:=nil;
  1528. while assigned(classh) do
  1529. begin
  1530. sym:=pvarsym(classh^.symtable^.search(pattern));
  1531. srsymtable:=classh^.symtable;
  1532. if assigned(sym) then
  1533. break;
  1534. classh:=classh^.childof;
  1535. end;
  1536. consume(_ID);
  1537. do_member_read(false,sym,p1,pd,again);
  1538. if (p1^.treetype<>calln) or
  1539. (assigned(p1^.procdefinition) and
  1540. (p1^.procdefinition^.proctypeoption<>potype_constructor)) then
  1541. Message(parser_e_expr_have_to_be_constructor_call);
  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. p1:=genzeronode(typen);
  1590. p1^.resulttype:=classh;
  1591. pd:=p1^.resulttype;
  1592. consume(_ID);
  1593. do_member_read(false,sym,p1,pd,again);
  1594. break;
  1595. end;
  1596. classh:=classh^.childof;
  1597. end;
  1598. if classh=nil then
  1599. begin
  1600. Message1(sym_e_id_no_member,pattern);
  1601. again:=false;
  1602. pd:=generrordef;
  1603. p1:=genzeronode(errorn);
  1604. end;
  1605. end
  1606. else
  1607. begin
  1608. Message(parser_e_generic_methods_only_in_methods);
  1609. again:=false;
  1610. pd:=generrordef;
  1611. p1:=genzeronode(errorn);
  1612. end;
  1613. postfixoperators;
  1614. end;
  1615. _INTCONST : begin
  1616. valint(pattern,l,code);
  1617. if code<>0 then
  1618. begin
  1619. val(pattern,d,code);
  1620. if code<>0 then
  1621. begin
  1622. Message(cg_e_invalid_integer);
  1623. consume(_INTCONST);
  1624. l:=1;
  1625. p1:=genordinalconstnode(l,s32bitdef);
  1626. end
  1627. else
  1628. begin
  1629. consume(_INTCONST);
  1630. p1:=genrealconstnode(d,bestrealdef^);
  1631. end;
  1632. end
  1633. else
  1634. begin
  1635. consume(_INTCONST);
  1636. p1:=genordinalconstnode(l,s32bitdef);
  1637. end;
  1638. end;
  1639. _REALNUMBER : begin
  1640. val(pattern,d,code);
  1641. if code<>0 then
  1642. begin
  1643. Message(parser_e_error_in_real);
  1644. d:=1.0;
  1645. end;
  1646. consume(_REALNUMBER);
  1647. p1:=genrealconstnode(d,bestrealdef^);
  1648. end;
  1649. _STRING : begin
  1650. pd:=stringtype;
  1651. { STRING can be also a type cast }
  1652. if token=_LKLAMMER then
  1653. begin
  1654. consume(_LKLAMMER);
  1655. p1:=comp_expr(true);
  1656. consume(_RKLAMMER);
  1657. p1:=gentypeconvnode(p1,pd);
  1658. p1^.explizit:=true;
  1659. { handle postfix operators here e.g. string(a)[10] }
  1660. again:=true;
  1661. postfixoperators;
  1662. end
  1663. else
  1664. p1:=gentypenode(pd,nil);
  1665. end;
  1666. _FILE : begin
  1667. pd:=cfiledef;
  1668. consume(_FILE);
  1669. { FILE can be also a type cast }
  1670. if token=_LKLAMMER then
  1671. begin
  1672. consume(_LKLAMMER);
  1673. p1:=comp_expr(true);
  1674. consume(_RKLAMMER);
  1675. p1:=gentypeconvnode(p1,pd);
  1676. p1^.explizit:=true;
  1677. { handle postfix operators here e.g. string(a)[10] }
  1678. again:=true;
  1679. postfixoperators;
  1680. end
  1681. else
  1682. p1:=gentypenode(pd,nil);
  1683. end;
  1684. _CSTRING : begin
  1685. p1:=genstringconstnode(pattern);
  1686. consume(_CSTRING);
  1687. end;
  1688. _CCHAR : begin
  1689. p1:=genordinalconstnode(ord(pattern[1]),cchardef);
  1690. consume(_CCHAR);
  1691. end;
  1692. _KLAMMERAFFE : begin
  1693. consume(_KLAMMERAFFE);
  1694. got_addrn:=true;
  1695. { support both @<x> and @(<x>) }
  1696. if token=_LKLAMMER then
  1697. begin
  1698. consume(_LKLAMMER);
  1699. p1:=factor(true);
  1700. consume(_RKLAMMER);
  1701. end
  1702. else
  1703. p1:=factor(true);
  1704. got_addrn:=false;
  1705. p1:=gensinglenode(addrn,p1);
  1706. end;
  1707. _LKLAMMER : begin
  1708. consume(_LKLAMMER);
  1709. p1:=comp_expr(true);
  1710. consume(_RKLAMMER);
  1711. { it's not a good solution }
  1712. { but (a+b)^ makes some problems }
  1713. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1714. begin
  1715. { we need the resulttype }
  1716. { of the expression in pd }
  1717. do_firstpass(p1);
  1718. pd:=p1^.resulttype;
  1719. again:=true;
  1720. postfixoperators;
  1721. end;
  1722. end;
  1723. _LECKKLAMMER : begin
  1724. consume(_LECKKLAMMER);
  1725. p1:=factor_read_set;
  1726. consume(_RECKKLAMMER);
  1727. end;
  1728. _PLUS : begin
  1729. consume(_PLUS);
  1730. p1:=factor(false);
  1731. end;
  1732. _MINUS : begin
  1733. consume(_MINUS);
  1734. p1:=factor(false);
  1735. p1:=gensinglenode(umminusn,p1);
  1736. end;
  1737. _NOT : begin
  1738. consume(_NOT);
  1739. p1:=factor(false);
  1740. p1:=gensinglenode(notn,p1);
  1741. end;
  1742. _TRUE : begin
  1743. consume(_TRUE);
  1744. p1:=genordinalconstnode(1,booldef);
  1745. end;
  1746. _FALSE : begin
  1747. consume(_FALSE);
  1748. p1:=genordinalconstnode(0,booldef);
  1749. end;
  1750. _NIL : begin
  1751. consume(_NIL);
  1752. p1:=genzeronode(niln);
  1753. end;
  1754. else
  1755. begin
  1756. p1:=genzeronode(errorn);
  1757. consume(token);
  1758. Message(cg_e_illegal_expression);
  1759. end;
  1760. end;
  1761. { generate error node if no node is created }
  1762. if not assigned(p1) then
  1763. p1:=genzeronode(errorn);
  1764. { tp7 procvar handling, but not if the next token
  1765. will be a := }
  1766. if (m_tp_procvar in aktmodeswitches) and
  1767. (token<>_ASSIGNMENT) then
  1768. check_tp_procvar(p1);
  1769. factor:=p1;
  1770. check_tokenpos;
  1771. end;
  1772. {****************************************************************************
  1773. Sub_Expr
  1774. ****************************************************************************}
  1775. type
  1776. Toperator_precedence=(opcompare,opaddition,opmultiply);
  1777. Ttok2nodeRec=record
  1778. tok : ttoken;
  1779. nod : ttreetyp;
  1780. end;
  1781. const
  1782. tok2nodes=23;
  1783. tok2node:array[1..tok2nodes] of ttok2noderec=(
  1784. (tok:_PLUS ;nod:addn),
  1785. (tok:_MINUS ;nod:subn),
  1786. (tok:_STAR ;nod:muln),
  1787. (tok:_SLASH ;nod:slashn),
  1788. (tok:_EQUAL ;nod:equaln),
  1789. (tok:_GT ;nod:gtn),
  1790. (tok:_LT ;nod:ltn),
  1791. (tok:_GTE ;nod:gten),
  1792. (tok:_LTE ;nod:lten),
  1793. (tok:_SYMDIF ;nod:symdifn),
  1794. (tok:_STARSTAR;nod:starstarn),
  1795. (tok:_CARET ;nod:caretn),
  1796. (tok:_UNEQUAL ;nod:unequaln),
  1797. (tok:_AS ;nod:asn),
  1798. (tok:_IN ;nod:inn),
  1799. (tok:_IS ;nod:isn),
  1800. (tok:_OR ;nod:orn),
  1801. (tok:_AND ;nod:andn),
  1802. (tok:_DIV ;nod:divn),
  1803. (tok:_MOD ;nod:modn),
  1804. (tok:_SHL ;nod:shln),
  1805. (tok:_SHR ;nod:shrn),
  1806. (tok:_XOR ;nod:xorn)
  1807. );
  1808. operator_levels:array[Toperator_precedence] of set of Ttoken=
  1809. ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_IN,_IS],
  1810. [_PLUS,_MINUS,_OR,_XOR],
  1811. [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,_DIV,_MOD,_AND,_SHL,_SHR,_AS]);
  1812. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):Ptree;
  1813. {Reads a subexpression while the operators are of the current precedence
  1814. level, or any higher level. Replaces the old term, simpl_expr and
  1815. simpl2_expr.}
  1816. var
  1817. low,high,mid : longint;
  1818. p1,p2 : Ptree;
  1819. oldt : Ttoken;
  1820. filepos : tfileposinfo;
  1821. begin
  1822. if pred_level=opmultiply then
  1823. p1:=factor(false)
  1824. else
  1825. p1:=sub_expr(succ(pred_level),true);
  1826. repeat
  1827. if (token in operator_levels[pred_level]) and
  1828. ((token<>_EQUAL) or accept_equal) then
  1829. begin
  1830. oldt:=token;
  1831. filepos:=tokenpos;
  1832. consume(token);
  1833. if pred_level=opmultiply then
  1834. p2:=factor(false)
  1835. else
  1836. p2:=sub_expr(succ(pred_level),true);
  1837. low:=1;
  1838. high:=tok2nodes;
  1839. while (low<high) do
  1840. begin
  1841. mid:=(low+high+1) shr 1;
  1842. if oldt<tok2node[mid].tok then
  1843. high:=mid-1
  1844. else
  1845. low:=mid;
  1846. end;
  1847. if tok2node[high].tok=oldt then
  1848. p1:=gennode(tok2node[high].nod,p1,p2)
  1849. else
  1850. p1:=gennode(nothingn,p1,p2);
  1851. set_tree_filepos(p1,filepos);
  1852. end
  1853. else
  1854. break;
  1855. until false;
  1856. sub_expr:=p1;
  1857. end;
  1858. function comp_expr(accept_equal : boolean):Ptree;
  1859. var
  1860. oldafterassignment : boolean;
  1861. p1 : ptree;
  1862. begin
  1863. oldafterassignment:=afterassignment;
  1864. afterassignment:=true;
  1865. p1:=sub_expr(opcompare,accept_equal);
  1866. afterassignment:=oldafterassignment;
  1867. comp_expr:=p1;
  1868. end;
  1869. function expr : ptree;
  1870. var
  1871. p1,p2 : ptree;
  1872. oldafterassignment : boolean;
  1873. oldp1 : ptree;
  1874. filepos : tfileposinfo;
  1875. begin
  1876. oldafterassignment:=afterassignment;
  1877. p1:=sub_expr(opcompare,true);
  1878. filepos:=tokenpos;
  1879. if (m_tp_procvar in aktmodeswitches) and
  1880. (token<>_ASSIGNMENT) then
  1881. check_tp_procvar(p1);
  1882. if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  1883. afterassignment:=true;
  1884. oldp1:=p1;
  1885. case token of
  1886. _POINTPOINT : begin
  1887. consume(_POINTPOINT);
  1888. p2:=sub_expr(opcompare,true);
  1889. p1:=gennode(rangen,p1,p2);
  1890. end;
  1891. _ASSIGNMENT : begin
  1892. consume(_ASSIGNMENT);
  1893. { avoid a firstpass of a procedure if
  1894. it must be assigned to a procvar }
  1895. { should be recursive for a:=b:=c !!! }
  1896. if (p1^.resulttype<>nil) and (p1^.resulttype^.deftype=procvardef) then
  1897. begin
  1898. getprocvar:=true;
  1899. getprocvardef:=pprocvardef(p1^.resulttype);
  1900. end;
  1901. p2:=sub_expr(opcompare,true);
  1902. if getprocvar then
  1903. begin
  1904. if (p2^.treetype=calln) then
  1905. handle_procvar(getprocvardef,p2)
  1906. else
  1907. { also allow p:= proc(t); !! (PM) }
  1908. if (p2^.treetype=typeconvn) and
  1909. (p2^.left^.treetype=calln) then
  1910. handle_procvar(getprocvardef,p2^.left);
  1911. end;
  1912. getprocvar:=false;
  1913. p1:=gennode(assignn,p1,p2);
  1914. end;
  1915. { this is the code for C like assignements }
  1916. { from an improvement of Peter Schaefer }
  1917. _PLUSASN : begin
  1918. consume(_PLUSASN );
  1919. p2:=sub_expr(opcompare,true);
  1920. p1:=gennode(assignn,p1,gennode(addn,getcopy(p1),p2));
  1921. { was first
  1922. p1:=gennode(assignn,p1,gennode(addn,p1,p2));
  1923. but disposetree assumes that we have a real
  1924. *** tree *** }
  1925. end;
  1926. _MINUSASN : begin
  1927. consume(_MINUSASN );
  1928. p2:=sub_expr(opcompare,true);
  1929. p1:=gennode(assignn,p1,gennode(subn,getcopy(p1),p2));
  1930. end;
  1931. _STARASN : begin
  1932. consume(_STARASN );
  1933. p2:=sub_expr(opcompare,true);
  1934. p1:=gennode(assignn,p1,gennode(muln,getcopy(p1),p2));
  1935. end;
  1936. _SLASHASN : begin
  1937. consume(_SLASHASN );
  1938. p2:=sub_expr(opcompare,true);
  1939. p1:=gennode(assignn,p1,gennode(slashn,getcopy(p1),p2));
  1940. end;
  1941. end;
  1942. afterassignment:=oldafterassignment;
  1943. if p1<>oldp1 then
  1944. set_tree_filepos(p1,filepos);
  1945. expr:=p1;
  1946. end;
  1947. function get_intconst:longint;
  1948. {Reads an expression, tries to evalute it and check if it is an integer
  1949. constant. Then the constant is returned.}
  1950. var
  1951. p:Ptree;
  1952. begin
  1953. p:=comp_expr(true);
  1954. do_firstpass(p);
  1955. if not codegenerror then
  1956. begin
  1957. if (p^.treetype<>ordconstn) and
  1958. (p^.resulttype^.deftype=orddef) and
  1959. not(Porddef(p^.resulttype)^.typ in [uvoid,uchar,bool8bit,bool16bit,bool32bit]) then
  1960. Message(cg_e_illegal_expression)
  1961. else
  1962. get_intconst:=p^.value;
  1963. end;
  1964. disposetree(p);
  1965. end;
  1966. function get_stringconst:string;
  1967. {Reads an expression, tries to evaluate it and checks if it is a string
  1968. constant. Then the constant is returned.}
  1969. var
  1970. p:Ptree;
  1971. begin
  1972. get_stringconst:='';
  1973. p:=comp_expr(true);
  1974. do_firstpass(p);
  1975. if p^.treetype<>stringconstn then
  1976. begin
  1977. if (p^.treetype=ordconstn) and is_char(p^.resulttype) then
  1978. get_stringconst:=char(p^.value)
  1979. else
  1980. Message(cg_e_illegal_expression);
  1981. end
  1982. else
  1983. get_stringconst:=strpas(p^.value_str);
  1984. disposetree(p);
  1985. end;
  1986. end.
  1987. {
  1988. $Log$
  1989. Revision 1.140 1999-09-11 09:08:33 florian
  1990. * fixed bug 596
  1991. * fixed some problems with procedure variables and procedures of object,
  1992. especially in TP mode. Procedure of object doesn't apply only to classes,
  1993. it is also allowed for objects !!
  1994. Revision 1.139 1999/09/10 18:48:07 florian
  1995. * some bug fixes (e.g. must_be_valid and procinfo.funcret_is_valid)
  1996. * most things for stored properties fixed
  1997. Revision 1.138 1999/09/07 08:01:20 peter
  1998. * @(<x>) support
  1999. Revision 1.137 1999/09/01 22:08:58 peter
  2000. * fixed crash with assigned()
  2001. Revision 1.136 1999/08/15 22:47:45 peter
  2002. * fixed property writeaccess which was buggy after my previous
  2003. subscribed property access
  2004. Revision 1.135 1999/08/14 00:38:56 peter
  2005. * hack to support property with record fields
  2006. Revision 1.134 1999/08/09 22:16:29 peter
  2007. * fixed crash after wrong para's with class contrustor
  2008. Revision 1.133 1999/08/05 16:53:04 peter
  2009. * V_Fatal=1, all other V_ are also increased
  2010. * Check for local procedure when assigning procvar
  2011. * fixed comment parsing because directives
  2012. * oldtp mode directives better supported
  2013. * added some messages to errore.msg
  2014. Revision 1.132 1999/08/04 13:49:45 florian
  2015. * new(...)^. is now allowed
  2016. Revision 1.131 1999/08/04 13:02:55 jonas
  2017. * all tokens now start with an underscore
  2018. * PowerPC compiles!!
  2019. Revision 1.130 1999/08/04 00:23:12 florian
  2020. * renamed i386asm and i386base to cpuasm and cpubase
  2021. Revision 1.129 1999/08/03 22:02:59 peter
  2022. * moved bitmask constants to sets
  2023. * some other type/const renamings
  2024. Revision 1.128 1999/08/03 13:50:17 michael
  2025. + Changes for alpha
  2026. Revision 1.127 1999/08/01 18:28:13 florian
  2027. * modifications for the new code generator
  2028. Revision 1.126 1999/07/30 12:28:40 peter
  2029. * fixed crash with unknown id and colon parameter in write
  2030. Revision 1.125 1999/07/27 23:42:14 peter
  2031. * indirect type referencing is now allowed
  2032. Revision 1.124 1999/07/23 21:31:42 peter
  2033. * fixed crash with resourcestring
  2034. Revision 1.123 1999/07/23 11:37:46 peter
  2035. * error for illegal type reference, instead of 10998
  2036. Revision 1.122 1999/07/22 09:37:52 florian
  2037. + resourcestring implemented
  2038. + start of longstring support
  2039. Revision 1.121 1999/07/16 10:04:35 peter
  2040. * merged
  2041. Revision 1.120 1999/07/06 22:38:11 florian
  2042. * another fix for TP/Delphi styled procedure variables
  2043. Revision 1.119 1999/07/05 20:13:16 peter
  2044. * removed temp defines
  2045. Revision 1.118 1999/07/01 21:33:57 peter
  2046. * merged
  2047. Revision 1.117 1999/06/30 15:43:20 florian
  2048. * two bugs regarding method variables fixed
  2049. - if you take in a method the address of another method
  2050. don't need self anymore
  2051. - if the class pointer was in a register, wrong code for a method
  2052. variable load was generated
  2053. Revision 1.116 1999/06/26 00:24:53 pierre
  2054. * mereg from fixes-0_99_12 branch
  2055. Revision 1.112.2.8 1999/07/16 09:54:57 peter
  2056. * @procvar support in tp7 mode works again
  2057. Revision 1.112.2.7 1999/07/07 07:53:10 michael
  2058. + Merged patches from florian
  2059. Revision 1.112.2.6 1999/07/01 21:31:59 peter
  2060. * procvar fixes again
  2061. Revision 1.112.2.5 1999/07/01 15:17:17 peter
  2062. * methoidpointer fixes from florian
  2063. Revision 1.112.2.4 1999/06/26 00:22:30 pierre
  2064. * wrong warnings in -So mode suppressed
  2065. Revision 1.112.2.3 1999/06/17 12:51:44 pierre
  2066. * changed is_assignment_overloaded into
  2067. function assignment_overloaded : pprocdef
  2068. to allow overloading of assignment with only different result type
  2069. Revision 1.112.2.2 1999/06/15 18:54:52 peter
  2070. * more procvar fixes
  2071. Revision 1.112.2.1 1999/06/13 22:38:09 peter
  2072. * tp_procvar check for loading of procvars when getaddr=false
  2073. Revision 1.112 1999/06/02 22:44:11 pierre
  2074. * previous wrong log corrected
  2075. Revision 1.111 1999/06/02 22:25:43 pierre
  2076. * changed $ifdef FPC @ into $ifndef TP
  2077. * changes for correct procvar handling under tp mode
  2078. Revision 1.110 1999/06/01 19:27:55 peter
  2079. * better checks for procvar and methodpointer
  2080. Revision 1.109 1999/05/27 19:44:46 peter
  2081. * removed oldasm
  2082. * plabel -> pasmlabel
  2083. * -a switches to source writing automaticly
  2084. * assembler readers OOPed
  2085. * asmsymbol automaticly external
  2086. * jumptables and other label fixes for asm readers
  2087. Revision 1.108 1999/05/18 14:15:54 peter
  2088. * containsself fixes
  2089. * checktypes()
  2090. Revision 1.107 1999/05/18 09:52:18 peter
  2091. * procedure of object and addrn fixes
  2092. Revision 1.106 1999/05/16 17:06:31 peter
  2093. * remove firstcallparan which looks obsolete
  2094. Revision 1.105 1999/05/12 22:36:09 florian
  2095. * override isn't allowed in objects!
  2096. Revision 1.104 1999/05/07 10:35:23 florian
  2097. * first fix for a problem with method pointer properties, still doesn't work
  2098. with WITH
  2099. Revision 1.103 1999/05/06 21:40:16 peter
  2100. * fixed crash
  2101. Revision 1.101 1999/05/06 09:05:21 peter
  2102. * generic write_float and str_float
  2103. * fixed constant float conversions
  2104. Revision 1.100 1999/05/04 21:44:57 florian
  2105. * changes to compile it with Delphi 4.0
  2106. Revision 1.99 1999/05/01 13:24:31 peter
  2107. * merged nasm compiler
  2108. * old asm moved to oldasm/
  2109. Revision 1.98 1999/04/26 18:29:56 peter
  2110. * farpointerdef moved into pointerdef.is_far
  2111. Revision 1.97 1999/04/19 09:27:48 peter
  2112. * removed my property fix
  2113. Revision 1.96 1999/04/19 09:13:47 peter
  2114. * class property without write support
  2115. Revision 1.95 1999/04/19 06:10:08 florian
  2116. * property problem fixed: a propertysym is only a write
  2117. access if it is followed by a assignment token
  2118. Revision 1.94 1999/04/17 13:12:17 peter
  2119. * addr() internal
  2120. Revision 1.93 1999/04/15 09:00:08 peter
  2121. * fixed property write
  2122. Revision 1.92 1999/04/08 20:59:43 florian
  2123. * fixed problem with default properties which are a class
  2124. * case bug (from the mailing list with -O2) fixed, the
  2125. distance of the case labels can be greater than the positive
  2126. range of a longint => it is now a dword for fpc
  2127. Revision 1.91 1999/04/06 11:21:56 peter
  2128. * more use of ttoken
  2129. Revision 1.90 1999/03/31 13:55:12 peter
  2130. * assembler inlining working for ag386bin
  2131. Revision 1.89 1999/03/26 00:05:36 peter
  2132. * released valintern
  2133. + deffile is now removed when compiling is finished
  2134. * ^( compiles now correct
  2135. + static directive
  2136. * shrd fixed
  2137. Revision 1.88 1999/03/24 23:17:15 peter
  2138. * fixed bugs 212,222,225,227,229,231,233
  2139. Revision 1.87 1999/03/16 17:52:52 jonas
  2140. * changes for internal Val code (do a "make cycle OPT=-dvalintern" to test)
  2141. * in cgi386inl: also range checking for subrange types (compile with "-dreadrangecheck")
  2142. * in cgai386: also small fixes to emitrangecheck
  2143. Revision 1.86 1999/03/04 13:55:44 pierre
  2144. * some m68k fixes (still not compilable !)
  2145. * new(tobj) does not give warning if tobj has no VMT !
  2146. Revision 1.85 1999/02/22 15:09:39 florian
  2147. * behaviaor of PROTECTED and PRIVATE fixed, works now like TP/Delphi
  2148. Revision 1.84 1999/02/22 02:15:26 peter
  2149. * updates for ag386bin
  2150. Revision 1.83 1999/02/11 09:46:25 pierre
  2151. * fix for normal method calls inside static methods :
  2152. WARNING there were both parser and codegen errors !!
  2153. added static_call boolean to calln tree
  2154. Revision 1.82 1999/01/28 14:06:47 florian
  2155. * small fix for method pointers
  2156. * found the annoying strpas bug, mainly nested call to type cast which
  2157. use ansistrings crash
  2158. Revision 1.81 1999/01/27 00:13:55 florian
  2159. * "procedure of object"-stuff fixed
  2160. Revision 1.80 1999/01/21 16:41:01 pierre
  2161. * fix for constructor inside with statements
  2162. Revision 1.79 1998/12/30 22:15:48 peter
  2163. + farpointer type
  2164. * absolutesym now also stores if its far
  2165. Revision 1.78 1998/12/11 00:03:32 peter
  2166. + globtype,tokens,version unit splitted from globals
  2167. Revision 1.77 1998/12/04 10:18:09 florian
  2168. * some stuff for procedures of object added
  2169. * bug with overridden virtual constructors fixed (reported by Italo Gomes)
  2170. Revision 1.76 1998/11/27 14:50:40 peter
  2171. + open strings, $P switch support
  2172. Revision 1.75 1998/11/25 19:12:51 pierre
  2173. * var:=new(pointer_type) support added
  2174. Revision 1.74 1998/11/13 10:18:11 peter
  2175. + nil constants
  2176. Revision 1.73 1998/11/05 12:02:52 peter
  2177. * released useansistring
  2178. * removed -Sv, its now available in fpc modes
  2179. Revision 1.72 1998/11/04 10:11:41 peter
  2180. * ansistring fixes
  2181. Revision 1.71 1998/10/22 23:57:29 peter
  2182. * fixed filedef for typenodetype
  2183. Revision 1.70 1998/10/21 15:12:54 pierre
  2184. * bug fix for IOCHECK inside a procedure with iocheck modifier
  2185. * removed the GPF for unexistant overloading
  2186. (firstcall was called with procedinition=nil !)
  2187. * changed typen to what Florian proposed
  2188. gentypenode(p : pdef) sets the typenodetype field
  2189. and resulttype is only set if inside bt_type block !
  2190. Revision 1.69 1998/10/20 15:10:19 pierre
  2191. * type ptree only allowed inside expression
  2192. if following sizeof typeof low high or as first arg of new !!
  2193. Revision 1.68 1998/10/20 11:15:44 pierre
  2194. * calling of private method allowed inside child object method
  2195. Revision 1.67 1998/10/19 08:54:57 pierre
  2196. * wrong stabs info corrected once again !!
  2197. + variable vmt offset with vmt field only if required
  2198. implemented now !!!
  2199. Revision 1.66 1998/10/15 15:13:28 pierre
  2200. + added oo_hasconstructor and oo_hasdestructor
  2201. for objects options
  2202. Revision 1.65 1998/10/13 13:10:24 peter
  2203. * new style for m68k/i386 infos and enums
  2204. Revision 1.64 1998/10/12 12:20:55 pierre
  2205. + added tai_const_symbol_offset
  2206. for r : pointer = @var.field;
  2207. * better message for different arg names on implementation
  2208. of function
  2209. Revision 1.63 1998/10/12 10:28:30 florian
  2210. + auto dereferencing of pointers to structured types in delphi mode
  2211. Revision 1.62 1998/10/12 10:05:41 peter
  2212. * fixed mem leak with arrayconstrutor
  2213. Revision 1.61 1998/10/05 13:57:15 peter
  2214. * crash preventions
  2215. Revision 1.60 1998/10/05 12:32:46 peter
  2216. + assert() support
  2217. Revision 1.59 1998/10/01 14:56:24 peter
  2218. * crash preventions
  2219. Revision 1.58 1998/09/30 07:40:35 florian
  2220. * better error recovering
  2221. Revision 1.57 1998/09/28 16:18:16 florian
  2222. * two fixes to get ansi strings work
  2223. Revision 1.56 1998/09/26 17:45:36 peter
  2224. + idtoken and only one token table
  2225. Revision 1.55 1998/09/24 23:49:10 peter
  2226. + aktmodeswitches
  2227. Revision 1.54 1998/09/23 15:46:39 florian
  2228. * problem with with and classes fixed
  2229. Revision 1.53 1998/09/23 09:58:54 peter
  2230. * first working array of const things
  2231. Revision 1.52 1998/09/20 09:38:45 florian
  2232. * hasharray for defs fixed
  2233. * ansistring code generation corrected (init/final, assignement)
  2234. Revision 1.51 1998/09/18 16:03:43 florian
  2235. * some changes to compile with Delphi
  2236. Revision 1.50 1998/09/17 13:41:18 pierre
  2237. sizeof(TPOINT) problem
  2238. Revision 1.49.2.1 1998/09/17 08:42:31 pierre
  2239. TPOINT sizeof fix
  2240. Revision 1.49 1998/09/09 11:50:53 pierre
  2241. * forward def are not put in record or objects
  2242. + added check for forwards also in record and objects
  2243. * dummy parasymtable for unit initialization removed from
  2244. symtable stack
  2245. Revision 1.48 1998/09/07 22:25:53 peter
  2246. * fixed str(boolean,string) which was allowed
  2247. * fixed write(' ':<int expression>) only constants where allowed :(
  2248. Revision 1.47 1998/09/07 18:46:10 peter
  2249. * update smartlinking, uses getdatalabel
  2250. * renamed ptree.value vars to value_str,value_real,value_set
  2251. Revision 1.46 1998/09/04 08:42:03 peter
  2252. * updated some error messages
  2253. Revision 1.45 1998/09/01 17:39:49 peter
  2254. + internal constant functions
  2255. Revision 1.44 1998/08/28 10:54:24 peter
  2256. * fixed smallset generation from elements, it has never worked before!
  2257. Revision 1.43 1998/08/23 16:07:24 florian
  2258. * internalerror with mod/div fixed
  2259. Revision 1.42 1998/08/21 14:08:50 pierre
  2260. + TEST_FUNCRET now default (old code removed)
  2261. works also for m68k (at least compiles)
  2262. Revision 1.41 1998/08/20 21:36:39 peter
  2263. * fixed 'with object do' bug
  2264. Revision 1.40 1998/08/20 09:26:41 pierre
  2265. + funcret setting in underproc testing
  2266. compile with _dTEST_FUNCRET
  2267. Revision 1.39 1998/08/18 16:48:48 pierre
  2268. * bug for -So proc assignment to p^rocvar fixed
  2269. Revision 1.38 1998/08/18 14:17:09 pierre
  2270. * bug about assigning the return value of a function to
  2271. a procvar fixed : warning
  2272. assigning a proc to a procvar need @ in FPC mode !!
  2273. * missing file/line info restored
  2274. Revision 1.37 1998/08/18 09:24:43 pierre
  2275. * small warning position bug fixed
  2276. * support_mmx switches splitting was missing
  2277. * rhide error and warning output corrected
  2278. Revision 1.36 1998/08/15 16:50:29 peter
  2279. * fixed proc()=expr which was not allowed anymore by my previous fix
  2280. Revision 1.35 1998/08/14 18:18:46 peter
  2281. + dynamic set contruction
  2282. * smallsets are now working (always longint size)
  2283. Revision 1.34 1998/08/13 11:00:12 peter
  2284. * fixed procedure<>procedure construct
  2285. Revision 1.33 1998/08/11 15:31:39 peter
  2286. * write extended to ppu file
  2287. * new version 0.99.7
  2288. Revision 1.32 1998/08/11 14:05:32 peter
  2289. * fixed sizeof(array of char)
  2290. Revision 1.31 1998/08/10 14:50:11 peter
  2291. + localswitches, moduleswitches, globalswitches splitting
  2292. Revision 1.30 1998/07/28 21:52:54 florian
  2293. + implementation of raise and try..finally
  2294. + some misc. exception stuff
  2295. Revision 1.29 1998/07/27 21:57:13 florian
  2296. * fix to allow tv like stream registration:
  2297. @tmenu.load doesn't work if load had parameters or if load was only
  2298. declared in an anchestor class of tmenu
  2299. Revision 1.28 1998/07/14 21:46:51 peter
  2300. * updated messages file
  2301. Revision 1.27 1998/06/25 14:04:23 peter
  2302. + internal inc/dec
  2303. Revision 1.26 1998/06/09 16:01:46 pierre
  2304. + added procedure directive parsing for procvars
  2305. (accepted are popstack cdecl and pascal)
  2306. + added C vars with the following syntax
  2307. var C calias 'true_c_name';(can be followed by external)
  2308. reason is that you must add the Cprefix
  2309. which is target dependent
  2310. Revision 1.25 1998/06/05 14:37:33 pierre
  2311. * fixes for inline for operators
  2312. * inline procedure more correctly restricted
  2313. Revision 1.24 1998/06/04 23:51:52 peter
  2314. * m68k compiles
  2315. + .def file creation moved to gendef.pas so it could also be used
  2316. for win32
  2317. Revision 1.23 1998/06/04 09:55:40 pierre
  2318. * demangled name of procsym reworked to become independant of the mangling scheme
  2319. Revision 1.22 1998/06/02 17:03:03 pierre
  2320. * with node corrected for objects
  2321. * small bugs for SUPPORT_MMX fixed
  2322. Revision 1.21 1998/05/27 19:45:05 peter
  2323. * symtable.pas splitted into includefiles
  2324. * symtable adapted for $ifdef NEWPPU
  2325. Revision 1.20 1998/05/26 07:53:59 pierre
  2326. * bug fix for empty sets (nil pd was dereferenced )
  2327. Revision 1.19 1998/05/25 17:11:43 pierre
  2328. * firstpasscount bug fixed
  2329. now all is already set correctly the first time
  2330. under EXTDEBUG try -gp to skip all other firstpasses
  2331. it works !!
  2332. * small bug fixes
  2333. - for smallsets with -dTESTSMALLSET
  2334. - some warnings removed (by correcting code !)
  2335. Revision 1.18 1998/05/23 01:21:20 peter
  2336. + aktasmmode, aktoptprocessor, aktoutputformat
  2337. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  2338. + $LIBNAME to set the library name where the unit will be put in
  2339. * splitted cgi386 a bit (codeseg to large for bp7)
  2340. * nasm, tasm works again. nasm moved to ag386nsm.pas
  2341. Revision 1.17 1998/05/22 12:37:03 carl
  2342. * crash bugfix (patched msanually to main branch)
  2343. Revision 1.16 1998/05/21 19:33:32 peter
  2344. + better procedure directive handling and only one table
  2345. Revision 1.15 1998/05/20 09:42:35 pierre
  2346. + UseTokenInfo now default
  2347. * unit in interface uses and implementation uses gives error now
  2348. * only one error for unknown symbol (uses lastsymknown boolean)
  2349. the problem came from the label code !
  2350. + first inlined procedures and function work
  2351. (warning there might be allowed cases were the result is still wrong !!)
  2352. * UseBrower updated gives a global list of all position of all used symbols
  2353. with switch -gb
  2354. Revision 1.14 1998/05/11 13:07:56 peter
  2355. + $ifdef NEWPPU for the new ppuformat
  2356. + $define GDB not longer required
  2357. * removed all warnings and stripped some log comments
  2358. * no findfirst/findnext anymore to remove smartlink *.o files
  2359. Revision 1.13 1998/05/06 08:38:45 pierre
  2360. * better position info with UseTokenInfo
  2361. UseTokenInfo greatly simplified
  2362. + added check for changed tree after first time firstpass
  2363. (if we could remove all the cases were it happen
  2364. we could skip all firstpass if firstpasscount > 1)
  2365. Only with ExtDebug
  2366. Revision 1.12 1998/05/05 12:05:42 florian
  2367. * problems with properties fixed
  2368. * crash fixed: i:=l when i and l are undefined, was a problem with
  2369. implementation of private/protected
  2370. Revision 1.11 1998/05/04 11:22:26 florian
  2371. * problem with DOM solved: it crashes when accessing a property in a method
  2372. Revision 1.10 1998/05/01 16:38:45 florian
  2373. * handling of private and protected fixed
  2374. + change_keywords_to_tp implemented to remove
  2375. keywords which aren't supported by tp
  2376. * break and continue are now symbols of the system unit
  2377. + widestring, longstring and ansistring type released
  2378. Revision 1.9 1998/04/29 10:33:58 pierre
  2379. + added some code for ansistring (not complete nor working yet)
  2380. * corrected operator overloading
  2381. * corrected nasm output
  2382. + started inline procedures
  2383. + added starstarn : use ** for exponentiation (^ gave problems)
  2384. + started UseTokenInfo cond to get accurate positions
  2385. Revision 1.8 1998/04/14 23:27:03 florian
  2386. + exclude/include with constant second parameter added
  2387. Revision 1.7 1998/04/09 23:02:15 florian
  2388. * small problems solved to get remake3 work
  2389. Revision 1.6 1998/04/09 22:16:35 florian
  2390. * problem with previous REGALLOC solved
  2391. * improved property support
  2392. Revision 1.5 1998/04/08 10:26:09 florian
  2393. * correct error handling of virtual constructors
  2394. * problem with new type declaration handling fixed
  2395. Revision 1.4 1998/04/07 22:45:05 florian
  2396. * bug0092, bug0115 and bug0121 fixed
  2397. + packed object/class/array
  2398. Revision 1.3 1998/04/07 13:19:46 pierre
  2399. * bugfixes for reset_gdb_info
  2400. in MEM parsing for go32v2
  2401. better external symbol creation
  2402. support for rhgdb.exe (lowercase file names)
  2403. }