Supporting (static) meta-programming

I have already hinted a few times in this forum that I would like to
support certain forms of “meta-programming” for generating ATS source
code.

The first form I intend to support is what I call static meta-programming.

Essentially, the programmer is to be given access to some kind of internal
representation of abstract syntax trees (of ATS programs). This is more or
less like JS programmers having access to DOM trees. Then various sorts
of meta-programming tools can be written to generate ATS source code based
internal abstract syntax trees. For instance, a print function for a
declared datatype
can be automatically generated by applying such a tool.

Say we have the following datatype declaration:

datatype
tree0(a:t@ype) =
| tree0_nil of ()
| tree0_cons of (tree0(a), a, tree0(a))

Then we can expect to generate the following code automatically:

extern
fun
{a:t@ype}
fprint_tree0:fprint_type(tree0(a))
and
fprint_tree0_nil:fprint_type(tree0(a))
and
fprint_tree0_cons:fprint_type(tree0(a))

implement(a)
fprint_val<tree0(a)> = fprint_tree0

implement
{a}(tmp)
fprint_tree0(out, x) =
case+ x of
| tree0_nil _ => fprint_tree0_nil(out, x)
| tree0_cons _ => fprint_tree0_cons(out, x)

implement
{a}(tmp)
fprint_tree0_nil(out, x) =
{
//
val-tree0_nil() = x
val () = fprint(out, “tree0_nil”)
val () = fprint(out, “(”)
val () = fprint(out, “)”)
//
} (* end of [fprint_tree0_nil] *)

implement
{a}(tmp)
fprint_tree0_cons
(out, x0) =
{
//
val-tree0_cons(x1, x2, x3) = x0
//
val () = fprint(out, “tree0_cons”)
val () = fprint(out, “(”)
val () = fprint_tree0 (out, x1)
val () = fprint(out, ", ")
val () = fprint_val
(out, x2)
val () = fprint(out, ", ")
val () = fprint_tree0
(out, x3)
val () = fprint(out, “)”)
//
} (* end of [fprint_tree0_cons] *)

In most cases, we should try to generate function templates (instead of
functions). Doing so
can allow us to maximally take advantage of the support for extreme
late-binding of functions
in ATS. In this way, I would certainly hope to get something that is a
great deal more flexible
than type classes.

If you have ideas and suggestions, you are mostly welcome discuss them here.

Cheers!

Here is version that I have just worked out. The included use case
shows how the templates in the generated code can be re-implemented
(manually) to achieve desired functionalities:

extern
fun
{a:t0p}
fprint_tree0: (FILEref, tree0(a)) → void
and
fprint_tree0$beg : (FILEref, tree0(a)) → void
and
fprint_tree0$end : (FILEref, tree0(a)) → void
and
fprint_tree0$sep : (FILEref, tree0(a)) → void

(* ****** ****** *)

extern
fun
{a:t0p}
fprint_tree0_tree0_nil: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_nil$beg: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_nil$end: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_nil$sep: (FILEref, tree0(a)) → void

(* ****** ****** *)

extern
fun
{a:t0p}
fprint_tree0_tree0_cons: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_cons$beg: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_cons$end: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_cons$sep: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_cons$sep1: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_cons$sep2: (FILEref, tree0(a)) → void
and
fprint_tree0_tree0_cons$arg1: (FILEref, tree0(a), tree0(a)) → void
and
fprint_tree0_tree0_cons$arg2: (FILEref, tree0(a), a) → void
and
fprint_tree0_tree0_cons$arg3: (FILEref, tree0(a), tree0(a)) → void

(* ****** ****** *)

implement
{a}(tmp)
fprint_tree0_tree0_cons
(out, arg0) =
{
//
val-
tree0_cons
(carg1, carg2, carg3) = arg0
//
val () = fprint_tree0_tree0_cons$beg(out, arg0)
val () = fprint_tree0_tree0_cons$arg1(out, arg0, carg1)
val () = fprint_tree0_tree0_cons$sep1(out, arg0)
val () = fprint_tree0_tree0_cons$arg2(out, arg0, carg2)
val () = fprint_tree0_tree0_cons$sep2(out, arg0)
val () = fprint_tree0_tree0_cons$arg3(out, arg0, carg3)
val () = fprint_tree0_tree0_cons$end(out, arg0)
//
} (* end of [fprint_tree0_tree0_cons] *)

