pexpr.pas 89 KB

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