pexpr.pas 87 KB

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