pexpr.pas 88 KB

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