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
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.
An integral number in decimal notation.
A raw string.
A boolean value either "true
" or "false
".
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.
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
The interface is the .h
file and the implementation is the .c
file.
The interface is the .hxx
file and the implementation is the .cxx
file.
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.
The interface is the generated signature the implementation is the structure.
The interface is the export list of the module. The implementation is the module body.
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.
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.
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
}
}