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