pexpr.pas 86 KB

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