pexpr.pas 85 KB

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