A couple of weeks ago I was working on a small program that required generating code in different ways depending on a user option. I was trying to make as few changes as possible. Because of the way the program was created and the language it was written in (not *OCaml*), it required changing several places in the code.

### OCaml functors

I remembered reading a little bit about the concept of a functor in OCaml. Functors are a powerful mechanism that allow you to create modules parameterized by modules. In the case of the task I was working on, I can use it to write the code generation section using module parameterized by a module that provides the final implementation of the code generation.

### The example: Code generation via method calls or operators

I’m going to use a simple example of using a *functor*. Say that we have a representation for a *very* simple language:

```
(* ast.ml *)
type expr =
| Plus of expr * expr
| Minus of expr * expr
| Div of expr * expr
| Times of expr * expr
| Call of expr * (expr list)
| Var of string
| Dot of expr * string
```

I want to have the posibility of generating arithmetic expressions in this language in two ways:

- Generating method calls of arithmetic operations for a Java-like language
- Generate common operators

One example of option #1 is:

`var1.multiply(10).plus(var2)`

For option #2 is:

`var1 * 10 + var2`

The code that generates the expressions must not be aware of the strategy that we are using to generate the code. To do this in OCaml we define a signature for the module used to generate the code:

```
module type GeneratorFuncs = sig
val (+) : Ast.expr -> Ast.expr -> Ast.expr
val (-) : Ast.expr -> Ast.expr -> Ast.expr
val (/) : Ast.expr -> Ast.expr -> Ast.expr
val ( * ) : Ast.expr -> Ast.expr -> Ast.expr
end
```

We use operators to make it easy to write the code generation. The module that makes the code generator is written as a functor with a parameter that is the module which implements the `GeneratorFuncs`

signature.

The following code shows the “generator” which generates random arithmetic expressions using the provided module for emitting the code:

```
module Make_generator(Current_funcs : GeneratorFuncs) = struct
let gen_single() =
if Random.int 10 > 5 then
Ast.Var "x"
else
Ast.Lit (1 + Random.int 5)
let rec generate_sample (depth: int) =
let new_depth = depth - 1 in
Current_funcs.(
match depth, Random.int 10 with
| 0, _ -> gen_single()
| _, r when r >= 0 && r <= 3 ->
((generate_sample new_depth) + (generate_sample new_depth))
| _, r when r >= 4 && r <= 6 ->
((generate_sample new_depth) - (generate_sample new_depth))
| _, r when r >= 7 && r <= 10 ->
((generate_sample new_depth) / (generate_sample new_depth))
| _, _ -> Ast.Var "x")
end
```

We can write our emitter for generating code using method calls like this:

```
(* mgenerator.ml *)
module MGenerator = struct
let simple_call (obj: Ast.expr) mmethod arg =
Ast.Call(
Ast.Dot(
obj,
mmethod), [arg])
let (+) (a: Ast.expr) (b: Ast.expr) = simple_call a "plus" b
let ( * ) a b = simple_call a "times" b
let (-) a b = simple_call a "minus" b
let (/) a b = simple_call a "div" b
end
module MGen = Generator.Make_generator(MGenerator)
```

An alternative module that generates arithmetic expression using operators:

```
module OGenerator = struct
let (+) (a: Ast.expr) (b: Ast.expr) = Ast.Plus(a, b)
let ( * ) a b = Ast.Times(a, b)
let (-) a b = Ast.Minus(a, b)
let (/) a b = Ast.Div(a, b)
end
module OGen = Generator.Make_generator(OGenerator)
```

We can use this modules to generate sample code snippets:

```
let main =
let _ = Random.self_init() in
in let generat = Mgenerator.MGen.generate_sample 3
in let generat2 = Ogenerator.OGen.generate_sample 3
in
print_endline (Ast.pprint_string generat);
print_endline (Ast.pprint_string generat2)
```

Output:

```
x.plus(2).plus(5.div(4)).div(x.plus(x).plus(5.div(1)))
x + 4 / x - 2 + 4 + x + 5 + x
```