Next Previous Contents

5. Views

Views provide a general mechanism to customize the output of asdlGen. Views allow description writers to annotate modules, constructors, and types with directives or properties that are interpreted by asdlGen. Currently asdlGen properties that allow for the

5.1 Interpretation of View Entry Values

See the section on Input Syntax for details on view the syntax and some basic view terminology. The view syntax associates an arbitrary string whose interpretation depends on the property it is assigned too. Currently there is a small set of standard interpretations.

integer

An integral number in decimal notation.

string

A raw string.

boolean

A boolean value either "true" or "false".

qualified identifier

A possibly qualified identifier. For example "M.t" or "t". Qualified identifiers are language independent identifiers that are translated to the appropriate output language in a uniform way. For example M.t would appear as M_t in C and C++ but remain M.t in SML, Java, and Haskell.

5.2 Adding User Code

It is useful to be able to add arbitrary user code to the modules produced by asdlGen. Modules have six properties that can be set to allow the addition of user code. strings.

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.

suppress

Default value is false. Do not produce any code for this module, assume it's implementation is written by hand. It's often a good idea to first generate code and then set the flag, so the generated code can be used as stubs for the user implementation.

is_library

Default value is false. If true assume all types can be used as lists or options and generate any needed code, rather then generating list and option code on demand. Useful for generating stubs.

The precise meaning of interface and implementation for the different languages is as follows

C

The interface is the .h file and the implementation is the .c file.

C++

The interface is the .hxx file and the implementation is the .cxx file.

Java

Java has no notion of interfaces so this property is ignored. The implementation_prologue is placed outside the class definition of a Java class that contains package wide global constants. The implementation_epilogue is placed inside the class definition of a Java class that contains package wide global constants.

ML

The interface is the generated signature the implementation is the structure.

Haskell

The interface is the export list of the module. The implementation is the module body.

5.3 Other Properties

doc_string

All entities have this property. Its value is interpreted as a string. Currently only the --doc command recognizes the property. It includes the property value in the HTML documentation produced for the module.

source_name

All entities have this property. The value is interpreted as a string. Choose a different name for the type constructor or module in the output code. The name has no case restrictions. This is particularly useful when producing Java code on Windows NT/95 since the file system is case insensitive and types and constructors that differ only in case will cause problems.

user_attribute

Property of types only. The value is interpreted as a qualified identifier. Add a field called client_data as an attribute to the type. The value is the qualified identifier that represents an arbitrary user type of the field. The client_data field is ignored by the pickling code and does not appear in constructors. This property is currently only recognized when outputting C.

user_init

Property of types only. The value is interpreted as a qualified identifier. Call the function specified by the value before returning a the data structure created by a constructor function. This property is currently only recognized when outputting C.

base_class

Property of types only. The value is interpreted as a qualified identifier. The name of the class from which all classes generated for that type should inherit from. This property is recognized only when outputting C++ and Java.

reader

Property of types only. The value is interpreted as a qualified identifier. Replace the body of the read pickle function for this type with a call to a function with the proper arguments.

writer

Property of types only. The value is interpreted as a qualified identifier. Replace the body of the writer pickle function for this type with a call to a function with the proper arguments.

enum_value

Property of constructors only. The value is interpreted as an integer. Use this integer value as the internal tag value for the constructor. The external pickle tag remains unchanged. This property is recognized only when outputting C, C++, and Java.

5.4 Choosing a Different Representation

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. If we decided to change the implementation of int_maps to use a hash table the all other clients that use our type will have to be updated.

The view properties natural_type, natural_type_con, wrapper, and unwrapper provide a general mechanism to choose a different more efficient representation through coercion functions. All of these properties apply to types only and are interpreted as qualified identifiers.

natural_type

The type to use in place of the original type in all the resulting code. Supported by all output languages.

natural_type_con

A unary type constructor to apply to the old type to get a new type to use in all the resulting code. e.g. ref in ML to make a type mutable. Supported by ML and Haskell. Support for C++ templates will be added in the near future.

wrapper

A function to convert the new type to the old type when writing the pickle. Supported by all output languages.

unwrapper

A function to convert the old type to the new type when reading the pickle. Supported by all output languages.

When using natural_type and natural_type_con the automatically generated type definitions for the original type still remain, but all other references to the original type in constructors, picklers, and other type definitions that referred to it are replaced with the new type. The original definition must remain to support pickling of the type. Pickling is achieved by appropriately coercing the new type to the old type and vice versa with functions specified by wrapper and unwrapper properties.

Examples

Need more examples

module Slp {

 real = (int mantissa, int exp)
...
  exp = Id(identifier id)
      | Num(int v)
      | Op(exp lexp,binop?,exp rexp)
       attributes (real? value) 
...

}

view C {

-- represent reals as a double

  Slp.exp <= {
   natural_type : my_real
   wrapper      : real2my_real
   unwrapper    : my_real2real
  }
  
  module Slp <= {
  interface_epilogue : typedef double my_real_ty
  
  implementation_prologue
%%
  my_real_ty real2my_real(Slp_real_ty x) {
    /* hairy code to actually do this */
  }

  Slp_real_ty my_real2real(my_real_ty x) {
    /* hairy code to actually do this */
  }
%% 
  } 
}

view SML {
   -- unpickle exp trees as a mutable type
    Slp.exp <= {
       natural_type_con : ref
       wrapper          : !
       unwrapper        : ref
    }

}


Next Previous Contents