pexpr.pas 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715
  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
  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. { if there is a localcopy then use that }
  666. if assigned(vs.localvarsym) then
  667. vs:=vs.localvarsym;
  668. para:=ccallparanode.create(cloadnode.create(vs,vs.owner),para);
  669. end;
  670. currpara:=tparaitem(currpara.next);
  671. end;
  672. end
  673. else
  674. begin
  675. if try_to_consume(_LKLAMMER) then
  676. begin
  677. para:=parse_paras(false,false);
  678. consume(_RKLAMMER);
  679. end;
  680. end;
  681. p1:=ccallnode.create(para,tprocsym(sym),st,p1);
  682. { indicate if this call was generated by a member and
  683. no explicit self is used, this is needed to determine
  684. how to handle a destructor call (PFV) }
  685. if membercall then
  686. include(p1.flags,nf_member_call);
  687. end;
  688. afterassignment:=prevafterassn;
  689. end;
  690. procedure handle_procvar(pv : tprocvardef;var p2 : tnode);
  691. var
  692. hp,hp2 : tnode;
  693. hpp : ^tnode;
  694. currprocdef : tprocdef;
  695. begin
  696. if not assigned(pv) then
  697. internalerror(200301121);
  698. if (m_tp_procvar in aktmodeswitches) then
  699. begin
  700. hp:=p2;
  701. hpp:=@p2;
  702. while assigned(hp) and
  703. (hp.nodetype=typeconvn) do
  704. begin
  705. hp:=ttypeconvnode(hp).left;
  706. { save orignal address of the old tree so we can replace the node }
  707. hpp:=@hp;
  708. end;
  709. if (hp.nodetype=calln) and
  710. { a procvar can't have parameters! }
  711. not assigned(tcallnode(hp).left) then
  712. begin
  713. currprocdef:=tcallnode(hp).symtableprocentry.search_procdef_byprocvardef(pv);
  714. if assigned(currprocdef) then
  715. begin
  716. hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
  717. if (po_methodpointer in pv.procoptions) then
  718. tloadnode(hp2).set_mp(tnode(tcallnode(hp).methodpointer).getcopy);
  719. hp.destroy;
  720. { replace the old callnode with the new loadnode }
  721. hpp^:=hp2;
  722. end;
  723. end;
  724. end;
  725. end;
  726. { the following procedure handles the access to a property symbol }
  727. procedure handle_propertysym(sym : tsym;st : tsymtable;var p1 : tnode; getaddr: boolean);
  728. procedure symlist_to_node(var p1:tnode;pl:tsymlist);
  729. var
  730. plist : psymlistitem;
  731. begin
  732. plist:=pl.firstsym;
  733. while assigned(plist) do
  734. begin
  735. case plist^.sltype of
  736. sl_load :
  737. begin
  738. { p1 can already contain the loadnode of
  739. the class variable. When there is no tree yet we
  740. may need to load it for with or objects }
  741. if not assigned(p1) then
  742. begin
  743. case st.symtabletype of
  744. withsymtable :
  745. p1:=tnode(twithsymtable(st).withrefnode).getcopy;
  746. objectsymtable :
  747. p1:=load_self_node;
  748. end;
  749. end;
  750. if assigned(p1) then
  751. p1:=csubscriptnode.create(plist^.sym,p1)
  752. else
  753. p1:=cloadnode.create(plist^.sym,st);
  754. end;
  755. sl_subscript :
  756. p1:=csubscriptnode.create(plist^.sym,p1);
  757. sl_vec :
  758. p1:=cvecnode.create(p1,cordconstnode.create(plist^.value,s32bittype,true));
  759. else
  760. internalerror(200110205);
  761. end;
  762. plist:=plist^.next;
  763. end;
  764. include(p1.flags,nf_isproperty);
  765. end;
  766. var
  767. paras : tnode;
  768. p2 : tnode;
  769. membercall : boolean;
  770. begin
  771. paras:=nil;
  772. { property parameters? read them only if the property really }
  773. { has parameters }
  774. if (ppo_hasparameters in tpropertysym(sym).propoptions) then
  775. begin
  776. if token=_LECKKLAMMER then
  777. begin
  778. consume(_LECKKLAMMER);
  779. paras:=parse_paras(false,true);
  780. consume(_RECKKLAMMER);
  781. end;
  782. end;
  783. { indexed property }
  784. if (ppo_indexed in tpropertysym(sym).propoptions) then
  785. begin
  786. p2:=cordconstnode.create(tpropertysym(sym).index,tpropertysym(sym).indextype,true);
  787. paras:=ccallparanode.create(p2,paras);
  788. end;
  789. { we need only a write property if a := follows }
  790. { if not(afterassignment) and not(in_args) then }
  791. if token=_ASSIGNMENT then
  792. begin
  793. { write property: }
  794. if not tpropertysym(sym).writeaccess.empty then
  795. begin
  796. case tpropertysym(sym).writeaccess.firstsym^.sym.typ of
  797. procsym :
  798. begin
  799. { generate the method call }
  800. membercall:=maybe_load_methodpointer(st,p1);
  801. p1:=ccallnode.create(paras,
  802. tprocsym(tpropertysym(sym).writeaccess.firstsym^.sym),st,p1);
  803. if membercall then
  804. include(tcallnode(p1).flags,nf_member_call);
  805. paras:=nil;
  806. consume(_ASSIGNMENT);
  807. { read the expression }
  808. if tpropertysym(sym).proptype.def.deftype=procvardef then
  809. getprocvardef:=tprocvardef(tpropertysym(sym).proptype.def);
  810. p2:=comp_expr(true);
  811. if assigned(getprocvardef) then
  812. handle_procvar(getprocvardef,p2);
  813. tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
  814. include(tcallnode(p1).flags,nf_isproperty);
  815. getprocvardef:=nil;
  816. end;
  817. varsym :
  818. begin
  819. { generate access code }
  820. symlist_to_node(p1,tpropertysym(sym).writeaccess);
  821. consume(_ASSIGNMENT);
  822. { read the expression }
  823. p2:=comp_expr(true);
  824. p1:=cassignmentnode.create(p1,p2);
  825. end
  826. else
  827. begin
  828. p1:=cerrornode.create;
  829. Message(parser_e_no_procedure_to_access_property);
  830. end;
  831. end;
  832. end
  833. else
  834. begin
  835. p1:=cerrornode.create;
  836. Message(parser_e_no_procedure_to_access_property);
  837. end;
  838. end
  839. else
  840. begin
  841. { read property: }
  842. if not tpropertysym(sym).readaccess.empty then
  843. begin
  844. case tpropertysym(sym).readaccess.firstsym^.sym.typ of
  845. varsym :
  846. begin
  847. { generate access code }
  848. symlist_to_node(p1,tpropertysym(sym).readaccess);
  849. end;
  850. procsym :
  851. begin
  852. { generate the method call }
  853. membercall:=maybe_load_methodpointer(st,p1);
  854. p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).readaccess.firstsym^.sym),st,p1);
  855. if membercall then
  856. include(tcallnode(p1).flags,nf_member_call);
  857. paras:=nil;
  858. include(p1.flags,nf_isproperty);
  859. end
  860. else
  861. begin
  862. p1:=cerrornode.create;
  863. Message(type_e_mismatch);
  864. end;
  865. end;
  866. end
  867. else
  868. begin
  869. { error, no function to read property }
  870. p1:=cerrornode.create;
  871. Message(parser_e_no_procedure_to_access_property);
  872. end;
  873. end;
  874. { release paras if not used }
  875. if assigned(paras) then
  876. paras.free;
  877. end;
  878. { the ID token has to be consumed before calling this function }
  879. procedure do_member_read(getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callnflags:tnodeflags);
  880. var
  881. static_name : string;
  882. isclassref : boolean;
  883. srsymtable : tsymtable;
  884. {$ifdef CHECKINHERITEDRESULT}
  885. newstatement : tstatementnode;
  886. newblock : tblocknode;
  887. {$endif CHECKINHERITEDRESULT}
  888. begin
  889. if sym=nil then
  890. begin
  891. { pattern is still valid unless
  892. there is another ID just after the ID of sym }
  893. Message1(sym_e_id_no_member,pattern);
  894. p1.free;
  895. p1:=cerrornode.create;
  896. { try to clean up }
  897. again:=false;
  898. end
  899. else
  900. begin
  901. if assigned(p1) then
  902. begin
  903. if not assigned(p1.resulttype.def) then
  904. do_resulttypepass(p1);
  905. isclassref:=(p1.resulttype.def.deftype=classrefdef);
  906. end
  907. else
  908. isclassref:=false;
  909. { we assume, that only procsyms and varsyms are in an object }
  910. { symbol table, for classes, properties are allowed }
  911. case sym.typ of
  912. procsym:
  913. begin
  914. do_proc_call(sym,sym.owner,
  915. (getaddr and not(token in [_CARET,_POINT])),
  916. again,p1);
  917. { add provided flags }
  918. if (p1.nodetype=calln) then
  919. p1.flags:=p1.flags+callnflags;
  920. { we need to know which procedure is called }
  921. do_resulttypepass(p1);
  922. { now we know the method that is called }
  923. if (p1.nodetype=calln) and
  924. assigned(tcallnode(p1).procdefinition) then
  925. begin
  926. { calling using classref? }
  927. if isclassref and
  928. not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
  929. not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
  930. Message(parser_e_only_class_methods_via_class_ref);
  931. {$ifdef CHECKINHERITEDRESULT}
  932. { when calling inherited constructor we need to check the return value }
  933. if (nf_inherited in callnflags) and
  934. (tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
  935. begin
  936. {
  937. For Classes:
  938. self:=inherited constructor
  939. if self=nil then
  940. exit
  941. For objects:
  942. if inherited constructor=false then
  943. begin
  944. self:=nil;
  945. exit;
  946. end;
  947. }
  948. if is_class(tprocdef(tcallnode(p1).procdefinition)._class) then
  949. begin
  950. newblock:=internalstatements(newstatement,true);
  951. addstatement(newstatement,cassignmentnode.create(
  952. ctypeconvnode.create(
  953. load_self_pointer_node,
  954. voidpointertype),
  955. ctypeconvnode.create(
  956. p1,
  957. voidpointertype)));
  958. addstatement(newstatement,cifnode.create(
  959. caddnode.create(equaln,
  960. load_self_pointer_node,
  961. cnilnode.create),
  962. cexitnode.create(nil),
  963. nil));
  964. p1:=newblock;
  965. end
  966. else
  967. if is_object(tprocdef(tcallnode(p1).procdefinition)._class) then
  968. begin
  969. newblock:=internalstatements(newstatement,true);
  970. addstatement(newstatement,call_fail_node);
  971. addstatement(newstatement,cexitnode.create(nil));
  972. p1:=cifnode.create(
  973. caddnode.create(equaln,
  974. cordconstnode.create(0,booltype,false),
  975. p1),
  976. newblock,
  977. nil);
  978. end
  979. else
  980. internalerror(200305133);
  981. end;
  982. {$endif CHECKINHERITEDRESULT}
  983. do_resulttypepass(p1);
  984. end;
  985. end;
  986. varsym:
  987. begin
  988. if (sp_static in sym.symoptions) then
  989. begin
  990. static_name:=lower(sym.owner.name^)+'_'+sym.name;
  991. searchsym(static_name,sym,srsymtable);
  992. check_hints(sym);
  993. p1.free;
  994. p1:=cloadnode.create(sym,srsymtable);
  995. end
  996. else
  997. begin
  998. if isclassref then
  999. Message(parser_e_only_class_methods_via_class_ref);
  1000. p1:=csubscriptnode.create(sym,p1);
  1001. end;
  1002. end;
  1003. propertysym:
  1004. begin
  1005. if isclassref then
  1006. Message(parser_e_only_class_methods_via_class_ref);
  1007. handle_propertysym(sym,sym.owner,p1,getaddr);
  1008. end;
  1009. else internalerror(16);
  1010. end;
  1011. end;
  1012. end;
  1013. {****************************************************************************
  1014. Factor
  1015. ****************************************************************************}
  1016. {$ifdef fpc}
  1017. {$maxfpuregisters 0}
  1018. {$endif fpc}
  1019. function factor(getaddr : boolean) : tnode;
  1020. {---------------------------------------------
  1021. Factor_read_id
  1022. ---------------------------------------------}
  1023. procedure factor_read_id(var p1:tnode;var again:boolean);
  1024. var
  1025. pc : pchar;
  1026. len : longint;
  1027. srsym : tsym;
  1028. possible_error : boolean;
  1029. srsymtable : tsymtable;
  1030. storesymtablestack : tsymtable;
  1031. htype : ttype;
  1032. static_name : string;
  1033. begin
  1034. { allow post fix operators }
  1035. again:=true;
  1036. consume_sym(srsym,srsymtable);
  1037. { Access to funcret or need to call the function? }
  1038. if (srsym.typ in [absolutesym,varsym]) and
  1039. (vo_is_funcret in tvarsym(srsym).varoptions) and
  1040. (
  1041. (token=_LKLAMMER) or
  1042. (not(m_fpc in aktmodeswitches) and
  1043. (afterassignment or in_args) and
  1044. not(vo_is_result in tvarsym(srsym).varoptions))
  1045. ) then
  1046. begin
  1047. storesymtablestack:=symtablestack;
  1048. symtablestack:=srsym.owner.next;
  1049. searchsym(srsym.name,srsym,srsymtable);
  1050. if not assigned(srsym) then
  1051. srsym:=generrorsym;
  1052. if (srsym.typ<>procsym) then
  1053. Message(cg_e_illegal_expression);
  1054. symtablestack:=storesymtablestack;
  1055. end;
  1056. begin
  1057. { check semantics of private }
  1058. if (srsym.typ in [propertysym,procsym,varsym]) and
  1059. (srsym.owner.symtabletype=objectsymtable) then
  1060. begin
  1061. if (sp_private in srsym.symoptions) and
  1062. (tobjectdef(srsym.owner.defowner).owner.symtabletype=globalsymtable) and
  1063. (tobjectdef(srsym.owner.defowner).owner.unitid<>0) then
  1064. Message(parser_e_cant_access_private_member);
  1065. end;
  1066. case srsym.typ of
  1067. absolutesym :
  1068. begin
  1069. p1:=cloadnode.create(srsym,srsymtable);
  1070. end;
  1071. varsym :
  1072. begin
  1073. if (sp_static in srsym.symoptions) then
  1074. begin
  1075. static_name:=lower(srsym.owner.name^)+'_'+srsym.name;
  1076. searchsym(static_name,srsym,srsymtable);
  1077. check_hints(srsym);
  1078. end
  1079. else
  1080. begin
  1081. { are we in a class method, we check here the
  1082. srsymtable, because a field in another object
  1083. also has objectsymtable. And withsymtable is
  1084. not possible for self in class methods (PFV) }
  1085. if (srsymtable.symtabletype=objectsymtable) and
  1086. assigned(current_procinfo) and
  1087. (po_classmethod in current_procinfo.procdef.procoptions) then
  1088. Message(parser_e_only_class_methods);
  1089. end;
  1090. case srsymtable.symtabletype of
  1091. objectsymtable :
  1092. p1:=csubscriptnode.create(srsym,load_self_node);
  1093. withsymtable :
  1094. p1:=csubscriptnode.create(srsym,tnode(twithsymtable(srsymtable).withrefnode).getcopy);
  1095. else
  1096. p1:=cloadnode.create(srsym,srsymtable);
  1097. end;
  1098. if tvarsym(srsym).varstate=vs_declared then
  1099. begin
  1100. include(p1.flags,nf_first_use);
  1101. { set special between first loaded until checked in resulttypepass }
  1102. tvarsym(srsym).varstate:=vs_declared_and_first_found;
  1103. end;
  1104. end;
  1105. typedconstsym :
  1106. begin
  1107. p1:=cloadnode.create(srsym,srsymtable);
  1108. end;
  1109. syssym :
  1110. begin
  1111. p1:=statement_syssym(tsyssym(srsym).number);
  1112. end;
  1113. typesym :
  1114. begin
  1115. htype.setsym(srsym);
  1116. if not assigned(htype.def) then
  1117. begin
  1118. again:=false;
  1119. end
  1120. else
  1121. begin
  1122. if token=_LKLAMMER then
  1123. begin
  1124. consume(_LKLAMMER);
  1125. p1:=comp_expr(true);
  1126. consume(_RKLAMMER);
  1127. p1:=ctypeconvnode.create_explicit(p1,htype);
  1128. end
  1129. else { not LKLAMMER }
  1130. if (token=_POINT) and
  1131. is_object(htype.def) then
  1132. begin
  1133. consume(_POINT);
  1134. if assigned(current_procinfo) and
  1135. assigned(current_procinfo.procdef._class) and
  1136. not(getaddr) then
  1137. begin
  1138. if current_procinfo.procdef._class.is_related(tobjectdef(htype.def)) then
  1139. begin
  1140. p1:=ctypenode.create(htype);
  1141. { search also in inherited methods }
  1142. srsym:=searchsym_in_class(tobjectdef(htype.def),pattern);
  1143. check_hints(srsym);
  1144. consume(_ID);
  1145. do_member_read(false,srsym,p1,again,[]);
  1146. end
  1147. else
  1148. begin
  1149. Message(parser_e_no_super_class);
  1150. again:=false;
  1151. end;
  1152. end
  1153. else
  1154. begin
  1155. { allows @TObject.Load }
  1156. { also allows static methods and variables }
  1157. p1:=ctypenode.create(htype);
  1158. { TP allows also @TMenu.Load if Load is only }
  1159. { defined in an anchestor class }
  1160. srsym:=search_class_member(tobjectdef(htype.def),pattern);
  1161. check_hints(srsym);
  1162. if not assigned(srsym) then
  1163. Message1(sym_e_id_no_member,pattern)
  1164. else if not(getaddr) and not(sp_static in srsym.symoptions) then
  1165. Message(sym_e_only_static_in_static)
  1166. else
  1167. begin
  1168. consume(_ID);
  1169. do_member_read(getaddr,srsym,p1,again,[]);
  1170. end;
  1171. end;
  1172. end
  1173. else
  1174. begin
  1175. { class reference ? }
  1176. if is_class(htype.def) then
  1177. begin
  1178. if getaddr and (token=_POINT) then
  1179. begin
  1180. consume(_POINT);
  1181. { allows @Object.Method }
  1182. { also allows static methods and variables }
  1183. p1:=ctypenode.create(htype);
  1184. { TP allows also @TMenu.Load if Load is only }
  1185. { defined in an anchestor class }
  1186. srsym:=search_class_member(tobjectdef(htype.def),pattern);
  1187. check_hints(srsym);
  1188. if not assigned(srsym) then
  1189. Message1(sym_e_id_no_member,pattern)
  1190. else
  1191. begin
  1192. consume(_ID);
  1193. do_member_read(getaddr,srsym,p1,again,[]);
  1194. end;
  1195. end
  1196. else
  1197. begin
  1198. p1:=ctypenode.create(htype);
  1199. { For a type block we simply return only
  1200. the type. For all other blocks we return
  1201. a loadvmt node }
  1202. if (block_type<>bt_type) then
  1203. p1:=cloadvmtaddrnode.create(p1);
  1204. end;
  1205. end
  1206. else
  1207. p1:=ctypenode.create(htype);
  1208. end;
  1209. end;
  1210. end;
  1211. enumsym :
  1212. begin
  1213. p1:=genenumnode(tenumsym(srsym));
  1214. end;
  1215. constsym :
  1216. begin
  1217. case tconstsym(srsym).consttyp of
  1218. constint :
  1219. begin
  1220. { do a very dirty trick to bootstrap this code }
  1221. if (tconstsym(srsym).value.valueord>=-(int64(2147483647)+int64(1))) and
  1222. (tconstsym(srsym).value.valueord<=2147483647) then
  1223. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,s32bittype,true)
  1224. else if (tconstsym(srsym).value.valueord > maxlongint) and
  1225. (tconstsym(srsym).value.valueord <= int64(maxlongint)+int64(maxlongint)+1) then
  1226. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,u32bittype,true)
  1227. else
  1228. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,cs64bittype,true);
  1229. end;
  1230. conststring :
  1231. begin
  1232. len:=tconstsym(srsym).value.len;
  1233. if not(cs_ansistrings in aktlocalswitches) and (len>255) then
  1234. len:=255;
  1235. getmem(pc,len+1);
  1236. move(pchar(tconstsym(srsym).value.valueptr)^,pc^,len);
  1237. pc[len]:=#0;
  1238. p1:=cstringconstnode.createpchar(pc,len);
  1239. end;
  1240. constchar :
  1241. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,cchartype,true);
  1242. constreal :
  1243. p1:=crealconstnode.create(pbestreal(tconstsym(srsym).value.valueptr)^,pbestrealtype^);
  1244. constbool :
  1245. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,booltype,true);
  1246. constset :
  1247. p1:=csetconstnode.create(pconstset(tconstsym(srsym).value.valueptr),tconstsym(srsym).consttype);
  1248. constord :
  1249. p1:=cordconstnode.create(tconstsym(srsym).value.valueord,tconstsym(srsym).consttype,true);
  1250. constpointer :
  1251. p1:=cpointerconstnode.create(tconstsym(srsym).value.valueordptr,tconstsym(srsym).consttype);
  1252. constnil :
  1253. p1:=cnilnode.create;
  1254. constresourcestring:
  1255. begin
  1256. p1:=cloadnode.create(srsym,srsymtable);
  1257. do_resulttypepass(p1);
  1258. p1.resulttype:=cansistringtype;
  1259. end;
  1260. constguid :
  1261. p1:=cguidconstnode.create(pguid(tconstsym(srsym).value.valueptr)^);
  1262. end;
  1263. end;
  1264. procsym :
  1265. begin
  1266. { are we in a class method ? }
  1267. possible_error:=(srsymtable.symtabletype<>withsymtable) and
  1268. (srsym.owner.symtabletype=objectsymtable) and
  1269. not(is_interface(tdef(srsym.owner.defowner))) and
  1270. assigned(current_procinfo) and
  1271. (po_classmethod in current_procinfo.procdef.procoptions);
  1272. do_proc_call(srsym,srsymtable,
  1273. (getaddr and not(token in [_CARET,_POINT])),
  1274. again,p1);
  1275. { we need to know which procedure is called }
  1276. if possible_error then
  1277. begin
  1278. do_resulttypepass(p1);
  1279. if not(po_classmethod in tcallnode(p1).procdefinition.procoptions) then
  1280. Message(parser_e_only_class_methods);
  1281. end;
  1282. end;
  1283. propertysym :
  1284. begin
  1285. { access to property in a method }
  1286. { are we in a class method ? }
  1287. if (srsymtable.symtabletype=objectsymtable) and
  1288. assigned(current_procinfo) and
  1289. (po_classmethod in current_procinfo.procdef.procoptions) then
  1290. Message(parser_e_only_class_methods);
  1291. { no method pointer }
  1292. p1:=nil;
  1293. handle_propertysym(srsym,srsymtable,p1,getaddr);
  1294. end;
  1295. labelsym :
  1296. begin
  1297. consume(_COLON);
  1298. if tlabelsym(srsym).defined then
  1299. Message(sym_e_label_already_defined);
  1300. tlabelsym(srsym).defined:=true;
  1301. p1:=clabelnode.create(tlabelsym(srsym),nil);
  1302. end;
  1303. errorsym :
  1304. begin
  1305. p1:=cerrornode.create;
  1306. if token=_LKLAMMER then
  1307. begin
  1308. consume(_LKLAMMER);
  1309. parse_paras(false,false);
  1310. consume(_RKLAMMER);
  1311. end;
  1312. end;
  1313. else
  1314. begin
  1315. p1:=cerrornode.create;
  1316. Message(cg_e_illegal_expression);
  1317. end;
  1318. end; { end case }
  1319. end;
  1320. end;
  1321. {---------------------------------------------
  1322. Factor_Read_Set
  1323. ---------------------------------------------}
  1324. { Read a set between [] }
  1325. function factor_read_set:tnode;
  1326. var
  1327. p1,p2 : tnode;
  1328. lastp,
  1329. buildp : tarrayconstructornode;
  1330. begin
  1331. buildp:=nil;
  1332. { be sure that a least one arrayconstructn is used, also for an
  1333. empty [] }
  1334. if token=_RECKKLAMMER then
  1335. buildp:=carrayconstructornode.create(nil,buildp)
  1336. else
  1337. begin
  1338. while true do
  1339. begin
  1340. p1:=comp_expr(true);
  1341. if token=_POINTPOINT then
  1342. begin
  1343. consume(_POINTPOINT);
  1344. p2:=comp_expr(true);
  1345. p1:=carrayconstructorrangenode.create(p1,p2);
  1346. end;
  1347. { insert at the end of the tree, to get the correct order }
  1348. if not assigned(buildp) then
  1349. begin
  1350. buildp:=carrayconstructornode.create(p1,nil);
  1351. lastp:=buildp;
  1352. end
  1353. else
  1354. begin
  1355. lastp.right:=carrayconstructornode.create(p1,nil);
  1356. lastp:=tarrayconstructornode(lastp.right);
  1357. end;
  1358. { there could be more elements }
  1359. if token=_COMMA then
  1360. consume(_COMMA)
  1361. else
  1362. break;
  1363. end;
  1364. end;
  1365. factor_read_set:=buildp;
  1366. end;
  1367. {---------------------------------------------
  1368. PostFixOperators
  1369. ---------------------------------------------}
  1370. procedure postfixoperators(var p1:tnode;var again:boolean);
  1371. { tries to avoid syntax errors after invalid qualifiers }
  1372. procedure recoverconsume_postfixops;
  1373. begin
  1374. while true do
  1375. begin
  1376. case token of
  1377. _CARET:
  1378. consume(_CARET);
  1379. _POINT:
  1380. begin
  1381. consume(_POINT);
  1382. if token=_ID then
  1383. consume(_ID);
  1384. end;
  1385. _LECKKLAMMER:
  1386. begin
  1387. consume(_LECKKLAMMER);
  1388. repeat
  1389. comp_expr(true);
  1390. if token=_COMMA then
  1391. consume(_COMMA)
  1392. else
  1393. break;
  1394. until false;
  1395. consume(_RECKKLAMMER);
  1396. end
  1397. else
  1398. break;
  1399. end;
  1400. end;
  1401. end;
  1402. var
  1403. store_static : boolean;
  1404. protsym : tpropertysym;
  1405. p2,p3 : tnode;
  1406. hsym : tsym;
  1407. classh : tobjectdef;
  1408. begin
  1409. again:=true;
  1410. while again do
  1411. begin
  1412. { we need the resulttype }
  1413. do_resulttypepass(p1);
  1414. if codegenerror then
  1415. begin
  1416. recoverconsume_postfixops;
  1417. exit;
  1418. end;
  1419. { handle token }
  1420. case token of
  1421. _CARET:
  1422. begin
  1423. consume(_CARET);
  1424. if (p1.resulttype.def.deftype<>pointerdef) then
  1425. begin
  1426. { ^ as binary operator is a problem!!!! (FK) }
  1427. again:=false;
  1428. Message(cg_e_invalid_qualifier);
  1429. recoverconsume_postfixops;
  1430. p1.destroy;
  1431. p1:=cerrornode.create;
  1432. end
  1433. else
  1434. begin
  1435. p1:=cderefnode.create(p1);
  1436. end;
  1437. end;
  1438. _LECKKLAMMER:
  1439. begin
  1440. if is_class_or_interface(p1.resulttype.def) then
  1441. begin
  1442. { default property }
  1443. protsym:=search_default_property(tobjectdef(p1.resulttype.def));
  1444. if not(assigned(protsym)) then
  1445. begin
  1446. p1.destroy;
  1447. p1:=cerrornode.create;
  1448. again:=false;
  1449. message(parser_e_no_default_property_available);
  1450. end
  1451. else
  1452. begin
  1453. { The property symbol is referenced indirect }
  1454. inc(protsym.refs);
  1455. handle_propertysym(protsym,protsym.owner,p1,getaddr);
  1456. end;
  1457. end
  1458. else
  1459. begin
  1460. consume(_LECKKLAMMER);
  1461. repeat
  1462. case p1.resulttype.def.deftype of
  1463. pointerdef:
  1464. begin
  1465. { support delphi autoderef }
  1466. if (tpointerdef(p1.resulttype.def).pointertype.def.deftype=arraydef) and
  1467. (m_autoderef in aktmodeswitches) then
  1468. begin
  1469. p1:=cderefnode.create(p1);
  1470. end;
  1471. p2:=comp_expr(true);
  1472. p1:=cvecnode.create(p1,p2);
  1473. end;
  1474. stringdef :
  1475. begin
  1476. p2:=comp_expr(true);
  1477. p1:=cvecnode.create(p1,p2);
  1478. end;
  1479. arraydef :
  1480. begin
  1481. p2:=comp_expr(true);
  1482. { support SEG:OFS for go32v2 Mem[] }
  1483. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  1484. (p1.nodetype=loadn) and
  1485. assigned(tloadnode(p1).symtableentry) and
  1486. assigned(tloadnode(p1).symtableentry.owner.name) and
  1487. (tloadnode(p1).symtableentry.owner.name^='SYSTEM') and
  1488. ((tloadnode(p1).symtableentry.name='MEM') or
  1489. (tloadnode(p1).symtableentry.name='MEMW') or
  1490. (tloadnode(p1).symtableentry.name='MEML')) then
  1491. begin
  1492. if (token=_COLON) then
  1493. begin
  1494. consume(_COLON);
  1495. p3:=caddnode.create(muln,cordconstnode.create($10,s32bittype,false),p2);
  1496. p2:=comp_expr(true);
  1497. p2:=caddnode.create(addn,p2,p3);
  1498. p1:=cvecnode.create(p1,p2);
  1499. include(tvecnode(p1).flags,nf_memseg);
  1500. include(tvecnode(p1).flags,nf_memindex);
  1501. end
  1502. else
  1503. begin
  1504. p1:=cvecnode.create(p1,p2);
  1505. include(tvecnode(p1).flags,nf_memindex);
  1506. end;
  1507. end
  1508. else
  1509. p1:=cvecnode.create(p1,p2);
  1510. end;
  1511. else
  1512. begin
  1513. Message(cg_e_invalid_qualifier);
  1514. p1.destroy;
  1515. p1:=cerrornode.create;
  1516. comp_expr(true);
  1517. again:=false;
  1518. end;
  1519. end;
  1520. do_resulttypepass(p1);
  1521. if token=_COMMA then
  1522. consume(_COMMA)
  1523. else
  1524. break;
  1525. until false;
  1526. consume(_RECKKLAMMER);
  1527. end;
  1528. end;
  1529. _POINT :
  1530. begin
  1531. consume(_POINT);
  1532. if (p1.resulttype.def.deftype=pointerdef) and
  1533. (m_autoderef in aktmodeswitches) then
  1534. begin
  1535. p1:=cderefnode.create(p1);
  1536. do_resulttypepass(p1);
  1537. end;
  1538. case p1.resulttype.def.deftype of
  1539. recorddef:
  1540. begin
  1541. hsym:=tsym(trecorddef(p1.resulttype.def).symtable.search(pattern));
  1542. check_hints(hsym);
  1543. if assigned(hsym) and
  1544. (hsym.typ=varsym) then
  1545. p1:=csubscriptnode.create(hsym,p1)
  1546. else
  1547. begin
  1548. Message1(sym_e_illegal_field,pattern);
  1549. p1.destroy;
  1550. p1:=cerrornode.create;
  1551. end;
  1552. consume(_ID);
  1553. end;
  1554. variantdef:
  1555. begin
  1556. end;
  1557. classrefdef:
  1558. begin
  1559. classh:=tobjectdef(tclassrefdef(p1.resulttype.def).pointertype.def);
  1560. hsym:=searchsym_in_class(classh,pattern);
  1561. check_hints(hsym);
  1562. if hsym=nil then
  1563. begin
  1564. Message1(sym_e_id_no_member,pattern);
  1565. p1.destroy;
  1566. p1:=cerrornode.create;
  1567. { try to clean up }
  1568. consume(_ID);
  1569. end
  1570. else
  1571. begin
  1572. consume(_ID);
  1573. do_member_read(getaddr,hsym,p1,again,[]);
  1574. end;
  1575. end;
  1576. objectdef:
  1577. begin
  1578. store_static:=allow_only_static;
  1579. allow_only_static:=false;
  1580. classh:=tobjectdef(p1.resulttype.def);
  1581. hsym:=searchsym_in_class(classh,pattern);
  1582. check_hints(hsym);
  1583. allow_only_static:=store_static;
  1584. if hsym=nil then
  1585. begin
  1586. Message1(sym_e_id_no_member,pattern);
  1587. p1.destroy;
  1588. p1:=cerrornode.create;
  1589. { try to clean up }
  1590. consume(_ID);
  1591. end
  1592. else
  1593. begin
  1594. consume(_ID);
  1595. do_member_read(getaddr,hsym,p1,again,[]);
  1596. end;
  1597. end;
  1598. pointerdef:
  1599. begin
  1600. Message(cg_e_invalid_qualifier);
  1601. if tpointerdef(p1.resulttype.def).pointertype.def.deftype in [recorddef,objectdef,classrefdef] then
  1602. Message(parser_h_maybe_deref_caret_missing);
  1603. end;
  1604. else
  1605. begin
  1606. Message(cg_e_invalid_qualifier);
  1607. p1.destroy;
  1608. p1:=cerrornode.create;
  1609. consume(_ID);
  1610. end;
  1611. end;
  1612. end;
  1613. else
  1614. begin
  1615. { is this a procedure variable ? }
  1616. if assigned(p1.resulttype.def) then
  1617. begin
  1618. if (p1.resulttype.def.deftype=procvardef) then
  1619. begin
  1620. if assigned(getprocvardef) and
  1621. equal_defs(p1.resulttype.def,getprocvardef) then
  1622. again:=false
  1623. else
  1624. if (token=_LKLAMMER) or
  1625. ((tprocvardef(p1.resulttype.def).maxparacount=0) and
  1626. (not((token in [_ASSIGNMENT,_UNEQUAL,_EQUAL]))) and
  1627. (not afterassignment) and
  1628. (not in_args)) then
  1629. begin
  1630. if try_to_consume(_LKLAMMER) then
  1631. begin
  1632. p2:=parse_paras(false,false);
  1633. consume(_RKLAMMER);
  1634. end
  1635. else
  1636. p2:=nil;
  1637. p1:=ccallnode.create_procvar(p2,p1);
  1638. { proc():= is never possible }
  1639. if token=_ASSIGNMENT then
  1640. begin
  1641. Message(cg_e_illegal_expression);
  1642. p1.free;
  1643. p1:=cerrornode.create;
  1644. again:=false;
  1645. end;
  1646. end
  1647. else
  1648. again:=false;
  1649. end
  1650. else
  1651. again:=false;
  1652. end
  1653. else
  1654. again:=false;
  1655. end;
  1656. end;
  1657. end; { while again }
  1658. end;
  1659. {---------------------------------------------
  1660. Factor (Main)
  1661. ---------------------------------------------}
  1662. var
  1663. l : longint;
  1664. card : cardinal;
  1665. ic : TConstExprInt;
  1666. oldp1,
  1667. p1 : tnode;
  1668. code : integer;
  1669. again : boolean;
  1670. sym : tsym;
  1671. pd : tprocdef;
  1672. classh : tobjectdef;
  1673. d : bestreal;
  1674. hs : string;
  1675. htype : ttype;
  1676. filepos : tfileposinfo;
  1677. {---------------------------------------------
  1678. Helpers
  1679. ---------------------------------------------}
  1680. procedure check_tokenpos;
  1681. begin
  1682. if (p1<>oldp1) then
  1683. begin
  1684. if assigned(p1) then
  1685. p1.set_tree_filepos(filepos);
  1686. oldp1:=p1;
  1687. filepos:=akttokenpos;
  1688. end;
  1689. end;
  1690. begin
  1691. oldp1:=nil;
  1692. p1:=nil;
  1693. filepos:=akttokenpos;
  1694. again:=false;
  1695. if token=_ID then
  1696. begin
  1697. factor_read_id(p1,again);
  1698. if again then
  1699. begin
  1700. check_tokenpos;
  1701. { handle post fix operators }
  1702. postfixoperators(p1,again);
  1703. end;
  1704. end
  1705. else
  1706. case token of
  1707. _SELF :
  1708. begin
  1709. again:=true;
  1710. consume(_SELF);
  1711. if not(assigned(current_procinfo) and
  1712. assigned(current_procinfo.procdef._class)) then
  1713. begin
  1714. p1:=cerrornode.create;
  1715. again:=false;
  1716. Message(parser_e_self_not_in_method);
  1717. end
  1718. else
  1719. begin
  1720. p1:=load_self_node;
  1721. postfixoperators(p1,again);
  1722. end;
  1723. end;
  1724. _INHERITED :
  1725. begin
  1726. again:=true;
  1727. consume(_INHERITED);
  1728. if assigned(current_procinfo) and
  1729. assigned(current_procinfo.procdef._class) then
  1730. begin
  1731. classh:=current_procinfo.procdef._class.childof;
  1732. { if inherited; only then we need the method with
  1733. the same name }
  1734. if token in endtokens then
  1735. begin
  1736. hs:=current_procinfo.procdef.procsym.name;
  1737. anon_inherited:=true;
  1738. { For message methods we need to search using the message
  1739. number or string }
  1740. pd:=tprocsym(current_procinfo.procdef.procsym).first_procdef;
  1741. if (po_msgint in pd.procoptions) then
  1742. sym:=searchsym_in_class_by_msgint(classh,pd.messageinf.i)
  1743. else
  1744. if (po_msgstr in pd.procoptions) then
  1745. sym:=searchsym_in_class_by_msgstr(classh,pd.messageinf.str)
  1746. else
  1747. sym:=searchsym_in_class(classh,hs);
  1748. end
  1749. else
  1750. begin
  1751. hs:=pattern;
  1752. consume(_ID);
  1753. anon_inherited:=false;
  1754. sym:=searchsym_in_class(classh,hs);
  1755. end;
  1756. if assigned(sym) then
  1757. begin
  1758. check_hints(sym);
  1759. { load the procdef from the inherited class and
  1760. not from self }
  1761. if sym.typ=procsym then
  1762. begin
  1763. htype.setdef(classh);
  1764. p1:=ctypenode.create(htype);
  1765. end;
  1766. do_member_read(false,sym,p1,again,[nf_inherited,nf_anon_inherited]);
  1767. end
  1768. else
  1769. begin
  1770. if anon_inherited then
  1771. begin
  1772. { For message methods we need to call DefaultHandler }
  1773. if (po_msgint in pd.procoptions) or
  1774. (po_msgstr in pd.procoptions) then
  1775. begin
  1776. sym:=searchsym_in_class(classh,'DEFAULTHANDLER');
  1777. if not assigned(sym) or
  1778. (sym.typ<>procsym) then
  1779. internalerror(200303171);
  1780. p1:=nil;
  1781. do_proc_call(sym,sym.owner,false,again,p1);
  1782. end
  1783. else
  1784. begin
  1785. { we need to ignore the inherited; }
  1786. p1:=cnothingnode.create;
  1787. end;
  1788. end
  1789. else
  1790. begin
  1791. Message1(sym_e_id_no_member,hs);
  1792. p1:=cerrornode.create;
  1793. end;
  1794. again:=false;
  1795. end;
  1796. { turn auto inheriting off }
  1797. anon_inherited:=false;
  1798. end
  1799. else
  1800. begin
  1801. Message(parser_e_generic_methods_only_in_methods);
  1802. again:=false;
  1803. p1:=cerrornode.create;
  1804. end;
  1805. postfixoperators(p1,again);
  1806. end;
  1807. _INTCONST :
  1808. begin
  1809. { try cardinal first }
  1810. val(pattern,card,code);
  1811. if code<>0 then
  1812. begin
  1813. { then longint }
  1814. valint(pattern,l,code);
  1815. if code <> 0 then
  1816. begin
  1817. { then int64 }
  1818. val(pattern,ic,code);
  1819. if code<>0 then
  1820. begin
  1821. {finally float }
  1822. val(pattern,d,code);
  1823. if code<>0 then
  1824. begin
  1825. Message(cg_e_invalid_integer);
  1826. consume(_INTCONST);
  1827. l:=1;
  1828. p1:=cordconstnode.create(l,s32bittype,true);
  1829. end
  1830. else
  1831. begin
  1832. consume(_INTCONST);
  1833. p1:=crealconstnode.create(d,pbestrealtype^);
  1834. end;
  1835. end
  1836. else
  1837. begin
  1838. consume(_INTCONST);
  1839. p1:=cordconstnode.create(ic,cs64bittype,true);
  1840. end
  1841. end
  1842. else
  1843. begin
  1844. consume(_INTCONST);
  1845. p1:=cordconstnode.create(l,defaultordconsttype,true)
  1846. end
  1847. end
  1848. else
  1849. begin
  1850. consume(_INTCONST);
  1851. { check whether the value isn't in the longint range as well }
  1852. { (longint is easier to perform calculations with) (JM) }
  1853. if card <= $7fffffff then
  1854. { no sign extension necessary, so not longint typecast (JM) }
  1855. p1:=cordconstnode.create(card,s32bittype,true)
  1856. else
  1857. p1:=cordconstnode.create(card,u32bittype,true)
  1858. end;
  1859. end;
  1860. _REALNUMBER :
  1861. begin
  1862. val(pattern,d,code);
  1863. if code<>0 then
  1864. begin
  1865. Message(parser_e_error_in_real);
  1866. d:=1.0;
  1867. end;
  1868. consume(_REALNUMBER);
  1869. p1:=crealconstnode.create(d,pbestrealtype^);
  1870. end;
  1871. _STRING :
  1872. begin
  1873. string_dec(htype);
  1874. { STRING can be also a type cast }
  1875. if token=_LKLAMMER then
  1876. begin
  1877. consume(_LKLAMMER);
  1878. p1:=comp_expr(true);
  1879. consume(_RKLAMMER);
  1880. p1:=ctypeconvnode.create_explicit(p1,htype);
  1881. { handle postfix operators here e.g. string(a)[10] }
  1882. again:=true;
  1883. postfixoperators(p1,again);
  1884. end
  1885. else
  1886. p1:=ctypenode.create(htype);
  1887. end;
  1888. _FILE :
  1889. begin
  1890. htype:=cfiletype;
  1891. consume(_FILE);
  1892. { FILE can be also a type cast }
  1893. if token=_LKLAMMER then
  1894. begin
  1895. consume(_LKLAMMER);
  1896. p1:=comp_expr(true);
  1897. consume(_RKLAMMER);
  1898. p1:=ctypeconvnode.create_explicit(p1,htype);
  1899. { handle postfix operators here e.g. string(a)[10] }
  1900. again:=true;
  1901. postfixoperators(p1,again);
  1902. end
  1903. else
  1904. begin
  1905. p1:=ctypenode.create(htype);
  1906. end;
  1907. end;
  1908. _CSTRING :
  1909. begin
  1910. p1:=cstringconstnode.createstr(pattern,st_default);
  1911. consume(_CSTRING);
  1912. end;
  1913. _CCHAR :
  1914. begin
  1915. p1:=cordconstnode.create(ord(pattern[1]),cchartype,true);
  1916. consume(_CCHAR);
  1917. end;
  1918. _CWSTRING:
  1919. begin
  1920. p1:=cstringconstnode.createwstr(patternw);
  1921. consume(_CWSTRING);
  1922. end;
  1923. _CWCHAR:
  1924. begin
  1925. p1:=cordconstnode.create(ord(getcharwidestring(patternw,0)),cwidechartype,true);
  1926. consume(_CWCHAR);
  1927. end;
  1928. _KLAMMERAFFE :
  1929. begin
  1930. consume(_KLAMMERAFFE);
  1931. got_addrn:=true;
  1932. { support both @<x> and @(<x>) }
  1933. if try_to_consume(_LKLAMMER) then
  1934. begin
  1935. p1:=factor(true);
  1936. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1937. begin
  1938. again:=true;
  1939. postfixoperators(p1,again);
  1940. end;
  1941. consume(_RKLAMMER);
  1942. end
  1943. else
  1944. p1:=factor(true);
  1945. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1946. begin
  1947. again:=true;
  1948. postfixoperators(p1,again);
  1949. end;
  1950. got_addrn:=false;
  1951. p1:=caddrnode.create(p1);
  1952. { Store the procvar that we are expecting, the
  1953. addrn will use the information to find the correct
  1954. procdef or it will return an error }
  1955. if assigned(getprocvardef) and
  1956. (taddrnode(p1).left.nodetype = loadn) then
  1957. taddrnode(p1).getprocvardef:=getprocvardef;
  1958. end;
  1959. _LKLAMMER :
  1960. begin
  1961. consume(_LKLAMMER);
  1962. p1:=comp_expr(true);
  1963. consume(_RKLAMMER);
  1964. { it's not a good solution }
  1965. { but (a+b)^ makes some problems }
  1966. if token in [_CARET,_POINT,_LECKKLAMMER] then
  1967. begin
  1968. again:=true;
  1969. postfixoperators(p1,again);
  1970. end;
  1971. end;
  1972. _LECKKLAMMER :
  1973. begin
  1974. consume(_LECKKLAMMER);
  1975. p1:=factor_read_set;
  1976. consume(_RECKKLAMMER);
  1977. end;
  1978. _PLUS :
  1979. begin
  1980. consume(_PLUS);
  1981. p1:=factor(false);
  1982. end;
  1983. _MINUS :
  1984. begin
  1985. consume(_MINUS);
  1986. p1:=sub_expr(oppower,false);
  1987. p1:=cunaryminusnode.create(p1);
  1988. end;
  1989. _OP_NOT :
  1990. begin
  1991. consume(_OP_NOT);
  1992. p1:=factor(false);
  1993. p1:=cnotnode.create(p1);
  1994. end;
  1995. _TRUE :
  1996. begin
  1997. consume(_TRUE);
  1998. p1:=cordconstnode.create(1,booltype,false);
  1999. end;
  2000. _FALSE :
  2001. begin
  2002. consume(_FALSE);
  2003. p1:=cordconstnode.create(0,booltype,false);
  2004. end;
  2005. _NIL :
  2006. begin
  2007. consume(_NIL);
  2008. p1:=cnilnode.create;
  2009. { It's really ugly code nil^, but delphi allows it }
  2010. if token in [_CARET] then
  2011. begin
  2012. again:=true;
  2013. postfixoperators(p1,again);
  2014. end;
  2015. end;
  2016. else
  2017. begin
  2018. p1:=cerrornode.create;
  2019. consume(token);
  2020. Message(cg_e_illegal_expression);
  2021. end;
  2022. end;
  2023. { generate error node if no node is created }
  2024. if not assigned(p1) then
  2025. begin
  2026. {$ifdef EXTDEBUG}
  2027. Comment(V_Warning,'factor: p1=nil');
  2028. {$endif}
  2029. p1:=cerrornode.create;
  2030. end;
  2031. { get the resulttype for the node }
  2032. if (not assigned(p1.resulttype.def)) then
  2033. do_resulttypepass(p1);
  2034. { tp7 procvar handling, but not if the next token
  2035. will be a := }
  2036. check_tp_procvar(p1);
  2037. factor:=p1;
  2038. check_tokenpos;
  2039. end;
  2040. {$ifdef fpc}
  2041. {$maxfpuregisters default}
  2042. {$endif fpc}
  2043. {****************************************************************************
  2044. Sub_Expr
  2045. ****************************************************************************}
  2046. const
  2047. { Warning these stay be ordered !! }
  2048. operator_levels:array[Toperator_precedence] of set of Ttoken=
  2049. ([_LT,_LTE,_GT,_GTE,_EQUAL,_UNEQUAL,_OP_IN,_OP_IS],
  2050. [_PLUS,_MINUS,_OP_OR,_OP_XOR],
  2051. [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,
  2052. _OP_AS,_OP_AND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
  2053. [_STARSTAR] );
  2054. function sub_expr(pred_level:Toperator_precedence;accept_equal : boolean):tnode;
  2055. {Reads a subexpression while the operators are of the current precedence
  2056. level, or any higher level. Replaces the old term, simpl_expr and
  2057. simpl2_expr.}
  2058. var
  2059. p1,p2 : tnode;
  2060. oldt : Ttoken;
  2061. filepos : tfileposinfo;
  2062. begin
  2063. if pred_level=highest_precedence then
  2064. p1:=factor(false)
  2065. else
  2066. p1:=sub_expr(succ(pred_level),true);
  2067. repeat
  2068. if (token in operator_levels[pred_level]) and
  2069. ((token<>_EQUAL) or accept_equal) then
  2070. begin
  2071. oldt:=token;
  2072. filepos:=akttokenpos;
  2073. consume(token);
  2074. if pred_level=highest_precedence then
  2075. p2:=factor(false)
  2076. else
  2077. p2:=sub_expr(succ(pred_level),true);
  2078. case oldt of
  2079. _PLUS :
  2080. p1:=caddnode.create(addn,p1,p2);
  2081. _MINUS :
  2082. p1:=caddnode.create(subn,p1,p2);
  2083. _STAR :
  2084. p1:=caddnode.create(muln,p1,p2);
  2085. _SLASH :
  2086. p1:=caddnode.create(slashn,p1,p2);
  2087. _EQUAL :
  2088. p1:=caddnode.create(equaln,p1,p2);
  2089. _GT :
  2090. p1:=caddnode.create(gtn,p1,p2);
  2091. _LT :
  2092. p1:=caddnode.create(ltn,p1,p2);
  2093. _GTE :
  2094. p1:=caddnode.create(gten,p1,p2);
  2095. _LTE :
  2096. p1:=caddnode.create(lten,p1,p2);
  2097. _SYMDIF :
  2098. p1:=caddnode.create(symdifn,p1,p2);
  2099. _STARSTAR :
  2100. p1:=caddnode.create(starstarn,p1,p2);
  2101. _OP_AS :
  2102. p1:=casnode.create(p1,p2);
  2103. _OP_IN :
  2104. p1:=cinnode.create(p1,p2);
  2105. _OP_IS :
  2106. p1:=cisnode.create(p1,p2);
  2107. _OP_OR :
  2108. p1:=caddnode.create(orn,p1,p2);
  2109. _OP_AND :
  2110. p1:=caddnode.create(andn,p1,p2);
  2111. _OP_DIV :
  2112. p1:=cmoddivnode.create(divn,p1,p2);
  2113. _OP_NOT :
  2114. p1:=cnotnode.create(p1);
  2115. _OP_MOD :
  2116. p1:=cmoddivnode.create(modn,p1,p2);
  2117. _OP_SHL :
  2118. p1:=cshlshrnode.create(shln,p1,p2);
  2119. _OP_SHR :
  2120. p1:=cshlshrnode.create(shrn,p1,p2);
  2121. _OP_XOR :
  2122. p1:=caddnode.create(xorn,p1,p2);
  2123. _ASSIGNMENT :
  2124. p1:=cassignmentnode.create(p1,p2);
  2125. _CARET :
  2126. p1:=caddnode.create(caretn,p1,p2);
  2127. _UNEQUAL :
  2128. p1:=caddnode.create(unequaln,p1,p2);
  2129. end;
  2130. p1.set_tree_filepos(filepos);
  2131. end
  2132. else
  2133. break;
  2134. until false;
  2135. sub_expr:=p1;
  2136. end;
  2137. function comp_expr(accept_equal : boolean):tnode;
  2138. var
  2139. oldafterassignment : boolean;
  2140. p1 : tnode;
  2141. begin
  2142. oldafterassignment:=afterassignment;
  2143. afterassignment:=true;
  2144. p1:=sub_expr(opcompare,accept_equal);
  2145. { get the resulttype for this expression }
  2146. if not assigned(p1.resulttype.def) then
  2147. do_resulttypepass(p1);
  2148. afterassignment:=oldafterassignment;
  2149. comp_expr:=p1;
  2150. end;
  2151. function expr : tnode;
  2152. var
  2153. p1,p2 : tnode;
  2154. oldafterassignment : boolean;
  2155. oldp1 : tnode;
  2156. filepos : tfileposinfo;
  2157. begin
  2158. oldafterassignment:=afterassignment;
  2159. p1:=sub_expr(opcompare,true);
  2160. { get the resulttype for this expression }
  2161. if not assigned(p1.resulttype.def) then
  2162. do_resulttypepass(p1);
  2163. filepos:=akttokenpos;
  2164. check_tp_procvar(p1);
  2165. if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
  2166. afterassignment:=true;
  2167. oldp1:=p1;
  2168. case token of
  2169. _POINTPOINT :
  2170. begin
  2171. consume(_POINTPOINT);
  2172. p2:=sub_expr(opcompare,true);
  2173. p1:=crangenode.create(p1,p2);
  2174. end;
  2175. _ASSIGNMENT :
  2176. begin
  2177. consume(_ASSIGNMENT);
  2178. if (p1.resulttype.def.deftype=procvardef) then
  2179. getprocvardef:=tprocvardef(p1.resulttype.def);
  2180. p2:=sub_expr(opcompare,true);
  2181. if assigned(getprocvardef) then
  2182. handle_procvar(getprocvardef,p2);
  2183. getprocvardef:=nil;
  2184. p1:=cassignmentnode.create(p1,p2);
  2185. end;
  2186. _PLUSASN :
  2187. begin
  2188. consume(_PLUSASN);
  2189. p2:=sub_expr(opcompare,true);
  2190. p1:=cassignmentnode.create(p1,caddnode.create(addn,p1.getcopy,p2));
  2191. end;
  2192. _MINUSASN :
  2193. begin
  2194. consume(_MINUSASN);
  2195. p2:=sub_expr(opcompare,true);
  2196. p1:=cassignmentnode.create(p1,caddnode.create(subn,p1.getcopy,p2));
  2197. end;
  2198. _STARASN :
  2199. begin
  2200. consume(_STARASN );
  2201. p2:=sub_expr(opcompare,true);
  2202. p1:=cassignmentnode.create(p1,caddnode.create(muln,p1.getcopy,p2));
  2203. end;
  2204. _SLASHASN :
  2205. begin
  2206. consume(_SLASHASN );
  2207. p2:=sub_expr(opcompare,true);
  2208. p1:=cassignmentnode.create(p1,caddnode.create(slashn,p1.getcopy,p2));
  2209. end;
  2210. end;
  2211. { get the resulttype for this expression }
  2212. if not assigned(p1.resulttype.def) then
  2213. do_resulttypepass(p1);
  2214. afterassignment:=oldafterassignment;
  2215. if p1<>oldp1 then
  2216. p1.set_tree_filepos(filepos);
  2217. expr:=p1;
  2218. end;
  2219. {$ifdef int64funcresok}
  2220. function get_intconst:TConstExprInt;
  2221. {$else int64funcresok}
  2222. function get_intconst:longint;
  2223. {$endif int64funcresok}
  2224. {Reads an expression, tries to evalute it and check if it is an integer
  2225. constant. Then the constant is returned.}
  2226. var
  2227. p:tnode;
  2228. begin
  2229. p:=comp_expr(true);
  2230. if not codegenerror then
  2231. begin
  2232. if (p.nodetype<>ordconstn) or
  2233. not(is_integer(p.resulttype.def)) then
  2234. Message(cg_e_illegal_expression)
  2235. else
  2236. get_intconst:=tordconstnode(p).value;
  2237. end;
  2238. p.free;
  2239. end;
  2240. function get_stringconst:string;
  2241. {Reads an expression, tries to evaluate it and checks if it is a string
  2242. constant. Then the constant is returned.}
  2243. var
  2244. p:tnode;
  2245. begin
  2246. get_stringconst:='';
  2247. p:=comp_expr(true);
  2248. if p.nodetype<>stringconstn then
  2249. begin
  2250. if (p.nodetype=ordconstn) and is_char(p.resulttype.def) then
  2251. get_stringconst:=char(tordconstnode(p).value)
  2252. else
  2253. Message(cg_e_illegal_expression);
  2254. end
  2255. else
  2256. get_stringconst:=strpas(tstringconstnode(p).value_str);
  2257. p.free;
  2258. end;
  2259. end.
  2260. {
  2261. $Log$
  2262. Revision 1.128 2003-09-06 22:27:09 florian
  2263. * fixed web bug 2669
  2264. * cosmetic fix in printnode
  2265. * tobjectdef.gettypename implemented
  2266. Revision 1.127 2003/09/05 17:41:12 florian
  2267. * merged Wiktor's Watcom patches in 1.1
  2268. Revision 1.126 2003/08/23 22:29:51 peter
  2269. * fixed static class check for properties
  2270. Revision 1.125 2003/08/23 18:41:52 peter
  2271. * allow typeof(self) in class methods
  2272. Revision 1.124 2003/08/10 17:25:23 peter
  2273. * fixed some reported bugs
  2274. Revision 1.123 2003/06/13 21:19:31 peter
  2275. * current_procdef removed, use current_procinfo.procdef instead
  2276. Revision 1.122 2003/06/03 21:02:57 peter
  2277. * don't set nf_member when loaded from with symtable
  2278. * allow static variables in class methods
  2279. Revision 1.121 2003/05/22 17:43:21 peter
  2280. * search defaulthandler only for message methods
  2281. Revision 1.120 2003/05/15 18:58:53 peter
  2282. * removed selfpointer_offset, vmtpointer_offset
  2283. * tvarsym.adjusted_address
  2284. * address in localsymtable is now in the real direction
  2285. * removed some obsolete globals
  2286. Revision 1.119 2003/05/13 20:54:39 peter
  2287. * ifdef'd code that checked for failed inherited constructors
  2288. Revision 1.118 2003/05/13 19:14:41 peter
  2289. * failn removed
  2290. * inherited result code check moven to pexpr
  2291. Revision 1.117 2003/05/11 21:37:03 peter
  2292. * moved implicit exception frame from ncgutil to psub
  2293. * constructor/destructor helpers moved from cobj/ncgutil to psub
  2294. Revision 1.116 2003/05/11 14:45:12 peter
  2295. * tloadnode does not support objectsymtable,withsymtable anymore
  2296. * withnode cleanup
  2297. * direct with rewritten to use temprefnode
  2298. Revision 1.115 2003/05/09 17:47:03 peter
  2299. * self moved to hidden parameter
  2300. * removed hdisposen,hnewn,selfn
  2301. Revision 1.114 2003/05/01 07:59:42 florian
  2302. * introduced defaultordconsttype to decribe the default size of ordinal constants
  2303. on 64 bit CPUs it's equal to cs64bitdef while on 32 bit CPUs it's equal to s32bitdef
  2304. + added defines CPU32 and CPU64 for 32 bit and 64 bit CPUs
  2305. * int64s/qwords are allowed as for loop counter on 64 bit CPUs
  2306. Revision 1.113 2003/04/27 11:21:33 peter
  2307. * aktprocdef renamed to current_procinfo.procdef
  2308. * procinfo renamed to current_procinfo
  2309. * procinfo will now be stored in current_module so it can be
  2310. cleaned up properly
  2311. * gen_main_procsym changed to create_main_proc and release_main_proc
  2312. to also generate a tprocinfo structure
  2313. * fixed unit implicit initfinal
  2314. Revision 1.112 2003/04/27 07:29:50 peter
  2315. * current_procinfo.procdef cleanup, current_procdef is now always nil when parsing
  2316. a new procdef declaration
  2317. * aktprocsym removed
  2318. * lexlevel removed, use symtable.symtablelevel instead
  2319. * implicit init/final code uses the normal genentry/genexit
  2320. * funcret state checking updated for new funcret handling
  2321. Revision 1.111 2003/04/26 00:33:07 peter
  2322. * vo_is_result flag added for the special RESULT symbol
  2323. Revision 1.110 2003/04/25 20:59:33 peter
  2324. * removed funcretn,funcretsym, function result is now in varsym
  2325. and aliases for result and function name are added using absolutesym
  2326. * vs_hidden parameter for funcret passed in parameter
  2327. * vs_hidden fixes
  2328. * writenode changed to printnode and released from extdebug
  2329. * -vp option added to generate a tree.log with the nodetree
  2330. * nicer printnode for statements, callnode
  2331. Revision 1.109 2003/04/23 10:13:55 peter
  2332. * firstaddr will check procvardef
  2333. Revision 1.108 2003/04/22 23:50:23 peter
  2334. * firstpass uses expectloc
  2335. * checks if there are differences between the expectloc and
  2336. location.loc from secondpass in EXTDEBUG
  2337. Revision 1.107 2003/04/11 15:49:01 peter
  2338. * default property also increased the reference count for the
  2339. property symbol
  2340. Revision 1.106 2003/04/11 14:50:08 peter
  2341. * fix tw2454
  2342. Revision 1.105 2003/03/27 17:44:13 peter
  2343. * fixed small mem leaks
  2344. Revision 1.104 2003/03/17 18:55:30 peter
  2345. * allow more tokens instead of only semicolon after inherited
  2346. Revision 1.103 2003/03/17 16:54:41 peter
  2347. * support DefaultHandler and anonymous inheritance fixed
  2348. for message methods
  2349. Revision 1.102 2003/01/30 21:46:57 peter
  2350. * self fixes for static methods (merged)
  2351. Revision 1.101 2003/01/16 22:12:22 peter
  2352. * Find the correct procvar to load when using @ in fpc mode
  2353. Revision 1.100 2003/01/15 01:44:32 peter
  2354. * merged methodpointer fixes from 1.0.x
  2355. Revision 1.98 2003/01/12 17:51:42 peter
  2356. * tp procvar handling fix for tb0448
  2357. Revision 1.97 2003/01/05 22:44:14 peter
  2358. * remove a lot of code to support typen in loadn-procsym
  2359. Revision 1.96 2002/12/11 22:40:36 peter
  2360. * assigned(procvar) fix for delphi mode, fixes tb0430
  2361. Revision 1.95 2002/11/30 11:12:48 carl
  2362. + checking for symbols used with hint directives is done mostly in pexpr
  2363. only now
  2364. Revision 1.94 2002/11/27 15:33:47 peter
  2365. * the never ending story of tp procvar hacks
  2366. Revision 1.93 2002/11/26 22:58:24 peter
  2367. * fix for tw2178. When a ^ or . follows a procsym then the procsym
  2368. needs to be called
  2369. Revision 1.92 2002/11/25 17:43:22 peter
  2370. * splitted defbase in defutil,symutil,defcmp
  2371. * merged isconvertable and is_equal into compare_defs(_ext)
  2372. * made operator search faster by walking the list only once
  2373. Revision 1.91 2002/11/22 22:48:10 carl
  2374. * memory optimization with tconstsym (1.5%)
  2375. Revision 1.90 2002/11/20 22:49:55 pierre
  2376. * commented check code tht was invalid in 1.1
  2377. Revision 1.89 2002/11/18 18:34:41 peter
  2378. * fix crash with EXTDEBUG code
  2379. Revision 1.88 2002/11/18 17:48:21 peter
  2380. * fix tw2209 (merged)
  2381. Revision 1.87 2002/11/18 17:31:58 peter
  2382. * pass proccalloption to ret_in_xxx and push_xxx functions
  2383. Revision 1.86 2002/10/05 00:48:57 peter
  2384. * support inherited; support for overload as it is handled by
  2385. delphi. This is only for delphi mode as it is working is
  2386. undocumented and hard to predict what is done
  2387. Revision 1.85 2002/10/04 21:13:59 peter
  2388. * ignore vecn,subscriptn when checking for a procvar loadn
  2389. Revision 1.84 2002/10/02 20:51:22 peter
  2390. * don't check interfaces for class methods
  2391. Revision 1.83 2002/10/02 18:20:52 peter
  2392. * Copy() is now internal syssym that calls compilerprocs
  2393. Revision 1.82 2002/09/30 07:00:48 florian
  2394. * fixes to common code to get the alpha compiler compiled applied
  2395. Revision 1.81 2002/09/16 19:06:14 peter
  2396. * allow ^ after nil
  2397. Revision 1.80 2002/09/07 15:25:07 peter
  2398. * old logs removed and tabs fixed
  2399. Revision 1.79 2002/09/07 12:16:03 carl
  2400. * second part bug report 1996 fix, testrange in cordconstnode
  2401. only called if option is set (also make parsing a tiny faster)
  2402. Revision 1.78 2002/09/03 16:26:27 daniel
  2403. * Make Tprocdef.defs protected
  2404. Revision 1.77 2002/08/18 20:06:24 peter
  2405. * inlining is now also allowed in interface
  2406. * renamed write/load to ppuwrite/ppuload
  2407. * tnode storing in ppu
  2408. * nld,ncon,nbas are already updated for storing in ppu
  2409. Revision 1.76 2002/08/17 09:23:39 florian
  2410. * first part of procinfo rewrite
  2411. Revision 1.75 2002/08/01 16:37:47 jonas
  2412. - removed some superfluous "in_paras := true" statements
  2413. Revision 1.74 2002/07/26 21:15:41 florian
  2414. * rewrote the system handling
  2415. Revision 1.73 2002/07/23 09:51:23 daniel
  2416. * Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
  2417. are worth comitting.
  2418. Revision 1.72 2002/07/20 11:57:55 florian
  2419. * types.pas renamed to defbase.pas because D6 contains a types
  2420. unit so this would conflicts if D6 programms are compiled
  2421. + Willamette/SSE2 instructions to assembler added
  2422. Revision 1.71 2002/07/16 15:34:20 florian
  2423. * exit is now a syssym instead of a keyword
  2424. Revision 1.70 2002/07/06 20:18:02 carl
  2425. * longstring declaration now gives parser error since its not supported!
  2426. Revision 1.69 2002/06/12 15:46:14 jonas
  2427. * fixed web bug 1995
  2428. Revision 1.68 2002/05/18 13:34:12 peter
  2429. * readded missing revisions
  2430. Revision 1.67 2002/05/16 19:46:43 carl
  2431. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  2432. + try to fix temp allocation (still in ifdef)
  2433. + generic constructor calls
  2434. + start of tassembler / tmodulebase class cleanup
  2435. Revision 1.65 2002/05/12 16:53:09 peter
  2436. * moved entry and exitcode to ncgutil and cgobj
  2437. * foreach gets extra argument for passing local data to the
  2438. iterator function
  2439. * -CR checks also class typecasts at runtime by changing them
  2440. into as
  2441. * fixed compiler to cycle with the -CR option
  2442. * fixed stabs with elf writer, finally the global variables can
  2443. be watched
  2444. * removed a lot of routines from cga unit and replaced them by
  2445. calls to cgobj
  2446. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  2447. u32bit then the other is typecasted also to u32bit without giving
  2448. a rangecheck warning/error.
  2449. * fixed pascal calling method with reversing also the high tree in
  2450. the parast, detected by tcalcst3 test
  2451. Revision 1.64 2002/04/23 19:16:34 peter
  2452. * add pinline unit that inserts compiler supported functions using
  2453. one or more statements
  2454. * moved finalize and setlength from ninl to pinline
  2455. Revision 1.63 2002/04/21 19:02:05 peter
  2456. * removed newn and disposen nodes, the code is now directly
  2457. inlined from pexpr
  2458. * -an option that will write the secondpass nodes to the .s file, this
  2459. requires EXTDEBUG define to actually write the info
  2460. * fixed various internal errors and crashes due recent code changes
  2461. Revision 1.62 2002/04/16 16:11:17 peter
  2462. * using inherited; without a parent having the same function
  2463. will do nothing like delphi
  2464. Revision 1.61 2002/04/07 13:31:36 carl
  2465. + change unit use
  2466. Revision 1.60 2002/04/01 20:57:13 jonas
  2467. * fixed web bug 1907
  2468. * fixed some other procvar related bugs (all related to accepting procvar
  2469. constructs with either too many or too little parameters)
  2470. (both merged, includes second typo fix of pexpr.pas)
  2471. Revision 1.59 2002/03/31 20:26:35 jonas
  2472. + a_loadfpu_* and a_loadmm_* methods in tcg
  2473. * register allocation is now handled by a class and is mostly processor
  2474. independent (+rgobj.pas and i386/rgcpu.pas)
  2475. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  2476. * some small improvements and fixes to the optimizer
  2477. * some register allocation fixes
  2478. * some fpuvaroffset fixes in the unary minus node
  2479. * push/popusedregisters is now called rg.save/restoreusedregisters and
  2480. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  2481. also better optimizable)
  2482. * fixed and optimized register saving/restoring for new/dispose nodes
  2483. * LOC_FPU locations now also require their "register" field to be set to
  2484. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  2485. - list field removed of the tnode class because it's not used currently
  2486. and can cause hard-to-find bugs
  2487. }