There is now a little bit of support for static meta-programming in ATS2.
Say we have a datatype declared as follows:
datatype abc = A of () | B of (int) | C of (abc, abc)
The function for printing out values of the type ‘abc’ is declared as
follows:
extern fun fprint_abc : (FILEref, abc) -> void
Instead of implementing ‘fprint_abc’ directly, one can write the following
line to indicate to the compiler that the code for fprint_abc is to be
generated
automatically:
#codegen2(fprint, abc, fprint_abc)
Because ‘abc’ is defined recursively, the following line needs to be
added to make the generated code work:
implement
fprint_abc$carg (out, x) = fprint_abc<>(out, x)
Please find more details in
The generated code is listed as follows, which is template-based and allows
for easy adaptation
through template re-implementation:
(* ****** ****** )
//
extern
fun{}
fprint_abc$A: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$B: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$C: $d2ctype(fprint_abc<>)
//
( ****** ****** )
//
implement{}
fprint_abc
(out, arg0) =
(
case+ arg0 of
| A _ => fprint_abc$A<>(out, arg0)
| B _ => fprint_abc$B<>(out, arg0)
| C _ => fprint_abc$C<>(out, arg0)
)
//
( ****** ****** )
//
extern
fun{}
fprint_abc$sep: (FILEref) -> void
implement{}
fprint_abc$sep(out) = fprint(out, “,”)
//
extern
fun{}
fprint_abc$lpar: (FILEref) -> void
implement{}
fprint_abc$lpar(out) = fprint(out, “(”)
//
extern
fun{}
fprint_abc$rpar: (FILEref) -> void
implement{}
fprint_abc$rpar(out) = fprint(out, “)”)
//
extern
fun{a:t0p}
fprint_abc$carg: (FILEref, INV(a)) -> void
implement{a}
fprint_abc$carg(out, arg) = fprint_val(out, arg)
//
( ****** ****** *)
ile Edit Options Buffers Tools Help
//
extern
fun{}
fprint_abc$A$con: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$A$lpar: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$A$rpar: $d2ctype(fprint_abc<>)
//
implement{}
fprint_abc$A(out, arg0) =
{
//
val () = fprint_abc$A$con<>(out, arg0)
val () = fprint_abc$A$lpar<>(out, arg0)
val () = fprint_abc$A$rpar<>(out, arg0)
//
}
implement{}
fprint_abc$A$con(out, _) = fprint(out, “A”)
implement{}
fprint_abc$A$lpar(out, _) = fprint_abc$lpar(out)
implement{}
fprint_abc$A$rpar(out, _) = fprint_abc$rpar(out)
//
extern
fun{}
fprint_abc$B$con: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$B$lpar: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$B$rpar: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$B$arg1: $d2ctype(fprint_abc<>)
//
implement{}
fprint_abc$B(out, arg0) =
{
//
val () = fprint_abc$B$con<>(out, arg0)
val () = fprint_abc$B$lpar<>(out, arg0)
val () = fprint_abc$B$arg1<>(out, arg0)
val () = fprint_abc$B$rpar<>(out, arg0)
//
}
implement{}
fprint_abc$B$con(out, _) = fprint(out, “B”)
implement{}
fprint_abc$B$lpar(out, _) = fprint_abc$lpar(out)
implement{}
fprint_abc$B$rpar(out, _) = fprint_abc$rpar(out)
implement{}
fprint_abc$B$arg1(out, arg0) =
let val-B(arg1) = arg0 in fprint_abc$carg(out, arg1) end
//
extern
fun{}
fprint_abc$C$con: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$C$lpar: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$C$rpar: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$C$sep1: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$C$arg1: $d2ctype(fprint_abc<>)
extern
fun{}
fprint_abc$C$arg2: $d2ctype(fprint_abc<>)
//
implement{}
fprint_abc$C(out, arg0) =
{
//
val () = fprint_abc$C$con<>(out, arg0)
val () = fprint_abc$C$lpar<>(out, arg0)
val () = fprint_abc$C$arg1<>(out, arg0)
val () = fprint_abc$C$sep1<>(out, arg0)
val () = fprint_abc$C$arg2<>(out, arg0)
val () = fprint_abc$C$rpar<>(out, arg0)
//
}
implement{}
fprint_abc$C$con(out, _) = fprint(out, “C”)
implement{}
fprint_abc$C$lpar(out, _) = fprint_abc$lpar(out)
implement{}
fprint_abc$C$rpar(out, _) = fprint_abc$rpar(out)
implement{}
fprint_abc$C$sep1(out, _) = fprint_abc$sep<>(out)
implement{}
fprint_abc$C$arg1(out, arg0) =
let val-C(arg1, ) = arg0 in fprint_abc$carg(out, arg1) end
implement{}
fprint_abc$C$arg2(out, arg0) =
let val-C(, arg2) = arg0 in fprint_abc$carg(out, arg2) end
//
(* ****** ****** *)