pexpr.pas 97 KB

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