pexpr.pas 85 KB

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