pexpr.pas 86 KB

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