Skip to topic | Skip to bottom
Home
Projects
Projects.MetaGeneTranslationr1.6 - 26 Nov 2003 - 14:39 - FrancisMaes?topic end

Start of topic | Skip to actions
This page presents Metagene translation rules. Some implementation details are not detailed, but the core of the Metagene translator is here presented. This translator is made of two parts: the core program (written in OCaml with the help of Camlp4) and a set of C++ headers which declares all utility classes used by Metagene generated code. Three main kind of constructs are detailed here: Expressions, Patterns (used in pattern matching and function declarations) and Types.

Expressions

Due to complexity of the C++ grammar related to class templates manipulation, nested expression are first splitted into a set of simple expressions. This fist step can be seen as syntaxic sugar. For example, let f = compose (plus 1) (times 10) is transformed into

let rec temp1 = plus 1 
    and temp2 = times 10
    and temp3 = compose temp1 temp2
    and f = temp3

So, Metagene only processes expressions of type: let name = a_simple_expression.

Type constructors

  • Integer: (let name = ) intvalue
typedef mtg :: Int < intvalue >    name;

// with mtg :: Int defined as
template<int N>
struct Int {
  enum {value = N};
};

  • Char: (let name = ) charvalue
typedef mtg :: Char < charvalue >    name;

//with mtg :: Char defined as
template<char C>
struct Char {
  static const char value = C;
};

  • String: charlist
[translation as static list of characters with mtg :: ES_ the empty list and mtg :: S_ a non empty list]
[ex: "AB" becomes mtg :: S_< mtg :: Char<'A'>, mtg :: S_< mtg :: Char<'B'>, mtg :: ES_ > > ]

// with mtg :: ES_ and mtg :: S_ defined as:
struct ES_ {};
template<typename hd, typename tl>
struct S_ {};

  • Type constructor: Constructor ( arguments )
[translate arguments with unique names]
typedef Constructor< [arguments unique names] >  name;
OCaml pervasives type constructors are translated as Metagene pervasives type constructors:
()    -> mtg :: Unit
[]    -> mtg :: EmptyList
::    -> mtg :: List
True  -> mtg :: true_
False -> mtg :: false_

  • Tuple constructor: ( arguments )
[translate arguments with unique names]
[translate tuple as a static list of arguments with mtg :: EmptyTuple and mtg :: Tuple]

// with mtg :: EmptyTuple and mtg :: Tuple defined as:
struct EmptyTuple {};
template<typename hd, typename tl = EmptyTuple>
struct Tuple {};

Scopes, functions and pattern matchings

  • Pattern matching: match var with patternlist is seen as (function patternlist) var.

  • Function declaration: function patternlist
[Case 1: Only one pattern in patternlist: function x -> expr]
struct name {
  template<typename x>
  struct value {
    [translate expr as "res"]
  };
};

[Case 2: Multiple patterns with a default case: function x -> defexpr | pattern1 -> expr1 | pattern2 -> expr2 ...]
struct name {
  template<typename x, class _Nil = mtg::nil>
  struct value {
    [translate defexpr as "res"]
  };
  template<[translate pattern1 params], class _Nil>
  struct value< [translate pattern1 spec], _Nil > {
    [translate expr1 as "res"]
  };
  template<[translate pattern2 params], class _Nil>
  struct value< [translate pattern2 spec], _Nil > {
    [translate expr2 as "res"]
  };
  ...
};

[Case 3: Multiple patterns without default case]
struct name {
  template<typename x, class _Nil = mtg::nil>
  struct value {
    // res should never be accessed in this version of the template specialization.
  };
  template<[translate pattern1 params], class _Nil>
  struct value< [translate pattern1 spec], _Nil > {
    [translate expr1 as "res"]
  };
  ...  
};
C++ doesn't allow template total specialization in structures, therefore we use only partial specialization thanks to mtg :: nil. (See Horror Show). Each pattern is translated into two parts: parameters and specialization. This is detailed in the section concerning patterns.

  • Function application: function argument
