pexpr.pas 86 KB

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