procdefutil.pas 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742
  1. {
  2. Copyright (c) 2018 by Jonas Maebe
  3. Copyright (c) 2011-2021 by Blaise.ru
  4. This unit provides helpers for creating procdefs
  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. {$i fpcdefs.inc}
  19. unit procdefutil;
  20. interface
  21. uses
  22. globtype,procinfo,
  23. symconst,symtype,symdef,
  24. node,nbas;
  25. { create a nested procdef that will be used to outline code from a procedure;
  26. astruct should usually be nil, except in special cases like the Windows SEH
  27. exception handling funclets }
  28. function create_outline_procdef(const basesymname: string; astruct: tabstractrecorddef; potype: tproctypeoption; resultdef: tdef): tprocdef;
  29. procedure convert_to_funcref_intf(const n:tidstring;var def:tdef);
  30. function adjust_funcref(var def:tdef;sym,dummysym:tsym):boolean;
  31. { functionality related to capturing local variables for anonymous functions }
  32. function get_or_create_capturer(pd:tprocdef):tsym;
  33. function capturer_add_anonymous_proc(owner:tprocinfo;pd:tprocdef;out capturer:tsym):tobjectdef;
  34. function capturer_add_procvar_or_proc(owner:tprocinfo;n:tnode;out capturer:tsym;out capturen:tnode):tobjectdef;
  35. procedure initialize_capturer(ctx:tprocinfo;var stmt:tstatementnode);
  36. procedure postprocess_capturer(ctx:tprocinfo);
  37. procedure convert_captured_syms(pd:tprocdef;tree:tnode);
  38. implementation
  39. uses
  40. cutils,cclasses,verbose,globals,
  41. fmodule,
  42. pass_1,
  43. nobj,ncal,nmem,nld,nutils,
  44. ngenutil,
  45. symbase,symsym,symtable,defutil,defcmp,
  46. htypechk,
  47. pparautl,psub;
  48. function create_outline_procdef(const basesymname: string; astruct: tabstractrecorddef; potype: tproctypeoption; resultdef: tdef): tprocdef;
  49. var
  50. st:TSymTable;
  51. checkstack: psymtablestackitem;
  52. oldsymtablestack: tsymtablestack;
  53. sym:tprocsym;
  54. begin
  55. { get actual procedure symtable (skip withsymtables, etc.) }
  56. st:=nil;
  57. checkstack:=symtablestack.stack;
  58. while assigned(checkstack) do
  59. begin
  60. st:=checkstack^.symtable;
  61. if st.symtabletype in [staticsymtable,globalsymtable,localsymtable] then
  62. break;
  63. checkstack:=checkstack^.next;
  64. end;
  65. { Create a nested procedure, even from main_program_level.
  66. Furthermore, force procdef and procsym into the same symtable
  67. (by default, defs are registered with symtablestack.top which may be
  68. something temporary like exceptsymtable - in that case, procdef can be
  69. destroyed before procsym, leaving invalid pointers). }
  70. oldsymtablestack:=symtablestack;
  71. symtablestack:=nil;
  72. result:=cprocdef.create(max(normal_function_level,st.symtablelevel)+1,true);
  73. result.returndef:=resultdef;
  74. { if the parent is a generic or a specialization, the new function is one
  75. as well }
  76. if st.symtabletype=localsymtable then
  77. result.defoptions:=result.defoptions+(tstoreddef(st.defowner).defoptions*[df_generic,df_specialization]);
  78. symtablestack:=oldsymtablestack;
  79. st.insertdef(result);
  80. result.struct:=astruct;
  81. { tabstractprocdef constructor sets po_delphi_nested_cc whenever
  82. nested procvars modeswitch is active. We must be independent of this switch. }
  83. exclude(result.procoptions,po_delphi_nested_cc);
  84. result.proctypeoption:=potype;
  85. { always use the default calling convention }
  86. result.proccalloption:=pocall_default;
  87. include(result.procoptions,po_hascallingconvention);
  88. handle_calling_convention(result,hcc_default_actions_impl);
  89. sym:=cprocsym.create(basesymname+result.unique_id_str);
  90. st.insertsym(sym);
  91. result.procsym:=sym;
  92. proc_add_definition(result);
  93. { the code will be assigned directly to the "code" field later }
  94. result.forwarddef:=false;
  95. result.aliasnames.insert(result.mangledname);
  96. end;
  97. function fileinfo_to_suffix(const fileinfo:tfileposinfo):tsymstr;inline;
  98. begin
  99. result:=tostr(fileinfo.moduleindex)+'_'+
  100. tostr(fileinfo.fileindex)+'_'+
  101. tostr(fileinfo.line)+'_'+
  102. tostr(fileinfo.column);
  103. end;
  104. const
  105. anon_funcref_prefix='$FuncRef_';
  106. capturer_class_name='$CapturerClass';
  107. { the leading $ is only added when registering the var symbol }
  108. capturer_var_name='Capturer';
  109. keepalive_suffix='_keepalive';
  110. outer_self_field_name='OuterSelf';
  111. procedure convert_to_funcref_intf(const n:tidstring;var def:tdef);
  112. var
  113. oldsymtablestack : tsymtablestack;
  114. pvdef : tprocvardef absolute def;
  115. intfdef : tobjectdef;
  116. invokedef : tprocdef;
  117. psym : tprocsym;
  118. sym : tsym;
  119. st : tsymtable;
  120. i : longint;
  121. name : tidstring;
  122. begin
  123. if def.typ<>procvardef then
  124. internalerror(2021040201);
  125. if not (po_is_function_ref in tprocvardef(pvdef).procoptions) then
  126. internalerror(2021022101);
  127. if n='' then
  128. name:=anon_funcref_prefix+fileinfo_to_suffix(current_filepos)
  129. else
  130. name:=n;
  131. intfdef:=cobjectdef.create(odt_interfacecom,name,interface_iunknown,true);
  132. include(intfdef.objectoptions,oo_is_funcref);
  133. include(intfdef.objectoptions,oo_is_invokable);
  134. include(intfdef.objectoptions,oo_has_virtual);
  135. intfdef.typesym:=pvdef.typesym;
  136. pvdef.typesym:=nil;
  137. intfdef.defoptions:=intfdef.defoptions+pvdef.defoptions*[df_generic,df_specialization];
  138. { also inherit the general flags from the surrounding structured type or
  139. function }
  140. if assigned(current_structdef) then
  141. begin
  142. intfdef.defoptions:=intfdef.defoptions+current_structdef.defoptions*[df_generic,df_specialization];
  143. end
  144. else if assigned(current_procinfo) then
  145. begin
  146. intfdef.defoptions:=intfdef.defoptions+current_procinfo.procdef.defoptions*[df_generic,df_specialization];
  147. end;
  148. if cs_generate_rtti in current_settings.localswitches then
  149. include(intfdef.objectoptions,oo_can_have_published);
  150. oldsymtablestack:=symtablestack;
  151. symtablestack:=nil;
  152. invokedef:=tprocdef(pvdef.getcopyas(procdef,pc_normal_no_paras,'',false));
  153. invokedef.struct:=intfdef;
  154. invokedef.forwarddef:=false;
  155. include(invokedef.procoptions,po_overload);
  156. include(invokedef.procoptions,po_virtualmethod);
  157. invokedef.procsym:=cprocsym.create(method_name_funcref_invoke_decl);
  158. if cs_generate_rtti in current_settings.localswitches then
  159. invokedef.visibility:=vis_published
  160. else
  161. invokedef.visibility:=vis_public;
  162. intfdef.symtable.insertsym(invokedef.procsym);
  163. intfdef.symtable.insertdef(invokedef);
  164. { we need to do this even if the def isn't a generic/specialization itself,
  165. but *belongs* to one }
  166. if intfdef.defoptions*[df_generic,df_specialization]<>[] then
  167. begin
  168. if assigned(pvdef.genericdef) and (pvdef.genericdef.typ<>objectdef) then
  169. internalerror(2021040501);
  170. intfdef.genericdef:=pvdef.genericdef;
  171. { in case of a generic we move all involved syms/defs to the interface }
  172. intfdef.genericparas:=pvdef.genericparas;
  173. pvdef.genericparas:=nil;
  174. if assigned(intfdef.genericparas) then
  175. for i:=0 to intfdef.genericparas.count-1 do
  176. begin
  177. sym:=tsym(intfdef.genericparas[i]);
  178. if sym.owner<>pvdef.parast then
  179. continue;
  180. sym.changeowner(intfdef.symtable);
  181. if (sym.typ=typesym) and (ttypesym(sym).typedef.owner=pvdef.parast) then
  182. ttypesym(sym).typedef.changeowner(intfdef.symtable);
  183. end;
  184. end;
  185. { now move the symtable over }
  186. invokedef.parast.free;
  187. invokedef.parast:=pvdef.parast;
  188. invokedef.parast.defowner:=invokedef;
  189. pvdef.parast:=nil;
  190. for i:=0 to invokedef.parast.symlist.count-1 do
  191. begin
  192. sym:=tsym(invokedef.parast.symlist[i]);
  193. if sym.typ<>paravarsym then
  194. continue;
  195. if tparavarsym(sym).vardef=pvdef then
  196. tparavarsym(sym).vardef:=intfdef;
  197. end;
  198. symtablestack:=oldsymtablestack;
  199. if invokedef.returndef=pvdef then
  200. invokedef.returndef:=intfdef;
  201. handle_calling_convention(invokedef,hcc_default_actions_intf_struct);
  202. proc_add_definition(invokedef);
  203. invokedef.calcparas;
  204. { def is not owned, so it can be simply freed }
  205. def.free;
  206. def:=intfdef;
  207. end;
  208. function adjust_funcref(var def:tdef;sym,dummysym:tsym):boolean;
  209. var
  210. sympos : tfileposinfo;
  211. name : string;
  212. begin
  213. result:=false;
  214. if (def.typ<>procvardef) and not is_funcref(def) then
  215. internalerror(2022020401);
  216. if assigned(sym) and not (sym.typ=typesym) then
  217. internalerror(2022020402);
  218. { these always support everything, no "of object" or
  219. "is_nested" is allowed }
  220. if is_nested_pd(tprocvardef(def)) or
  221. is_methodpointer(def) then
  222. cgmessage(type_e_function_reference_kind);
  223. if not (po_is_block in tprocvardef(def).procoptions) then
  224. begin
  225. if assigned(dummysym) then
  226. ttypesym(dummysym).typedef:=nil;
  227. if assigned(sym) then
  228. begin
  229. ttypesym(sym).typedef:=nil;
  230. name:=sym.name;
  231. end
  232. else
  233. name:='';
  234. convert_to_funcref_intf(name,def);
  235. if assigned(sym) then
  236. ttypesym(sym).typedef:=def;
  237. if assigned(dummysym) then
  238. ttypesym(dummysym).typedef:=def;
  239. build_vmt(tobjectdef(def));
  240. result:=true;
  241. end
  242. else
  243. begin
  244. if assigned(sym) and (sym.refs>0) then
  245. begin
  246. { find where the symbol was used and trigger
  247. a "symbol not completely defined" error }
  248. if not fileinfo_of_typesym_in_def(def,sym,sympos) then
  249. sympos:=sym.fileinfo;
  250. messagepos1(sympos,type_e_type_is_not_completly_defined,sym.realname);
  251. end;
  252. end;
  253. end;
  254. function funcref_intf_for_proc(pd:tabstractprocdef;const suffix:string):tobjectdef;
  255. var
  256. name : tsymstr;
  257. sym : tsym;
  258. symowner : tsymtable;
  259. oldsymtablestack: TSymtablestack;
  260. invokedef: tprocdef;
  261. begin
  262. if pd.is_generic then
  263. internalerror(2022010710);
  264. name:='funcrefintf_'+suffix;
  265. if pd.owner.symtabletype=globalsymtable then
  266. symowner:=current_module.localsymtable
  267. else
  268. symowner:=pd.owner;
  269. sym:=tsym(symowner.find(name));
  270. if assigned(sym) then
  271. begin
  272. if sym.typ<>typesym then
  273. internalerror(2022010708);
  274. if not is_funcref(ttypesym(sym).typedef) then
  275. internalerror(2022010709);
  276. result:=tobjectdef(ttypesym(sym).typedef);
  277. exit;
  278. end;
  279. name:='$'+name;
  280. result:=cobjectdef.create(odt_interfacecom,name,interface_iunknown,false);
  281. include(result.objectoptions,oo_is_funcref);
  282. include(result.objectoptions,oo_is_invokable);
  283. sym:=ctypesym.create(name,result);
  284. oldsymtablestack:=symtablestack;
  285. symtablestack:=nil;
  286. invokedef:=tprocdef(pd.getcopyas(procdef,pc_normal_no_hidden,'',false));
  287. invokedef.struct:=result;
  288. invokedef.visibility:=vis_public;
  289. invokedef.procsym:=cprocsym.create(method_name_funcref_invoke_decl);
  290. invokedef.parast.symtablelevel:=normal_function_level;
  291. invokedef.localst.symtablelevel:=normal_function_level;
  292. include(invokedef.procoptions,po_virtualmethod);
  293. exclude(invokedef.procoptions,po_staticmethod);
  294. exclude(invokedef.procoptions,po_classmethod);
  295. invokedef.forwarddef:=false;
  296. symtablestack:=oldsymtablestack;
  297. result.symtable.insertsym(invokedef.procsym);
  298. result.symtable.insertdef(invokedef);
  299. proc_add_definition(invokedef);
  300. invokedef.calcparas;
  301. include(result.objectoptions,oo_has_virtual);
  302. symowner.insertsym(sym);
  303. symowner.insertdef(result);
  304. addsymref(sym);
  305. build_vmt(result);
  306. end;
  307. {.$define DEBUG_CAPTURER}
  308. function get_capturer(pd:tprocdef):tabstractvarsym;
  309. function getsym(st:tsymtable;typ:tsymtyp):tabstractvarsym;
  310. begin
  311. result:=tabstractvarsym(st.find(capturer_var_name));
  312. if not assigned(result) then
  313. internalerror(2022010703);
  314. if result.typ<>typ then
  315. internalerror(2022010704);
  316. if not is_class(result.vardef) then
  317. internalerror(2022010705);
  318. end;
  319. begin
  320. case pd.proctypeoption of
  321. potype_unitfinalize,
  322. potype_unitinit,
  323. potype_proginit:
  324. begin
  325. if not assigned(pd.owner) then
  326. internalerror(2022052401);
  327. if pd.owner.symtabletype<>staticsymtable then
  328. internalerror(2022052402);
  329. result:=getsym(pd.owner,staticvarsym);
  330. end;
  331. else
  332. begin
  333. if not assigned(pd.localst) then
  334. internalerror(2022020502);
  335. result:=getsym(pd.localst,localvarsym);
  336. end;
  337. end;
  338. end;
  339. function get_capturer_alive(pd:tprocdef):tabstractvarsym;
  340. function getsym(st:tsymtable;typ:tsymtyp):tabstractvarsym;
  341. begin
  342. result:=tabstractvarsym(st.find(capturer_var_name+keepalive_suffix));
  343. if not assigned(result) then
  344. internalerror(2022051703);
  345. if result.typ<>typ then
  346. internalerror(2022051704);
  347. if not is_interfacecom(result.vardef) then
  348. internalerror(2022051705);
  349. end;
  350. begin
  351. case pd.proctypeoption of
  352. potype_unitfinalize,
  353. potype_unitinit,
  354. potype_proginit:
  355. begin
  356. if not assigned(pd.owner) then
  357. internalerror(2022052403);
  358. if pd.owner.symtabletype<>staticsymtable then
  359. internalerror(2022052404);
  360. result:=getsym(pd.owner,staticvarsym);
  361. end;
  362. else
  363. begin
  364. if not assigned(pd.localst) then
  365. internalerror(2022051702);
  366. result:=getsym(pd.localst,localvarsym);
  367. end;
  368. end;
  369. end;
  370. function get_or_create_capturer(pd:tprocdef):tsym;
  371. var
  372. name : tsymstr;
  373. parent,
  374. def : tobjectdef;
  375. typesym : tsym;
  376. keepalive : tabstractvarsym;
  377. intfimpl : TImplementedInterface;
  378. st : tsymtable;
  379. begin
  380. if pd.has_capturer then
  381. begin
  382. result:=get_capturer(pd);
  383. end
  384. else
  385. begin
  386. parent:=tobjectdef(search_system_type('TINTERFACEDOBJECT').typedef);
  387. if not is_class(parent) then
  388. internalerror(2022010706);
  389. name:=capturer_class_name+'_'+fileinfo_to_suffix(pd.fileinfo);
  390. case pd.proctypeoption of
  391. potype_unitfinalize,
  392. potype_unitinit,
  393. potype_proginit:
  394. st:=pd.owner;
  395. else
  396. st:=pd.localst;
  397. end;
  398. def:=cobjectdef.create(odt_class,name,parent,false);
  399. include(def.objectoptions,oo_is_capturer);
  400. typesym:=ctypesym.create(name,def);
  401. typesym.fileinfo:=pd.fileinfo;
  402. st.insertdef(def);
  403. st.insertsym(typesym);
  404. addsymref(typesym);
  405. if df_generic in pd.defoptions then
  406. include(def.defoptions,df_generic);
  407. { don't set df_specialization as in that case genericdef needs to be
  408. set, but the local symtables are freed once a unit is finished }
  409. {if df_specialization in pd.defoptions then
  410. begin
  411. if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
  412. internalerror(2022020501);
  413. def.genericdef:=tstoreddef(get_capturer(tprocdef(pd.genericdef)).vardef);
  414. include(def.defoptions,df_specialization);
  415. end;}
  416. if st.symtabletype=localsymtable then
  417. result:=clocalvarsym.create('$'+capturer_var_name,vs_value,def,[vo_is_internal])
  418. else
  419. result:=cstaticvarsym.create('$'+capturer_var_name,vs_value,def,[vo_is_internal]);
  420. result.fileinfo:=pd.fileinfo;
  421. st.insertsym(result);
  422. addsymref(result);
  423. if st.symtabletype=localsymtable then
  424. keepalive:=clocalvarsym.create('$'+capturer_var_name+keepalive_suffix,vs_value,interface_iunknown,[vo_is_internal])
  425. else
  426. keepalive:=cstaticvarsym.create('$'+capturer_var_name+keepalive_suffix,vs_value,interface_iunknown,[vo_is_internal]);
  427. keepalive.fileinfo:=pd.fileinfo;
  428. st.insertsym(keepalive);
  429. addsymref(keepalive);
  430. if st.symtabletype<>localsymtable then
  431. begin
  432. cnodeutils.insertbssdata(tstaticvarsym(result));
  433. cnodeutils.insertbssdata(tstaticvarsym(keepalive));
  434. end;
  435. { avoid warnings as these symbols are initialized using initialize_capturer
  436. after parsing the body }
  437. tabstractvarsym(result).varstate:=vs_readwritten;
  438. keepalive.varstate:=vs_readwritten;
  439. pd.has_capturer:=true;
  440. end;
  441. end;
  442. function can_be_captured(sym:tsym;curpd:tprocdef):boolean;
  443. begin
  444. result:=false;
  445. if (sym.typ=procsym) and assigned(curpd) and (curpd.procsym=sym) then
  446. exit(true);
  447. if not (sym.typ in [localvarsym,paravarsym]) then
  448. exit;
  449. if tabstractnormalvarsym(sym).varoptions*[vo_is_result,vo_is_funcret]<>[] then
  450. exit;
  451. if sym.typ=paravarsym then
  452. begin
  453. if (tparavarsym(sym).varspez in [vs_out,vs_var]) and
  454. not (vo_is_self in tparavarsym(sym).varoptions) then
  455. exit;
  456. if is_open_array(tparavarsym(sym).vardef) then
  457. exit;
  458. end;
  459. result:=true;
  460. end;
  461. type
  462. tsym_mapping = record
  463. oldsym:tsym;
  464. newsym:tsym;
  465. end;
  466. psym_mapping = ^tsym_mapping;
  467. function replace_self_sym(var n:tnode;arg:pointer):foreachnoderesult;
  468. var
  469. mapping : psym_mapping absolute arg;
  470. ld : tloadnode;
  471. begin
  472. if n.nodetype=loadn then
  473. begin
  474. ld:=tloadnode(n);
  475. if ld.symtableentry=mapping^.oldsym then
  476. begin
  477. ld.symtableentry:=mapping^.newsym;
  478. { make sure that the node is processed again }
  479. ld.resultdef:=nil;
  480. if assigned(ld.left) then
  481. begin
  482. { no longer loaded through the frame pointer }
  483. ld.left.free;
  484. ld.left:=nil;
  485. end;
  486. typecheckpass(n);
  487. end;
  488. end;
  489. result:=fen_true;
  490. end;
  491. procedure capture_captured_syms(pd:tprocdef;owner:tprocinfo;capturedef:tobjectdef;oldpd:tprocdef);
  492. var
  493. curpd : tprocdef;
  494. subcapturer : tobjectdef;
  495. symstodo : TFPList;
  496. i : longint;
  497. sym : tsym;
  498. fieldsym : tfieldvarsym;
  499. fieldname : tsymstr;
  500. fielddef : tdef;
  501. begin
  502. if not pd.was_anonymous or not assigned(pd.capturedsyms) or (pd.capturedsyms.count=0) then
  503. exit;
  504. { capture all variables that the original procdef captured }
  505. curpd:=owner.procdef;
  506. subcapturer:=capturedef;
  507. symstodo:=tfplist.create;
  508. for i:=0 to pd.capturedsyms.count-1 do
  509. if can_be_captured(pcapturedsyminfo(pd.capturedsyms[i])^.sym,oldpd) and
  510. (pcapturedsyminfo(pd.capturedsyms[i])^.sym.typ<>procsym) then
  511. symstodo.add(pcapturedsyminfo(pd.capturedsyms[i])^.sym);
  512. while symstodo.count>0 do
  513. begin
  514. { we know we have symbols left to capture thus we either have a
  515. symbol that's located in the capturer of the current procdef or
  516. we need to put in the OuterSelf reference }
  517. if curpd=owner.procdef then
  518. subcapturer:=capturedef
  519. else
  520. subcapturer:=tobjectdef(tabstractvarsym(get_or_create_capturer(curpd)).vardef);
  521. i:=0;
  522. while i<symstodo.count do
  523. begin
  524. sym:=tsym(symstodo[i]);
  525. if (sym.owner=curpd.localst) or
  526. (sym.owner=curpd.parast) then
  527. begin
  528. {$ifdef DEBUG_CAPTURER}writeln('Symbol ',sym.name,' captured from ',curpd.procsym.name);{$endif}
  529. { the symbol belongs to the current procdef, so add a field to
  530. the capturer if it doesn't already exist }
  531. if vo_is_self in tabstractnormalvarsym(sym).varoptions then
  532. fieldname:=outer_self_field_name
  533. else
  534. fieldname:=sym.name;
  535. fieldsym:=tfieldvarsym(subcapturer.symtable.find(fieldname));
  536. if not assigned(fieldsym) then
  537. begin
  538. {$ifdef DEBUG_CAPTURER}writeln('Adding field ',fieldname,' to ',subcapturer.typesym.name);{$endif}
  539. fielddef:=tabstractvarsym(sym).vardef;
  540. if vo_is_self in tabstractnormalvarsym(sym).varoptions then
  541. begin
  542. fieldname:='$'+fieldname;
  543. if not is_implicit_pointer_object_type(fielddef) then
  544. fielddef:=cpointerdef.getreusable(fielddef);
  545. end;
  546. fieldsym:=cfieldvarsym.create(fieldname,vs_value,fielddef,[]);
  547. fieldsym.fileinfo:=sym.fileinfo;
  548. subcapturer.symtable.insertsym(fieldsym);
  549. tabstractrecordsymtable(subcapturer.symtable).addfield(fieldsym,vis_public);
  550. end;
  551. if not assigned(tabstractnormalvarsym(sym).capture_sym) then
  552. tabstractnormalvarsym(sym).capture_sym:=fieldsym
  553. else if tabstractnormalvarsym(sym).capture_sym<>fieldsym then
  554. internalerror(2022011602);
  555. symstodo.delete(i);
  556. end
  557. else if sym=pd.procsym then
  558. { no explicit capturing needed here }
  559. symstodo.delete(i)
  560. else
  561. inc(i);
  562. end;
  563. if symstodo.count>0 then
  564. begin
  565. if curpd.owner.symtabletype<>localsymtable then
  566. internalerror(2022011001);
  567. { there are still symbols left, so before we move to the parent
  568. procdef we add the OuterSelf field to set up the chain of
  569. capturers }
  570. {$ifdef DEBUG_CAPTURER}writeln('Initialize capturer for ',curpd.procsym.name);{$endif}
  571. { we no longer need the curpd, but we need the parent, so change
  572. curpd here }
  573. curpd:=tprocdef(curpd.owner.defowner);
  574. if curpd.typ<>procdef then
  575. internalerror(2022011002);
  576. if not assigned(subcapturer.symtable.find(outer_self_field_name)) then
  577. begin
  578. {$ifdef DEBUG_CAPTURER}writeln('Adding field OuterSelf to ',subcapturer.typesym.name);{$endif}
  579. if subcapturer.owner.symtablelevel>normal_function_level then
  580. begin
  581. { the outer self is the capturer of the outer procdef }
  582. sym:=get_or_create_capturer(curpd);
  583. { ensure that the outer capturer isn't put into a register anymore }
  584. tabstractvarsym(sym).different_scope:=true;
  585. tabstractvarsym(sym).varregable:=vr_none;
  586. end
  587. else
  588. begin
  589. { the outer self is the self of the method }
  590. if not (curpd.owner.symtabletype in [objectsymtable,recordsymtable]) then
  591. internalerror(2022011603);
  592. sym:=tsym(curpd.parast.find('self'));
  593. if not assigned(sym) then
  594. internalerror(2022011604);
  595. end;
  596. { add the keep alive IUnknown symbol }
  597. fieldsym:=cfieldvarsym.create('$'+outer_self_field_name+keepalive_suffix,vs_value,interface_iunknown,[]);
  598. fieldsym.fileinfo:=sym.fileinfo;
  599. subcapturer.symtable.insertsym(fieldsym);
  600. tabstractrecordsymtable(subcapturer.symtable).addfield(fieldsym,vis_public);
  601. { add the capturer symbol }
  602. fieldsym:=cfieldvarsym.create('$'+outer_self_field_name,vs_value,tabstractvarsym(sym).vardef,[]);
  603. fieldsym.fileinfo:=sym.fileinfo;
  604. subcapturer.symtable.insertsym(fieldsym);
  605. tabstractrecordsymtable(subcapturer.symtable).addfield(fieldsym,vis_public);
  606. if (sym.typ=paravarsym) and (vo_is_self in tparavarsym(sym).varoptions) then
  607. begin
  608. if assigned(tparavarsym(sym).capture_sym) then
  609. internalerror(2022011705);
  610. tparavarsym(sym).capture_sym:=fieldsym;
  611. end;
  612. end;
  613. end;
  614. end;
  615. symstodo.free;
  616. end;
  617. function retrieve_sym_for_filepos(var n:tnode;arg:pointer):foreachnoderesult;
  618. var
  619. sym : ^tsym absolute arg;
  620. begin
  621. if assigned(sym^) then
  622. exit(fen_norecurse_true);
  623. result:=fen_false;
  624. if not (n.resultdef.typ in [procdef,procvardef]) then
  625. exit;
  626. if n.nodetype=loadn then
  627. begin
  628. sym^:=tloadnode(n).symtableentry;
  629. result:=fen_norecurse_true;
  630. end
  631. else if n.nodetype=subscriptn then
  632. begin
  633. sym^:=tsubscriptnode(n).vs;
  634. result:=fen_norecurse_true;
  635. end;
  636. end;
  637. function collect_syms_to_capture(var n:tnode;arg:pointer):foreachnoderesult;
  638. var
  639. pd : tprocdef absolute arg;
  640. sym : tsym;
  641. begin
  642. result:=fen_false;
  643. if n.nodetype<>loadn then
  644. exit;
  645. sym:=tsym(tloadnode(n).symtableentry);
  646. if not (sym.owner.symtabletype in [parasymtable,localsymtable]) then
  647. exit;
  648. if sym.owner.symtablelevel>normal_function_level then begin
  649. pd.add_captured_sym(sym,tloadnode(n).resultdef,n.fileinfo);
  650. result:=fen_true;
  651. end;
  652. end;
  653. type
  654. tselfinfo=record
  655. selfsym:tsym;
  656. ignore:tsym;
  657. end;
  658. pselfinfo=^tselfinfo;
  659. function find_self_sym(var n:tnode;arg:pointer):foreachnoderesult;
  660. var
  661. info : pselfinfo absolute arg;
  662. begin
  663. result:=fen_false;
  664. if assigned(info^.selfsym) then
  665. exit(fen_norecurse_true);
  666. if n.nodetype<>loadn then
  667. exit;
  668. if tloadnode(n).symtableentry.typ<>paravarsym then
  669. exit;
  670. if tloadnode(n).symtableentry=info^.ignore then
  671. exit;
  672. if vo_is_self in tparavarsym(tloadnode(n).symtableentry).varoptions then
  673. begin
  674. info^.selfsym:=tparavarsym(tloadnode(n).symtableentry);
  675. result:=fen_norecurse_true;
  676. end;
  677. end;
  678. function find_outermost_loaded_sym(var n:tnode;arg:pointer):foreachnoderesult;
  679. var
  680. sym : ^tsym absolute arg;
  681. begin
  682. if assigned(sym^) then
  683. exit(fen_norecurse_true);
  684. result:=fen_false;
  685. if n.nodetype<>loadn then
  686. exit;
  687. if not (n.resultdef.typ in [procdef,procvardef]) then
  688. exit;
  689. sym^:=tloadnode(n).symtableentry;
  690. result:=fen_norecurse_true;
  691. end;
  692. function find_procdef(var n:tnode;arg:pointer):foreachnoderesult;
  693. var
  694. pd : ^tprocdef absolute arg;
  695. begin
  696. if assigned(pd^) then
  697. exit(fen_norecurse_true);
  698. result:=fen_false;
  699. if n.resultdef.typ<>procdef then
  700. exit;
  701. pd^:=tprocdef(n.resultdef);
  702. result:=fen_norecurse_true;
  703. end;
  704. function capturer_add_procvar_or_proc(owner:tprocinfo;n:tnode;out capturer:tsym;out capturen:tnode):tobjectdef;
  705. function create_paras(pd:tprocdef):tcallparanode;
  706. var
  707. para : tparavarsym;
  708. i : longint;
  709. begin
  710. result:=nil;
  711. for i:=0 to pd.paras.count-1 do
  712. begin
  713. para:=tparavarsym(pd.paras[i]);
  714. if vo_is_hidden_para in para.varoptions then
  715. continue;
  716. result:=ccallparanode.create(cloadnode.create(para,pd.parast),result);
  717. end;
  718. end;
  719. function find_nested_procinfo(pd:tprocdef):tcgprocinfo;
  720. var
  721. tmp,
  722. res : tprocinfo;
  723. begin
  724. tmp:=owner;
  725. while assigned(tmp) and (tmp.procdef.parast.symtablelevel>=normal_function_level) do
  726. begin
  727. res:=tmp.find_nestedproc_by_pd(pd);
  728. if assigned(res) then
  729. exit(tcgprocinfo(res));
  730. tmp:=tmp.parent;
  731. end;
  732. result:=nil;
  733. end;
  734. procedure swap_symtable(var st1,st2:tsymtable);
  735. var
  736. st : tsymtable;
  737. owner : tdefentry;
  738. level : byte;
  739. begin
  740. { first swap the symtables themselves }
  741. st:=st1;
  742. st1:=st2;
  743. st2:=st;
  744. { then swap the symtables' owners }
  745. owner:=st1.defowner;
  746. st1.defowner:=st2.defowner;
  747. st2.defowner:=owner;
  748. { and finally the symtable level }
  749. level:=st1.symtablelevel;
  750. st1.symtablelevel:=st2.symtablelevel;
  751. st2.symtablelevel:=level;
  752. end;
  753. procedure print_procinfo(pi:tcgprocinfo);
  754. begin
  755. { Print the node to tree.log }
  756. if paraprintnodetree <> 0 then
  757. pi.printproc('after parsing');
  758. {$ifdef DEBUG_NODE_XML}
  759. { Methods of generic classes don't get any code generated, so output
  760. the node tree here }
  761. if (df_generic in pi.procdef.defoptions) then
  762. pi.XMLPrintProc(True);
  763. {$endif DEBUG_NODE_XML}
  764. end;
  765. var
  766. ps : tprocsym;
  767. oldpd,
  768. pd : tprocdef;
  769. pinested,
  770. pi : tcgprocinfo;
  771. sym,
  772. fpsym,
  773. selfsym : tsym;
  774. invokename : tsymstr;
  775. capturedef : tobjectdef;
  776. capturesyms : tfplist;
  777. captured : pcapturedsyminfo;
  778. implintf : TImplementedInterface;
  779. i : longint;
  780. stmt : tstatementnode;
  781. n1 : tnode;
  782. fieldsym : tfieldvarsym;
  783. selfinfo : tselfinfo;
  784. begin
  785. if not (n.resultdef.typ in [procdef,procvardef]) then
  786. internalerror(2022022101);
  787. capturer:=nil;
  788. capturen:=nil;
  789. pinested:=nil;
  790. oldpd:=nil;
  791. { determine a unique name for the variable, field for function of the
  792. node we're trying to load }
  793. sym:=nil;
  794. if not foreachnodestatic(pm_preprocess,n,@find_outermost_loaded_sym,@sym) then
  795. internalerror(2022022102);
  796. result:=funcref_intf_for_proc(tabstractprocdef(n.resultdef),fileinfo_to_suffix(sym.fileinfo));
  797. if (sym.typ=procsym) and (sym.owner.symtabletype=localsymtable) then
  798. begin
  799. { this is assigning a nested function, so retrieve the correct procdef
  800. so that we can then retrieve the procinfo for it }
  801. if n.resultdef.typ=procdef then
  802. pd:=tprocdef(n.resultdef)
  803. else
  804. begin
  805. pd:=nil;
  806. if not foreachnodestatic(pm_preprocess,n,@find_procdef,@pd) then
  807. internalerror(2022041801);
  808. if not assigned(pd) then
  809. internalerror(2022041802);
  810. end;
  811. { check whether all captured symbols can indeed be captured }
  812. capturesyms:=pd.capturedsyms;
  813. if assigned(capturesyms) then
  814. for i:=0 to capturesyms.count-1 do
  815. begin
  816. captured:=pcapturedsyminfo(capturesyms[i]);
  817. if not can_be_captured(captured^.sym,pd) then
  818. MessagePos1(captured^.fileinfo,sym_e_symbol_no_capture,captured^.sym.realname);
  819. end;
  820. if not (df_generic in owner.procdef.defoptions) then
  821. begin
  822. pinested:=find_nested_procinfo(pd);
  823. if not assigned(pinested) then
  824. internalerror(2022041803);
  825. oldpd:=pd;
  826. if pinested.parent<>owner then
  827. begin
  828. { we need to capture this into the owner of the nested function
  829. instead }
  830. owner:=pinested;
  831. capturer:=get_or_create_capturer(pinested.procdef);
  832. if not assigned(capturer) then
  833. internalerror(2022041804);
  834. end;
  835. end;
  836. end
  837. else if (n.resultdef.typ=procvardef) and
  838. (po_delphi_nested_cc in tprocvardef(n.resultdef).procoptions) then
  839. begin
  840. MessagePos(n.fileinfo,type_e_nested_procvar_to_funcref);
  841. exit;
  842. end
  843. else
  844. pinested:=nil;
  845. if df_generic in owner.procdef.defoptions then
  846. exit;
  847. if not assigned(capturer) then
  848. capturer:=get_or_create_capturer(owner.procdef);
  849. if not (capturer.typ in [localvarsym,staticvarsym]) then
  850. internalerror(2022022103);
  851. capturedef:=tobjectdef(tabstractvarsym(capturer).vardef);
  852. if not is_class(capturedef) then
  853. internalerror(2022022104);
  854. implintf:=find_implemented_interface(capturedef,result);
  855. if assigned(implintf) then
  856. begin
  857. { this is already captured into a method of the capturer, so nothing
  858. further to do }
  859. exit;
  860. end;
  861. implintf:=capturedef.register_implemented_interface(result,true);
  862. invokename:=method_name_funcref_invoke_decl+'__FPCINTERNAL__'+fileinfo_to_suffix(sym.fileinfo);
  863. ps:=cprocsym.create(invokename);
  864. pd:=tprocdef(tabstractprocdef(n.resultdef).getcopyas(procdef,pc_normal_no_hidden,'',false));
  865. pd.aliasnames.clear;
  866. pd.procsym:=ps;
  867. pd.struct:=capturedef;
  868. pd.changeowner(capturedef.symtable);
  869. pd.parast.symtablelevel:=normal_function_level;
  870. pd.localst.symtablelevel:=normal_function_level;
  871. { reset procoptions }
  872. pd.procoptions:=[];
  873. ps.ProcdefList.Add(pd);
  874. pd.forwarddef:=false;
  875. { set procinfo and current_procinfo.procdef }
  876. pi:=tcgprocinfo(cprocinfo.create(nil));
  877. pi.procdef:=pd;
  878. if not assigned(pinested) then
  879. begin
  880. insert_funcret_para(pd);
  881. insert_funcret_local(pd);
  882. { we always do a call, namely to the provided function }
  883. include(pi.flags,pi_do_call);
  884. end
  885. else
  886. begin
  887. { the original nested function now calls the method }
  888. include(pinested.flags,pi_do_call);
  889. { swap the para and local symtables of the nested and new routine }
  890. swap_symtable(pinested.procdef.parast,pd.parast);
  891. swap_symtable(pinested.procdef.localst,pd.localst);
  892. { fix function return symbol }
  893. pd.funcretsym:=pinested.procdef.funcretsym;
  894. pinested.procdef.funcretsym:=nil;
  895. insert_funcret_para(pinested.procdef);
  896. insert_funcret_local(pinested.procdef);
  897. { the nested function needs access to the parent's framepointer to
  898. access the capturer }
  899. insert_parentfp_para(pinested.procdef);
  900. pd.copied_from:=pinested.procdef;
  901. end;
  902. { to simplify some checks, but only after insert_funcret_para }
  903. pd.was_anonymous:=true;
  904. capturedef.symtable.insertsym(ps);
  905. owner.addnestedproc(pi);
  906. { remove self and parentfp parameter if any as that will be replaced by
  907. the capturer }
  908. selfsym:=nil;
  909. fpsym:=nil;
  910. for i:=0 to pd.parast.symlist.count-1 do
  911. begin
  912. sym:=tsym(pd.parast.symlist[i]);
  913. if sym.typ<>paravarsym then
  914. continue;
  915. if vo_is_self in tparavarsym(sym).varoptions then
  916. selfsym:=sym
  917. else if vo_is_parentfp in tparavarsym(sym).varoptions then
  918. fpsym:=sym;
  919. if assigned(selfsym) and assigned(fpsym) then
  920. break;
  921. end;
  922. if assigned(selfsym) then
  923. pd.parast.deletesym(selfsym);
  924. if assigned(fpsym) then
  925. pd.parast.deletesym(fpsym);
  926. pd.calcparas;
  927. if assigned(pinested) then
  928. pinested.procdef.calcparas;
  929. insert_self_and_vmt_para(pd);
  930. if assigned(pinested) then
  931. begin
  932. { when we're assigning a nested function to a function reference we
  933. move the code of the nested function to the newly created capturer
  934. method (including the captured symbols) and have the original nested
  935. function simply call that function-turned-method }
  936. pi.code:=pinested.code;
  937. pinested.code:=internalstatements(stmt);
  938. end
  939. else
  940. pi.code:=internalstatements(stmt);
  941. selfinfo.selfsym:=nil;
  942. selfinfo.ignore:=nil;
  943. fieldsym:=nil;
  944. if assigned(pinested) then
  945. begin
  946. n1:=ccallnode.create(create_paras(pinested.procdef),ps,capturedef.symtable,cloadnode.create(capturer,capturer.owner),[],nil);
  947. { captured variables cannot be in registers }
  948. make_not_regable(tcallnode(n1).methodpointer,[ra_addr_regable,ra_addr_taken]);
  949. end
  950. else if n.resultdef.typ=procvardef then
  951. begin
  952. { store the procvar in a field so that it won't be changed if the
  953. procvar itself is changed }
  954. fieldsym:=cfieldvarsym.create('$'+fileinfo_to_suffix(n.fileinfo),vs_value,n.resultdef,[]);
  955. fieldsym.fileinfo:=n.fileinfo;
  956. capturedef.symtable.insertsym(fieldsym);
  957. tabstractrecordsymtable(capturedef.symtable).addfield(fieldsym,vis_public);
  958. capturen:=csubscriptnode.create(fieldsym,cloadnode.create(capturer,capturer.owner));
  959. selfsym:=tsym(pd.parast.find('self'));
  960. if not assigned(selfsym) then
  961. internalerror(2022052301);
  962. selfinfo.ignore:=selfsym;
  963. n1:=ccallnode.create_procvar(create_paras(pd),csubscriptnode.create(fieldsym,cloadnode.create(selfsym,selfsym.owner)));
  964. end
  965. else
  966. begin
  967. if n.nodetype<>loadn then
  968. internalerror(2022032401);
  969. if tloadnode(n).symtableentry.typ<>procsym then
  970. internalerror(2022032402);
  971. n1:=ccallnode.create(create_paras(pd),tprocsym(tloadnode(n).symtableentry),tloadnode(n).symtable,tloadnode(n).left,[],nil);
  972. tloadnode(n).left:=nil;
  973. end;
  974. if assigned(pd.returndef) and not is_void(pd.returndef) then
  975. begin
  976. if assigned(pinested) then
  977. sym:=pinested.procdef.funcretsym
  978. else
  979. sym:=pd.funcretsym;
  980. n1:=cassignmentnode.create(
  981. cloadnode.create(sym,sym.owner),
  982. n1
  983. );
  984. { captured variables cannot be in registers }
  985. make_not_regable(tassignmentnode(n1).left,[ra_addr_regable,ra_addr_taken]);
  986. end;
  987. addstatement(stmt,n1);
  988. pd.aliasnames.insert(pd.mangledname);
  989. if assigned(pinested) then
  990. begin
  991. { transfer all captured syms }
  992. capturesyms:=pinested.procdef.capturedsyms;
  993. if assigned(capturesyms) then
  994. begin
  995. for i:=0 to capturesyms.count-1 do
  996. begin
  997. captured:=pcapturedsyminfo(capturesyms[i]);
  998. pi.add_captured_sym(captured^.sym,captured^.def,captured^.fileinfo);
  999. dispose(captured);
  1000. end;
  1001. capturesyms.clear;
  1002. end;
  1003. { the original nested function now needs to capture only the capturer }
  1004. pinested.procdef.add_captured_sym(capturer,capturedef,n.fileinfo);
  1005. end
  1006. { does this need to capture Self? }
  1007. else if not foreachnodestatic(pm_postprocess,n,@find_self_sym,@selfinfo) then
  1008. begin
  1009. { is this a method of the current class? }
  1010. if (n.resultdef.typ=procdef) and
  1011. assigned(tprocdef(n.resultdef).struct) and
  1012. not (po_staticmethod in tprocdef(n.resultdef).procoptions) and
  1013. assigned(current_procinfo.procdef.struct) and
  1014. def_is_related(current_procinfo.procdef.struct,tprocdef(n.resultdef).struct) then
  1015. begin
  1016. selfinfo.selfsym:=tsym(current_procinfo.procdef.parast.find('self'));
  1017. if not assigned(selfinfo.selfsym) then
  1018. internalerror(2022110601);
  1019. end
  1020. else
  1021. { does this need some other local variable or parameter? }
  1022. foreachnodestatic(pm_postprocess,n,@collect_syms_to_capture,@pd)
  1023. end;
  1024. if assigned(selfinfo.selfsym) and not assigned(fieldsym) then
  1025. { this isn't a procdef that was captured into a field, so capture the
  1026. self }
  1027. pd.add_captured_sym(selfinfo.selfsym,tabstractvarsym(selfinfo.selfsym).vardef,n.fileinfo);
  1028. print_procinfo(pi);
  1029. if assigned(pinested) then
  1030. print_procinfo(pinested);
  1031. implintf.AddMapping(upcase(result.objrealname^+'.')+method_name_funcref_invoke_find,upcase(invokename));
  1032. capture_captured_syms(pd,owner,capturedef,oldpd);
  1033. end;
  1034. function capturer_add_anonymous_proc(owner:tprocinfo;pd:tprocdef;out capturer:tsym):tobjectdef;
  1035. var
  1036. capturedef : tobjectdef;
  1037. implintf : TImplementedInterface;
  1038. invokename : tsymstr;
  1039. i : longint;
  1040. outerself,
  1041. fpsym,
  1042. selfsym,
  1043. sym : tsym;
  1044. info : pcapturedsyminfo;
  1045. pi : tprocinfo;
  1046. mapping : tsym_mapping;
  1047. invokedef,
  1048. parentdef,
  1049. curpd : tprocdef;
  1050. begin
  1051. capturer:=nil;
  1052. result:=funcref_intf_for_proc(pd,fileinfo_to_suffix(pd.fileinfo));
  1053. if df_generic in pd.defoptions then
  1054. begin
  1055. if (po_anonymous in pd.procoptions) and
  1056. assigned(pd.capturedsyms) and
  1057. (pd.capturedsyms.count>0) then
  1058. begin
  1059. { only check whether the symbols can be captured, but don't
  1060. convert anything to avoid problems }
  1061. for i:=0 to pd.capturedsyms.count-1 do
  1062. begin
  1063. info:=pcapturedsyminfo(pd.capturedsyms[i]);
  1064. if not can_be_captured(info^.sym,pd) then
  1065. MessagePos1(info^.fileinfo,sym_e_symbol_no_capture,info^.sym.realname)
  1066. end;
  1067. end;
  1068. exit;
  1069. end;
  1070. capturer:=get_or_create_capturer(owner.procdef);
  1071. if not (capturer.typ in [localvarsym,staticvarsym]) then
  1072. internalerror(2022010711);
  1073. capturedef:=tobjectdef(tabstractvarsym(capturer).vardef);
  1074. if not is_class(capturedef) then
  1075. internalerror(2022010712);
  1076. implintf:=find_implemented_interface(capturedef,result);
  1077. if assigned(implintf) then
  1078. begin
  1079. { this can only already be an implemented interface if a named procdef
  1080. was assigned to a function ref at an earlier point, an anonymous
  1081. function can be used only once }
  1082. if po_anonymous in pd.procoptions then
  1083. internalerror(2022010713);
  1084. exit;
  1085. end;
  1086. implintf:=capturedef.register_implemented_interface(result,true);
  1087. invokename:=method_name_funcref_invoke_decl+'__FPCINTERNAL__'+fileinfo_to_suffix(pd.fileinfo);
  1088. if po_anonymous in pd.procoptions then
  1089. begin
  1090. { turn the anonymous function into a method of the capturer }
  1091. pd.changeowner(capturedef.symtable);
  1092. pd.struct:=capturedef;
  1093. exclude(pd.procoptions,po_anonymous);
  1094. exclude(pd.procoptions,po_delphi_nested_cc);
  1095. exclude(pd.procoptions,po_staticmethod);
  1096. exclude(pd.procoptions,po_classmethod);
  1097. pd.was_anonymous:=true;
  1098. pd.procsym.ChangeOwnerAndName(capturedef.symtable,upcase(invokename));
  1099. pd.procsym.realname:=invokename;
  1100. pd.parast.symtablelevel:=normal_function_level;
  1101. pd.localst.symtablelevel:=normal_function_level;
  1102. { retrieve framepointer and self parameters if any }
  1103. fpsym:=nil;
  1104. selfsym:=nil;
  1105. for i:=0 to pd.parast.symlist.count-1 do
  1106. begin
  1107. sym:=tsym(pd.parast.symlist[i]);
  1108. if sym.typ<>paravarsym then
  1109. continue;
  1110. if vo_is_parentfp in tparavarsym(sym).varoptions then
  1111. fpsym:=sym
  1112. else if vo_is_self in tparavarsym(sym).varoptions then
  1113. selfsym:=sym;
  1114. if assigned(fpsym) and assigned(selfsym) then
  1115. break;
  1116. end;
  1117. { get rid of the framepointer parameter }
  1118. if assigned(fpsym) then
  1119. pd.parast.deletesym(fpsym);
  1120. outerself:=nil;
  1121. { complain about all symbols that can't be captured and add the symbols
  1122. to this procdefs capturedsyms if it isn't a top level function }
  1123. if assigned(pd.capturedsyms) and (pd.capturedsyms.count>0) then
  1124. begin
  1125. for i:=0 to pd.capturedsyms.count-1 do
  1126. begin
  1127. info:=pcapturedsyminfo(pd.capturedsyms[i]);
  1128. if not can_be_captured(info^.sym,pd) then
  1129. MessagePos1(info^.fileinfo,sym_e_symbol_no_capture,info^.sym.realname)
  1130. else if info^.sym=selfsym then
  1131. begin
  1132. { we need to replace the captured "dummy" self parameter
  1133. with the real self parameter symbol from the surrounding
  1134. method }
  1135. if not assigned(outerself) then
  1136. outerself:=tsym(owner.get_normal_proc.procdef.parast.find('self'));
  1137. if not assigned(outerself) then
  1138. internalerror(2022010905);
  1139. { the anonymous function can only be a direct child of the
  1140. owner }
  1141. pi:=owner.get_first_nestedproc;
  1142. while assigned(pi) do
  1143. begin
  1144. if pi.procdef=pd then
  1145. break;
  1146. pi:=tprocinfo(pi.next);
  1147. end;
  1148. if not assigned(pi) then
  1149. internalerror(2022010906);
  1150. mapping.oldsym:=selfsym;
  1151. mapping.newsym:=outerself;
  1152. { replace all uses of the captured Self by the new Self
  1153. parameter }
  1154. foreachnodestatic(pm_preprocess,tcgprocinfo(pi).code,@replace_self_sym,@mapping);
  1155. { update the captured symbol }
  1156. info^.sym:=outerself;
  1157. info^.def:=tabstractvarsym(outerself).vardef;
  1158. end
  1159. else if info^.sym.owner.defowner<>owner.procdef then
  1160. owner.procdef.add_captured_sym(info^.sym,info^.def,info^.fileinfo);
  1161. end;
  1162. end;
  1163. { delete the original self parameter }
  1164. if assigned(selfsym) then
  1165. pd.parast.deletesym(selfsym);
  1166. { note: don't call insert_self_and_vmt_para here, as that is later on
  1167. done when building the VMT }
  1168. end
  1169. else
  1170. internalerror(2022022201);
  1171. implintf.AddMapping(upcase(result.objrealname^+'.')+method_name_funcref_invoke_find,upcase(invokename));
  1172. capture_captured_syms(pd,owner,capturedef,nil);
  1173. end;
  1174. function load_capturer(capturer:tabstractvarsym):tnode;inline;
  1175. begin
  1176. result:=cloadnode.create(capturer,capturer.owner);
  1177. end;
  1178. function instantiate_capturer(capturer_sym:tabstractvarsym):tnode;
  1179. var
  1180. capturer_def : tobjectdef;
  1181. ctor : tprocsym;
  1182. begin
  1183. capturer_def:=tobjectdef(capturer_sym.vardef);
  1184. { Neither TInterfacedObject, nor TCapturer have a custom constructor }
  1185. ctor:=tprocsym(class_tobject.symtable.Find('CREATE'));
  1186. if not assigned(ctor) then
  1187. internalerror(2022010801);
  1188. { Insert "Capturer := TCapturer.Create()" as the first statement of the routine }
  1189. result:=cloadvmtaddrnode.create(ctypenode.create(capturer_def));
  1190. result:=ccallnode.create(nil,ctor,capturer_def.symtable,result,[],nil);
  1191. result:=cassignmentnode.create(load_capturer(capturer_sym),result);
  1192. end;
  1193. procedure initialize_captured_paras(pd:tprocdef;capturer:tabstractvarsym;var stmt:tstatementnode);
  1194. var
  1195. i : longint;
  1196. psym: tparavarsym;
  1197. n : tnode;
  1198. begin
  1199. for i:=0 to pd.paras.count-1 do
  1200. begin
  1201. psym:=tparavarsym(pd.paras[i]);
  1202. if not psym.is_captured then
  1203. continue;
  1204. {$ifdef DEBUG_CAPTURER}writeln(#9'initialize captured parameter ',psym.RealName);{$endif}
  1205. n:=cloadnode.create(psym,psym.owner);
  1206. if psym.capture_sym.owner.defowner<>capturer.vardef then
  1207. internalerror(2022010903);
  1208. if (vo_is_self in psym.varoptions) and not is_implicit_pointer_object_type(psym.vardef) then
  1209. n:=caddrnode.create(n);
  1210. n:=cassignmentnode.create(
  1211. csubscriptnode.create(psym.capture_sym,cloadnode.create(capturer,capturer.owner)),
  1212. n
  1213. );
  1214. addstatement(stmt,n);
  1215. end;
  1216. end;
  1217. procedure attach_outer_capturer(ctx:tprocinfo;capturer:tabstractvarsym;var stmt:tstatementnode);
  1218. var
  1219. alivefield,
  1220. selffield : tfieldvarsym;
  1221. outeralive,
  1222. outercapturer : tabstractvarsym;
  1223. alivenode,
  1224. selfnode : tnode;
  1225. begin
  1226. if not ctx.procdef.was_anonymous and
  1227. not (ctx.procdef.owner.symtabletype=localsymtable) then
  1228. exit;
  1229. selffield:=tfieldvarsym(tobjectdef(capturer.vardef).symtable.find(outer_self_field_name));
  1230. if not assigned(selffield) then
  1231. { we'll simply assume that we don't need the outer capturer }
  1232. exit;
  1233. alivefield:=tfieldvarsym(tobjectdef(capturer.vardef).symtable.find(outer_self_field_name+keepalive_suffix));
  1234. if not assigned(alivefield) then
  1235. internalerror(2022051701);
  1236. if ctx.procdef.was_anonymous then
  1237. begin
  1238. selfnode:=load_self_node;
  1239. alivenode:=selfnode.getcopy;
  1240. end
  1241. else
  1242. begin
  1243. outercapturer:=get_capturer(tprocdef(ctx.procdef.owner.defowner));
  1244. if not assigned(outercapturer) then
  1245. internalerror(2022011605);
  1246. selfnode:=cloadnode.create(outercapturer,outercapturer.owner);
  1247. make_not_regable(selfnode,[ra_different_scope]);
  1248. outeralive:=get_capturer_alive(tprocdef(ctx.procdef.owner.defowner));
  1249. if not assigned(outeralive) then
  1250. internalerror(2022051706);
  1251. alivenode:=cloadnode.create(outeralive,outeralive.owner);
  1252. make_not_regable(alivenode,[ra_different_scope]);
  1253. end;
  1254. addstatement(stmt,cassignmentnode.create(
  1255. csubscriptnode.create(
  1256. selffield,
  1257. cloadnode.create(
  1258. capturer,
  1259. capturer.owner
  1260. )
  1261. ),
  1262. selfnode));
  1263. addstatement(stmt,cassignmentnode.create(
  1264. csubscriptnode.create(
  1265. alivefield,
  1266. cloadnode.create(
  1267. capturer,
  1268. capturer.owner
  1269. )
  1270. ),
  1271. alivenode));
  1272. end;
  1273. procedure initialize_capturer(ctx:tprocinfo;var stmt:tstatementnode);
  1274. var
  1275. capturer_sym,
  1276. keepalive_sym : tabstractvarsym;
  1277. begin
  1278. if ctx.procdef.has_capturer then
  1279. begin
  1280. capturer_sym:=get_capturer(ctx.procdef);
  1281. {$ifdef DEBUG_CAPTURER}writeln('initialize_capturer @ ',ctx.procdef.procsym.RealName);{$endif}
  1282. addstatement(stmt,instantiate_capturer(capturer_sym));
  1283. attach_outer_capturer(ctx,capturer_sym,stmt);
  1284. initialize_captured_paras(ctx.procdef,capturer_sym,stmt);
  1285. keepalive_sym:=get_capturer_alive(ctx.procdef);
  1286. if not assigned(keepalive_sym) then
  1287. internalerror(2022010701);
  1288. addstatement(stmt,cassignmentnode.create(cloadnode.create(keepalive_sym,keepalive_sym.owner),load_capturer(capturer_sym)));
  1289. end;
  1290. end;
  1291. procedure postprocess_capturer(ctx: tprocinfo);
  1292. var
  1293. def: tobjectdef;
  1294. begin
  1295. if not ctx.procdef.has_capturer then
  1296. exit;
  1297. def:=tobjectdef(get_capturer(ctx.procdef).vardef);
  1298. {$ifdef DEBUG_CAPTURER}writeln('process capturer ',def.typesym.Name);{$endif}
  1299. { These two are delayed until this point because
  1300. ... we have been adding fields on-the-fly }
  1301. tabstractrecordsymtable(def.symtable).addalignmentpadding;
  1302. { ... we have been adding interfaces on-the-fly }
  1303. build_vmt(def);
  1304. end;
  1305. type
  1306. tconvert_arg=record
  1307. mappings:tfplist;
  1308. end;
  1309. pconvert_arg=^tconvert_arg;
  1310. tconvert_mapping=record
  1311. oldsym:tsym;
  1312. newsym:tsym;
  1313. olddef:tdef;
  1314. selfnode:tnode;
  1315. end;
  1316. pconvert_mapping=^tconvert_mapping;
  1317. function convert_captured_sym(var n:tnode;arg:pointer):foreachnoderesult;
  1318. var
  1319. convertarg : pconvert_arg absolute arg;
  1320. mapping : pconvert_mapping;
  1321. i : longint;
  1322. old_filepos : tfileposinfo;
  1323. loadprocvar : boolean;
  1324. paras,
  1325. mp : tnode;
  1326. cnf : tcallnodeflags;
  1327. paraold,
  1328. paranew : tcallparanode;
  1329. begin
  1330. result:=fen_true;
  1331. if not (n.nodetype in [loadn,calln]) then
  1332. exit;
  1333. for i:=0 to convertarg^.mappings.count-1 do
  1334. begin
  1335. mapping:=convertarg^.mappings[i];
  1336. case n.nodetype of
  1337. loadn:
  1338. begin
  1339. if tloadnode(n).symtableentry<>mapping^.oldsym then
  1340. continue;
  1341. old_filepos:=current_filepos;
  1342. current_filepos:=n.fileinfo;
  1343. loadprocvar:=nf_load_procvar in n.flags;
  1344. n.free;
  1345. n:=csubscriptnode.create(mapping^.newsym,mapping^.selfnode.getcopy);
  1346. if loadprocvar then
  1347. include(n.flags,nf_load_procvar);
  1348. if (mapping^.oldsym.typ=paravarsym) and
  1349. (vo_is_self in tparavarsym(mapping^.oldsym).varoptions) and
  1350. not is_implicit_pointer_object_type(tparavarsym(mapping^.oldsym).vardef) then
  1351. n:=cderefnode.create(n);
  1352. typecheckpass(n);
  1353. current_filepos:=old_filepos;
  1354. break;
  1355. end;
  1356. calln:
  1357. begin
  1358. if mapping^.oldsym.typ<>procsym then
  1359. continue;
  1360. if tcallnode(n).symtableprocentry<>tprocsym(mapping^.oldsym) then
  1361. continue;
  1362. if tcallnode(n).procdefinition<>tprocdef(mapping^.olddef) then
  1363. continue;
  1364. old_filepos:=current_filepos;
  1365. current_filepos:=n.fileinfo;
  1366. loadprocvar:=nf_load_procvar in n.flags;
  1367. paras:=tcallnode(n).left;
  1368. paraold:=tcallparanode(paras);
  1369. paranew:=nil;
  1370. while assigned(paraold) do
  1371. begin
  1372. if not (vo_is_hidden_para in paraold.parasym.varoptions) then
  1373. begin
  1374. paranew:=ccallparanode.create(paraold.left,paranew);
  1375. paraold.left:=nil;
  1376. end;
  1377. paraold:=tcallparanode(paraold.right);
  1378. end;
  1379. reverseparameters(paranew);
  1380. if assigned(tcallnode(n).methodpointer) then
  1381. internalerror(2023120802);
  1382. cnf:=tcallnode(n).callnodeflags;
  1383. n.free;
  1384. n:=ccallnode.create(paranew,tprocsym(mapping^.newsym),mapping^.newsym.owner,mapping^.selfnode.getcopy,cnf,nil);
  1385. if loadprocvar then
  1386. include(n.flags,nf_load_procvar);
  1387. typecheckpass(n);
  1388. current_filepos:=old_filepos;
  1389. break;
  1390. end;
  1391. else
  1392. internalerror(2023120801);
  1393. end;
  1394. end;
  1395. end;
  1396. procedure convert_captured_syms(pd:tprocdef;tree:tnode);
  1397. function self_tree_for_sym(selfsym:tsym;fieldsym:tsym):tnode;
  1398. var
  1399. fieldowner : tdef;
  1400. newsym : tsym;
  1401. begin
  1402. result:=cloadnode.create(selfsym,selfsym.owner);
  1403. fieldowner:=tdef(fieldsym.owner.defowner);
  1404. newsym:=selfsym;
  1405. while (tabstractvarsym(newsym).vardef<>fieldowner) do
  1406. begin
  1407. newsym:=tsym(tobjectdef(tabstractvarsym(newsym).vardef).symtable.find(outer_self_field_name));
  1408. if not assigned(newsym) then
  1409. internalerror(2022011101);
  1410. result:=csubscriptnode.create(newsym,result);
  1411. end;
  1412. end;
  1413. var
  1414. i,j : longint;
  1415. capturer : tobjectdef;
  1416. tocapture,
  1417. capturedsyms : tfplist;
  1418. convertarg : tconvert_arg;
  1419. mapping : pconvert_mapping;
  1420. invokepd : tprocdef;
  1421. selfsym,
  1422. sym : tsym;
  1423. info: pcapturedsyminfo;
  1424. begin
  1425. {$ifdef DEBUG_CAPTURER}writeln('Converting captured symbols of ',pd.procsym.name);{$endif}
  1426. convertarg.mappings:=tfplist.create;
  1427. capturedsyms:=tfplist.create;
  1428. if pd.was_anonymous and
  1429. assigned(pd.capturedsyms) and
  1430. (pd.capturedsyms.count>0) then
  1431. begin
  1432. {$ifdef DEBUG_CAPTURER}writeln('Converting symbols of converted anonymous function ',pd.procsym.name);{$endif}
  1433. { this is a converted anonymous function, so rework all symbols that
  1434. now belong to the new Self }
  1435. selfsym:=tsym(pd.parast.find('self'));
  1436. if not assigned(selfsym) then
  1437. internalerror(2022010809);
  1438. for i:=0 to pd.capturedsyms.count-1 do
  1439. begin
  1440. sym:=tsym(pcapturedsyminfo(pd.capturedsyms[i])^.sym);
  1441. if not can_be_captured(sym,pd) and
  1442. not (
  1443. (sym.typ=procsym) and
  1444. assigned(pd.copied_from) and
  1445. (pd.copied_from.procsym=sym)
  1446. ) then
  1447. continue;
  1448. {$ifdef DEBUG_CAPTURER}writeln('Replacing symbol ',sym.Name);{$endif}
  1449. new(mapping);
  1450. mapping^.oldsym:=sym;
  1451. if sym.typ=procsym then
  1452. begin
  1453. if not assigned(pd.copied_from) or
  1454. (pd.copied_from.procsym<>sym) then
  1455. internalerror(2023123001);
  1456. mapping^.newsym:=pd.procsym;
  1457. end
  1458. else
  1459. mapping^.newsym:=tabstractnormalvarsym(sym).capture_sym;
  1460. mapping^.olddef:=pcapturedsyminfo(pd.capturedsyms[i])^.def;
  1461. if not assigned(mapping^.newsym) then
  1462. internalerror(2022010810);
  1463. mapping^.selfnode:=self_tree_for_sym(selfsym,mapping^.newsym);
  1464. convertarg.mappings.add(mapping);
  1465. capturedsyms.add(sym);
  1466. end;
  1467. end;
  1468. if (pd.parast.symtablelevel>normal_function_level) and
  1469. assigned(pd.capturedsyms) and
  1470. (pd.capturedsyms.count>0) then
  1471. begin
  1472. if pd.was_anonymous then
  1473. internalerror(2022081201);
  1474. {$ifdef DEBUG_CAPTURER}writeln('Converting symbols of nested function ',pd.procsym.name);{$endif}
  1475. { this is a nested function, so rework all symbols that are used from
  1476. a parent function, but that might have been captured }
  1477. for i:=0 to pd.capturedsyms.count-1 do
  1478. begin
  1479. sym:=tsym(pcapturedsyminfo(pd.capturedsyms[i])^.sym);
  1480. if not can_be_captured(sym,pd) or
  1481. (sym.typ=procsym) or
  1482. not assigned(tabstractnormalvarsym(sym).capture_sym) then
  1483. continue;
  1484. {$ifdef DEBUG_CAPTURER}writeln('Replacing symbol ',sym.Name);{$endif}
  1485. new(mapping);
  1486. mapping^.oldsym:=sym;
  1487. mapping^.newsym:=tabstractnormalvarsym(sym).capture_sym;
  1488. mapping^.olddef:=pcapturedsyminfo(pd.capturedsyms[i])^.def;
  1489. capturer:=tobjectdef(mapping^.newsym.owner.defowner);
  1490. if not is_class(capturer) then
  1491. internalerror(2022012701);
  1492. if not (capturer.typesym.owner.symtabletype in [localsymtable,staticsymtable]) then
  1493. internalerror(2022012702);
  1494. selfsym:=tsym(capturer.typesym.owner.find(capturer_var_name));
  1495. if not assigned(selfsym) then
  1496. internalerror(2022012703);
  1497. mapping^.selfnode:=self_tree_for_sym(selfsym,mapping^.newsym);
  1498. convertarg.mappings.add(mapping);
  1499. capturedsyms.add(sym);
  1500. end;
  1501. end;
  1502. if pd.has_capturer then
  1503. begin
  1504. {$ifdef DEBUG_CAPTURER}writeln('Converting symbols of function ',pd.procsym.name,' with capturer');{$endif}
  1505. { this procedure has a capturer, so rework all symbols that are
  1506. captured in that capturer }
  1507. selfsym:=get_capturer(pd);
  1508. { only capture those symbols that weren't captured already by one of
  1509. the above if-clauses and thus are now listed in capturedsyms }
  1510. tocapture:=tfplist.create;
  1511. for i:=0 to pd.localst.symlist.count-1 do
  1512. begin
  1513. sym:=tsym(pd.localst.symlist[i]);
  1514. if sym.typ<>localvarsym then
  1515. continue;
  1516. if assigned(tabstractnormalvarsym(sym).capture_sym) then
  1517. if capturedsyms.indexof(sym)<0 then
  1518. tocapture.add(sym);
  1519. end;
  1520. for i:=0 to pd.parast.symlist.count-1 do
  1521. begin
  1522. sym:=tsym(pd.parast.symlist[i]);
  1523. if sym.typ<>paravarsym then
  1524. continue;
  1525. if assigned(tabstractnormalvarsym(sym).capture_sym) and
  1526. { no need to adjust accesses to the outermost Self inside the
  1527. outermost method }
  1528. not (vo_is_self in tabstractvarsym(sym).varoptions) then
  1529. if capturedsyms.indexof(sym)<0 then
  1530. tocapture.add(sym);
  1531. end;
  1532. convertarg.mappings.capacity:=convertarg.mappings.count+tocapture.count;
  1533. for i:=0 to tocapture.count-1 do
  1534. begin
  1535. new(mapping);
  1536. mapping^.oldsym:=tsym(tocapture[i]);
  1537. {$ifdef DEBUG_CAPTURER}writeln('Replacing symbol ',mapping^.oldsym.Name);{$endif}
  1538. mapping^.newsym:=tabstractnormalvarsym(mapping^.oldsym).capture_sym;
  1539. if not assigned(mapping^.newsym) then
  1540. internalerror(2022010805);
  1541. mapping^.selfnode:=self_tree_for_sym(selfsym,mapping^.newsym);
  1542. convertarg.mappings.add(mapping);
  1543. end;
  1544. tocapture.free;
  1545. end;
  1546. { not required anymore }
  1547. capturedsyms.free;
  1548. if convertarg.mappings.count>0 then
  1549. foreachnodestatic(pm_postprocess,tree,@convert_captured_sym,@convertarg);
  1550. for i:=0 to convertarg.mappings.count-1 do
  1551. begin
  1552. mapping:=pconvert_mapping(convertarg.mappings[i]);
  1553. mapping^.selfnode.free;
  1554. dispose(mapping);
  1555. end;
  1556. convertarg.mappings.free;
  1557. end;
  1558. end.