pexpr.pas 85 KB

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