pexpr.pas 86 KB

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