pexpr.pas 89 KB

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