🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.functional
Article #945

Run-Time Code Generation ?

#945
From: Jan Roland Olsson
Date: Mon, 14 Dec 1992 15:27
81 lines
3068 bytes
Functions that return other functions are common in
functional programs. The function returned is created
at run-time and is in strict languages most often 
represented using closures. 

In my view, a closure consists of 

1. A pointer to the machine code for a function.
2. One or more pointers to "arguments" of the function.
   These arguments may be other closures.

It sometimes happens that the function returned is
represented by 10 or more closures pointing to each
other. If the function is not recursive, these closures
normally form a tree that is isomorphic to the
expression tree for the right hand side of the
function definition.

A recursive function may be represented by closures 
that form a directed cyclic graph, where the cycle
can be introduced with a pointer i.e. a value of
ref type in ML.

I have a program in Standard ML of New Jersey that
synthesizes, i.e. writes, function definitions and
translates them to closures in order to execute them.

This works fine except for the fact that the resulting
functions execute about twice as slowly as functions
that are defined by ML source code and compiled.
Since the functions created at run-time are needed
over and over again, perhaps even millions of times
including recursive calls, this is a significant
performance problem for me.
Here is a small trivial example that illustrates
the problem.


fun compose 0 F = ( fn X => X )
  | compose N F = 
      let val g = compose (N-1) F
      in
       fn X => F ( g X )
      end;


val f1 = compose 5 tl;

val f2 = fn X => tl(tl(tl(tl(tl(X)))));


The functions f1 and f2 are the same, but calls
to f1 execute much slower than calls to f2.

What I really would like to have is a built-in
function 

compile : ( 'a -> 'b ) -> ( 'a -> 'b )

which has the same semantics as the identity 
function, but changes the representation of the
definition of its argument from lots of inter-
linked closures to pure machine code.
Since Standard ML of New Jersey stores machine
code on the heap as garbage collectable byte
sequences and since the compiler is part of a
running ML program this seems possible.

Am I the only ML programmer on this planet that
finds such a function useful ?

Or maybe there are some drawbacks or solutions that
I have overlooked ?

Or maybe I should use Common Lisp instead, which after
all has compile built in ? Needing to switch to
Lisp just for a performance problem like this would
really be a pity, since ML in my view is a much
better language and since Standard ML of New Jersey 
is an excellent implementation.
Technical Details
Message-ID: <1992Dec14.152715.6442@ifi.uio.no>
Path: arc1-ca.pugleaf.net!sparky!uunet!mcsun!sunic!aun.uninett.no!nuug!ifi.uio.no!olsson

Show Full Headers
Complete Article Headers
Nntp-Posting-Host: hauken.ifi.uio.no
Newsgroups: comp.lang.functional
Path: arc1-ca.pugleaf.net!sparky!uunet!mcsun!sunic!aun.uninett.no!nuug!ifi.uio.no!olsson
From: olsson@ifi.uio.no (Jan Roland Olsson)
Subject: Run-Time Code Generation ?
Message-ID: <1992Dec14.152715.6442@ifi.uio.no>
Organization: Dept. of Informatics, University of Oslo, Norway
Date: Mon, 14 Dec 1992 15:27:15 GMT
Lines: 90
Originator: olsson@hauken.ifi.uio.no