pexpr.pas 99 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. symtype,
  23. node,
  24. globals,
  25. cpuinfo;
  26. { reads a whole expression }
  27. function expr : tnode;
  28. { reads an expression without assignements and .. }
  29. function comp_expr(accept_equal : boolean):tnode;
  30. { reads a single factor }
  31. function factor(getaddr : boolean) : tnode;
  32. procedure string_dec(var t: ttype);
  33. function parse_paras(__colon,in_prop_paras : boolean) : tnode;
  34. { the ID token has to be consumed before calling this function }
  35. procedure do_member_read(getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callnflags:tnodeflags);
  36. {$ifdef int64funcresok}
  37. function get_intconst:TConstExprInt;
  38. {$else int64funcresok}
  39. function get_intconst:longint;
  40. {$endif int64funcresok}
  41. function get_stringconst:string;
  42. implementation
  43. uses
  44. {$ifdef delphi}
  45. SysUtils,
  46. {$endif}
  47. { common }
  48. cutils,
  49. { global }
  50. globtype,tokens,verbose,
  51. systems,widestr,
  52. { symtable }
  53. symconst,symbase,symdef,symsym,symtable,defutil,defcmp,
  54. { pass 1 }
  55. pass_1,htypechk,
  56. nutils,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,
  57. { parser }
  58. scanner,
  59. pbase,pinline,
  60. { codegen }
  61. cgbase,procinfo
  62. ;
  63. { sub_expr(opmultiply) is need to get -1 ** 4 to be
  64. read as - (1**4) and not (-1)**4 PM }
  65. type
  66. Toperator_precedence=(opcompare,opaddition,opmultiply,oppower);
  67. const
  68. highest_precedence = oppower;
  69. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):tnode;forward;
  70. const
  71. { true, if the inherited call is anonymous }
  72. anon_inherited : boolean = false;
  73. procedure string_dec(var t: ttype);
  74. { reads a string type with optional length }
  75. { and returns a pointer to the string }
  76. { definition }
  77. var
  78. p : tnode;
  79. begin
  80. t:=cshortstringtype;
  81. consume(_STRING);
  82. if token=_LECKKLAMMER then
  83. begin
  84. consume(_LECKKLAMMER);
  85. p:=comp_expr(true);
  86. if not is_constintnode(p) then
  87. begin
  88. Message(cg_e_illegal_expression);
  89. { error recovery }
  90. consume(_RECKKLAMMER);
  91. end
  92. else
  93. begin
  94. if (tordconstnode(p).value<=0) then
  95. begin
  96. Message(parser_e_invalid_string_size);
  97. tordconstnode(p).value:=255;
  98. end;
  99. consume(_RECKKLAMMER);
  100. if tordconstnode(p).value>255 then
  101. begin
  102. { longstring is currently unsupported (CEC)! }
  103. { t.setdef(tstringdef.createlong(tordconstnode(p).value))}
  104. Message(parser_e_invalid_string_size);
  105. tordconstnode(p).value:=255;
  106. t.setdef(tstringdef.createshort(tordconstnode(p).value));
  107. end
  108. else
  109. if tordconstnode(p).value<>255 then
  110. t.setdef(tstringdef.createshort(tordconstnode(p).value));
  111. end;
  112. p.free;
  113. end
  114. else
  115. begin
  116. if cs_ansistrings in aktlocalswitches then
  117. t:=cansistringtype
  118. else
  119. t:=cshortstringtype;
  120. end;
  121. end;
  122. function parse_paras(__colon,in_prop_paras : boolean) : tnode;
  123. var
  124. p1,p2 : tnode;
  125. end_of_paras : ttoken;
  126. prev_in_args : boolean;
  127. old_allow_array_constructor : boolean;
  128. begin
  129. if in_prop_paras then
  130. end_of_paras:=_RECKKLAMMER
  131. else
  132. end_of_paras:=_RKLAMMER;
  133. if token=end_of_paras then
  134. begin
  135. parse_paras:=nil;
  136. exit;
  137. end;
  138. { save old values }
  139. prev_in_args:=in_args;
  140. old_allow_array_constructor:=allow_array_constructor;
  141. { set para parsing values }
  142. in_args:=true;
  143. inc(parsing_para_level);
  144. allow_array_constructor:=true;
  145. p2:=nil;
  146. while true do
  147. begin
  148. p1:=comp_expr(true);
  149. p2:=ccallparanode.create(p1,p2);
  150. { it's for the str(l:5,s); }
  151. if __colon and (token=_COLON) then
  152. begin
  153. consume(_COLON);
  154. p1:=comp_expr(true);
  155. p2:=ccallparanode.create(p1,p2);
  156. include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
  157. if token=_COLON then
  158. begin
  159. consume(_COLON);
  160. p1:=comp_expr(true);
  161. p2:=ccallparanode.create(p1,p2);
  162. include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
  163. end
  164. end;
  165. if token=_COMMA then
  166. consume(_COMMA)
  167. else
  168. break;
  169. end;
  170. allow_array_constructor:=old_allow_array_constructor;
  171. dec(parsing_para_level);
  172. in_args:=prev_in_args;
  173. parse_paras:=p2;
  174. end;
  175. procedure check_tp_procvar(var p : tnode);
  176. var
  177. hp,
  178. p1 : tnode;
  179. begin
  180. if (m_tp_procvar in aktmodeswitches) and
  181. (token<>_ASSIGNMENT) and
  182. (not got_addrn) and
  183. (block_type=bt_general) then
  184. begin
  185. { ignore vecn,subscriptn }
  186. hp:=p;
  187. repeat
  188. case hp.nodetype of
  189. vecn :
  190. hp:=tvecnode(hp).left;
  191. subscriptn :
  192. hp:=tsubscriptnode(hp).left;
  193. else
  194. break;
  195. end;
  196. until false;
  197. if (hp.nodetype=loadn) then
  198. begin
  199. { get the resulttype of p }
  200. do_resulttypepass(p);
  201. { convert the procvar load to a call:
  202. - not expecting a procvar
  203. - the procvar does not get arguments, when it
  204. requires arguments the callnode will fail
  205. Note: When arguments were passed there was no loadn }
  206. if (getprocvardef=nil) and
  207. (p.resulttype.def.deftype=procvardef) and
  208. (tprocvardef(p.resulttype.def).minparacount=0) then
  209. begin
  210. p1:=ccallnode.create_procvar(nil,p);
  211. resulttypepass(p1);
  212. p:=p1;
  213. end;
  214. end;
  215. end;
  216. end;
  217. function statement_syssym(l : longint) : tnode;
  218. var
  219. p1,p2,paras : tnode;
  220. err,
  221. prev_in_args : boolean;
  222. begin
  223. prev_in_args:=in_args;
  224. case l of
  225. in_new_x :
  226. begin
  227. if afterassignment or in_args then
  228. statement_syssym:=new_function
  229. else
  230. statement_syssym:=new_dispose_statement(true);
  231. end;
  232. in_dispose_x :
  233. begin
  234. statement_syssym:=new_dispose_statement(false);
  235. end;
  236. in_ord_x :
  237. begin
  238. consume(_LKLAMMER);
  239. in_args:=true;
  240. p1:=comp_expr(true);
  241. consume(_RKLAMMER);
  242. p1:=geninlinenode(in_ord_x,false,p1);
  243. statement_syssym := p1;
  244. end;
  245. in_exit :
  246. begin
  247. if try_to_consume(_LKLAMMER) then
  248. begin
  249. p1:=comp_expr(true);
  250. consume(_RKLAMMER);
  251. if (block_type=bt_except) then
  252. Message(parser_e_exit_with_argument_not__possible);
  253. if (not assigned(current_procinfo) or
  254. is_void(current_procinfo.procdef.rettype.def)) then
  255. Message(parser_e_void_function);
  256. end
  257. else
  258. p1:=nil;
  259. statement_syssym:=cexitnode.create(p1);
  260. end;
  261. in_break :
  262. begin
  263. statement_syssym:=cbreaknode.create;
  264. end;
  265. in_continue :
  266. begin
  267. statement_syssym:=ccontinuenode.create;
  268. end;
  269. in_typeof_x :
  270. begin
  271. consume(_LKLAMMER);
  272. in_args:=true;
  273. p1:=comp_expr(true);
  274. consume(_RKLAMMER);
  275. if p1.nodetype=typen then
  276. ttypenode(p1).allowed:=true;
  277. { Allow classrefdef, which is required for
  278. Typeof(self) in static class methods }
  279. if (p1.resulttype.def.deftype = objectdef) or
  280. (assigned(current_procinfo) and
  281. ((po_classmethod in current_procinfo.procdef.procoptions) or
  282. (po_staticmethod in current_procinfo.procdef.procoptions)) and
  283. (p1.resulttype.def.deftype=classrefdef)) then
  284. statement_syssym:=geninlinenode(in_typeof_x,false,p1)
  285. else
  286. begin
  287. Message(parser_e_class_id_expected);
  288. p1.destroy;
  289. statement_syssym:=cerrornode.create;
  290. end;
  291. end;
  292. in_sizeof_x :
  293. begin
  294. consume(_LKLAMMER);
  295. in_args:=true;
  296. p1:=comp_expr(true);
  297. consume(_RKLAMMER);
  298. if (p1.nodetype<>typen) and
  299. (
  300. (is_object(p1.resulttype.def) and
  301. (oo_has_constructor in tobjectdef(p1.resulttype.def).objectoptions)) or
  302. is_open_array(p1.resulttype.def) or
  303. is_open_string(p1.resulttype.def)
  304. ) then
  305. statement_syssym:=geninlinenode(in_sizeof_x,false,p1)
  306. else
  307. begin
  308. statement_syssym:=cordconstnode.create(p1.resulttype.def.size,s32bittype,true);
  309. { p1 not needed !}
  310. p1.destroy;
  311. end;
  312. end;
  313. in_typeinfo_x :
  314. begin
  315. consume(_LKLAMMER);
  316. in_args:=true;
  317. p1:=comp_expr(true);
  318. if p1.nodetype=typen then
  319. ttypenode(p1).allowed:=true
  320. else
  321. begin
  322. p1.destroy;
  323. p1:=cerrornode.create;
  324. Message(parser_e_illegal_parameter_list);
  325. end;
  326. consume(_RKLAMMER);
  327. p2:=ccallparanode.create(p1,nil);
  328. p2:=geninlinenode(in_typeinfo_x,false,p2);
  329. statement_syssym:=p2;
  330. end;
  331. in_assigned_x :
  332. begin
  333. err:=false;
  334. consume(_LKLAMMER);
  335. in_args:=true;
  336. p1:=comp_expr(true);
  337. if not codegenerror then
  338. begin
  339. { With tp procvars we allways need to load a
  340. procvar when it is passed }
  341. if (m_tp_procvar in aktmodeswitches) and
  342. (p1.nodetype=calln) then
  343. load_procvar_from_calln(p1);
  344. case p1.resulttype.def.deftype of
  345. pointerdef,
  346. procvardef,
  347. classrefdef : ;
  348. objectdef :
  349. if not is_class_or_interface(p1.resulttype.def) then
  350. begin
  351. Message(parser_e_illegal_parameter_list);
  352. err:=true;
  353. end;
  354. else
  355. begin
  356. Message(parser_e_illegal_parameter_list);
  357. err:=true;
  358. end;
  359. end;
  360. end
  361. else
  362. err:=true;
  363. if not err then
  364. begin
  365. p2:=ccallparanode.create(p1,nil);
  366. p2:=geninlinenode(in_assigned_x,false,p2);
  367. end
  368. else
  369. begin
  370. p1.free;
  371. p2:=cerrornode.create;
  372. end;
  373. consume(_RKLAMMER);
  374. statement_syssym:=p2;
  375. end;
  376. in_addr_x :
  377. begin
  378. consume(_LKLAMMER);
  379. in_args:=true;
  380. p1:=comp_expr(true);
  381. p1:=caddrnode.create(p1);
  382. consume(_RKLAMMER);
  383. statement_syssym:=p1;
  384. end;
  385. in_ofs_x :
  386. begin
  387. consume(_LKLAMMER);
  388. in_args:=true;
  389. p1:=comp_expr(true);
  390. p1:=caddrnode.create(p1);
  391. do_resulttypepass(p1);
  392. { Ofs() returns a cardinal, not a pointer }
  393. p1.resulttype:=u32bittype;
  394. consume(_RKLAMMER);
  395. statement_syssym:=p1;
  396. end;
  397. in_seg_x :
  398. begin
  399. consume(_LKLAMMER);
  400. in_args:=true;
  401. p1:=comp_expr(true);
  402. p1:=geninlinenode(in_seg_x,false,p1);
  403. consume(_RKLAMMER);
  404. statement_syssym:=p1;
  405. end;
  406. in_high_x,
  407. in_low_x :
  408. begin
  409. consume(_LKLAMMER);
  410. in_args:=true;
  411. p1:=comp_expr(true);
  412. p2:=geninlinenode(l,false,p1);
  413. consume(_RKLAMMER);
  414. statement_syssym:=p2;
  415. end;
  416. in_succ_x,
  417. in_pred_x :
  418. begin
  419. consume(_LKLAMMER);
  420. in_args:=true;
  421. p1:=comp_expr(true);
  422. p2:=geninlinenode(l,false,p1);
  423. consume(_RKLAMMER);
  424. statement_syssym:=p2;
  425. end;
  426. in_inc_x,
  427. in_dec_x :
  428. begin
  429. consume(_LKLAMMER);
  430. in_args:=true;
  431. p1:=comp_expr(true);
  432. if token=_COMMA then
  433. begin
  434. consume(_COMMA);
  435. p2:=ccallparanode.create(comp_expr(true),nil);
  436. end
  437. else
  438. p2:=nil;
  439. p2:=ccallparanode.create(p1,p2);
  440. statement_syssym:=geninlinenode(l,false,p2);
  441. consume(_RKLAMMER);
  442. end;
  443. in_finalize_x:
  444. begin
  445. statement_syssym:=inline_finalize;
  446. end;
  447. in_copy_x:
  448. begin
  449. statement_syssym:=inline_copy;
  450. end;
  451. in_concat_x :
  452. begin
  453. consume(_LKLAMMER);
  454. in_args:=true;
  455. p2:=nil;
  456. while true do
  457. begin
  458. p1:=comp_expr(true);
  459. set_varstate(p1,true);
  460. if not((p1.resulttype.def.deftype=stringdef) or
  461. ((p1.resulttype.def.deftype=orddef) and
  462. (torddef(p1.resulttype.def).typ=uchar))) then
  463. Message(parser_e_illegal_parameter_list);
  464. if p2<>nil then
  465. p2:=caddnode.create(addn,p2,p1)
  466. else
  467. p2:=p1;
  468. if token=_COMMA then
  469. consume(_COMMA)
  470. else
  471. break;
  472. end;
  473. consume(_RKLAMMER);
  474. statement_syssym:=p2;
  475. end;
  476. in_read_x,
  477. in_readln_x :
  478. begin
  479. if token=_LKLAMMER then
  480. begin
  481. consume(_LKLAMMER);
  482. paras:=parse_paras(false,false);
  483. consume(_RKLAMMER);
  484. end
  485. else
  486. paras:=nil;
  487. p1:=geninlinenode(l,false,paras);
  488. statement_syssym := p1;
  489. end;
  490. in_setlength_x:
  491. begin
  492. statement_syssym := inline_setlength;
  493. end;
  494. in_length_x:
  495. begin
  496. consume(_LKLAMMER);
  497. in_args:=true;
  498. p1:=comp_expr(true);
  499. p2:=geninlinenode(l,false,p1);
  500. consume(_RKLAMMER);
  501. statement_syssym:=p2;
  502. end;
  503. in_write_x,
  504. in_writeln_x :
  505. begin
  506. if token=_LKLAMMER then
  507. begin
  508. consume(_LKLAMMER);
  509. paras:=parse_paras(true,false);
  510. consume(_RKLAMMER);
  511. end
  512. else
  513. paras:=nil;
  514. p1 := geninlinenode(l,false,paras);
  515. statement_syssym := p1;
  516. end;
  517. in_str_x_string :
  518. begin
  519. consume(_LKLAMMER);
  520. paras:=parse_paras(true,false);
  521. consume(_RKLAMMER);
  522. p1 := geninlinenode(l,false,paras);
  523. statement_syssym := p1;
  524. end;
  525. in_val_x:
  526. Begin
  527. consume(_LKLAMMER);
  528. in_args := true;
  529. p1:= ccallparanode.create(comp_expr(true), nil);
  530. consume(_COMMA);
  531. p2 := ccallparanode.create(comp_expr(true),p1);
  532. if (token = _COMMA) then
  533. Begin
  534. consume(_COMMA);
  535. p2 := ccallparanode.create(comp_expr(true),p2)
  536. End;
  537. consume(_RKLAMMER);
  538. p2 := geninlinenode(l,false,p2);
  539. statement_syssym := p2;
  540. End;
  541. in_include_x_y,
  542. in_exclude_x_y :
  543. begin
  544. consume(_LKLAMMER);
  545. in_args:=true;
  546. p1:=comp_expr(true);
  547. consume(_COMMA);
  548. p2:=comp_expr(true);
  549. statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
  550. consume(_RKLAMMER);
  551. end;
  552. in_assert_x_y :
  553. begin
  554. consume(_LKLAMMER);
  555. in_args:=true;
  556. p1:=comp_expr(true);
  557. if token=_COMMA then
  558. begin
  559. consume(_COMMA);
  560. p2:=comp_expr(true);
  561. end
  562. else
  563. begin
  564. { then insert an empty string }
  565. p2:=cstringconstnode.createstr('',st_default);
  566. end;
  567. statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
  568. consume(_RKLAMMER);
  569. end;
  570. else
  571. internalerror(15);
  572. end;
  573. in_args:=prev_in_args;
  574. end;
  575. function maybe_load_methodpointer(st:tsymtable;var p1:tnode):boolean;
  576. begin
  577. maybe_load_methodpointer:=false;
  578. if not assigned(p1) then
  579. begin
  580. case st.symtabletype of
  581. withsymtable :
  582. begin
  583. if (st.defowner.deftype=objectdef) then
  584. p1:=tnode(twithsymtable(st).withrefnode).getcopy;
  585. end;
  586. objectsymtable :
  587. begin
  588. p1:=load_self_node;
  589. { We are calling a member }
  590. maybe_load_methodpointer:=true;
  591. end;
  592. end;
  593. end;
  594. end;
  595. { reads the parameter for a subroutine call }
  596. procedure do_proc_call(sym:tsym;st:tsymtable;getaddr:boolean;var again : boolean;var p1:tnode);
  597. var
  598. membercall,
  599. prevafterassn : boolean;
  600. vs : tvarsym;
  601. para,p2 : tnode;
  602. currpara : tparaitem;
  603. aprocdef : tprocdef;
  604. begin
  605. prevafterassn:=afterassignment;
  606. afterassignment:=false;
  607. membercall:=false;
  608. aprocdef:=nil;
  609. { when it is a call to a member we need to load the
  610. methodpointer first }
  611. membercall:=maybe_load_methodpointer(st,p1);
  612. { When we are expecting a procvar we also need
  613. to get the address in some cases }
  614. if assigned(getprocvardef) then
  615. begin
  616. if (block_type=bt_const) or
  617. getaddr then
  618. begin
  619. aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
  620. getaddr:=true;
  621. end
  622. else
  623. if (m_tp_procvar in aktmodeswitches) then
  624. begin
  625. aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
  626. if assigned(aprocdef) then
  627. getaddr:=true;
  628. end;
  629. end;
  630. { only need to get the address of the procedure? }
  631. if getaddr then
  632. begin
  633. { Retrieve info which procvar to call. For tp_procvar the
  634. aprocdef is already loaded above so we can reuse it }
  635. if not assigned(aprocdef) and
  636. assigned(getprocvardef) then
  637. aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
  638. { generate a methodcallnode or proccallnode }
  639. { we shouldn't convert things like @tcollection.load }
  640. p2:=cloadnode.create_procvar(sym,aprocdef,st);
  641. if assigned(p1) then
  642. begin
  643. if (p1.nodetype<>typen) then
  644. tloadnode(p2).set_mp(p1)
  645. else
  646. p1.free;
  647. end;
  648. p1:=p2;
  649. { no postfix operators }
  650. again:=false;
  651. end
  652. else
  653. begin
  654. para:=nil;
  655. if anon_inherited then
  656. begin
  657. if not assigned(current_procinfo) then
  658. internalerror(200305054);
  659. currpara:=tparaitem(current_procinfo.procdef.para.first);
  660. while assigned(currpara) do
  661. begin
  662. if not currpara.is_hidden then
  663. begin
  664. vs:=tvarsym(currpara.parasym);
  665. para:=ccallparanode.create(cloadnode.create(vs,vs.owner),para);
  666. end;
  667. currpara:=tparaitem(currpara.next);
  668. end;
  669. end
  670. else
  671. begin
  672. if try_to_consume(_LKLAMMER) then
  673. begin
  674. para:=parse_paras(false,false);
  675. consume(_RKLAMMER);
  676. end;
  677. end;
  678. p1:=ccallnode.create(para,tprocsym(sym),st,p1);
  679. { indicate if this call was generated by a member and
  680. no explicit self is used, this is needed to determine
  681. how to handle a destructor call (PFV) }
  682. if membercall then
  683. include(p1.flags,nf_member_call);
  684. end;
  685. afterassignment:=prevafterassn;
  686. end;
  687. procedure handle_procvar(pv : tprocvardef;var p2 : tnode);
  688. var
  689. hp,hp2 : tnode;
  690. hpp : ^tnode;
  691. currprocdef : tprocdef;
  692. begin
  693. if not assigned(pv) then
  694. internalerror(200301121);
  695. if (m_tp_procvar in aktmodeswitches) then
  696. begin
  697. hp:=p2;
  698. hpp:=@p2;
  699. while assigned(hp) and
  700. (hp.nodetype=typeconvn) do
  701. begin
  702. hp:=ttypeconvnode(hp).left;
  703. { save orignal address of the old tree so we can replace the node }
  704. hpp:=@hp;
  705. end;
  706. if (hp.nodetype=calln) and
  707. { a procvar can't have parameters! }
  708. not assigned(tcallnode(hp).left) then
  709. begin
  710. currprocdef:=tcallnode(hp).symtableprocentry.search_procdef_byprocvardef(pv);
  711. if assigned(currprocdef) then
  712. begin
  713. hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
  714. if (po_methodpointer in pv.procoptions) then
  715. tloadnode(hp2).set_mp(tnode(tcallnode(hp).methodpointer).getcopy);
  716. hp.destroy;
  717. { replace the old callnode with the new loadnode }
  718. hpp^:=hp2;
  719. end;
  720. end;
  721. end;
  722. end;
  723. { the following procedure handles the access to a property symbol }
  724. procedure handle_propertysym(sym : tsym;st : tsymtable;var p1 : tnode; getaddr: boolean);
  725. procedure symlist_to_node(var p1:tnode;pl:tsymlist);
  726. var
  727. plist : psymlistitem;
  728. begin
  729. plist:=pl.firstsym;
  730. while assigned(plist) do
  731. begin
  732. case plist^.sltype of
  733. sl_load :
  734. begin
  735. { p1 can already contain the loadnode of
  736. the class variable. When there is no tree yet we
  737. may need to load it for with or objects }
  738. if not assigned(p1) then
  739. begin
  740. case st.symtabletype of
  741. withsymtable :
  742. p1:=tnode(twithsymtable(st).withrefnode).getcopy;
  743. objectsymtable :
  744. p1:=load_self_node;
  745. end;
  746. end;
  747. if assigned(p1) then
  748. p1:=csubscriptnode.create(plist^.sym,p1)
  749. else
  750. p1:=cloadnode.create(plist^.sym,st);
  751. end;
  752. sl_subscript :
  753. p1:=csubscriptnode.create(plist^.sym,p1);
  754. sl_vec :
  755. p1:=cvecnode.create(p1,cordconstnode.create(plist^.value,s32bittype,true));
  756. else
  757. internalerror(200110205);
  758. end;
  759. plist:=plist^.next;
  760. end;
  761. include(p1.flags,nf_isproperty);
  762. end;
  763. var
  764. paras : tnode;
  765. p2 : tnode;
  766. membercall : boolean;
  767. begin
  768. paras:=nil;
  769. { property parameters? read them only if the property really }
  770. { has parameters }
  771. if (ppo_hasparameters in tpropertysym(sym).propoptions) then
  772. begin
  773. if token=_LECKKLAMMER then
  774. begin
  775. consume(_LECKKLAMMER);
  776. paras:=parse_paras(false,true);
  777. consume(_RECKKLAMMER);
  778. end;
  779. end;
  780. { indexed property }
  781. if (ppo_indexed in tpropertysym(sym).propoptions) then
  782. begin
  783. p2:=cordconstnode.create(tpropertysym(sym).index,tpropertysym(sym).indextype,true);
  784. paras:=ccallparanode.create(p2,paras);
  785. end;
  786. { we need only a write property if a := follows }
  787. { if not(afterassignment) and not(in_args) then }
  788. if token=_ASSIGNMENT then
  789. begin
  790. { write property: }
  791. if not tpropertysym(sym).writeaccess.empty then
  792. begin
  793. case tpropertysym(sym).writeaccess.firstsym^.sym.typ of
  794. procsym :
  795. begin
  796. { generate the method call }
  797. membercall:=maybe_load_methodpointer(st,p1);
  798. p1:=ccallnode.create(paras,
  799. tprocsym(tpropertysym(sym).writeaccess.firstsym^.sym),st,p1);
  800. if membercall then
  801. include(tcallnode(p1).flags,nf_member_call);
  802. paras:=nil;
  803. consume(_ASSIGNMENT);
  804. { read the expression }
  805. if tpropertysym(sym).proptype.def.deftype=procvardef then
  806. getprocvardef:=tprocvardef(tpropertysym(sym).proptype.def);
  807. p2:=comp_expr(true);
  808. if assigned(getprocvardef) then
  809. handle_procvar(getprocvardef,p2);
  810. tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
  811. include(tcallnode(p1).flags,nf_isproperty);
  812. getprocvardef:=nil;
  813. end;
  814. varsym :
  815. begin
  816. { generate access code }
  817. symlist_to_node(p1,tpropertysym(sym).writeaccess);
  818. consume(_ASSIGNMENT);
  819. { read the expression }
  820. p2:=comp_expr(true);
  821. p1:=cassignmentnode.create(p1,p2);
  822. end
  823. else
  824. begin
  825. p1:=cerrornode.create;
  826. Message(parser_e_no_procedure_to_access_property);
  827. end;
  828. end;
  829. end
  830. else
  831. begin
  832. p1:=cerrornode.create;
  833. Message(parser_e_no_procedure_to_access_property);
  834. end;
  835. end
  836. else
  837. begin
  838. { read property: }
  839. if not tpropertysym(sym).readaccess.empty then
  840. begin
  841. case tpropertysym(sym).readaccess.firstsym^.sym.typ of
  842. varsym :
  843. begin
  844. { generate access code }
  845. symlist_to_node(p1,tpropertysym(sym).readaccess);
  846. end;
  847. procsym :
  848. begin
  849. { generate the method call }
  850. membercall:=maybe_load_methodpointer(st,p1);
  851. p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).readaccess.firstsym^.sym),st,p1);
  852. if membercall then
  853. include(tcallnode(p1).flags,nf_member_call);
  854. paras:=nil;
  855. include(p1.flags,nf_isproperty);
  856. end
  857. else
  858. begin
  859. p1:=cerrornode.create;
  860. Message(type_e_mismatch);
  861. end;
  862. end;
  863. end
  864. else
  865. begin
  866. { error, no function to read property }
  867. p1:=cerrornode.create;
  868. Message(parser_e_no_procedure_to_access_property);
  869. end;
  870. end;
  871. { release paras if not used }
  872. if assigned(paras) then
  873. paras.free;
  874. end;
  875. { the ID token has to be consumed before calling this function }
  876. procedure do_member_read(getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callnflags:tnodeflags);
  877. var
  878. static_name : string;
  879. isclassref : boolean;
  880. srsymtable : tsymtable;
  881. {$ifdef CHECKINHERITEDRESULT}
  882. newstatement : tstatementnode;
  883. newblock : tblocknode;
  884. {$endif CHECKINHERITEDRESULT}
  885. begin
  886. if sym=nil then
  887. begin
  888. { pattern is still valid unless
  889. there is another ID just after the ID of sym }
  890. Message1(sym_e_id_no_member,pattern);
  891. p1.free;
  892. p1:=cerrornode.create;
  893. { try to clean up }
  894. again:=false;
  895. end
  896. else
  897. begin
  898. if assigned(p1) then
  899. begin
  900. if not assigned(p1.resulttype.def) then
  901. do_resulttypepass(p1);
  902. isclassref:=(p1.resulttype.def.deftype=classrefdef);
  903. end
  904. else
  905. isclassref:=false;
  906. { we assume, that only procsyms and varsyms are in an object }
  907. { symbol table, for classes, properties are allowed }
  908. case sym.typ of
  909. procsym:
  910. begin
  911. do_proc_call(sym,sym.owner,
  912. (getaddr and not(token in [_CARET,_POINT])),
  913. again,p1);
  914. { add provided flags }
  915. if (p1.nodetype=calln) then
  916. p1.flags:=p1.flags+callnflags;
  917. { we need to know which procedure is called }
  918. do_resulttypepass(p1);
  919. { now we know the method that is called }
  920. if (p1.nodetype=calln) and
  921. assigned(tcallnode(p1).procdefinition) then
  922. begin
  923. { calling using classref? }
  924. if isclassref and
  925. not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
  926. not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
  927. Message(parser_e_only_class_methods_via_class_ref);
  928. {$ifdef CHECKINHERITEDRESULT}
  929. { when calling inherited constructor we need to check the return value }
  930. if (nf_inherited in callnflags) and
  931. (tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
  932. begin
  933. {
  934. For Classes:
  935. self:=inherited constructor
  936. if self=nil then
  937. exit
  938. For objects:
  939. if inherited constructor=false then
  940. begin
  941. self:=nil;
  942. exit;
  943. end;
  944. }
  945. if is_class(tprocdef(tcallnode(p1).procdefinition)._class) then
  946. begin
  947. newblock:=internalstatements(newstatement,true);
  948. addstatement(newstatement,cassignmentnode.create(
  949. ctypeconvnode.create(
  950. load_self_pointer_node,
  951. voidpointertype),
  952. ctypeconvnode.create(
  953. p1,
  954. voidpointertype)));
  955. addstatement(newstatement,cifnode.create(
  956. caddnode.create(equaln,
  957. load_self_pointer_node,
  958. cnilnode.create),
  959. cexitnode.create(nil),
  960. nil));
  961. p1:=newblock;
  962. end
  963. else
  964. if is_object(tprocdef(tcallnode(p1).procdefinition)._class) then
  965. begin
  966. newblock:=internalstatements(newstatement,true);
  967. addstatement(newstatement,call_fail_node);
  968. addstatement(newstatement,cexitnode.create(nil));
  969. p1:=cifnode.create(
  970. caddnode.create(equaln,
  971. cordconstnode.create(0,booltype,false),
  972. p1),
  973. newblock,
  974. nil);
  975. end
  976. else
  977. internalerror(200305133);
  978. end;
  979. {$endif CHECKINHERITEDRESULT}
  980. do_resulttypepass(p1);
  981. end;
  982. end;
  983. varsym:
  984. begin
  985. if (sp_static in sym.symoptions) then
  986. begin
  987. static_name:=lower(sym.owner.name^)+'_'+sym.name;
  988. searchsym(static_name,sym,srsymtable);
  989. check_hints(sym);
  990. p1.free;
  991. p1:=cloadnode.create(sym,srsymtable);
  992. end
  993. else
  994. begin
  995. if isclassref then
  996. Message(parser_e_only_class_methods_via_class_ref);
  997. p1:=csubscriptnode.create(sym,p1);
  998. end;
  999. end;
  1000. propertysym:
  1001. begin
  1002. if isclassref then
  1003. Message(parser_e_only_class_methods_via_class_ref);
  1004. handle_propertysym(sym,sym.owner,p1,getaddr);
  1005. end;
  1006. else internalerror(16);
  1007. end;
  1008. end;
  1009. end;
  1010. {****************************************************************************
  1011. Factor
  1012. ****************************************************************************}
  1013. {$ifdef fpc}
  1014. {$maxfpuregisters 0}
  1015. {$endif fpc}
  1016. function factor(getaddr : boolean) : tnode;
  1017. {---------------------------------------------
  1018. Factor_read_id
  1019. ---------------------------------------------}
  1020. procedure factor_read_id(var p1:tnode;var again:boolean);
  1021. var
  1022. pc : pchar;
  1023. len : longint;
  1024. srsym : tsym;
  1025. possible_error : boolean;
  1026. srsymtable : tsymtable;
  1027. storesymtablestack : tsymtable;
  1028. htype : ttype;
  1029. static_name : string;
  1030. begin
  1031. { allow post fix operators }
  1032. again:=true;
  1033. consume_sym(srsym,srsymtable);
  1034. { Access to funcret or need to call the function? }
  1035. if (srsym.typ in [absolutesym,varsym]) and
  1036. (vo_is_funcret in tvarsym(srsym).varoptions) and
  1037. (
  1038. (token=_LKLAMMER) or
  1039. (not(m_fpc in aktmodeswitches) and
  1040. (afterassignment or in_args) and
  1041. not(vo_is_result in tvarsym(srsym).varoptions))
  1042. ) then
  1043. begin
  1044. storesymtablestack:=symtablestack;
  1045. symtablestack:=srsym.owner.next;
  1046. searchsym(srsym.name,srsym,srsymtable);
  1047. if not assigned(srsym) then
  1048. srsym:=generrorsym;
  1049. if (srsym.typ<>procsym) then
  1050. Message(cg_e_illegal_expression);
  1051. symtablestack:=storesymtablestack;
  1052. end;
  1053. begin
  1054. { check semantics of private }
  1055. if (srsym.typ in [propertysym,procsym,varsym]) and
  1056. (srsym.owner.symtabletype=objectsymtable) then
  1057. begin
  1058. if (sp_private in srsym.symoptions) and
  1059. (tobjectdef(srsym.owner.defowner).owner.symtabletype=globalsymtable) and
  1060. (tobjectdef(srsym.owner.defowner).owner.unitid<>0) then
  1061. Message(parser_e_cant_access_private_member);
  1062. end;
  1063. case srsym.typ of
  1064. absolutesym :
  1065. begin
  1066. p1:=cloadnode.create(srsym,srsymtable);
  1067. end;
  1068. varsym :
  1069. begin
  1070. if (sp_static in srsym.symoptions) then
  1071. begin
  1072. static_name:=lower(srsym.owner.name^)+'_'+srsym.name;
  1073. searchsym(static_name,srsym,srsymtable);
  1074. check_hints(srsym);
  1075. end
  1076. else
  1077. begin
  1078. { are we in a class method, we check here the
  1079. srsymtable, because a field in another object
  1080. also has objectsymtable. And withsymtable is
  1081. not possible for self in class methods (PFV) }
  1082. if (srsymtable.symtabletype=objectsymtable) and
  1083. assigned(current_procinfo) and
  1084. (po_classmethod in current_procinfo.procdef.procoptions) then
  1085. Message(parser_e_only_class_methods);
  1086. end;
  1087. case srsymtable.symtabletype of
  1088. objectsymtable :
  1089. p1:=csubscriptnode.create(srsym,load_self_node);
  1090. withsymtable :
  1091. p1:=csubscriptnode.create(srsym,tnode(twithsymtable(srsymtable).withrefnode).getcopy);
  1092. else
  1093. p1:=cloadnode.create(srsym,srsymtable);
  1094. end;
  1095. if tvarsym(srsym).varstate=vs_declared then
  1096. begin
  1097. include(p1.flags,nf_first_use);
  1098. { set special between first loaded until checked in resulttypepass }
  1099. tvarsym(srsym).varstate:=vs_declared_and_first_found;
  1100. end;
  1101. end;
  1102. typedconstsym :
  1103. begin
  1104. p1:=cloadnode.create(srsym,srsymtable);
  1105. end;
  1106. syssym :
  1107. begin
  1108. p1:=statement_syssym(tsyssym(srsym).number);
  1109. end;
  1110. typesym :
  1111. begin
  1112. htype.setsym(srsym);
  1113. if not assigned(htype.def) then
  1114. begin
  1115. again:=false;
  1116. end
  1117. else
  1118. begin
  1119. if token=_LKLAMMER then
  1120. begin
  1121. consume(_LKLAMMER);
  1122. p1:=comp_expr(true);
  1123. consume(_RKLAMMER);
  1124. p1:=ctypeconvnode.create_explicit(p1,htype);
  1125. end
  1126. else { not LKLAMMER }
  1127. if (token=_POINT) and
  1128. is_object(htype.def) then
  1129. begin
  1130. consume(_POINT);
  1131. if assigned(current_procinfo) and
  1132. assigned(current_procinfo.procdef._class) and
  1133. not(getaddr) then
  1134. begin
  1135. if current_procinfo.procdef._class.is_related(tobjectdef(htype.def)) then
  1136. begin
  1137. p1:=ctypenode.create(htype);
  1138. { search also in inherited methods }
  1139. srsym:=searchsym_in_class(tobjectdef(htype.def),pattern);
  1140. check_hints(srsym);
  1141. consume(_ID);
  1142. do_member_read(false,srsym,p1,again,[]);
  1143. end
  1144. else
  1145. begin
  1146. Message(parser_e_no_super_class);
  1147. again:=false;
  1148. end;
  1149. end
  1150. else
  1151. begin
  1152. { allows @TObject.Load }
  1153. { also allows static methods and variables }
  1154. p1:=ctypenode.create(htype);
  1155. { TP allows also @TMenu.Load if Load is only }
  1156. { defined in an anchestor class }
  1157. srsym:=search_class_member(tobjectdef(htype.def),pattern);
  1158. check_hints(srsym);
  1159. if not assigned(srsym) then
  1160. Message1(sym_e_id_no_member,pattern)
  1161. else if not(getaddr) and not(sp_static in srsym.symoptions) then
  1162. Message(sym_e_only_static_in_static)
  1163. else
  1164. begin
  1165. consume(_ID);
  1166. do_member_read(getaddr,srsym,p1,again,[]);
  1167. end;
  1168. end;
  1169. end
  1170. else
  1171. begin
  1172. { class reference ? }
  1173. if is_class(htype.def) then
  1174. begin
  1175. if getaddr and (token=_POINT) then
  1176. begin
  1177. consume(_POINT);
  1178. { allows @Object.Method }
  1179. { also allows static methods and variables }
  1180. p1:=ctypenode.create(htype);
  1181. { TP allows also @TMenu.Load if Load is only }
  1182. { defined in an anchestor class }
  1183. srsym:=search_class_member(tobjectdef(htype.def),pattern);
  1184. check_hints(srsym);
  1185. if not assigned(srsym) then
  1186. Message1(sym_e_id_no_member,pattern)
  1187. else
  1188. begin
  1189. consume(_ID);
  1190. do_member_read(getaddr,srsym,p1,again,[]);
  1191. end;
  1192. end
  1193. else
  1194. begin
  1195. p1:=ctypenode.create(htype);
  1196. { For a type block we simply return only
  1197. the type. For all other blocks we return
  1198. a loadvmt node }
  1199. if (block_type<>bt_type) then
  1200. p1:=cloadvmtaddrnode.create(p1);
  1201. end;
  1202. end
  1203. else
  1204. p1:=ctypenode.create(htype);
  1205. end;
  1206. end;
  1207. end;
  1208. enumsym :
  1209. begin
  1210. p1:=genenumnode(tenumsym(srsym));
  1211. end;
  1212. constsym :
  1213. begin
  1214. case tconstsym(srsym).consttyp of
  1215. constint :
  1216. begin
  1217. { do a very dirty trick to bootstrap this code }
  1218. if (tconstsym(srsym).value.valueord>=-(int64(2147483647)+int64(1))) and
  1219. (tconstsym(srsym).value.valueord<=2147483647) then
  1220. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,s32bittype,true)
  1221. else if (tconstsym(srsym).value.valueord > maxlongint) and
  1222. (tconstsym(srsym).value.valueord <= int64(maxlongint)+int64(maxlongint)+1) then
  1223. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,u32bittype,true)
  1224. else
  1225. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,cs64bittype,true);
  1226. end;
  1227. conststring :
  1228. begin
  1229. len:=tconstsym(srsym).value.len;
  1230. if not(cs_ansistrings in aktlocalswitches) and (len>255) then
  1231. len:=255;
  1232. getmem(pc,len+1);
  1233. move(pchar(tconstsym(srsym).value.valueptr)^,pc^,len);
  1234. pc[len]:=#0;
  1235. p1:=cstringconstnode.createpchar(pc,len);
  1236. end;
  1237. constchar :
  1238. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,cchartype,true);
  1239. constreal :
  1240. p1:=crealconstnode.create(pbestreal(tconstsym(srsym).value.valueptr)^,pbestrealtype^);
  1241. constbool :
  1242. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,booltype,true);
  1243. constset :
  1244. p1:=csetconstnode.create(pconstset(tconstsym(srsym).value.valueptr),tconstsym(srsym).consttype);
  1245. constord :
  1246. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,tconstsym(srsym).consttype,true);
  1247. constpointer :
  1248. p1:=cpointerconstnode.create(tconstsym(srsym).value.valueordptr,tconstsym(srsym).consttype);
  1249. constnil :
  1250. p1:=cnilnode.create;
  1251. constresourcestring:
  1252. begin
  1253. p1:=cloadnode.create(srsym,srsymtable);
  1254. do_resulttypepass(p1);
  1255. p1.resulttype:=cansistringtype;
  1256. end;
  1257. constguid :
  1258. p1:=cguidconstnode.create(pguid(tconstsym(srsym).value.valueptr)^);
  1259. end;
  1260. end;
  1261. procsym :
  1262. begin
  1263. { are we in a class method ? }
  1264. possible_error:=(srsymtable.symtabletype<>withsymtable) and
  1265. (srsym.owner.symtabletype=objectsymtable) and
  1266. not(is_interface(tdef(srsym.owner.defowner))) and
  1267. assigned(current_procinfo) and
  1268. (po_classmethod in current_procinfo.procdef.procoptions);
  1269. do_proc_call(srsym,srsymtable,
  1270. (getaddr and not(token in [_CARET,_POINT])),
  1271. again,p1);
  1272. { we need to know which procedure is called }
  1273. if possible_error then
  1274. begin
  1275. do_resulttypepass(p1);
  1276. if not(po_classmethod in tcallnode(p1).procdefinition.procoptions) then
  1277. Message(parser_e_only_class_methods);
  1278. end;
  1279. end;
  1280. propertysym :
  1281. begin
  1282. { access to property in a method }
  1283. { are we in a class method ? }
  1284. if (srsymtable.symtabletype=objectsymtable) and
  1285. assigned(current_procinfo) and
  1286. (po_classmethod in current_procinfo.procdef.procoptions) then
  1287. Message(parser_e_only_class_methods);
  1288. { no method pointer }
  1289. p1:=nil;
  1290. handle_propertysym(srsym,srsymtable,p1,getaddr);
  1291. end;
  1292. labelsym :
  1293. begin
  1294. consume(_COLON);
  1295. if tlabelsym(srsym).defined then
  1296. Message(sym_e_label_already_defined);
  1297. tlabelsym(srsym).defined:=true;
  1298. p1:=clabelnode.create(tlabelsym(srsym),nil);
  1299. end;
  1300. errorsym :
  1301. begin
  1302. p1:=cerrornode.create;
  1303. if token=_LKLAMMER then
  1304. begin
  1305. consume(_LKLAMMER);
  1306. parse_paras(false,false);
  1307. consume(_RKLAMMER);
  1308. end;
  1309. end;
  1310. else
  1311. begin
  1312. p1:=cerrornode.create;
  1313. Message(cg_e_illegal_expression);
  1314. end;
  1315. end; { end case }
  1316. end;
  1317. end;
  1318. {---------------------------------------------
  1319. Factor_Read_Set
  1320. ---------------------------------------------}
  1321. { Read a set between [] }
  1322. function factor_read_set:tnode;
  1323. var
  1324. p1,p2 : tnode;
  1325. lastp,
  1326. buildp : tarrayconstructornode;
  1327. begin
  1328. buildp:=nil;
  1329. { be sure that a least one arrayconstructn is used, also for an
  1330. empty [] }
  1331. if token=_RECKKLAMMER then
  1332. buildp:=carrayconstructornode.create(nil,buildp)
  1333. else
  1334. begin
  1335. while true do
  1336. begin
  1337. p1:=comp_expr(true);
  1338. if token=_POINTPOINT then
  1339. begin
  1340. consume(_POINTPOINT);
  1341. p2:=comp_expr(true);
  1342. p1:=carrayconstructorrangenode.create(p1,p2);
  1343. end;
  1344. { insert at the end of the tree, to get the correct order }
  1345. if not assigned(buildp) then
  1346. begin
  1347. buildp:=carrayconstructornode.create(p1,nil);
  1348. lastp:=buildp;
  1349. end
  1350. else
  1351. begin
  1352. lastp.right:=carrayconstructornode.create(p1,nil);
  1353. lastp:=tarrayconstructornode(lastp.right);
  1354. end;
  1355. { there could be more elements }
  1356. if token=_COMMA then
  1357. consume(_COMMA)
  1358. else
  1359. break;
  1360. end;
  1361. end;
  1362. factor_read_set:=buildp;
  1363. end;
  1364. {---------------------------------------------
  1365. PostFixOperators
  1366. ---------------------------------------------}
  1367. procedure postfixoperators(var p1:tnode;var again:boolean);
  1368. { tries to avoid syntax errors after invalid qualifiers }
  1369. procedure recoverconsume_postfixops;
  1370. begin
  1371. while true do
  1372. begin
  1373. case token of
  1374. _CARET:
  1375. consume(_CARET);
  1376. _POINT:
  1377. begin
  1378. consume(_POINT);
  1379. if token=_ID then
  1380. consume(_ID);
  1381. end;
  1382. _LECKKLAMMER:
  1383. begin
  1384. consume(_LECKKLAMMER);
  1385. repeat
  1386. comp_expr(true);
  1387. if token=_COMMA then
  1388. consume(_COMMA)
  1389. else
  1390. break;
  1391. until false;
  1392. consume(_RECKKLAMMER);
  1393. end
  1394. else
  1395. break;
  1396. end;
  1397. end;
  1398. end;
  1399. var
  1400. store_static : boolean;
  1401. protsym : tpropertysym;
  1402. p2,p3 : tnode;
  1403. hsym : tsym;
  1404. classh : tobjectdef;
  1405. begin
  1406. again:=true;
  1407. while again do
  1408. begin
  1409. { we need the resulttype }
  1410. do_resulttypepass(p1);
  1411. if codegenerror then
  1412. begin
  1413. recoverconsume_postfixops;
  1414. exit;
  1415. end;
  1416. { handle token }
  1417. case token of
  1418. _CARET:
  1419. begin
  1420. consume(_CARET);
  1421. if (p1.resulttype.def.deftype<>pointerdef) then
  1422. begin
  1423. { ^ as binary operator is a problem!!!! (FK) }
  1424. again:=false;
  1425. Message(cg_e_invalid_qualifier);
  1426. recoverconsume_postfixops;
  1427. p1.destroy;
  1428. p1:=cerrornode.create;
  1429. end
  1430. else
  1431. begin
  1432. p1:=cderefnode.create(p1);
  1433. end;
  1434. end;
  1435. _LECKKLAMMER:
  1436. begin
  1437. if is_class_or_interface(p1.resulttype.def) then
  1438. begin
  1439. { default property }
  1440. protsym:=search_default_property(tobjectdef(p1.resulttype.def));
  1441. if not(assigned(protsym)) then
  1442. begin
  1443. p1.destroy;
  1444. p1:=cerrornode.create;
  1445. again:=false;
  1446. message(parser_e_no_default_property_available);
  1447. end
  1448. else
  1449. begin
  1450. { The property symbol is referenced indirect }
  1451. inc(protsym.refs);
  1452. handle_propertysym(protsym,protsym.owner,p1,getaddr);
  1453. end;
  1454. end
  1455. else
  1456. begin
  1457. consume(_LECKKLAMMER);
  1458. repeat
  1459. case p1.resulttype.def.deftype of
  1460. pointerdef:
  1461. begin
  1462. { support delphi autoderef }
  1463. if (tpointerdef(p1.resulttype.def).pointertype.def.deftype=arraydef) and
  1464. (m_autoderef in aktmodeswitches) then
  1465. begin
  1466. p1:=cderefnode.create(p1);
  1467. end;
  1468. p2:=comp_expr(true);
  1469. p1:=cvecnode.create(p1,p2);
  1470. end;
  1471. stringdef :
  1472. begin
  1473. p2:=comp_expr(true);
  1474. p1:=cvecnode.create(p1,p2);
  1475. end;
  1476. arraydef :
  1477. begin
  1478. p2:=comp_expr(true);
  1479. { support SEG:OFS for go32v2 Mem[] }
  1480. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  1481. (p1.nodetype=loadn) and
  1482. assigned(tloadnode(p1).symtableentry) and
  1483. assigned(tloadnode(p1).symtableentry.owner.name) and
  1484. (tloadnode(p1).symtableentry.owner.name^='SYSTEM') and
  1485. ((tloadnode(p1).symtableentry.name='MEM') or
  1486. (tloadnode(p1).symtableentry.name='MEMW') or
  1487. (tloadnode(p1).symtableentry.name='MEML')) then
  1488. begin
  1489. if (token=_COLON) then
  1490. begin
  1491. consume(_COLON);
  1492. p3:=caddnode.create(muln,cordconstnode.create($10,s32bittype,false),p2);
  1493. p2:=comp_expr(true);
  1494. p2:=caddnode.create(addn,p2,p3);
  1495. p1:=cvecnode.create(p1,p2);
  1496. include(tvecnode(p1).flags,nf_memseg);
  1497. include(tvecnode(p1).flags,nf_memindex);
  1498. end
  1499. else
  1500. begin
  1501. p1:=cvecnode.create(p1,p2);
  1502. include(tvecnode(p1).flags,nf_memindex);
  1503. end;
  1504. end
  1505. else
  1506. p1:=cvecnode.create(p1,p2);
  1507. end;
  1508. else
  1509. begin
  1510. Message(cg_e_invalid_qualifier);
  1511. p1.destroy;
  1512. p1:=cerrornode.create;
  1513. comp_expr(true);
  1514. again:=false;
  1515. end;
  1516. end;
  1517. do_resulttypepass(p1);
  1518. if token=_COMMA then
  1519. consume(_COMMA)
  1520. else
  1521. break;
  1522. until false;
  1523. consume(_RECKKLAMMER);
  1524. end;
  1525. end;
  1526. _POINT :
  1527. begin
  1528. consume(_POINT);
  1529. if (p1.resulttype.def.deftype=pointerdef) and
  1530. (m_autoderef in aktmodeswitches) then
  1531. begin
  1532. p1:=cderefnode.create(p1);
  1533. do_resulttypepass(p1);
  1534. end;
  1535. case p1.resulttype.def.deftype of
  1536. recorddef:
  1537. begin
  1538. hsym:=tsym(trecorddef(p1.resulttype.def).symtable.search(pattern));
  1539. check_hints(hsym);
  1540. if assigned(hsym) and
  1541. (hsym.typ=varsym) then
  1542. p1:=csubscriptnode.create(hsym,p1)
  1543. else
  1544. begin
  1545. Message1(sym_e_illegal_field,pattern);
  1546. p1.destroy;
  1547. p1:=cerrornode.create;
  1548. end;
  1549. consume(_ID);
  1550. end;
  1551. variantdef:
  1552. begin
  1553. end;
  1554. classrefdef:
  1555. begin
  1556. classh:=tobjectdef(tclassrefdef(p1.resulttype.def).pointertype.def);
  1557. hsym:=searchsym_in_class(classh,pattern);
  1558. check_hints(hsym);
  1559. if hsym=nil then
  1560. begin
  1561. Message1(sym_e_id_no_member,pattern);
  1562. p1.destroy;
  1563. p1:=cerrornode.create;
  1564. { try to clean up }
  1565. consume(_ID);
  1566. end
  1567. else
  1568. begin
  1569. consume(_ID);
  1570. do_member_read(getaddr,hsym,p1,again,[]);
  1571. end;
  1572. end;
  1573. objectdef:
  1574. begin
  1575. store_static:=allow_only_static;
  1576. allow_only_static:=false;
  1577. classh:=tobjectdef(p1.resulttype.def);
  1578. hsym:=searchsym_in_class(classh,pattern);
  1579. check_hints(hsym);
  1580. allow_only_static:=store_static;
  1581. if hsym=nil then
  1582. begin
  1583. Message1(sym_e_id_no_member,pattern);
  1584. p1.destroy;
  1585. p1:=cerrornode.create;
  1586. { try to clean up }
  1587. consume(_ID);
  1588. end
  1589. else
  1590. begin
  1591. consume(_ID);
  1592. do_member_read(getaddr,hsym,p1,again,[]);
  1593. end;
  1594. end;
  1595. pointerdef:
  1596. begin
  1597. Message(cg_e_invalid_qualifier);
  1598. if tpointerdef(p1.resulttype.def).pointertype.def.deftype in [recorddef,objectdef,classrefdef] then
  1599. Message(parser_h_maybe_deref_caret_missing);
  1600. end;
  1601. else
  1602. begin
  1603. Message(cg_e_invalid_qualifier);
  1604. p1.destroy;
  1605. p1:=cerrornode.create;
  1606. consume(_ID);
  1607. end;
  1608. end;
  1609. end;
  1610. else
  1611. begin
  1612. { is this a procedure variable ? }
  1613. if assigned(p1.resulttype.def) then
  1614. begin
  1615. if (p1.resulttype.def.deftype=procvardef) then
  1616. begin
  1617. if assigned(getprocvardef) and
  1618. equal_defs(p1.resulttype.def,getprocvardef) then
  1619. again:=false
  1620. else
  1621. if (token=_LKLAMMER) or
  1622. ((tprocvardef(p1.resulttype.def).maxparacount=0) and
  1623. (not((token in [_ASSIGNMENT,_UNEQUAL,_EQUAL]))) and
  1624. (not afterassignment) and
  1625. (not in_args)) then
  1626. begin
  1627. if try_to_consume(_LKLAMMER) then
  1628. begin
  1629. p2:=parse_paras(false,false);
  1630. consume(_RKLAMMER);
  1631. end
  1632. else
  1633. p2:=nil;
  1634. p1:=ccallnode.create_procvar(p2,p1);
  1635. { proc():= is never possible }
  1636. if token=_ASSIGNMENT then
  1637. begin
  1638. Message(cg_e_illegal_expression);
  1639. p1.free;
  1640. p1:=cerrornode.create;
  1641. again:=false;
  1642. end;
  1643. end
  1644. else
  1645. again:=false;
  1646. end
  1647. else
  1648. again:=false;
  1649. end
  1650. else
  1651. again:=false;
  1652. end;
  1653. end;
  1654. end; { while again }
  1655. end;
  1656. {---------------------------------------------
  1657. Factor (Main)
  1658. ---------------------------------------------}
  1659. var
  1660. l : longint;
  1661. card : cardinal;
  1662. ic : TConstExprInt;
  1663. oldp1,
  1664. p1 : tnode;
  1665. code : integer;
  1666. again : boolean;
  1667. sym : tsym;
  1668. pd : tprocdef;
  1669. classh : tobjectdef;
  1670. d : bestreal;
  1671. hs : string;
  1672. htype : ttype;
  1673. filepos : tfileposinfo;
  1674. {---------------------------------------------
  1675. Helpers
  1676. ---------------------------------------------}
  1677. procedure check_tokenpos;
  1678. begin
  1679. if (p1<>oldp1) then
  1680. begin
  1681. if assigned(p1) then
  1682. p1.set_tree_filepos(filepos);
  1683. oldp1:=p1;
  1684. filepos:=akttokenpos;
  1685. end;
  1686. end;
  1687. begin
  1688. oldp1:=nil;
  1689. p1:=nil;
  1690. filepos:=akttokenpos;
  1691. again:=false;
  1692. if token=_ID then
  1693. begin
  1694. factor_read_id(p1,again);
  1695. if again then
  1696. begin
  1697. check_tokenpos;
  1698. { handle post fix operators }
  1699. postfixoperators(p1,again);
  1700. end;
  1701. end
  1702. else
  1703. case token of
  1704. _SELF :
  1705. begin
  1706. again:=true;
  1707. consume(_SELF);
  1708. if not(assigned(current_procinfo) and
  1709. assigned(current_procinfo.procdef._class)) then
  1710. begin
  1711. p1:=cerrornode.create;
  1712. again:=false;
  1713. Message(parser_e_self_not_in_method);
  1714. end
  1715. else
  1716. begin
  1717. p1:=load_self_node;
  1718. postfixoperators(p1,again);
  1719. end;
  1720. end;
  1721. _INHERITED :
  1722. begin
  1723. again:=true;
  1724. consume(_INHERITED);
  1725. if assigned(current_procinfo) and
  1726. assigned(current_procinfo.procdef._class) then
  1727. begin
  1728. classh:=current_procinfo.procdef._class.childof;
  1729. { if inherited; only then we need the method with
  1730. the same name }
  1731. if token in endtokens then
  1732. begin
  1733. hs:=current_procinfo.procdef.procsym.name;
  1734. anon_inherited:=true;
  1735. { For message methods we need to search using the message
  1736. number or string }
  1737. pd:=tprocsym(current_procinfo.procdef.procsym).first_procdef;
  1738. if (po_msgint in pd.procoptions) then
  1739. sym:=searchsym_in_class_by_msgint(classh,pd.messageinf.i)
  1740. else
  1741. if (po_msgstr in pd.procoptions) then
  1742. sym:=searchsym_in_class_by_msgstr(classh,pd.messageinf.str)
  1743. else
  1744. sym:=searchsym_in_class(classh,hs);
  1745. end
  1746. else
  1747. begin
  1748. hs:=pattern;
  1749. consume(_ID);
  1750. anon_inherited:=false;
  1751. sym:=searchsym_in_class(classh,hs);
  1752. end;
  1753. if assigned(sym) then
  1754. begin
  1755. check_hints(sym);
  1756. { load the procdef from the inherited class and
  1757. not from self }
  1758. if sym.typ=procsym then
  1759. begin
  1760. htype.setdef(classh);
  1761. p1:=ctypenode.create(htype);
  1762. end;
  1763. do_member_read(false,sym,p1,again,[nf_inherited,nf_anon_inherited]);
  1764. end
  1765. else
  1766. begin
  1767. if anon_inherited then
  1768. begin
  1769. { For message methods we need to call DefaultHandler }
  1770. if (po_msgint in pd.procoptions) or
  1771. (po_msgstr in pd.procoptions) then
  1772. begin
  1773. sym:=searchsym_in_class(classh,'DEFAULTHANDLER');
  1774. if not assigned(sym) or
  1775. (sym.typ<>procsym) then
  1776. internalerror(200303171);
  1777. p1:=nil;
  1778. do_proc_call(sym,sym.owner,false,again,p1);
  1779. end
  1780. else
  1781. begin
  1782. { we need to ignore the inherited; }
  1783. p1:=cnothingnode.create;
  1784. end;
  1785. end
  1786. else
  1787. begin
  1788. Message1(sym_e_id_no_member,hs);
  1789. p1:=cerrornode.create;
  1790. end;
  1791. again:=false;
  1792. end;
  1793. { turn auto inheriting off }
  1794. anon_inherited:=false;
  1795. end
  1796. else
  1797. begin
  1798. Message(parser_e_generic_methods_only_in_methods);
  1799. again:=false;
  1800. p1:=cerrornode.create;
  1801. end;
  1802. postfixoperators(p1,again);
  1803. end;
  1804. _INTCONST :
  1805. begin
  1806. { try cardinal first }
  1807. val(pattern,card,code);
  1808. if code<>0 then
  1809. begin
  1810. { then longint }
  1811. valint(pattern,l,code);
  1812. if code <> 0 then
  1813. begin
  1814. { then int64 }
  1815. val(pattern,ic,code);
  1816. if code<>0 then
  1817. begin
  1818. {finally float }
  1819. val(pattern,d,code);
  1820. if code<>0 then
  1821. begin
  1822. Message(cg_e_invalid_integer);
  1823. consume(_INTCONST);
  1824. l:=1;
  1825. p1:=cordconstnode.create(l,s32bittype,true);
  1826. end
  1827. else
  1828. begin
  1829. consume(_INTCONST);
  1830. p1:=crealconstnode.create(d,pbestrealtype^);
  1831. end;
  1832. end
  1833. else
  1834. begin
  1835. consume(_INTCONST);
  1836. p1:=cordconstnode.create(ic,cs64bittype,true);
  1837. end
  1838. end
  1839. else
  1840. begin
  1841. consume(_INTCONST);
  1842. p1:=cordconstnode.create(l,defaultordconsttype,true)
  1843. end
  1844. end
  1845. else
  1846. begin
  1847. consume(_INTCONST);
  1848. { check whether the value isn't in the longint range as well }
  1849. { (longint is easier to perform calculations with) (JM) }
  1850. if card <= $7fffffff then
  1851. { no sign extension necessary, so not longint typecast (JM) }
  1852. p1:=cordconstnode.create(card,s32bittype,true)
  1853. else
  1854. p1:=cordconstnode.create(card,u32bittype,true)
  1855. end;
  1856. end;
  1857. _REALNUMBER :
  1858. begin
  1859. val(pattern,d,code);
  1860. if code<>0 then
  1861. begin
  1862. Message(parser_e_error_in_real);
  1863. d:=1.0;
  1864. end;
  1865. consume(_REALNUMBER);
  1866. p1:=crealconstnode.create(d,pbestrealtype^);
  1867. end;
  1868. _STRING :
  1869. begin
  1870. string_dec(htype);
  1871. { STRING can be also a type cast }
  1872. if token=_LKLAMMER then
  1873. begin
  1874. consume(_LKLAMMER);
  1875. p1:=comp_expr(true);
  1876. consume(_RKLAMMER);
  1877. p1:=ctypeconvnode.create_explicit(p1,htype);
  1878. { handle postfix operators here e.g. string(a)[10] }
  1879. again:=true;
  1880. postfixoperators(p1,again);
  1881. end
  1882. else
  1883. p1:=ctypenode.create(htype);
  1884. end;
  1885. _FILE :
  1886. begin
  1887. htype:=cfiletype;
  1888. consume(_FILE);
  1889. { FILE can be also a type cast }
  1890. if token=_LKLAMMER then
  1891. begin
  1892. consume(_LKLAMMER);
  1893. p1:=comp_expr(true);
  1894. consume(_RKLAMMER);
  1895. p1:=ctypeconvnode.create_explicit(p1,htype);
  1896. { handle postfix operators here e.g. string(a)[10] }
  1897. again:=true;
  1898. postfixoperators(p1,again);
  1899. end
  1900. else
  1901. begin
  1902. p1:=ctypenode.create(htype);
  1903. end;
  1904. end;
  1905. _CSTRING :
  1906. begin
  1907. p1:=cstringconstnode.createstr(pattern,st_default);
  1908. consume(_CSTRING);
  1909. end;
  1910. _CCHAR :
  1911. begin
  1912. p1:=cordconstnode.create(ord(pattern[1]),cchartype,true);
  1913. consume(_CCHAR);
  1914. end;
  1915. _CWSTRING:
  1916. begin
  1917. p1:=cstringconstnode.createwstr(patternw);
  1918. consume(_CWSTRING);
  1919. end;
  1920. _CWCHAR:
  1921. begin
  1922. p1:=cordconstnode.create(ord(getcharwidestring(patternw,0)),cwidechartype,true);
  1923. consume(_CWCHAR);
  1924. end;
  1925. _KLAMMERAFFE :
  1926. begin
  1927. consume(_KLAMMERAFFE);
  1928. got_addrn:=true;
  1929. { support both @<x> and @(<x>) }
  1930. if try_to_consume(_LKLAMMER) then
  1931. begin
  1932. p1:=factor(true);
  1933. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1934. begin
  1935. again:=true;
  1936. postfixoperators(p1,again);
  1937. end;
  1938. consume(_RKLAMMER);
  1939. end
  1940. else
  1941. p1:=factor(true);
  1942. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1943. begin
  1944. again:=true;
  1945. postfixoperators(p1,again);
  1946. end;
  1947. got_addrn:=false;
  1948. p1:=caddrnode.create(p1);
  1949. { Store the procvar that we are expecting, the
  1950. addrn will use the information to find the correct
  1951. procdef or it will return an error }
  1952. if assigned(getprocvardef) and
  1953. (taddrnode(p1).left.nodetype = loadn) then
  1954. taddrnode(p1).getprocvardef:=getprocvardef;
  1955. end;
  1956. _LKLAMMER :
  1957. begin
  1958. consume(_LKLAMMER);
  1959. p1:=comp_expr(true);
  1960. consume(_RKLAMMER);
  1961. { it's not a good solution }
  1962. { but (a+b)^ makes some problems }
  1963. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1964. begin
  1965. again:=true;
  1966. postfixoperators(p1,again);
  1967. end;
  1968. end;
  1969. _LECKKLAMMER :
  1970. begin
  1971. consume(_LECKKLAMMER);
  1972. p1:=factor_read_set;
  1973. consume(_RECKKLAMMER);
  1974. end;
  1975. _PLUS :
  1976. begin
  1977. consume(_PLUS);
  1978. p1:=factor(false);
  1979. end;
  1980. _MINUS :
  1981. begin
  1982. consume(_MINUS);
  1983. p1:=sub_expr(oppower,false);
  1984. p1:=cunaryminusnode.create(p1);
  1985. end;
  1986. _OP_NOT :
  1987. begin
  1988. consume(_OP_NOT);
  1989. p1:=factor(false);
  1990. p1:=cnotnode.create(p1);
  1991. end;
  1992. _TRUE :
  1993. begin
  1994. consume(_TRUE);
  1995. p1:=cordconstnode.create(1,booltype,false);
  1996. end;
  1997. _FALSE :
  1998. begin
  1999. consume(_FALSE);
  2000. p1:=cordconstnode.create(0,booltype,false);
  2001. end;
  2002. _NIL :
  2003. begin
  2004. consume(_NIL);
  2005. p1:=cnilnode.create;
  2006. { It's really ugly code nil^, but delphi allows it }
  2007. if token in [_CARET] then
  2008. begin
  2009. again:=true;
  2010. postfixoperators(p1,again);
  2011. end;
  2012. end;
  2013. else
  2014. begin
  2015. p1:=cerrornode.create;
  2016. consume(token);
  2017. Message(cg_e_illegal_expression);
  2018. end;
  2019. end;
  2020. { generate error node if no node is created }
  2021. if not assigned(p1) then
  2022. begin
  2023. {$ifdef EXTDEBUG}
  2024. Comment(V_Warning,'factor: p1=nil');
  2025. {$endif}
  2026. p1:=cerrornode.create;
  2027. end;
  2028. { get the resulttype for the node }
  2029. if (not assigned(p1.resulttype.def)) then
  2030. do_resulttypepass(p1);
  2031. { tp7 procvar handling, but not if the next token
  2032. will be a := }
  2033. check_tp_procvar(p1);
  2034. factor:=p1;
  2035. check_tokenpos;
  2036. end;
  2037. {$ifdef fpc}
  2038. {$maxfpuregisters default}
  2039. {$endif fpc}
  2040. {****************************************************************************
  2041. Sub_Expr
  2042. ****************************************************************************}
  2043. const
  2044. { Warning these stay be ordered !! }
  2045. operator_levels:array[Toperator_precedence] of set of Ttoken=
  2046. ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_OP_IN,_OP_IS],
  2047. [_PLUS,_MINUS,_OP_OR,_OP_XOR],
  2048. [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,
  2049. _OP_AS,_OP_AND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
  2050. [_STARSTAR] );
  2051. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):tnode;
  2052. {Reads a subexpression while the operators are of the current precedence
  2053. level, or any higher level. Replaces the old term, simpl_expr and
  2054. simpl2_expr.}
  2055. var
  2056. p1,p2 : tnode;
  2057. oldt : Ttoken;
  2058. filepos : tfileposinfo;
  2059. begin
  2060. if pred_level=highest_precedence then
  2061. p1:=factor(false)
  2062. else
  2063. p1:=sub_expr(succ(pred_level),true);
  2064. repeat
  2065. if (token in operator_levels[pred_level]) and
  2066. ((token<>_EQUAL) or accept_equal) then
  2067. begin
  2068. oldt:=token;
  2069. filepos:=akttokenpos;
  2070. consume(token);
  2071. if pred_level=highest_precedence then
  2072. p2:=factor(false)
  2073. else
  2074. p2:=sub_expr(succ(pred_level),true);
  2075. case oldt of
  2076. _PLUS :
  2077. p1:=caddnode.create(addn,p1,p2);
  2078. _MINUS :
  2079. p1:=caddnode.create(subn,p1,p2);
  2080. _STAR :
  2081. p1:=caddnode.create(muln,p1,p2);
  2082. _SLASH :
  2083. p1:=caddnode.create(slashn,p1,p2);
  2084. _EQUAL :
  2085. p1:=caddnode.create(equaln,p1,p2);
  2086. _GT :
  2087. p1:=caddnode.create(gtn,p1,p2);
  2088. _LT :
  2089. p1:=caddnode.create(ltn,p1,p2);
  2090. _GTE :
  2091. p1:=caddnode.create(gten,p1,p2);
  2092. _LTE :
  2093. p1:=caddnode.create(lten,p1,p2);
  2094. _SYMDIF :
  2095. p1:=caddnode.create(symdifn,p1,p2);
  2096. _STARSTAR :
  2097. p1:=caddnode.create(starstarn,p1,p2);
  2098. _OP_AS :
  2099. p1:=casnode.create(p1,p2);
  2100. _OP_IN :
  2101. p1:=cinnode.create(p1,p2);
  2102. _OP_IS :
  2103. p1:=cisnode.create(p1,p2);
  2104. _OP_OR :
  2105. p1:=caddnode.create(orn,p1,p2);
  2106. _OP_AND :
  2107. p1:=caddnode.create(andn,p1,p2);
  2108. _OP_DIV :
  2109. p1:=cmoddivnode.create(divn,p1,p2);
  2110. _OP_NOT :
  2111. p1:=cnotnode.create(p1);
  2112. _OP_MOD :
  2113. p1:=cmoddivnode.create(modn,p1,p2);
  2114. _OP_SHL :
  2115. p1:=cshlshrnode.create(shln,p1,p2);
  2116. _OP_SHR :
  2117. p1:=cshlshrnode.create(shrn,p1,p2);
  2118. _OP_XOR :
  2119. p1:=caddnode.create(xorn,p1,p2);
  2120. _ASSIGNMENT :
  2121. p1:=cassignmentnode.create(p1,p2);
  2122. _CARET :
  2123. p1:=caddnode.create(caretn,p1,p2);
  2124. _UNEQUAL :
  2125. p1:=caddnode.create(unequaln,p1,p2);
  2126. end;
  2127. p1.set_tree_filepos(filepos);
  2128. end
  2129. else
  2130. break;
  2131. until false;
  2132. sub_expr:=p1;
  2133. end;
  2134. function comp_expr(accept_equal : boolean):tnode;
  2135. var
  2136. oldafterassignment : boolean;
  2137. p1 : tnode;
  2138. begin
  2139. oldafterassignment:=afterassignment;
  2140. afterassignment:=true;
  2141. p1:=sub_expr(opcompare,accept_equal);
  2142. { get the resulttype for this expression }
  2143. if not assigned(p1.resulttype.def) then
  2144. do_resulttypepass(p1);
  2145. afterassignment:=oldafterassignment;
  2146. comp_expr:=p1;
  2147. end;
  2148. function expr : tnode;
  2149. var
  2150. p1,p2 : tnode;
  2151. oldafterassignment : boolean;
  2152. oldp1 : tnode;
  2153. filepos : tfileposinfo;
  2154. begin
  2155. oldafterassignment:=afterassignment;
  2156. p1:=sub_expr(opcompare,true);
  2157. { get the resulttype for this expression }
  2158. if not assigned(p1.resulttype.def) then
  2159. do_resulttypepass(p1);
  2160. filepos:=akttokenpos;
  2161. check_tp_procvar(p1);
  2162. if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  2163. afterassignment:=true;
  2164. oldp1:=p1;
  2165. case token of
  2166. _POINTPOINT :
  2167. begin
  2168. consume(_POINTPOINT);
  2169. p2:=sub_expr(opcompare,true);
  2170. p1:=crangenode.create(p1,p2);
  2171. end;
  2172. _ASSIGNMENT :
  2173. begin
  2174. consume(_ASSIGNMENT);
  2175. if (p1.resulttype.def.deftype=procvardef) then
  2176. getprocvardef:=tprocvardef(p1.resulttype.def);
  2177. p2:=sub_expr(opcompare,true);
  2178. if assigned(getprocvardef) then
  2179. handle_procvar(getprocvardef,p2);
  2180. getprocvardef:=nil;
  2181. p1:=cassignmentnode.create(p1,p2);
  2182. end;
  2183. _PLUSASN :
  2184. begin
  2185. consume(_PLUSASN);
  2186. p2:=sub_expr(opcompare,true);
  2187. p1:=cassignmentnode.create(p1,caddnode.create(addn,p1.getcopy,p2));
  2188. end;
  2189. _MINUSASN :
  2190. begin
  2191. consume(_MINUSASN);
  2192. p2:=sub_expr(opcompare,true);
  2193. p1:=cassignmentnode.create(p1,caddnode.create(subn,p1.getcopy,p2));
  2194. end;
  2195. _STARASN :
  2196. begin
  2197. consume(_STARASN );
  2198. p2:=sub_expr(opcompare,true);
  2199. p1:=cassignmentnode.create(p1,caddnode.create(muln,p1.getcopy,p2));
  2200. end;
  2201. _SLASHASN :
  2202. begin
  2203. consume(_SLASHASN );
  2204. p2:=sub_expr(opcompare,true);
  2205. p1:=cassignmentnode.create(p1,caddnode.create(slashn,p1.getcopy,p2));
  2206. end;
  2207. end;
  2208. { get the resulttype for this expression }
  2209. if not assigned(p1.resulttype.def) then
  2210. do_resulttypepass(p1);
  2211. afterassignment:=oldafterassignment;
  2212. if p1<>oldp1 then
  2213. p1.set_tree_filepos(filepos);
  2214. expr:=p1;
  2215. end;
  2216. {$ifdef int64funcresok}
  2217. function get_intconst:TConstExprInt;
  2218. {$else int64funcresok}
  2219. function get_intconst:longint;
  2220. {$endif int64funcresok}
  2221. {Reads an expression, tries to evalute it and check if it is an integer
  2222. constant. Then the constant is returned.}
  2223. var
  2224. p:tnode;
  2225. begin
  2226. p:=comp_expr(true);
  2227. if not codegenerror then
  2228. begin
  2229. if (p.nodetype<>ordconstn) or
  2230. not(is_integer(p.resulttype.def)) then
  2231. Message(cg_e_illegal_expression)
  2232. else
  2233. get_intconst:=tordconstnode(p).value;
  2234. end;
  2235. p.free;
  2236. end;
  2237. function get_stringconst:string;
  2238. {Reads an expression, tries to evaluate it and checks if it is a string
  2239. constant. Then the constant is returned.}
  2240. var
  2241. p:tnode;
  2242. begin
  2243. get_stringconst:='';
  2244. p:=comp_expr(true);
  2245. if p.nodetype<>stringconstn then
  2246. begin
  2247. if (p.nodetype=ordconstn) and is_char(p.resulttype.def) then
  2248. get_stringconst:=char(tordconstnode(p).value)
  2249. else
  2250. Message(cg_e_illegal_expression);
  2251. end
  2252. else
  2253. get_stringconst:=strpas(tstringconstnode(p).value_str);
  2254. p.free;
  2255. end;
  2256. end.
  2257. {
  2258. $Log$
  2259. Revision 1.130 2003-10-01 20:34:49 peter
  2260. * procinfo unit contains tprocinfo
  2261. * cginfo renamed to cgbase
  2262. * moved cgmessage to verbose
  2263. * fixed ppc and sparc compiles
  2264. Revision 1.129 2003/09/23 17:56:05 peter
  2265. * locals and paras are allocated in the code generation
  2266. * tvarsym.localloc contains the location of para/local when
  2267. generating code for the current procedure
  2268. Revision 1.128 2003/09/06 22:27:09 florian
  2269. * fixed web bug 2669
  2270. * cosmetic fix in printnode
  2271. * tobjectdef.gettypename implemented
  2272. Revision 1.127 2003/09/05 17:41:12 florian
  2273. * merged Wiktor's Watcom patches in 1.1
  2274. Revision 1.126 2003/08/23 22:29:51 peter
  2275. * fixed static class check for properties
  2276. Revision 1.125 2003/08/23 18:41:52 peter
  2277. * allow typeof(self) in class methods
  2278. Revision 1.124 2003/08/10 17:25:23 peter
  2279. * fixed some reported bugs
  2280. Revision 1.123 2003/06/13 21:19:31 peter
  2281. * current_procdef removed, use current_procinfo.procdef instead
  2282. Revision 1.122 2003/06/03 21:02:57 peter
  2283. * don't set nf_member when loaded from with symtable
  2284. * allow static variables in class methods
  2285. Revision 1.121 2003/05/22 17:43:21 peter
  2286. * search defaulthandler only for message methods
  2287. Revision 1.120 2003/05/15 18:58:53 peter
  2288. * removed selfpointer_offset, vmtpointer_offset
  2289. * tvarsym.adjusted_address
  2290. * address in localsymtable is now in the real direction
  2291. * removed some obsolete globals
  2292. Revision 1.119 2003/05/13 20:54:39 peter
  2293. * ifdef'd code that checked for failed inherited constructors
  2294. Revision 1.118 2003/05/13 19:14:41 peter
  2295. * failn removed
  2296. * inherited result code check moven to pexpr
  2297. Revision 1.117 2003/05/11 21:37:03 peter
  2298. * moved implicit exception frame from ncgutil to psub
  2299. * constructor/destructor helpers moved from cobj/ncgutil to psub
  2300. Revision 1.116 2003/05/11 14:45:12 peter
  2301. * tloadnode does not support objectsymtable,withsymtable anymore
  2302. * withnode cleanup
  2303. * direct with rewritten to use temprefnode
  2304. Revision 1.115 2003/05/09 17:47:03 peter
  2305. * self moved to hidden parameter
  2306. * removed hdisposen,hnewn,selfn
  2307. Revision 1.114 2003/05/01 07:59:42 florian
  2308. * introduced defaultordconsttype to decribe the default size of ordinal constants
  2309. on 64 bit CPUs it's equal to cs64bitdef while on 32 bit CPUs it's equal to s32bitdef
  2310. + added defines CPU32 and CPU64 for 32 bit and 64 bit CPUs
  2311. * int64s/qwords are allowed as for loop counter on 64 bit CPUs
  2312. Revision 1.113 2003/04/27 11:21:33 peter
  2313. * aktprocdef renamed to current_procinfo.procdef
  2314. * procinfo renamed to current_procinfo
  2315. * procinfo will now be stored in current_module so it can be
  2316. cleaned up properly
  2317. * gen_main_procsym changed to create_main_proc and release_main_proc
  2318. to also generate a tprocinfo structure
  2319. * fixed unit implicit initfinal
  2320. Revision 1.112 2003/04/27 07:29:50 peter
  2321. * current_procinfo.procdef cleanup, current_procdef is now always nil when parsing
  2322. a new procdef declaration
  2323. * aktprocsym removed
  2324. * lexlevel removed, use symtable.symtablelevel instead
  2325. * implicit init/final code uses the normal genentry/genexit
  2326. * funcret state checking updated for new funcret handling
  2327. Revision 1.111 2003/04/26 00:33:07 peter
  2328. * vo_is_result flag added for the special RESULT symbol
  2329. Revision 1.110 2003/04/25 20:59:33 peter
  2330. * removed funcretn,funcretsym, function result is now in varsym
  2331. and aliases for result and function name are added using absolutesym
  2332. * vs_hidden parameter for funcret passed in parameter
  2333. * vs_hidden fixes
  2334. * writenode changed to printnode and released from extdebug
  2335. * -vp option added to generate a tree.log with the nodetree
  2336. * nicer printnode for statements, callnode
  2337. Revision 1.109 2003/04/23 10:13:55 peter
  2338. * firstaddr will check procvardef
  2339. Revision 1.108 2003/04/22 23:50:23 peter
  2340. * firstpass uses expectloc
  2341. * checks if there are differences between the expectloc and
  2342. location.loc from secondpass in EXTDEBUG
  2343. Revision 1.107 2003/04/11 15:49:01 peter
  2344. * default property also increased the reference count for the
  2345. property symbol
  2346. Revision 1.106 2003/04/11 14:50:08 peter
  2347. * fix tw2454
  2348. Revision 1.105 2003/03/27 17:44:13 peter
  2349. * fixed small mem leaks
  2350. Revision 1.104 2003/03/17 18:55:30 peter
  2351. * allow more tokens instead of only semicolon after inherited
  2352. Revision 1.103 2003/03/17 16:54:41 peter
  2353. * support DefaultHandler and anonymous inheritance fixed
  2354. for message methods
  2355. Revision 1.102 2003/01/30 21:46:57 peter
  2356. * self fixes for static methods (merged)
  2357. Revision 1.101 2003/01/16 22:12:22 peter
  2358. * Find the correct procvar to load when using @ in fpc mode
  2359. Revision 1.100 2003/01/15 01:44:32 peter
  2360. * merged methodpointer fixes from 1.0.x
  2361. Revision 1.98 2003/01/12 17:51:42 peter
  2362. * tp procvar handling fix for tb0448
  2363. Revision 1.97 2003/01/05 22:44:14 peter
  2364. * remove a lot of code to support typen in loadn-procsym
  2365. Revision 1.96 2002/12/11 22:40:36 peter
  2366. * assigned(procvar) fix for delphi mode, fixes tb0430
  2367. Revision 1.95 2002/11/30 11:12:48 carl
  2368. + checking for symbols used with hint directives is done mostly in pexpr
  2369. only now
  2370. Revision 1.94 2002/11/27 15:33:47 peter
  2371. * the never ending story of tp procvar hacks
  2372. Revision 1.93 2002/11/26 22:58:24 peter
  2373. * fix for tw2178. When a ^ or . follows a procsym then the procsym
  2374. needs to be called
  2375. Revision 1.92 2002/11/25 17:43:22 peter
  2376. * splitted defbase in defutil,symutil,defcmp
  2377. * merged isconvertable and is_equal into compare_defs(_ext)
  2378. * made operator search faster by walking the list only once
  2379. Revision 1.91 2002/11/22 22:48:10 carl
  2380. * memory optimization with tconstsym (1.5%)
  2381. Revision 1.90 2002/11/20 22:49:55 pierre
  2382. * commented check code tht was invalid in 1.1
  2383. Revision 1.89 2002/11/18 18:34:41 peter
  2384. * fix crash with EXTDEBUG code
  2385. Revision 1.88 2002/11/18 17:48:21 peter
  2386. * fix tw2209 (merged)
  2387. Revision 1.87 2002/11/18 17:31:58 peter
  2388. * pass proccalloption to ret_in_xxx and push_xxx functions
  2389. Revision 1.86 2002/10/05 00:48:57 peter
  2390. * support inherited; support for overload as it is handled by
  2391. delphi. This is only for delphi mode as it is working is
  2392. undocumented and hard to predict what is done
  2393. Revision 1.85 2002/10/04 21:13:59 peter
  2394. * ignore vecn,subscriptn when checking for a procvar loadn
  2395. Revision 1.84 2002/10/02 20:51:22 peter
  2396. * don't check interfaces for class methods
  2397. Revision 1.83 2002/10/02 18:20:52 peter
  2398. * Copy() is now internal syssym that calls compilerprocs
  2399. Revision 1.82 2002/09/30 07:00:48 florian
  2400. * fixes to common code to get the alpha compiler compiled applied
  2401. Revision 1.81 2002/09/16 19:06:14 peter
  2402. * allow ^ after nil
  2403. Revision 1.80 2002/09/07 15:25:07 peter
  2404. * old logs removed and tabs fixed
  2405. Revision 1.79 2002/09/07 12:16:03 carl
  2406. * second part bug report 1996 fix, testrange in cordconstnode
  2407. only called if option is set (also make parsing a tiny faster)
  2408. Revision 1.78 2002/09/03 16:26:27 daniel
  2409. * Make Tprocdef.defs protected
  2410. Revision 1.77 2002/08/18 20:06:24 peter
  2411. * inlining is now also allowed in interface
  2412. * renamed write/load to ppuwrite/ppuload
  2413. * tnode storing in ppu
  2414. * nld,ncon,nbas are already updated for storing in ppu
  2415. Revision 1.76 2002/08/17 09:23:39 florian
  2416. * first part of procinfo rewrite
  2417. Revision 1.75 2002/08/01 16:37:47 jonas
  2418. - removed some superfluous "in_paras := true" statements
  2419. Revision 1.74 2002/07/26 21:15:41 florian
  2420. * rewrote the system handling
  2421. Revision 1.73 2002/07/23 09:51:23 daniel
  2422. * Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
  2423. are worth comitting.
  2424. Revision 1.72 2002/07/20 11:57:55 florian
  2425. * types.pas renamed to defbase.pas because D6 contains a types
  2426. unit so this would conflicts if D6 programms are compiled
  2427. + Willamette/SSE2 instructions to assembler added
  2428. Revision 1.71 2002/07/16 15:34:20 florian
  2429. * exit is now a syssym instead of a keyword
  2430. Revision 1.70 2002/07/06 20:18:02 carl
  2431. * longstring declaration now gives parser error since its not supported!
  2432. Revision 1.69 2002/06/12 15:46:14 jonas
  2433. * fixed web bug 1995
  2434. Revision 1.68 2002/05/18 13:34:12 peter
  2435. * readded missing revisions
  2436. Revision 1.67 2002/05/16 19:46:43 carl
  2437. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  2438. + try to fix temp allocation (still in ifdef)
  2439. + generic constructor calls
  2440. + start of tassembler / tmodulebase class cleanup
  2441. Revision 1.65 2002/05/12 16:53:09 peter
  2442. * moved entry and exitcode to ncgutil and cgobj
  2443. * foreach gets extra argument for passing local data to the
  2444. iterator function
  2445. * -CR checks also class typecasts at runtime by changing them
  2446. into as
  2447. * fixed compiler to cycle with the -CR option
  2448. * fixed stabs with elf writer, finally the global variables can
  2449. be watched
  2450. * removed a lot of routines from cga unit and replaced them by
  2451. calls to cgobj
  2452. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  2453. u32bit then the other is typecasted also to u32bit without giving
  2454. a rangecheck warning/error.
  2455. * fixed pascal calling method with reversing also the high tree in
  2456. the parast, detected by tcalcst3 test
  2457. Revision 1.64 2002/04/23 19:16:34 peter
  2458. * add pinline unit that inserts compiler supported functions using
  2459. one or more statements
  2460. * moved finalize and setlength from ninl to pinline
  2461. Revision 1.63 2002/04/21 19:02:05 peter
  2462. * removed newn and disposen nodes, the code is now directly
  2463. inlined from pexpr
  2464. * -an option that will write the secondpass nodes to the .s file, this
  2465. requires EXTDEBUG define to actually write the info
  2466. * fixed various internal errors and crashes due recent code changes
  2467. Revision 1.62 2002/04/16 16:11:17 peter
  2468. * using inherited; without a parent having the same function
  2469. will do nothing like delphi
  2470. Revision 1.61 2002/04/07 13:31:36 carl
  2471. + change unit use
  2472. Revision 1.60 2002/04/01 20:57:13 jonas
  2473. * fixed web bug 1907
  2474. * fixed some other procvar related bugs (all related to accepting procvar
  2475. constructs with either too many or too little parameters)
  2476. (both merged, includes second typo fix of pexpr.pas)
  2477. Revision 1.59 2002/03/31 20:26:35 jonas
  2478. + a_loadfpu_* and a_loadmm_* methods in tcg
  2479. * register allocation is now handled by a class and is mostly processor
  2480. independent (+rgobj.pas and i386/rgcpu.pas)
  2481. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  2482. * some small improvements and fixes to the optimizer
  2483. * some register allocation fixes
  2484. * some fpuvaroffset fixes in the unary minus node
  2485. * push/popusedregisters is now called rg.save/restoreusedregisters and
  2486. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  2487. also better optimizable)
  2488. * fixed and optimized register saving/restoring for new/dispose nodes
  2489. * LOC_FPU locations now also require their "register" field to be set to
  2490. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  2491. - list field removed of the tnode class because it's not used currently
  2492. and can cause hard-to-find bugs
  2493. }