(* ****** ****** )
//
implement
{a}(tmp)
fprint_tree0_tree0_cons$beg = fprint_tree0$beg
implement
{a}(tmp)
fprint_tree0_tree0_cons$end = fprint_tree0$end

implement
{a}(tmp)
fprint_tree0_tree0_cons$sep = fprint_tree0$sep

implement
{a}(tmp)
fprint_tree0_tree0_cons$sep1 = fprint_tree0_tree0_cons$sep

implement
{a}(tmp)
fprint_tree0_tree0_cons$sep2 = fprint_tree0_tree0_cons$sep

//
implement
{a}(tmp)
fprint_tree0_tree0_cons$arg1(out, arg0, carg1) = fprint_tree0
(out, carg1
)
implement
{a}(tmp)
fprint_tree0_tree0_cons$arg2(out, arg0, carg2) = fprint_val
(out, carg2)
implement
{a}(tmp)
fprint_tree0_tree0_cons$arg3(out, arg0, carg3) = fprint_tree0
(out, carg3
)
//
(
****** ****** )
//
// HX: A use case is given below:
//
(
****** ****** )
//
implement
fprint_tree0_tree0_nil$beg (out, _) = fprint(out, “nil(”)
//
implement
{a}(tmp)
fprint_tree0_tree0_cons$beg (out, _) = fprint(out, “cons(”)
//
(
****** ****** *)

implement
{a}(tmp)
fprint_tree0$sep(out, _) = fprint(out, "; ")

(* ****** ****** )
//
val t0 = tree0_nil{int}()
val t1 = tree0_cons(t0, 1, t0)
val t2 = tree0_cons(t1, 2, t1)
val t3 = tree0_cons(t2, 3, t2)
//
(
****** ****** *)

val () = fprint(stdout_ref, “t3=”)
val () = fprint_tree0(stdout_ref, t3)
val () = fprint_newline(stdout_ref)

(* ****** ****** *)

implement main0 () = ()

(* ****** ****** *)On Monday, June 29, 2015 at 11:44:51 AM UTC-4, gmhwxi wrote:

By static meta-programming, I mean explicit generation of source code.
For instance, the code for fprint_tree0 is supposed to be generated by
issuing
the following command-line (or something similar):

patsrcgen -i tree0_dats.json --codespec
“tree0::traverse
fprint

At this stage, there is no plan (nor need) to modify/extend the syntax of
ATS.

On Monday, June 29, 2015 at 4:59:45 AM UTC-4, Kiwamu Okabe wrote:

Hi Hongwei,
It’s good news for me.

On Mon, Jun 29, 2015 at 6:59 AM, gmhwxi gmh...@gmail.com wrote:

Say we have the following datatype declaration:

datatype
tree0(a:t@ype) =
| tree0_nil of ()
| tree0_cons of (tree0(a), a, tree0(a))

Then we can expect to generate the following code automatically:

It seems like “deriving Show” on Haskell.
I think it’s useful.

And how about support following style?

Regards,

Kiwamu Okabe at METASEPI DESIGN

By static meta-programming, I mean explicit generation of source code.
For instance, the code for fprint_tree0 is supposed to be generated by
issuing
the following command-line (or something similar):

patsrcgen -i tree0_dats.json --codespec
“tree0::traversefprint

At this stage, there is no plan (nor need) to modify/extend the syntax of
ATS.On Monday, June 29, 2015 at 4:59:45 AM UTC-4, Kiwamu Okabe wrote:

Hi Hongwei,
It’s good news for me.

On Mon, Jun 29, 2015 at 6:59 AM, gmhwxi <gmh...@gmail.com <javascript:>> wrote:

Say we have the following datatype declaration:

datatype
tree0(a:t@ype) =
| tree0_nil of ()
| tree0_cons of (tree0(a), a, tree0(a))

Then we can expect to generate the following code automatically:

It seems like “deriving Show” on Haskell.
I think it’s useful.

And how about support following style?

Regards,

Kiwamu Okabe at METASEPI DESIGN