© Jørgen Steensgaard-Madsen, Copenhagen, 2006
Illustration                                                  
 
   

This section reflects how to add an external definition for the semantics of a C-like for-statement. An internal definition could be:
demo> program {                                                
demo>   DEF for OF T(First:T,Cond(__:T):int,Next(__:T):T)      
demo>     [Body(__:T)]                                         
demo>     { induction(First) {                                 
demo>         if(Cond(this)){ Body(this); result(Next(this))}  
demo>         else {skip}                                      
demo>     } };                                                 
demo>                                                          
demo>   for i:(0,i<=10,i+2){ stdout << i << ~" "; };           
demo>   stdout << nl;                                          
demo> };                                                       
0 2 4 6 8 10 

Readers should compare the definitions and realise their common structure.
First a contribution directory with a Makefile and an appropriate file of signatures is defined. As a result we have:
> ( ls -a forstmt ; cat forstmt/.ulc )
./  ../  Makefile  .ulc
[for OF T(First:T,Cond(__:T):int,Next(__:T):T)[Body(__:T)[break]]]

The contents of the Makefile, without comments, is
> cat forstmt/Makefile | grep -v # | cat -b -s -
     1         ULCSYS = ulc_????
     2         PARTS  = operators types multiprogramming
     3         EXTRALL  = -lpthread
     4  BASELAN := $(shell (cd ..; pwd))
     5  include $(BASELAN)/makefile.include

Line 1 is crying for a test language name, line 2 suggests parts to include, line 3 illustrates that some contributions may require linking to additional libraries, and lines 4-5 are administrative information to make things easier. After modifications we get
> cat forstmt/Makefile | grep -v # | cat -b -s -
     1         ULCSYS = mytest
     2         PARTS  = operators types statements
     3         EXTRALL  = 
     4  BASELAN := $(shell (cd ..; pwd))
     5  include $(BASELAN)/makefile.include

Now it is possible to ask for a generated external definition for an empty semantics:
> cd forstmt; make incr ULCSIG=for
Now edit for_sem.c and call make

The contents of the generated file (after some manual compression) is shown in Figure 2.3. Manual modification leads to the final semantics shown in Figure 2.4. Readers are adviced to focus on the structure, since full explanations for all details are not provided.
When translated without errors interpreter ./mytest can be used. Inclusion into demo is straightforward for anyone familiar with make and Makefile.
Sometimes modifications involve changes in a signature - preferably so before release of a contribution. The Makefile in a contribution directory supports make update ULCSIG=for that generates a definition for an empty semantics in a file ./update.skel . In combination with a suitable version of the program diff this is useful to locate points where a previous definition for a non-empty semantics needs to be changed.
Instead of creating a new contribution directory, a contributor may add definitions to an existing one. In this case new signatures can be added to an existing .ulc file and make can be used as described above, in most cases without modifications.
When a contribution and its test language has been built, inspection of the development directory contains the following new files:
ID.ulc Signatures (etc.) for operations of the test language ID.
glue.c Interface to contributed external definitions.
glue.o The compiled version of glue.c
semantics.h Prototypes for external definitions in the test language.
libID... A library of the contribution's external definition.
types.h A link to types.h at the top level.
dispatch.c Implements a dispatch table for use in the test language.
dispatch.o The compiled version of dispatch.c
The interface routines rely on signatures to distinguish call-by-value from call-by-name arguments. It is a matter of taste whether these belong to dulce proper, or to the semantics.
Figure 3: External definition of semantics of for

#include "semantics.h"

  /************************************************************
   *      for OF T(First:T,Cond(__:T):int,Next(__:T):T)
   *        [Body(__:T)
   *          [break]]
   ************************************************************/

  #define T_ptr void*
  #define for_clauses \
    typedef void (*for_Cond)(T_ptr,CONTINUATION);\
    typedef void (*for_Next)(T_ptr,CONTINUATION);\
    typedef void (*for_Body)(T_ptr,void break_sem());\
  
for_clauses
  
void for_sem(typeinf T_inf,
             T_ptr First_sem,
             for_Cond Cond_sem,
             for_Next Next_sem,
             for_Body Body_sem) 
{ 

  #undef T_ptr
  TYPE(T);

  /*  Redefine the prototypes so that casts will work  */
  for_clauses
  #undef for_clauses

  void break_sem() { }

  //  Definition of the semantics of for

    /* Suggested: ((for_Cond)Cond_sem)(___sem,Return); */

    /* Suggested: ((for_Next)Next_sem)(___sem,Return); */

    /* Suggested: ((for_Body)Body_sem)(___sem,break_sem); */

}


Figure 4: Final semantics of for

#include "semantics.h"
  /************************************************************
   *      for OF T(First:T,Cond(__:T):int,Next(__:T):T)
   *        [Body(__:T)
   *          [break]]
   ************************************************************/
  #define T_ptr void*
  #define for_clauses \
    typedef void (*for_Cond)(T_ptr,CONTINUATION);\
    typedef void (*for_Next)(T_ptr,CONTINUATION);\
    typedef void (*for_Body)(T_ptr,void break_sem());\

for_clauses
  
void for_sem(typeinf T_inf,
             T_ptr First_sem,
             for_Cond Cond_sem,
             for_Next Next_sem,
             for_Body Body_sem) 
{ 
  __label__ out;     // not to advocate use of labels !
  #undef T_ptr
  TYPE(T);           // defines T_type and T_ptr from T_inf

  /*  Redefine the prototypes so that casts will work  */
  for_clauses
  #undef for_clauses

  void break_sem() { goto out; }   // GNU C supports locals!

  T_type x;
  int more;
  x = *(T_ptr)First_sem;           // a cast is required
                                   // CVAL is some macro:
  ((for_Cond)Cond_sem)(&x,CVAL(int,more));     // more := Cond;
  while (more) {
    ((for_Body)Body_sem)(&x,break_sem);        // Body(x,break);
    ((for_Next)Next_sem)(&x,CVAL(T_type,x));   // x := Next(x);
    ((for_Cond)Cond_sem)(&x,CVAL(int,more));   // more := Cond;
  }
  out:;
}



Contents

Demo language
·Implementation tool
Copyrights


Introduction
Principles
·Interpreter construction


Contribution directory
Make commands
Semantics
·Illustration
Auxiliary files
Toplevel files
Reference
Download
Appendices



File translated from TEX by TTH, version 3.33.
On 18 Oct 2006, 16:47.
SourceForge.net Logo