pexpr.pas 88 KB

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