pexpr.pas 89 KB

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