pexpr.pas 89 KB

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