summaryrefslogtreecommitdiff
path: root/compiler/pparautl.pas
diff options
context:
space:
mode:
authorjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2014-07-18 09:15:22 +0000
committerjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2014-07-18 09:15:22 +0000
commit806f1a2409160f9fbb1dac1b5c5a3c2812cb46d6 (patch)
treeb4d987646afa20d6934e3230467ff12194ee7778 /compiler/pparautl.pas
parentb089d1d8bf79f3d9ab983ca1f280687397f78e25 (diff)
downloadfpc-806f1a2409160f9fbb1dac1b5c5a3c2812cb46d6.tar.gz
+ support for http://en.wikipedia.org/wiki/Blocks_(C_language_extension)
o blocks are implemented as a variation of procedure variables o declaration of a block variable: "test: procedure(c: char) is block;" (C equivalent: (void)(^test)(char c) ) o the compiler automatically converts procedures/functions whose address is passed to a block parameter or assigned to a block variable into a "block". This consists of 1) generating a block descriptor (containing the size of the "block literal" (see below) and the signature of the invocation function encoded as an Objective-C selector) 2) generating a wrapper function around the original funcion (with C calling convention), that has an extra first hidden parameter (marked as vo_is_parentfp in the compiler) whose type is a pointer to the describing "block literal" 3) generating the "block literal", which contains a pointer to an external variable indicating whether this block captures context or not, some flags (see compiler/blockutl.get_block_literal_flags for info), a pointer to the wrapper function and a pointer to the descriptor. In the future, it will also contain captured variables. o right now, only global procedures/functions can be converted to blocks (because they don't require state capturing). The next steps are (Object Pascal) methods (not Objective-C methods, because Objective-C method procvars don't exist) and finally nested functions o on Mac OS X, the functionality will only work on Mac OS X 10.7 and later, because we have to use the so-called "ABI.2010.3.16" to ensure that our blocks aren't called as variadic functions by the runtime (which came out after the Mac OS X 10.6 release) o while the currently implemented functionality does not require any library support at all, there's no use enabling it on other platforms because unless it has been confirmed to work with a blocks runtime, there's no point in using blocks (they're just somewhat bulky procvars right now). Enabling it on other platforms (in combination with the GNUStep Objective-C run time), should simply be a matter of adding the right {$linklib xxx} statement to rtl/inc/blockrtl.pp file, adding that file to Makefile.fpc for that platform and adding that platform to the compiler/systems.systems_blocks_supported set git-svn-id: http://svn.freepascal.org/svn/fpc/branches/blocks@28232 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/pparautl.pas')
-rw-r--r--compiler/pparautl.pas27
1 files changed, 26 insertions, 1 deletions
diff --git a/compiler/pparautl.pas b/compiler/pparautl.pas
index 3545f61509..ee195e130a 100644
--- a/compiler/pparautl.pas
+++ b/compiler/pparautl.pas
@@ -39,7 +39,7 @@ implementation
uses
globals,globtype,verbose,systems,
- symconst,symtype,symbase,symsym,symtable,symcreat,defutil,
+ symconst,symtype,symbase,symsym,symtable,symcreat,defutil,blockutl,
paramgr;
@@ -176,6 +176,31 @@ implementation
vs:=cparavarsym.create('$self',paranr_self,vs_value,voidpointertype,[vo_is_self,vo_is_hidden_para]);
pd.parast.insert(vs);
end
+ { while only procvardefs of this type can be declared in Pascal code,
+ internally we also generate procdefs of this type when creating
+ block wrappers }
+ else if (po_is_block in pd.procoptions) then
+ begin
+ { generate the first hidden parameter, which is a so-called "block
+ literal" describing the block and containing its invocation
+ procedure }
+ hdef:=getpointerdef(get_block_literal_type_for_proc(pd));
+ { mark as vo_is_parentfp so that proc2procvar comparisons will
+ succeed when assigning arbitrary routines to the block }
+ vs:=cparavarsym.create('$_block_literal',paranr_blockselfpara,vs_value,
+ hdef,[vo_is_hidden_para,vo_is_parentfp]
+ );
+ pd.parast.insert(vs);
+ if pd.typ=procdef then
+ begin
+ { make accessible to code }
+ sl:=tpropaccesslist.create;
+ sl.addsym(sl_load,vs);
+ aliasvs:=cabsolutevarsym.create_ref('FPC_BLOCK_SELF',hdef,sl);
+ include(aliasvs.varoptions,vo_is_parentfp);
+ tlocalsymtable(tprocdef(pd).localst).insert(aliasvs);
+ end;
+ end
else
begin
if (pd.typ=procdef) and