1.7. Header and body tags

Header and body statements may include tag names which can be refered to in requires clauses of binding definitions.

Tagged bodies and headers are only emitted if a used primitive type, constant, function or procedure requires them.

Untagged headers and bodies are tagged with the synthesised name _root. Every primitive function, procedure, type, or constant requires all visible untagged headers and bodies, that is, they all implicitly require _root.

Root requirements are inherited: each untagged header or body requires its parents _root (if it has one).

The effect is that if no primitives are used, no header or body code will be generated. If you really need to unconditionally force execution of some C code, you should be using the 'code' primitive. Header and body statements are intended for declarations and definitions.

The same tag can be used on more than one code insertion statements: this is typically useful on a header-body pair.

Start C++ section to tut/examples/tut_bind135.flx[1 /1 ]
     1: body "#include <stdio.h>";
     2: body xprint = "void printx(char *fmt, char *s) { printf(fmt,s);}";
     3: body printu = 'void print(char *s) { printx("%s\\n",s); }';
     4: 
     5: proc hello:1='print("Hello");' requires xprint, printu;
     6: hello;
     7: 
End C++ section to tut/examples/tut_bind135.flx[1]
Header and body statements can also have requirements. We can reorganise the previous example using this fact.
Start C++ section to tut/examples/tut_bind136.flx[1 /1 ]
     1: body "#include <stdio.h>";
     2: body xprint = "void printx(char *fmt, char *s) { printf(fmt,s);}";
     3: body printu = 'void print(char *s) { printx("%s\\n",s); }'
     4:   requires xprint;
     5: 
     6: proc hello:1='print("Hello");' requires printu;
     7: hello;
     8: 
End C++ section to tut/examples/tut_bind136.flx[1]
Naked requires clauses can also be used. They can define dependencies, or simply specify existing tagged requirements are roots.
Start C++ section to tut/examples/tut_bind137.flx[1 /1 ]
     1: body "#include <stdio.h>";
     2: body xprint = "void printx(char *fmt, char *s) { printf(fmt,s);}";
     3: body printu = 'void print(char *s) { printx("%s\\n",s); }';
     4: requires xprint;
     5: xxxx requires printu;
     6: 
     7: proc hello:1='print("Hello");' requires xxxx;
     8: hello;
     9: 
End C++ section to tut/examples/tut_bind137.flx[1]
You can also use qualified names to refer to tags defined inside modules, unless they're marked private of course.
Start C++ section to tut/examples/tut_bind138.flx[1 /1 ]
     1: body "#include <stdio.h>";
     2: body xprint = "void printx(char *fmt, char *s) { printf(fmt,s);}";
     3: module fred {
     4:   body printu = 'void print(char *s) { printx("%s\\n",s); }';
     5: }
     6: requires xprint;
     7: 
     8: proc hello:1='print("Hello");' requires fred::printu;
     9: hello;
    10: 
End C++ section to tut/examples/tut_bind138.flx[1]
The next example demonstrates untagged bodies at work.
Start C++ section to tut/examples/tut_bind138a.flx[1 /1 ]
     1: include "std";
     2: 
     3: body top = 'int ptop() { printf("TOP\\n"); return 1; }';
     4: body 'int top = ptop();' requires top;
     5: 
     6: proc f() {
     7:   body pf = 'int pf(){ printf("f used\\n"); return 1;}';
     8:   body 'int x = pf();' requires pf;
     9:   print "Using f"; endl;
    10: }
    11: 
    12: module A {
    13:   body p = 'int p() { printf("A will be used\\n"); return 1;}';
    14:   body 'int y = p();' requires p;
    15:   proc f: unit = 'printf("A is used\\n");';
    16: }
    17: 
    18: module B {
    19:   body p = 'int p() { printf("B will be used\\n"); return 1;}';
    20:   body 'int y = p();' requires p;
    21:   proc f: unit = 'printf("B is used\\n");';
    22: }
    23: 
    24: A::f();
    25: print "Done"; endl;
    26: // B is not used .. (would cause y,p to be defined twice)
    27: 
End C++ section to tut/examples/tut_bind138a.flx[1]
Here you can see that insertions can be given literally too:
Start C++ section to tut/examples/tut_bind138b.flx[1 /1 ]
     1: 
     2: proc f: 1 = 'printf("A is used\\n");'
     3:   requires header '#include <stdio.h>';
     4: 
     5: f();
     6: 
End C++ section to tut/examples/tut_bind138b.flx[1]
Here's an example demonstrating polymorphic insertions.
Start C++ section to tut/examples/tut_bind138c.flx[1 /1 ]
     1: pod type int="int";
     2: pod type double="double";
     3: 
     4: body prb[t] = "void pr(?1 x) { std::cout << x << std::endl; }"
     5:   requires header "#include <iostream>";
     6: 
     7: proc pr[t]:t = "pr($1);" requires prb[t];
     8: pr 1; pr 1.1;
     9: 
End C++ section to tut/examples/tut_bind138c.flx[1]