typedef [typename] function :: value< argument > :: res    name;
The keywork typename is used when we are inside a class template. If we are inside a struct it is not used. OCaml pervasives functions are translated as Metagene pervasives functions. All this functions are implemented in Metagene core headers. They correspond to simple well known C++ Metaprograms.
=       -> mtg :: equal
<>      -> mtg :: notequal
==      -> mtg :: eq
!=      -> mtg :: noteq
<       -> mtg :: lessthan
>       -> mtg :: greaterthan
<=      -> mtg :: lessequal
>=      -> mtg :: greaterequal
compare -> mtg :: compare
+       -> mtg :: addint
-       -> mtg :: subint
*       -> mtg :: mulint
/       -> mtg :: divint
~-      -> mtg :: negint
not     -> mtg :: boolnot
or      -> mtg :: sequor
||      -> mtg :: sequor
&&      -> mtg :: sequand
@       -> mtg :: appendlist
^       -> mtg :: concatstr

  • Let-In declaration: let [rec] decls in expr (seen as let [rec] decls in (let res = expr))
struct [unique_id] {
  [translate decls as their own id]
  [translate expr as "res"]
};
typedef [unique_id] :: res    name;

C++ constructs seen as values

  • C++ Type: <@ cxxtype @>
typedef cxxtype    name;

  • C++ Primitive: <@@ arguments @ returntype @ cxxcode @>
struct name {
  static returntype value(arguments) {
    cxxcode
  }
};

Miscellaneous

  • If-Then-Else: if condition then trueexpr else falseexpr
typedef mtg :: if_<condition, trueexpr, falseexpr>::res  name;

// with mtg :: if_ defined as
template<typename condition, typename trueexpr, typename falseexpr>
struct if_ {
  typedef falseexpr res;
};
template<typename trueexpr, typename falseexpr>
struct if_<true_, trueexpr, falseexpr> {
  typedef trueexpr res;
};

  • Module access: Module . id
typedef Module :: id    name;

Patterns

As seen in the translation of functions and pattern matching, each pattern is translated into two parts: parameters and specialization.

Simple patterns

  • Simple Identifier: x
parameters: x
specialization: x

// which give us:
template<typename x, class _Nil>
struct value< x, _Nil > {
  // ...
};

  • Integer: intvalue
parameters: [none]
specialization: mtg :: Int < intvalue >

// which give us:
template<class _Nil>
struct value< mtg :: Int < intvalue >, _Nil > {
  // ...
};

  • Character: charvalue
parameters: [none]
specialization: mtg :: Char < charvalue >

  • String: charlist
parameters: [none]
specialization: [static list of characters, see String Expression]

  • Type constructor: Constructor ( arguments )
parameters: [all parameters of arguments]
specialization: Constructor< [arguments specialization] >

  • Tuple: ( arguments )
parameters: [all parameters of arguments]
specialization: [static list of arguments, see Tuple Expression]

C++ constructs

  • C++ type: <@ cxxtype @>
parameters: [none]
specialization: cxxtype

  • C++ Primitive: <@@ arguments @ returntype @ cxxcode @>
Error: A primitive cannot be matched.

Miscellaneous

  • Pattern Alias: pattern as alias
parameters: [pattern parameters]
specialization: [pattern specialization]

// The alias is handled with a typedef inside the class template specialization:
typedef [pattern specialization]  alias;

Types

Metagene is a typed language whereas the C++ generated meta-code is not. Therefore most of type informations are simply ignored. We only generate empty template and non-template in order to support Variant types. This is required to express Constructor Expressions.

Example: type 'a list = EmptyList? | List of 'a * 'a list

struct EmptyList {};
template<typename T1, typename T2>
struct List {};

Another example: type choice = Yes | No | Maybe

struct Yes {};
struct No {};
struct Maybe {};

This corresponds to a common C++ metaprogramming trick.

-- FrancisMaes? - 26 Nov 2003


MetaGeneZone


to top

You are here: Projects > MetaGeneExamples > MetaGeneTranslation

to top

Copyright © 1999-2010 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback