pexpr.pas 87 KB

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