> In other words magically turning desired-non-globally-accessible
> function calls into LABELS:
Here's a bare and manual version of the functionality:
(defpackage :model1
(:use)
#.`(:import-from :cl
,@(let (list)
(do-external-symbols (symbol :cl)
(unless (eq symbol 'defun) (push symbol list)))
list)))
(in-package model1)
(defmacro defun (name lambda-list &body body)
`(eval-when (:compile-toplevel)
(cl:defun ,name ,lambda-list ,@body)
(setf (get 'source ',name) '(,name ,lambda-list ,@body))))
(defmacro insert-labels (functions &rest args)
`(labels ,(loop for fn in functions collect (get 'source fn))
,@args))
;;--------------------
;;Standard code begins
;;--------------------
(defun fn-call (float)
(sqrt float))
(defun api ()
(insert-labels (fn-call)
(loop for i of-type (double-float 0d0)
from 0d0 to 100000000d0
sum (fn-call i) of-type double-float)))
The source code to each global function definition is seamlessly
stored using a custom DEFUN (which is why this symbol isn't imported from
:COMMON-LISP). The INSERT-LABELS macro allows each global function's
source to be easily inserted as a local function. By definition the
innermost FLET or LABELS forms override references to a global function
definition of the same name. Thus the cost of making a global function
call is avoided.
I haven't quite understood why adding this to the start of the source...
(eval-when (:compile-toplevel :load-toplevel :execute)
(declaim (optimize (safety 0) (speed 3))))
...appears to not affect compilation. I have to type (declaim (optimize
(safety 0) (speed 3))) into the REPL before compilation for optimisation
notes to start appearing.
This exploratory work indicates that an ANSI-conforming and user-friendly
type of block compilation is feasible.
Regards,
Adam
|