Introduction

module IntMap {
  int_map = (int size,entries map)
  entries = (entry* entries)
  entry = (int key, int value)
}
The above is one possible abstract description of a mapping from integers to integers. It would be more efficient to implement such a mapping as a binary tree. Described as with the ASDL definition below.
module IntMap {
  int_map = (size int,map tree)
  tree = Node(int key,int value,tree left,tree right)
       | Empty
}

Although this is a much more efficient representation it exposes implementation details in the pickle. If we decided to change the implementation of int_maps to use a hash table the underlying pickle format will change too, and all other clients that use our pickles will have to be updated.

Views let you write the first version so you get a simple and abstract representation on the disk, while letting you choose a different efficient in-core representation. They do this by letting the user control how asdlGen converts the description of a module into an actual implementation.

Syntax

Here's the view syntax in EBNF. This is all a hack right now the syntax is likely to change.
view       = "view" id "{" {view_entry} "}"
view_entry = id "." {id} "<=" id lit_txt
           | "module" id "<=" id lit_txt
where lit_txt is either a ":" followed by some arbitrary text that continues to the end of the line or a "%%" balanced by a "%%" at the beginning of a line. The lit_txt is then passed to another internal parser that interprets the string based on the property name. This is a hack to make the view mechanism extendible without changing the grammar.

Example

module IntMap {
  int_map = (int size,entries map)
  entries = (entry* entries)
  entry = (int key, int value)
}
view C {

  IntMap.entries <= natural_type          : Bst.bst
  IntMap.entries <= wrapper               : entries2bst
  IntMap.entries <= unwrapper             : bst2entries
  module  IntMap <= interface_prologue    
%%
#include "bst.h"
%%

  module  IntMap <= implementation_prologue
%%
  /* proto_types for wrapper functions */
  static entries2bst(IntMap_entries_ty x) {
    /* code to convert int_map to a bst */ 
 }

  static IntMap_entries_ty bst2entries(Bst_bst_ty x) {
 /* code to convert bst to an int map */
 }
%%
}

view C_with_HT {

  IntMap.entries <= natural_type          : Ht.ht
  IntMap.entries <= wrapper               : entries2ht
  IntMap.entries <= unwrapper             : ht2entries
  module IntMap  <= interface_prologue    : #include "ht.h"
  module IntMap  <= implementation_prologue 
%%
 /* ... */
%%
}

Views like modules are named. In this example we have two different views named C and C_with_HT. By default when translating a module asdlGen looks for a language specific view depending on the type of output code. When asdlGen is invoked with --lang it looks for the viewed named Lang. The default view can be overridden with the --view command line.

N.B. Currently only the C and SML translators do anything interesting with the view data.

Views contain entries of the form

entity <= property_name value
Entities name either an ASDL type, constructor, or module. Some entries are language independent others are language dependent. You can have many views with the same name. The entries of two views with the same name are merged and consists of the union of the entries in both. If two views name the same entity, it is an error. Currently I don't check for this so you randomly get one or the other.

It is illegal to name an ASDL base type as an entity. e.g.

int <= ...
This restriction maybe removed in the future.

For example natural_type is a property that is a language independent identifier which names the type identifier which describes the in-core type to use in place of entries. In the first view it refers to the type bst which lives in a Bst module. It is mangled so that it appears in the C code as Bst_bst_ty. Using the standard ASDL mangling conventions.

The module properties interface_prologue and implementation_prologue are language dependent since they allow the literal inclusion of arbitrary user defined code in the output. In future there will be better support to split the language dependent and independent parts of views, as well as support to inherit or import entries from other views.

Running asdlGen on the above code produces IntMap.h and IntMap.c. Notice how the definition for the entries type is not completely removed. You need this type definition in order to write the conversion functions. Everywhere there normally would have been a IntMap_entires_ty type there now is the user type Bst_bst_ty. For example there is still a constructor prototype and constructor for IntMap_entries_ty. But the IntMap_int_map constructor now expects an argument of type Bst_bst_ty. The structs also reflect this.

IntMap_entries_ty IntMap_entries(IntMap_entry_list_ty entries);
IntMap_int_map_ty IntMap_int_map(int_ty size, Bst_bst_ty map); 
Notice also that the pickle functions now return and expect a Bst_bst_ty
Bst_bst_ty IntMap_read_entries(instream_ty s);
void IntMap_write_entries(Bst_bst_ty x, outstream_ty s);

The implementation of the pickle functions now also call the user supplied wrapper and unwrapper functions. The wrapper and unwrapper function names are language independent identifiers. It just so happens they don't need to be mangled. Since they're also local to our implementation we don't qualify them.

Bst_bst_ty IntMap_read_entries(instream_ty s)
{
     Bst_bst_ty ret;
     ....
          tmp->entries = IntMap_read_entry_list(s);
          ret = bst2entries(tmp);
     return ret;
}

void IntMap_write_entries(Bst_bst_ty x, outstream_ty s)
{
    IntMap_entries_ty tmp;
    tmp = entries2bst(x);
    IntMap_write_entry_list(tmp->entries, s);
}

Properties of Entities

Constructors

enum_value
expects integer

Set the value of the enumeration produced in the code.


view C {
  Slp.Times <= enum_value : 1
  Slp.Plus  <= enum_value : 100
  Slp.Print <= enum_value : 5
}

Types

user_attribute
The type of the client_data user attribute added to a given type.
natural_type
A qualified identifier that names a type that describes the type to use in place of the ASDL type.
natural_type_con
A qualified identifier that names a type constructor that is applied to the default ASDL type to describes the type to use in place of the ASDL type.
wrapper
A qualified identifier that names a function that converts from the default ASDL type to a special type used in its place.
unwrapper
A qualified identifier that names a function that converts from a special in-core type to the default ASDL type.
user_reader
Identifier of function to call in order to implement a pickle reader in place of the default pickler code.
user_writer
Identifier of function to call in order to implement a pickle writer in place of the default pickler code.

Modules

interface_prologue
Include text verbatim after the introduction of the base environment, but before any type defined in the module interface.
interface_epilogue
Include text verbatim after all types defined in the module interface have been defined.
implementation_prologue
Include text verbatim after the introduction of the base environment, but before any other implementation code is defined.
implementation_epilogue
Include text verbatim after all definitions defined in the module implementation.

$Date: 1997/12/11 04:48:25 $