= Grammar = !ExtDecl ::= ... / ''!AspFuncDef'' / ''GIntroAdv'' !DeclOrFuncDef ::= ''Decl'' / ''!FuncDef'' GIntroAdv ::= `intro(`''Id''`) {` (''!DeclOrFuncDef'')^*^ `} ;` AspStructTDef ::= `struct` (''AttrSpecL'')^?^ (''!StructTag'')^?^ `{` ''AspStructDeclL'' `}` AspStructDeclL ::= (''!AnnotAspStructDecl'')^+^ ''Annotations'' / ''Annotations'' !AnnotAspStructDecl ::= ''!AspStructDecl'' !AspStructDecl ::= (`__extension__`)^?^ ''!StructAdvDecl''`;` / (`__extension__`)^?^ ''SpecQualL'' ''OptStructDeclL''`;` !StructAdvDecl ::= ... / ''AspStructTDef'' !AspFuncDef ::= (`__extension__`)^?^ (''!DeclSpecs'')^?^ ''Declarator'' ''!FuncDeclContext'' (''DeclL'')^?^ ''!AspCompStmt'' !AspCompStmt ::= `{` (''!LocalLabelDeclaration'')^*^ ''!ExtBlock'' (''!DeclOrStmt'')^*^ ''Annotations'' `}` !ExtBlock ::= `extension(`''Id''`) {` (''Declaration'')^*^ (''!BeforeStmt'')^?^ (''!AfterStmt'')^?^ `}` !BeforeStmt ::= `before(`''Ids''`) {` (''!DeclOrStmt'')^*^ `}` !AfterStmt ::= `after(`''Id''`) {` (''!DeclOrStmt'')^*^ `}` Ids ::= ''Id''(`,` ''Id'')^*^ == Code == The `before` block enables to specify some statements that should be executed ''prior'' the execution of the function containing this extension. === Basic Before Extension === {{{ #!c int main(void) { extension(c4_extension) { before () { printf("Before\n"); } } int i=0; for(; i<5; i++) { printf("i: %d\n", i); } return 0; } }}} This program will print: {{{ Before 0 1 2 3 4 }}} === Basic After Extension === The `after` block enables to specify some statements that should be executed ''after'' the execution of the function containing this extension. The `after` block must return the same type as the original function. {{{ #!c int main(void) { extension(c4_extension) { after() { printf("After\n"); return 0; } } int i=0; for(; i<5; i++) { printf("i: %d\n", i); } return 0; } }}} This program will print: {{{ 0 1 2 3 4 After }}} === Around Simulation === There is no longer an around block in C4. `before` and `after` block can emulate the around behavior. ==== State Sharing ==== `before` and `after` Extensions should be able to share some state. To do so, variables must be declared in the extension block to be made visible to both `before` and `after` extensions. {{{ #!c void trans_func(void) { extension(c4_extension) { LOCK * lock; before() { lock = acquire_lock(); } after() { release_lock(lock) } } do_something(); } }}} In this example, the `lock` variable is shared between the `before` and the `after` block. ==== Proceeding ==== In regular AOSD, the around pointcut enables to wrap the whole execution of a function. From the advice code, the original code can be called using the `proceed()` function. In C4, no need to call `proceed()`, the original function will be executed after the execution of the statements in the `before` block. The `before` block reproduces ''exactly'' the prototype of the including function (in terms of the number of parameters, the type is inferred). Optionally, the parameters names can be modified for more flexibility. {{{ #!c int trans_func(int parameter) { extension(c4_extension) { before(parameter) { printf("Before Parameter %d\n", parameter); parameter++; } after() { parameter--; printf("After Parameter %d\n", parameter); return parameter; } } printf("Main Body Parameter %d\n", parameter); return parameter; } }}} If called with `0`, the program should print: {{{ Before Parameter 0 Main Body Parameter 1 After Parameter 0 }}} What cannot be implemented using this approach: \begin{itemize} \item `proceed` in a loop \item `proceed` in one branch of an if \end{itemize} ==== No Proceeding ==== Sometimes the around advice is used to replace the body of a whole function. In regular AOSD approaches, the advice never calls the `proceed()` method. In C4, if the `before` block contains a `return` statement, the execution does not proceed to the original function body but goes straight to the beginning of the `after` block. The `before` block returns `void`. If some variables are supposed to be shared between the `before` and `after` advice, they must be declared in the `extension` block. {{{ #!c int trans_func(int parameter) { extension(c4_extension) { before(parameter) { printf("Before Parameter %d\n", parameter); parameter++; return; } after() { parameter--; printf("After Parameter %d\n", parameter); return parameter; } } printf("Main Body Parameter %d\n", parameter); return parameter; } }}} If called with `0`, the program should print: {{{ Before Parameter 0 After Parameter 0 }}} == Playing with Return Values in `After` Blocks == When entering an `after` advice, the ''value'' returned by the original function or by the corresponding `before` block is mapped with the variable name given as a parameter of the `after` block. If no variable name is given {{{ #!c int trans_func(int parameter) { extension(c4_extension) { before(parameter) { printf("Before Parameter %d\n", parameter); parameter++; } after(__returned__) { int result = __returned__ + 42; printf("After Parameter %d Returned %d\n", parameter, __returned__); return result; } } printf("Main Body Parameter %d\n", parameter); return parameter + 1; } }}} If called with `0`, the program should print: {{{ #!c Before Parameter 0 Main Body Parameter 1 After Parameter 1 Returned 2 }}} The `trans_func` function should return 44. = Compilation = == Before == `Before` blocks are translated as a regular block in the function including the extension. The ordering is important since It reflects the execution order. == After == `After` blocks are translated as nested functions. Those nested functions are pushed onto a stack. When returning from the including function, an orchestration function is called (just before returning to the calling function) that pops out all the after advice that were pushed on the stack. The last after advice to be executed returns from the function.