pexpr.pas 98 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656
  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) and
  971. not(getaddr) then
  972. begin
  973. if procinfo._class^.is_related(pobjectdef(pd)) then
  974. begin
  975. p1:=gentypenode(pd,ptypesym(srsym));
  976. p1^.resulttype:=pd;
  977. srsymtable:=pobjectdef(pd)^.symtable;
  978. sym:=pvarsym(srsymtable^.search(pattern));
  979. { search also in inherited methods }
  980. while sym=nil do
  981. begin
  982. pd:=pobjectdef(pd)^.childof;
  983. srsymtable:=pobjectdef(pd)^.symtable;
  984. sym:=pvarsym(srsymtable^.search(pattern));
  985. end;
  986. consume(_ID);
  987. do_member_read(false,sym,p1,pd,again);
  988. end
  989. else
  990. begin
  991. Message(parser_e_no_super_class);
  992. pd:=generrordef;
  993. again:=false;
  994. end;
  995. end
  996. else
  997. begin
  998. { allows @TObject.Load }
  999. { also allows static methods and variables }
  1000. p1:=genzeronode(typen);
  1001. p1^.resulttype:=pd;
  1002. { srsymtable:=pobjectdef(pd)^.symtable;
  1003. sym:=pvarsym(srsymtable^.search(pattern)); }
  1004. { TP allows also @TMenu.Load if Load is only }
  1005. { defined in an anchestor class }
  1006. sym:=pvarsym(search_class_member(pobjectdef(pd),pattern));
  1007. if not assigned(sym) then
  1008. Message1(sym_e_id_no_member,pattern)
  1009. else if not(getaddr) and not(sp_static in sym^.symoptions) then
  1010. Message(sym_e_only_static_in_static)
  1011. else
  1012. begin
  1013. consume(_ID);
  1014. do_member_read(getaddr,sym,p1,pd,again);
  1015. end;
  1016. end;
  1017. end
  1018. else
  1019. begin
  1020. { class reference ? }
  1021. if (pd^.deftype=objectdef)
  1022. and pobjectdef(pd)^.is_class then
  1023. begin
  1024. p1:=gentypenode(pd,nil);
  1025. p1^.resulttype:=pd;
  1026. pd:=new(pclassrefdef,init(pd));
  1027. p1:=gensinglenode(loadvmtn,p1);
  1028. p1^.resulttype:=pd;
  1029. end
  1030. else
  1031. begin
  1032. { generate a type node }
  1033. { (for typeof etc) }
  1034. if allow_type then
  1035. begin
  1036. p1:=gentypenode(pd,nil);
  1037. { here we must use typenodetype explicitly !! PM
  1038. p1^.resulttype:=pd; }
  1039. pd:=voiddef;
  1040. end
  1041. else
  1042. Message(parser_e_no_type_not_allowed_here);
  1043. end;
  1044. end;
  1045. end;
  1046. end;
  1047. end;
  1048. enumsym : begin
  1049. p1:=genenumnode(penumsym(srsym));
  1050. pd:=p1^.resulttype;
  1051. end;
  1052. constsym : begin
  1053. case pconstsym(srsym)^.consttype of
  1054. constint :
  1055. p1:=genordinalconstnode(pconstsym(srsym)^.value,s32bitdef);
  1056. conststring :
  1057. begin
  1058. len:=pconstsym(srsym)^.len;
  1059. if not(cs_ansistrings in aktlocalswitches) and (len>255) then
  1060. len:=255;
  1061. getmem(pc,len+1);
  1062. move(pchar(pconstsym(srsym)^.value)^,pc^,len);
  1063. pc[len]:=#0;
  1064. p1:=genpcharconstnode(pc,len);
  1065. end;
  1066. constchar :
  1067. p1:=genordinalconstnode(pconstsym(srsym)^.value,cchardef);
  1068. constreal :
  1069. p1:=genrealconstnode(pbestreal(pconstsym(srsym)^.value)^,bestrealdef^);
  1070. constbool :
  1071. p1:=genordinalconstnode(pconstsym(srsym)^.value,booldef);
  1072. constset :
  1073. p1:=gensetconstnode(pconstset(pconstsym(srsym)^.value),
  1074. psetdef(pconstsym(srsym)^.definition));
  1075. constord :
  1076. p1:=genordinalconstnode(pconstsym(srsym)^.value,
  1077. pconstsym(srsym)^.definition);
  1078. constnil :
  1079. p1:=genzeronode(niln);
  1080. constresourcestring:
  1081. begin
  1082. p1:=genloadnode(pvarsym(srsym),srsymtable);
  1083. p1^.resulttype:=cansistringdef;
  1084. end;
  1085. end;
  1086. pd:=p1^.resulttype;
  1087. end;
  1088. procsym : begin
  1089. { are we in a class method ? }
  1090. possible_error:=(srsymtable^.symtabletype=objectsymtable) and
  1091. assigned(aktprocsym) and
  1092. (po_classmethod in aktprocsym^.definition^.procoptions);
  1093. p1:=gencallnode(pprocsym(srsym),srsymtable);
  1094. p1^.unit_specific:=unit_specific;
  1095. do_proc_call(getaddr or
  1096. (getprocvar and
  1097. (m_tp_procvar in aktmodeswitches) and
  1098. proc_to_procvar_equal(pprocsym(srsym)^.definition,getprocvardef)),
  1099. again,p1,pd);
  1100. if possible_error and
  1101. not(po_classmethod in p1^.procdefinition^.procoptions) then
  1102. Message(parser_e_only_class_methods);
  1103. end;
  1104. propertysym : begin
  1105. { access to property in a method }
  1106. { are we in a class method ? }
  1107. if (srsymtable^.symtabletype=objectsymtable) and
  1108. assigned(aktprocsym) and
  1109. (po_classmethod in aktprocsym^.definition^.procoptions) then
  1110. Message(parser_e_only_class_methods);
  1111. { no method pointer }
  1112. p1:=nil;
  1113. handle_propertysym(srsym,srsymtable,p1,pd);
  1114. end;
  1115. errorsym : begin
  1116. p1:=genzeronode(errorn);
  1117. p1^.resulttype:=generrordef;
  1118. pd:=generrordef;
  1119. if token=_LKLAMMER then
  1120. begin
  1121. consume(_LKLAMMER);
  1122. parse_paras(false,false);
  1123. consume(_RKLAMMER);
  1124. end;
  1125. end;
  1126. else
  1127. begin
  1128. p1:=genzeronode(errorn);
  1129. pd:=generrordef;
  1130. Message(cg_e_illegal_expression);
  1131. end;
  1132. end; { end case }
  1133. end;
  1134. end;
  1135. end;
  1136. end;
  1137. {---------------------------------------------
  1138. Factor_Read_Set
  1139. ---------------------------------------------}
  1140. { Read a set between [] }
  1141. function factor_read_set:ptree;
  1142. var
  1143. p1,
  1144. lastp,
  1145. buildp : ptree;
  1146. begin
  1147. buildp:=nil;
  1148. { be sure that a least one arrayconstructn is used, also for an
  1149. empty [] }
  1150. if token=_RECKKLAMMER then
  1151. buildp:=gennode(arrayconstructn,nil,buildp)
  1152. else
  1153. begin
  1154. while true do
  1155. begin
  1156. p1:=comp_expr(true);
  1157. if token=_POINTPOINT then
  1158. begin
  1159. consume(_POINTPOINT);
  1160. p2:=comp_expr(true);
  1161. p1:=gennode(arrayconstructrangen,p1,p2);
  1162. end;
  1163. { insert at the end of the tree, to get the correct order }
  1164. if not assigned(buildp) then
  1165. begin
  1166. buildp:=gennode(arrayconstructn,p1,nil);
  1167. lastp:=buildp;
  1168. end
  1169. else
  1170. begin
  1171. lastp^.right:=gennode(arrayconstructn,p1,nil);
  1172. lastp:=lastp^.right;
  1173. end;
  1174. { there could be more elements }
  1175. if token=_COMMA then
  1176. consume(_COMMA)
  1177. else
  1178. break;
  1179. end;
  1180. end;
  1181. factor_read_set:=buildp;
  1182. end;
  1183. {---------------------------------------------
  1184. Helpers
  1185. ---------------------------------------------}
  1186. procedure check_tokenpos;
  1187. begin
  1188. if (p1<>oldp1) then
  1189. begin
  1190. if assigned(p1) then
  1191. set_tree_filepos(p1,filepos);
  1192. oldp1:=p1;
  1193. filepos:=tokenpos;
  1194. end;
  1195. end;
  1196. {---------------------------------------------
  1197. PostFixOperators
  1198. ---------------------------------------------}
  1199. procedure postfixoperators;
  1200. var
  1201. store_static : boolean;
  1202. { p1 and p2 must contain valid value_str }
  1203. begin
  1204. check_tokenpos;
  1205. while again do
  1206. begin
  1207. { prevent crashes with unknown types }
  1208. if not assigned(pd) then
  1209. begin
  1210. { try to recover }
  1211. repeat
  1212. case token of
  1213. _CARET:
  1214. consume(_CARET);
  1215. _POINT:
  1216. begin
  1217. consume(_POINT);
  1218. consume(_ID);
  1219. end;
  1220. _LECKKLAMMER:
  1221. begin
  1222. repeat
  1223. consume(token);
  1224. until token in [_RECKKLAMMER,_SEMICOLON];
  1225. end;
  1226. else
  1227. break;
  1228. end;
  1229. until false;
  1230. exit;
  1231. end;
  1232. { handle token }
  1233. case token of
  1234. _CARET:
  1235. begin
  1236. consume(_CARET);
  1237. if (pd^.deftype<>pointerdef) then
  1238. begin
  1239. { ^ as binary operator is a problem!!!! (FK) }
  1240. again:=false;
  1241. Message(cg_e_invalid_qualifier);
  1242. disposetree(p1);
  1243. p1:=genzeronode(errorn);
  1244. end
  1245. else
  1246. begin
  1247. p1:=gensinglenode(derefn,p1);
  1248. pd:=ppointerdef(pd)^.definition;
  1249. end;
  1250. end;
  1251. _LECKKLAMMER:
  1252. begin
  1253. if (pd^.deftype=objectdef) and pobjectdef(pd)^.is_class then
  1254. begin
  1255. { default property }
  1256. propsym:=search_default_property(pobjectdef(pd));
  1257. if not(assigned(propsym)) then
  1258. begin
  1259. disposetree(p1);
  1260. p1:=genzeronode(errorn);
  1261. again:=false;
  1262. message(parser_e_no_default_property_available);
  1263. end
  1264. else
  1265. handle_propertysym(propsym,propsym^.owner,p1,pd);
  1266. end
  1267. else
  1268. begin
  1269. consume(_LECKKLAMMER);
  1270. repeat
  1271. case pd^.deftype of
  1272. pointerdef:
  1273. begin
  1274. p2:=comp_expr(true);
  1275. p1:=gennode(vecn,p1,p2);
  1276. pd:=ppointerdef(pd)^.definition;
  1277. end;
  1278. stringdef : begin
  1279. p2:=comp_expr(true);
  1280. p1:=gennode(vecn,p1,p2);
  1281. pd:=cchardef
  1282. end;
  1283. arraydef : begin
  1284. p2:=comp_expr(true);
  1285. { support SEG:OFS for go32v2 Mem[] }
  1286. if (target_info.target=target_i386_go32v2) and
  1287. (p1^.treetype=loadn) and
  1288. assigned(p1^.symtableentry) and
  1289. assigned(p1^.symtableentry^.owner^.name) and
  1290. (p1^.symtableentry^.owner^.name^='SYSTEM') and
  1291. ((p1^.symtableentry^.name='MEM') or
  1292. (p1^.symtableentry^.name='MEMW') or
  1293. (p1^.symtableentry^.name='MEML')) then
  1294. begin
  1295. if (token=_COLON) then
  1296. begin
  1297. consume(_COLON);
  1298. p3:=gennode(muln,genordinalconstnode($10,s32bitdef),p2);
  1299. p2:=comp_expr(true);
  1300. p2:=gennode(addn,p2,p3);
  1301. p1:=gennode(vecn,p1,p2);
  1302. p1^.memseg:=true;
  1303. p1^.memindex:=true;
  1304. end
  1305. else
  1306. begin
  1307. p1:=gennode(vecn,p1,p2);
  1308. p1^.memindex:=true;
  1309. end;
  1310. end
  1311. else
  1312. p1:=gennode(vecn,p1,p2);
  1313. pd:=parraydef(pd)^.definition;
  1314. end;
  1315. else
  1316. begin
  1317. Message(cg_e_invalid_qualifier);
  1318. disposetree(p1);
  1319. p1:=genzeronode(errorn);
  1320. again:=false;
  1321. end;
  1322. end;
  1323. if token=_COMMA then
  1324. consume(_COMMA)
  1325. else
  1326. break;
  1327. until false;
  1328. consume(_RECKKLAMMER);
  1329. end;
  1330. end;
  1331. _POINT : begin
  1332. consume(_POINT);
  1333. if (pd^.deftype=pointerdef) and
  1334. (m_autoderef in aktmodeswitches) then
  1335. begin
  1336. p1:=gensinglenode(derefn,p1);
  1337. pd:=ppointerdef(pd)^.definition;
  1338. end;
  1339. case pd^.deftype of
  1340. recorddef:
  1341. begin
  1342. sym:=pvarsym(precorddef(pd)^.symtable^.search(pattern));
  1343. if sym=nil then
  1344. begin
  1345. Message1(sym_e_illegal_field,pattern);
  1346. disposetree(p1);
  1347. p1:=genzeronode(errorn);
  1348. end
  1349. else
  1350. begin
  1351. p1:=gensubscriptnode(sym,p1);
  1352. pd:=sym^.definition;
  1353. end;
  1354. consume(_ID);
  1355. end;
  1356. classrefdef:
  1357. begin
  1358. classh:=pobjectdef(pclassrefdef(pd)^.definition);
  1359. sym:=nil;
  1360. while assigned(classh) do
  1361. begin
  1362. sym:=pvarsym(classh^.symtable^.search(pattern));
  1363. srsymtable:=classh^.symtable;
  1364. if assigned(sym) then
  1365. break;
  1366. classh:=classh^.childof;
  1367. end;
  1368. consume(_ID);
  1369. do_member_read(getaddr,sym,p1,pd,again);
  1370. end;
  1371. objectdef:
  1372. begin
  1373. classh:=pobjectdef(pd);
  1374. sym:=nil;
  1375. store_static:=allow_only_static;
  1376. allow_only_static:=false;
  1377. while assigned(classh) do
  1378. begin
  1379. sym:=pvarsym(classh^.symtable^.search(pattern));
  1380. srsymtable:=classh^.symtable;
  1381. if assigned(sym) then
  1382. break;
  1383. classh:=classh^.childof;
  1384. end;
  1385. allow_only_static:=store_static;
  1386. consume(_ID);
  1387. do_member_read(getaddr,sym,p1,pd,again);
  1388. end;
  1389. pointerdef:
  1390. begin
  1391. Message(cg_e_invalid_qualifier);
  1392. if ppointerdef(pd)^.definition^.deftype in [recorddef,objectdef,classrefdef] then
  1393. Message(parser_h_maybe_deref_caret_missing);
  1394. end;
  1395. else
  1396. begin
  1397. Message(cg_e_invalid_qualifier);
  1398. disposetree(p1);
  1399. p1:=genzeronode(errorn);
  1400. end;
  1401. end;
  1402. end;
  1403. else
  1404. begin
  1405. { is this a procedure variable ? }
  1406. if assigned(pd) then
  1407. begin
  1408. if (pd^.deftype=procvardef) then
  1409. begin
  1410. if getprocvar and is_equal(pd,getprocvardef) then
  1411. again:=false
  1412. else
  1413. if (token=_LKLAMMER) or
  1414. ((pprocvardef(pd)^.para1=nil) and
  1415. (not((token in [_ASSIGNMENT,_UNEQUAL,_EQUAL]))) and
  1416. (not afterassignment) and
  1417. (not in_args)) then
  1418. begin
  1419. { do this in a strange way }
  1420. { it's not a clean solution }
  1421. p2:=p1;
  1422. p1:=gencallnode(nil,nil);
  1423. p1^.right:=p2;
  1424. p1^.unit_specific:=unit_specific;
  1425. p1^.symtableprocentry:=pprocsym(sym);
  1426. if token=_LKLAMMER then
  1427. begin
  1428. consume(_LKLAMMER);
  1429. p1^.left:=parse_paras(false,false);
  1430. consume(_RKLAMMER);
  1431. end;
  1432. pd:=pprocvardef(pd)^.retdef;
  1433. { proc():= is never possible }
  1434. if token=_ASSIGNMENT then
  1435. begin
  1436. Message(cg_e_illegal_expression);
  1437. p1:=genzeronode(errorn);
  1438. again:=false;
  1439. end;
  1440. p1^.resulttype:=pd;
  1441. end
  1442. else
  1443. again:=false;
  1444. p1^.resulttype:=pd;
  1445. end
  1446. else
  1447. again:=false;
  1448. end
  1449. else
  1450. again:=false;
  1451. end;
  1452. end;
  1453. check_tokenpos;
  1454. end; { while again }
  1455. end;
  1456. {---------------------------------------------
  1457. Factor (Main)
  1458. ---------------------------------------------}
  1459. begin
  1460. oldp1:=nil;
  1461. p1:=nil;
  1462. filepos:=tokenpos;
  1463. if token=_ID then
  1464. begin
  1465. factor_read_id;
  1466. { handle post fix operators }
  1467. postfixoperators;
  1468. end
  1469. else
  1470. case token of
  1471. _NEW : begin
  1472. consume(_NEW);
  1473. consume(_LKLAMMER);
  1474. {allow_type:=true;}
  1475. p1:=factor(false);
  1476. {allow_type:=false;}
  1477. if p1^.treetype<>typen then
  1478. begin
  1479. Message(type_e_type_id_expected);
  1480. disposetree(p1);
  1481. pd:=generrordef;
  1482. end
  1483. else
  1484. pd:=p1^.typenodetype;
  1485. pd2:=pd;
  1486. if (pd^.deftype<>pointerdef) then
  1487. Message1(type_e_pointer_type_expected,pd^.typename)
  1488. else if {(ppointerdef(pd)^.definition^.deftype<>objectdef)}
  1489. token=_RKLAMMER then
  1490. begin
  1491. if (ppointerdef(pd)^.definition^.deftype=objectdef) and
  1492. (oo_has_vmt in pobjectdef(ppointerdef(pd)^.definition)^.objectoptions) then
  1493. Message(parser_w_use_extended_syntax_for_objects);
  1494. p1:=gensinglenode(newn,nil);
  1495. p1^.resulttype:=pd2;
  1496. consume(_RKLAMMER);
  1497. (*Message(parser_e_pointer_to_class_expected);
  1498. { if an error occurs, read til the end of
  1499. the new statement }
  1500. p1:=genzeronode(errorn);
  1501. l:=1;
  1502. while true do
  1503. begin
  1504. case token of
  1505. _LKLAMMER : inc(l);
  1506. _RKLAMMER : dec(l);
  1507. end;
  1508. consume(token);
  1509. if l=0 then
  1510. break;
  1511. end;*)
  1512. end
  1513. else
  1514. begin
  1515. disposetree(p1);
  1516. p1:=genzeronode(hnewn);
  1517. p1^.resulttype:=ppointerdef(pd)^.definition;
  1518. consume(_COMMA);
  1519. afterassignment:=false;
  1520. { determines the current object defintion }
  1521. classh:=pobjectdef(ppointerdef(pd)^.definition);
  1522. { check for an abstract class }
  1523. if (oo_has_abstract in classh^.objectoptions) then
  1524. Message(sym_e_no_instance_of_abstract_object);
  1525. { search the constructor also in the symbol tables of
  1526. the parents }
  1527. { no constructor found }
  1528. sym:=nil;
  1529. while assigned(classh) do
  1530. begin
  1531. sym:=pvarsym(classh^.symtable^.search(pattern));
  1532. srsymtable:=classh^.symtable;
  1533. if assigned(sym) then
  1534. break;
  1535. classh:=classh^.childof;
  1536. end;
  1537. consume(_ID);
  1538. do_member_read(false,sym,p1,pd,again);
  1539. if (p1^.treetype<>calln) or
  1540. (assigned(p1^.procdefinition) and
  1541. (p1^.procdefinition^.proctypeoption<>potype_constructor)) then
  1542. Message(parser_e_expr_have_to_be_constructor_call);
  1543. p1:=gensinglenode(newn,p1);
  1544. { set the resulttype }
  1545. p1^.resulttype:=pd2;
  1546. consume(_RKLAMMER);
  1547. end;
  1548. postfixoperators;
  1549. end;
  1550. _SELF : begin
  1551. again:=true;
  1552. consume(_SELF);
  1553. if not assigned(procinfo._class) then
  1554. begin
  1555. p1:=genzeronode(errorn);
  1556. pd:=generrordef;
  1557. again:=false;
  1558. Message(parser_e_self_not_in_method);
  1559. end
  1560. else
  1561. begin
  1562. if (po_classmethod in aktprocsym^.definition^.procoptions) then
  1563. begin
  1564. { self in class methods is a class reference type }
  1565. pd:=new(pclassrefdef,init(procinfo._class));
  1566. p1:=genselfnode(pd);
  1567. p1^.resulttype:=pd;
  1568. end
  1569. else
  1570. begin
  1571. p1:=genselfnode(procinfo._class);
  1572. p1^.resulttype:=procinfo._class;
  1573. end;
  1574. pd:=p1^.resulttype;
  1575. postfixoperators;
  1576. end;
  1577. end;
  1578. _INHERITED : begin
  1579. again:=true;
  1580. consume(_INHERITED);
  1581. if assigned(procinfo._class) then
  1582. begin
  1583. classh:=procinfo._class^.childof;
  1584. while assigned(classh) do
  1585. begin
  1586. srsymtable:=pobjectdef(classh)^.symtable;
  1587. sym:=pvarsym(srsymtable^.search(pattern));
  1588. if assigned(sym) then
  1589. begin
  1590. p1:=genzeronode(typen);
  1591. p1^.resulttype:=classh;
  1592. pd:=p1^.resulttype;
  1593. consume(_ID);
  1594. do_member_read(false,sym,p1,pd,again);
  1595. break;
  1596. end;
  1597. classh:=classh^.childof;
  1598. end;
  1599. if classh=nil then
  1600. begin
  1601. Message1(sym_e_id_no_member,pattern);
  1602. again:=false;
  1603. pd:=generrordef;
  1604. p1:=genzeronode(errorn);
  1605. end;
  1606. end
  1607. else
  1608. begin
  1609. Message(parser_e_generic_methods_only_in_methods);
  1610. again:=false;
  1611. pd:=generrordef;
  1612. p1:=genzeronode(errorn);
  1613. end;
  1614. postfixoperators;
  1615. end;
  1616. _INTCONST : begin
  1617. valint(pattern,l,code);
  1618. if code<>0 then
  1619. begin
  1620. val(pattern,d,code);
  1621. if code<>0 then
  1622. begin
  1623. Message(cg_e_invalid_integer);
  1624. consume(_INTCONST);
  1625. l:=1;
  1626. p1:=genordinalconstnode(l,s32bitdef);
  1627. end
  1628. else
  1629. begin
  1630. consume(_INTCONST);
  1631. p1:=genrealconstnode(d,bestrealdef^);
  1632. end;
  1633. end
  1634. else
  1635. begin
  1636. consume(_INTCONST);
  1637. p1:=genordinalconstnode(l,s32bitdef);
  1638. end;
  1639. end;
  1640. _REALNUMBER : begin
  1641. val(pattern,d,code);
  1642. if code<>0 then
  1643. begin
  1644. Message(parser_e_error_in_real);
  1645. d:=1.0;
  1646. end;
  1647. consume(_REALNUMBER);
  1648. p1:=genrealconstnode(d,bestrealdef^);
  1649. end;
  1650. _STRING : begin
  1651. pd:=stringtype;
  1652. { STRING can be also a type cast }
  1653. if token=_LKLAMMER then
  1654. begin
  1655. consume(_LKLAMMER);
  1656. p1:=comp_expr(true);
  1657. consume(_RKLAMMER);
  1658. p1:=gentypeconvnode(p1,pd);
  1659. p1^.explizit:=true;
  1660. { handle postfix operators here e.g. string(a)[10] }
  1661. again:=true;
  1662. postfixoperators;
  1663. end
  1664. else
  1665. p1:=gentypenode(pd,nil);
  1666. end;
  1667. _FILE : begin
  1668. pd:=cfiledef;
  1669. consume(_FILE);
  1670. { FILE can be also a type cast }
  1671. if token=_LKLAMMER then
  1672. begin
  1673. consume(_LKLAMMER);
  1674. p1:=comp_expr(true);
  1675. consume(_RKLAMMER);
  1676. p1:=gentypeconvnode(p1,pd);
  1677. p1^.explizit:=true;
  1678. { handle postfix operators here e.g. string(a)[10] }
  1679. again:=true;
  1680. postfixoperators;
  1681. end
  1682. else
  1683. p1:=gentypenode(pd,nil);
  1684. end;
  1685. _CSTRING : begin
  1686. p1:=genstringconstnode(pattern);
  1687. consume(_CSTRING);
  1688. end;
  1689. _CCHAR : begin
  1690. p1:=genordinalconstnode(ord(pattern[1]),cchardef);
  1691. consume(_CCHAR);
  1692. end;
  1693. _KLAMMERAFFE : begin
  1694. consume(_KLAMMERAFFE);
  1695. got_addrn:=true;
  1696. { support both @<x> and @(<x>) }
  1697. if token=_LKLAMMER then
  1698. begin
  1699. consume(_LKLAMMER);
  1700. p1:=factor(true);
  1701. consume(_RKLAMMER);
  1702. end
  1703. else
  1704. p1:=factor(true);
  1705. got_addrn:=false;
  1706. p1:=gensinglenode(addrn,p1);
  1707. end;
  1708. _LKLAMMER : begin
  1709. consume(_LKLAMMER);
  1710. p1:=comp_expr(true);
  1711. consume(_RKLAMMER);
  1712. { it's not a good solution }
  1713. { but (a+b)^ makes some problems }
  1714. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1715. begin
  1716. { we need the resulttype }
  1717. { of the expression in pd }
  1718. do_firstpass(p1);
  1719. pd:=p1^.resulttype;
  1720. again:=true;
  1721. postfixoperators;
  1722. end;
  1723. end;
  1724. _LECKKLAMMER : begin
  1725. consume(_LECKKLAMMER);
  1726. p1:=factor_read_set;
  1727. consume(_RECKKLAMMER);
  1728. end;
  1729. _PLUS : begin
  1730. consume(_PLUS);
  1731. p1:=factor(false);
  1732. end;
  1733. _MINUS : begin
  1734. consume(_MINUS);
  1735. p1:=factor(false);
  1736. p1:=gensinglenode(umminusn,p1);
  1737. end;
  1738. _NOT : begin
  1739. consume(_NOT);
  1740. p1:=factor(false);
  1741. p1:=gensinglenode(notn,p1);
  1742. end;
  1743. _TRUE : begin
  1744. consume(_TRUE);
  1745. p1:=genordinalconstnode(1,booldef);
  1746. end;
  1747. _FALSE : begin
  1748. consume(_FALSE);
  1749. p1:=genordinalconstnode(0,booldef);
  1750. end;
  1751. _NIL : begin
  1752. consume(_NIL);
  1753. p1:=genzeronode(niln);
  1754. end;
  1755. else
  1756. begin
  1757. p1:=genzeronode(errorn);
  1758. consume(token);
  1759. Message(cg_e_illegal_expression);
  1760. end;
  1761. end;
  1762. { generate error node if no node is created }
  1763. if not assigned(p1) then
  1764. p1:=genzeronode(errorn);
  1765. { tp7 procvar handling, but not if the next token
  1766. will be a := }
  1767. if (m_tp_procvar in aktmodeswitches) and
  1768. (token<>_ASSIGNMENT) then
  1769. check_tp_procvar(p1);
  1770. factor:=p1;
  1771. check_tokenpos;
  1772. end;
  1773. {****************************************************************************
  1774. Sub_Expr
  1775. ****************************************************************************}
  1776. type
  1777. Toperator_precedence=(opcompare,opaddition,opmultiply);
  1778. Ttok2nodeRec=record
  1779. tok : ttoken;
  1780. nod : ttreetyp;
  1781. end;
  1782. const
  1783. tok2nodes=23;
  1784. tok2node:array[1..tok2nodes] of ttok2noderec=(
  1785. (tok:_PLUS ;nod:addn),
  1786. (tok:_MINUS ;nod:subn),
  1787. (tok:_STAR ;nod:muln),
  1788. (tok:_SLASH ;nod:slashn),
  1789. (tok:_EQUAL ;nod:equaln),
  1790. (tok:_GT ;nod:gtn),
  1791. (tok:_LT ;nod:ltn),
  1792. (tok:_GTE ;nod:gten),
  1793. (tok:_LTE ;nod:lten),
  1794. (tok:_SYMDIF ;nod:symdifn),
  1795. (tok:_STARSTAR;nod:starstarn),
  1796. (tok:_CARET ;nod:caretn),
  1797. (tok:_UNEQUAL ;nod:unequaln),
  1798. (tok:_AS ;nod:asn),
  1799. (tok:_IN ;nod:inn),
  1800. (tok:_IS ;nod:isn),
  1801. (tok:_OR ;nod:orn),
  1802. (tok:_AND ;nod:andn),
  1803. (tok:_DIV ;nod:divn),
  1804. (tok:_MOD ;nod:modn),
  1805. (tok:_SHL ;nod:shln),
  1806. (tok:_SHR ;nod:shrn),
  1807. (tok:_XOR ;nod:xorn)
  1808. );
  1809. operator_levels:array[Toperator_precedence] of set of Ttoken=
  1810. ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_IN,_IS],
  1811. [_PLUS,_MINUS,_OR,_XOR],
  1812. [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,_DIV,_MOD,_AND,_SHL,_SHR,_AS]);
  1813. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):Ptree;
  1814. {Reads a subexpression while the operators are of the current precedence
  1815. level, or any higher level. Replaces the old term, simpl_expr and
  1816. simpl2_expr.}
  1817. var
  1818. low,high,mid : longint;
  1819. p1,p2 : Ptree;
  1820. oldt : Ttoken;
  1821. filepos : tfileposinfo;
  1822. begin
  1823. if pred_level=opmultiply then
  1824. p1:=factor(false)
  1825. else
  1826. p1:=sub_expr(succ(pred_level),true);
  1827. repeat
  1828. if (token in operator_levels[pred_level]) and
  1829. ((token<>_EQUAL) or accept_equal) then
  1830. begin
  1831. oldt:=token;
  1832. filepos:=tokenpos;
  1833. consume(token);
  1834. if pred_level=opmultiply then
  1835. p2:=factor(false)
  1836. else
  1837. p2:=sub_expr(succ(pred_level),true);
  1838. low:=1;
  1839. high:=tok2nodes;
  1840. while (low<high) do
  1841. begin
  1842. mid:=(low+high+1) shr 1;
  1843. if oldt<tok2node[mid].tok then
  1844. high:=mid-1
  1845. else
  1846. low:=mid;
  1847. end;
  1848. if tok2node[high].tok=oldt then
  1849. p1:=gennode(tok2node[high].nod,p1,p2)
  1850. else
  1851. p1:=gennode(nothingn,p1,p2);
  1852. set_tree_filepos(p1,filepos);
  1853. end
  1854. else
  1855. break;
  1856. until false;
  1857. sub_expr:=p1;
  1858. end;
  1859. function comp_expr(accept_equal : boolean):Ptree;
  1860. var
  1861. oldafterassignment : boolean;
  1862. p1 : ptree;
  1863. begin
  1864. oldafterassignment:=afterassignment;
  1865. afterassignment:=true;
  1866. p1:=sub_expr(opcompare,accept_equal);
  1867. afterassignment:=oldafterassignment;
  1868. comp_expr:=p1;
  1869. end;
  1870. function expr : ptree;
  1871. var
  1872. p1,p2 : ptree;
  1873. oldafterassignment : boolean;
  1874. oldp1 : ptree;
  1875. filepos : tfileposinfo;
  1876. begin
  1877. oldafterassignment:=afterassignment;
  1878. p1:=sub_expr(opcompare,true);
  1879. filepos:=tokenpos;
  1880. if (m_tp_procvar in aktmodeswitches) and
  1881. (token<>_ASSIGNMENT) then
  1882. check_tp_procvar(p1);
  1883. if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  1884. afterassignment:=true;
  1885. oldp1:=p1;
  1886. case token of
  1887. _POINTPOINT : begin
  1888. consume(_POINTPOINT);
  1889. p2:=sub_expr(opcompare,true);
  1890. p1:=gennode(rangen,p1,p2);
  1891. end;
  1892. _ASSIGNMENT : begin
  1893. consume(_ASSIGNMENT);
  1894. { avoid a firstpass of a procedure if
  1895. it must be assigned to a procvar }
  1896. { should be recursive for a:=b:=c !!! }
  1897. if (p1^.resulttype<>nil) and (p1^.resulttype^.deftype=procvardef) then
  1898. begin
  1899. getprocvar:=true;
  1900. getprocvardef:=pprocvardef(p1^.resulttype);
  1901. end;
  1902. p2:=sub_expr(opcompare,true);
  1903. if getprocvar then
  1904. begin
  1905. if (p2^.treetype=calln) then
  1906. handle_procvar(getprocvardef,p2)
  1907. else
  1908. { also allow p:= proc(t); !! (PM) }
  1909. if (p2^.treetype=typeconvn) and
  1910. (p2^.left^.treetype=calln) then
  1911. handle_procvar(getprocvardef,p2^.left);
  1912. end;
  1913. getprocvar:=false;
  1914. p1:=gennode(assignn,p1,p2);
  1915. end;
  1916. { this is the code for C like assignements }
  1917. { from an improvement of Peter Schaefer }
  1918. _PLUSASN : begin
  1919. consume(_PLUSASN );
  1920. p2:=sub_expr(opcompare,true);
  1921. p1:=gennode(assignn,p1,gennode(addn,getcopy(p1),p2));
  1922. { was first
  1923. p1:=gennode(assignn,p1,gennode(addn,p1,p2));
  1924. but disposetree assumes that we have a real
  1925. *** tree *** }
  1926. end;
  1927. _MINUSASN : begin
  1928. consume(_MINUSASN );
  1929. p2:=sub_expr(opcompare,true);
  1930. p1:=gennode(assignn,p1,gennode(subn,getcopy(p1),p2));
  1931. end;
  1932. _STARASN : begin
  1933. consume(_STARASN );
  1934. p2:=sub_expr(opcompare,true);
  1935. p1:=gennode(assignn,p1,gennode(muln,getcopy(p1),p2));
  1936. end;
  1937. _SLASHASN : begin
  1938. consume(_SLASHASN );
  1939. p2:=sub_expr(opcompare,true);
  1940. p1:=gennode(assignn,p1,gennode(slashn,getcopy(p1),p2));
  1941. end;
  1942. end;
  1943. afterassignment:=oldafterassignment;
  1944. if p1<>oldp1 then
  1945. set_tree_filepos(p1,filepos);
  1946. expr:=p1;
  1947. end;
  1948. function get_intconst:longint;
  1949. {Reads an expression, tries to evalute it and check if it is an integer
  1950. constant. Then the constant is returned.}
  1951. var
  1952. p:Ptree;
  1953. begin
  1954. p:=comp_expr(true);
  1955. do_firstpass(p);
  1956. if not codegenerror then
  1957. begin
  1958. if (p^.treetype<>ordconstn) and
  1959. (p^.resulttype^.deftype=orddef) and
  1960. not(Porddef(p^.resulttype)^.typ in [uvoid,uchar,bool8bit,bool16bit,bool32bit]) then
  1961. Message(cg_e_illegal_expression)
  1962. else
  1963. get_intconst:=p^.value;
  1964. end;
  1965. disposetree(p);
  1966. end;
  1967. function get_stringconst:string;
  1968. {Reads an expression, tries to evaluate it and checks if it is a string
  1969. constant. Then the constant is returned.}
  1970. var
  1971. p:Ptree;
  1972. begin
  1973. get_stringconst:='';
  1974. p:=comp_expr(true);
  1975. do_firstpass(p);
  1976. if p^.treetype<>stringconstn then
  1977. begin
  1978. if (p^.treetype=ordconstn) and is_char(p^.resulttype) then
  1979. get_stringconst:=char(p^.value)
  1980. else
  1981. Message(cg_e_illegal_expression);
  1982. end
  1983. else
  1984. get_stringconst:=strpas(p^.value_str);
  1985. disposetree(p);
  1986. end;
  1987. end.
  1988. {
  1989. $Log$
  1990. Revision 1.141 1999-09-11 19:47:26 florian
  1991. * bug fix for @tobject.method, fixes bug 557, 605 and 606
  1992. Revision 1.140 1999/09/11 09:08:33 florian
  1993. * fixed bug 596
  1994. * fixed some problems with procedure variables and procedures of object,
  1995. especially in TP mode. Procedure of object doesn't apply only to classes,
  1996. it is also allowed for objects !!
  1997. Revision 1.139 1999/09/10 18:48:07 florian
  1998. * some bug fixes (e.g. must_be_valid and procinfo.funcret_is_valid)
  1999. * most things for stored properties fixed
  2000. Revision 1.138 1999/09/07 08:01:20 peter
  2001. * @(<x>) support
  2002. Revision 1.137 1999/09/01 22:08:58 peter
  2003. * fixed crash with assigned()
  2004. Revision 1.136 1999/08/15 22:47:45 peter
  2005. * fixed property writeaccess which was buggy after my previous
  2006. subscribed property access
  2007. Revision 1.135 1999/08/14 00:38:56 peter
  2008. * hack to support property with record fields
  2009. Revision 1.134 1999/08/09 22:16:29 peter
  2010. * fixed crash after wrong para's with class contrustor
  2011. Revision 1.133 1999/08/05 16:53:04 peter
  2012. * V_Fatal=1, all other V_ are also increased
  2013. * Check for local procedure when assigning procvar
  2014. * fixed comment parsing because directives
  2015. * oldtp mode directives better supported
  2016. * added some messages to errore.msg
  2017. Revision 1.132 1999/08/04 13:49:45 florian
  2018. * new(...)^. is now allowed
  2019. Revision 1.131 1999/08/04 13:02:55 jonas
  2020. * all tokens now start with an underscore
  2021. * PowerPC compiles!!
  2022. Revision 1.130 1999/08/04 00:23:12 florian
  2023. * renamed i386asm and i386base to cpuasm and cpubase
  2024. Revision 1.129 1999/08/03 22:02:59 peter
  2025. * moved bitmask constants to sets
  2026. * some other type/const renamings
  2027. Revision 1.128 1999/08/03 13:50:17 michael
  2028. + Changes for alpha
  2029. Revision 1.127 1999/08/01 18:28:13 florian
  2030. * modifications for the new code generator
  2031. Revision 1.126 1999/07/30 12:28:40 peter
  2032. * fixed crash with unknown id and colon parameter in write
  2033. Revision 1.125 1999/07/27 23:42:14 peter
  2034. * indirect type referencing is now allowed
  2035. Revision 1.124 1999/07/23 21:31:42 peter
  2036. * fixed crash with resourcestring
  2037. Revision 1.123 1999/07/23 11:37:46 peter
  2038. * error for illegal type reference, instead of 10998
  2039. Revision 1.122 1999/07/22 09:37:52 florian
  2040. + resourcestring implemented
  2041. + start of longstring support
  2042. Revision 1.121 1999/07/16 10:04:35 peter
  2043. * merged
  2044. Revision 1.120 1999/07/06 22:38:11 florian
  2045. * another fix for TP/Delphi styled procedure variables
  2046. Revision 1.119 1999/07/05 20:13:16 peter
  2047. * removed temp defines
  2048. Revision 1.118 1999/07/01 21:33:57 peter
  2049. * merged
  2050. Revision 1.117 1999/06/30 15:43:20 florian
  2051. * two bugs regarding method variables fixed
  2052. - if you take in a method the address of another method
  2053. don't need self anymore
  2054. - if the class pointer was in a register, wrong code for a method
  2055. variable load was generated
  2056. Revision 1.116 1999/06/26 00:24:53 pierre
  2057. * mereg from fixes-0_99_12 branch
  2058. Revision 1.112.2.8 1999/07/16 09:54:57 peter
  2059. * @procvar support in tp7 mode works again
  2060. Revision 1.112.2.7 1999/07/07 07:53:10 michael
  2061. + Merged patches from florian
  2062. Revision 1.112.2.6 1999/07/01 21:31:59 peter
  2063. * procvar fixes again
  2064. Revision 1.112.2.5 1999/07/01 15:17:17 peter
  2065. * methoidpointer fixes from florian
  2066. Revision 1.112.2.4 1999/06/26 00:22:30 pierre
  2067. * wrong warnings in -So mode suppressed
  2068. Revision 1.112.2.3 1999/06/17 12:51:44 pierre
  2069. * changed is_assignment_overloaded into
  2070. function assignment_overloaded : pprocdef
  2071. to allow overloading of assignment with only different result type
  2072. Revision 1.112.2.2 1999/06/15 18:54:52 peter
  2073. * more procvar fixes
  2074. Revision 1.112.2.1 1999/06/13 22:38:09 peter
  2075. * tp_procvar check for loading of procvars when getaddr=false
  2076. Revision 1.112 1999/06/02 22:44:11 pierre
  2077. * previous wrong log corrected
  2078. Revision 1.111 1999/06/02 22:25:43 pierre
  2079. * changed $ifdef FPC @ into $ifndef TP
  2080. * changes for correct procvar handling under tp mode
  2081. Revision 1.110 1999/06/01 19:27:55 peter
  2082. * better checks for procvar and methodpointer
  2083. Revision 1.109 1999/05/27 19:44:46 peter
  2084. * removed oldasm
  2085. * plabel -> pasmlabel
  2086. * -a switches to source writing automaticly
  2087. * assembler readers OOPed
  2088. * asmsymbol automaticly external
  2089. * jumptables and other label fixes for asm readers
  2090. Revision 1.108 1999/05/18 14:15:54 peter
  2091. * containsself fixes
  2092. * checktypes()
  2093. Revision 1.107 1999/05/18 09:52:18 peter
  2094. * procedure of object and addrn fixes
  2095. Revision 1.106 1999/05/16 17:06:31 peter
  2096. * remove firstcallparan which looks obsolete
  2097. Revision 1.105 1999/05/12 22:36:09 florian
  2098. * override isn't allowed in objects!
  2099. Revision 1.104 1999/05/07 10:35:23 florian
  2100. * first fix for a problem with method pointer properties, still doesn't work
  2101. with WITH
  2102. Revision 1.103 1999/05/06 21:40:16 peter
  2103. * fixed crash
  2104. Revision 1.101 1999/05/06 09:05:21 peter
  2105. * generic write_float and str_float
  2106. * fixed constant float conversions
  2107. Revision 1.100 1999/05/04 21:44:57 florian
  2108. * changes to compile it with Delphi 4.0
  2109. Revision 1.99 1999/05/01 13:24:31 peter
  2110. * merged nasm compiler
  2111. * old asm moved to oldasm/
  2112. Revision 1.98 1999/04/26 18:29:56 peter
  2113. * farpointerdef moved into pointerdef.is_far
  2114. Revision 1.97 1999/04/19 09:27:48 peter
  2115. * removed my property fix
  2116. Revision 1.96 1999/04/19 09:13:47 peter
  2117. * class property without write support
  2118. Revision 1.95 1999/04/19 06:10:08 florian
  2119. * property problem fixed: a propertysym is only a write
  2120. access if it is followed by a assignment token
  2121. Revision 1.94 1999/04/17 13:12:17 peter
  2122. * addr() internal
  2123. Revision 1.93 1999/04/15 09:00:08 peter
  2124. * fixed property write
  2125. Revision 1.92 1999/04/08 20:59:43 florian
  2126. * fixed problem with default properties which are a class
  2127. * case bug (from the mailing list with -O2) fixed, the
  2128. distance of the case labels can be greater than the positive
  2129. range of a longint => it is now a dword for fpc
  2130. Revision 1.91 1999/04/06 11:21:56 peter
  2131. * more use of ttoken
  2132. Revision 1.90 1999/03/31 13:55:12 peter
  2133. * assembler inlining working for ag386bin
  2134. Revision 1.89 1999/03/26 00:05:36 peter
  2135. * released valintern
  2136. + deffile is now removed when compiling is finished
  2137. * ^( compiles now correct
  2138. + static directive
  2139. * shrd fixed
  2140. Revision 1.88 1999/03/24 23:17:15 peter
  2141. * fixed bugs 212,222,225,227,229,231,233
  2142. Revision 1.87 1999/03/16 17:52:52 jonas
  2143. * changes for internal Val code (do a "make cycle OPT=-dvalintern" to test)
  2144. * in cgi386inl: also range checking for subrange types (compile with "-dreadrangecheck")
  2145. * in cgai386: also small fixes to emitrangecheck
  2146. Revision 1.86 1999/03/04 13:55:44 pierre
  2147. * some m68k fixes (still not compilable !)
  2148. * new(tobj) does not give warning if tobj has no VMT !
  2149. Revision 1.85 1999/02/22 15:09:39 florian
  2150. * behaviaor of PROTECTED and PRIVATE fixed, works now like TP/Delphi
  2151. Revision 1.84 1999/02/22 02:15:26 peter
  2152. * updates for ag386bin
  2153. Revision 1.83 1999/02/11 09:46:25 pierre
  2154. * fix for normal method calls inside static methods :
  2155. WARNING there were both parser and codegen errors !!
  2156. added static_call boolean to calln tree
  2157. Revision 1.82 1999/01/28 14:06:47 florian
  2158. * small fix for method pointers
  2159. * found the annoying strpas bug, mainly nested call to type cast which
  2160. use ansistrings crash
  2161. Revision 1.81 1999/01/27 00:13:55 florian
  2162. * "procedure of object"-stuff fixed
  2163. Revision 1.80 1999/01/21 16:41:01 pierre
  2164. * fix for constructor inside with statements
  2165. Revision 1.79 1998/12/30 22:15:48 peter
  2166. + farpointer type
  2167. * absolutesym now also stores if its far
  2168. Revision 1.78 1998/12/11 00:03:32 peter
  2169. + globtype,tokens,version unit splitted from globals
  2170. Revision 1.77 1998/12/04 10:18:09 florian
  2171. * some stuff for procedures of object added
  2172. * bug with overridden virtual constructors fixed (reported by Italo Gomes)
  2173. Revision 1.76 1998/11/27 14:50:40 peter
  2174. + open strings, $P switch support
  2175. Revision 1.75 1998/11/25 19:12:51 pierre
  2176. * var:=new(pointer_type) support added
  2177. Revision 1.74 1998/11/13 10:18:11 peter
  2178. + nil constants
  2179. Revision 1.73 1998/11/05 12:02:52 peter
  2180. * released useansistring
  2181. * removed -Sv, its now available in fpc modes
  2182. Revision 1.72 1998/11/04 10:11:41 peter
  2183. * ansistring fixes
  2184. Revision 1.71 1998/10/22 23:57:29 peter
  2185. * fixed filedef for typenodetype
  2186. Revision 1.70 1998/10/21 15:12:54 pierre
  2187. * bug fix for IOCHECK inside a procedure with iocheck modifier
  2188. * removed the GPF for unexistant overloading
  2189. (firstcall was called with procedinition=nil !)
  2190. * changed typen to what Florian proposed
  2191. gentypenode(p : pdef) sets the typenodetype field
  2192. and resulttype is only set if inside bt_type block !
  2193. Revision 1.69 1998/10/20 15:10:19 pierre
  2194. * type ptree only allowed inside expression
  2195. if following sizeof typeof low high or as first arg of new !!
  2196. Revision 1.68 1998/10/20 11:15:44 pierre
  2197. * calling of private method allowed inside child object method
  2198. Revision 1.67 1998/10/19 08:54:57 pierre
  2199. * wrong stabs info corrected once again !!
  2200. + variable vmt offset with vmt field only if required
  2201. implemented now !!!
  2202. Revision 1.66 1998/10/15 15:13:28 pierre
  2203. + added oo_hasconstructor and oo_hasdestructor
  2204. for objects options
  2205. Revision 1.65 1998/10/13 13:10:24 peter
  2206. * new style for m68k/i386 infos and enums
  2207. Revision 1.64 1998/10/12 12:20:55 pierre
  2208. + added tai_const_symbol_offset
  2209. for r : pointer = @var.field;
  2210. * better message for different arg names on implementation
  2211. of function
  2212. Revision 1.63 1998/10/12 10:28:30 florian
  2213. + auto dereferencing of pointers to structured types in delphi mode
  2214. Revision 1.62 1998/10/12 10:05:41 peter
  2215. * fixed mem leak with arrayconstrutor
  2216. Revision 1.61 1998/10/05 13:57:15 peter
  2217. * crash preventions
  2218. Revision 1.60 1998/10/05 12:32:46 peter
  2219. + assert() support
  2220. Revision 1.59 1998/10/01 14:56:24 peter
  2221. * crash preventions
  2222. Revision 1.58 1998/09/30 07:40:35 florian
  2223. * better error recovering
  2224. Revision 1.57 1998/09/28 16:18:16 florian
  2225. * two fixes to get ansi strings work
  2226. Revision 1.56 1998/09/26 17:45:36 peter
  2227. + idtoken and only one token table
  2228. Revision 1.55 1998/09/24 23:49:10 peter
  2229. + aktmodeswitches
  2230. Revision 1.54 1998/09/23 15:46:39 florian
  2231. * problem with with and classes fixed
  2232. Revision 1.53 1998/09/23 09:58:54 peter
  2233. * first working array of const things
  2234. Revision 1.52 1998/09/20 09:38:45 florian
  2235. * hasharray for defs fixed
  2236. * ansistring code generation corrected (init/final, assignement)
  2237. Revision 1.51 1998/09/18 16:03:43 florian
  2238. * some changes to compile with Delphi
  2239. Revision 1.50 1998/09/17 13:41:18 pierre
  2240. sizeof(TPOINT) problem
  2241. Revision 1.49.2.1 1998/09/17 08:42:31 pierre
  2242. TPOINT sizeof fix
  2243. Revision 1.49 1998/09/09 11:50:53 pierre
  2244. * forward def are not put in record or objects
  2245. + added check for forwards also in record and objects
  2246. * dummy parasymtable for unit initialization removed from
  2247. symtable stack
  2248. Revision 1.48 1998/09/07 22:25:53 peter
  2249. * fixed str(boolean,string) which was allowed
  2250. * fixed write(' ':<int expression>) only constants where allowed :(
  2251. Revision 1.47 1998/09/07 18:46:10 peter
  2252. * update smartlinking, uses getdatalabel
  2253. * renamed ptree.value vars to value_str,value_real,value_set
  2254. Revision 1.46 1998/09/04 08:42:03 peter
  2255. * updated some error messages
  2256. Revision 1.45 1998/09/01 17:39:49 peter
  2257. + internal constant functions
  2258. Revision 1.44 1998/08/28 10:54:24 peter
  2259. * fixed smallset generation from elements, it has never worked before!
  2260. Revision 1.43 1998/08/23 16:07:24 florian
  2261. * internalerror with mod/div fixed
  2262. Revision 1.42 1998/08/21 14:08:50 pierre
  2263. + TEST_FUNCRET now default (old code removed)
  2264. works also for m68k (at least compiles)
  2265. Revision 1.41 1998/08/20 21:36:39 peter
  2266. * fixed 'with object do' bug
  2267. Revision 1.40 1998/08/20 09:26:41 pierre
  2268. + funcret setting in underproc testing
  2269. compile with _dTEST_FUNCRET
  2270. Revision 1.39 1998/08/18 16:48:48 pierre
  2271. * bug for -So proc assignment to p^rocvar fixed
  2272. Revision 1.38 1998/08/18 14:17:09 pierre
  2273. * bug about assigning the return value of a function to
  2274. a procvar fixed : warning
  2275. assigning a proc to a procvar need @ in FPC mode !!
  2276. * missing file/line info restored
  2277. Revision 1.37 1998/08/18 09:24:43 pierre
  2278. * small warning position bug fixed
  2279. * support_mmx switches splitting was missing
  2280. * rhide error and warning output corrected
  2281. Revision 1.36 1998/08/15 16:50:29 peter
  2282. * fixed proc()=expr which was not allowed anymore by my previous fix
  2283. Revision 1.35 1998/08/14 18:18:46 peter
  2284. + dynamic set contruction
  2285. * smallsets are now working (always longint size)
  2286. Revision 1.34 1998/08/13 11:00:12 peter
  2287. * fixed procedure<>procedure construct
  2288. Revision 1.33 1998/08/11 15:31:39 peter
  2289. * write extended to ppu file
  2290. * new version 0.99.7
  2291. Revision 1.32 1998/08/11 14:05:32 peter
  2292. * fixed sizeof(array of char)
  2293. Revision 1.31 1998/08/10 14:50:11 peter
  2294. + localswitches, moduleswitches, globalswitches splitting
  2295. Revision 1.30 1998/07/28 21:52:54 florian
  2296. + implementation of raise and try..finally
  2297. + some misc. exception stuff
  2298. Revision 1.29 1998/07/27 21:57:13 florian
  2299. * fix to allow tv like stream registration:
  2300. @tmenu.load doesn't work if load had parameters or if load was only
  2301. declared in an anchestor class of tmenu
  2302. Revision 1.28 1998/07/14 21:46:51 peter
  2303. * updated messages file
  2304. Revision 1.27 1998/06/25 14:04:23 peter
  2305. + internal inc/dec
  2306. Revision 1.26 1998/06/09 16:01:46 pierre
  2307. + added procedure directive parsing for procvars
  2308. (accepted are popstack cdecl and pascal)
  2309. + added C vars with the following syntax
  2310. var C calias 'true_c_name';(can be followed by external)
  2311. reason is that you must add the Cprefix
  2312. which is target dependent
  2313. Revision 1.25 1998/06/05 14:37:33 pierre
  2314. * fixes for inline for operators
  2315. * inline procedure more correctly restricted
  2316. Revision 1.24 1998/06/04 23:51:52 peter
  2317. * m68k compiles
  2318. + .def file creation moved to gendef.pas so it could also be used
  2319. for win32
  2320. Revision 1.23 1998/06/04 09:55:40 pierre
  2321. * demangled name of procsym reworked to become independant of the mangling scheme
  2322. Revision 1.22 1998/06/02 17:03:03 pierre
  2323. * with node corrected for objects
  2324. * small bugs for SUPPORT_MMX fixed
  2325. Revision 1.21 1998/05/27 19:45:05 peter
  2326. * symtable.pas splitted into includefiles
  2327. * symtable adapted for $ifdef NEWPPU
  2328. Revision 1.20 1998/05/26 07:53:59 pierre
  2329. * bug fix for empty sets (nil pd was dereferenced )
  2330. Revision 1.19 1998/05/25 17:11:43 pierre
  2331. * firstpasscount bug fixed
  2332. now all is already set correctly the first time
  2333. under EXTDEBUG try -gp to skip all other firstpasses
  2334. it works !!
  2335. * small bug fixes
  2336. - for smallsets with -dTESTSMALLSET
  2337. - some warnings removed (by correcting code !)
  2338. Revision 1.18 1998/05/23 01:21:20 peter
  2339. + aktasmmode, aktoptprocessor, aktoutputformat
  2340. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  2341. + $LIBNAME to set the library name where the unit will be put in
  2342. * splitted cgi386 a bit (codeseg to large for bp7)
  2343. * nasm, tasm works again. nasm moved to ag386nsm.pas
  2344. Revision 1.17 1998/05/22 12:37:03 carl
  2345. * crash bugfix (patched msanually to main branch)
  2346. Revision 1.16 1998/05/21 19:33:32 peter
  2347. + better procedure directive handling and only one table
  2348. Revision 1.15 1998/05/20 09:42:35 pierre
  2349. + UseTokenInfo now default
  2350. * unit in interface uses and implementation uses gives error now
  2351. * only one error for unknown symbol (uses lastsymknown boolean)
  2352. the problem came from the label code !
  2353. + first inlined procedures and function work
  2354. (warning there might be allowed cases were the result is still wrong !!)
  2355. * UseBrower updated gives a global list of all position of all used symbols
  2356. with switch -gb
  2357. Revision 1.14 1998/05/11 13:07:56 peter
  2358. + $ifdef NEWPPU for the new ppuformat
  2359. + $define GDB not longer required
  2360. * removed all warnings and stripped some log comments
  2361. * no findfirst/findnext anymore to remove smartlink *.o files
  2362. Revision 1.13 1998/05/06 08:38:45 pierre
  2363. * better position info with UseTokenInfo
  2364. UseTokenInfo greatly simplified
  2365. + added check for changed tree after first time firstpass
  2366. (if we could remove all the cases were it happen
  2367. we could skip all firstpass if firstpasscount > 1)
  2368. Only with ExtDebug
  2369. Revision 1.12 1998/05/05 12:05:42 florian
  2370. * problems with properties fixed
  2371. * crash fixed: i:=l when i and l are undefined, was a problem with
  2372. implementation of private/protected
  2373. Revision 1.11 1998/05/04 11:22:26 florian
  2374. * problem with DOM solved: it crashes when accessing a property in a method
  2375. Revision 1.10 1998/05/01 16:38:45 florian
  2376. * handling of private and protected fixed
  2377. + change_keywords_to_tp implemented to remove
  2378. keywords which aren't supported by tp
  2379. * break and continue are now symbols of the system unit
  2380. + widestring, longstring and ansistring type released
  2381. Revision 1.9 1998/04/29 10:33:58 pierre
  2382. + added some code for ansistring (not complete nor working yet)
  2383. * corrected operator overloading
  2384. * corrected nasm output
  2385. + started inline procedures
  2386. + added starstarn : use ** for exponentiation (^ gave problems)
  2387. + started UseTokenInfo cond to get accurate positions
  2388. Revision 1.8 1998/04/14 23:27:03 florian
  2389. + exclude/include with constant second parameter added
  2390. Revision 1.7 1998/04/09 23:02:15 florian
  2391. * small problems solved to get remake3 work
  2392. Revision 1.6 1998/04/09 22:16:35 florian
  2393. * problem with previous REGALLOC solved
  2394. * improved property support
  2395. Revision 1.5 1998/04/08 10:26:09 florian
  2396. * correct error handling of virtual constructors
  2397. * problem with new type declaration handling fixed
  2398. Revision 1.4 1998/04/07 22:45:05 florian
  2399. * bug0092, bug0115 and bug0121 fixed
  2400. + packed object/class/array
  2401. Revision 1.3 1998/04/07 13:19:46 pierre
  2402. * bugfixes for reset_gdb_info
  2403. in MEM parsing for go32v2
  2404. better external symbol creation
  2405. support for rhgdb.exe (lowercase file names)
  2406. }