pexpr.pas 86 KB

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