From: Masoud Pirnazar
Subject: compile-time calculation
Date: 
Message-ID: <38F26691.77F7F4C2@poboxes.com>
I have (defun compile-frame (frame-as-cons) ...) which takes a list
formatted as a property-list and returns an object of class mt-prop
(internally, it could be hash tables or other data structures).

Using (compile-frame '(part-of-speech verb    form "book"    tense
past)) in a program causes the list to be converted to an mt-prop at
runtime.  I'd like to do this at compile-time, somewhat the way (quote
...) can give an already-prepared list.

So (quote-frame '(part-of-speech verb    form "book"    tense past))
should return an object of type mt-prop.

The only way I can think of doing this is with
(defmacro quote-frame (frame-as-cons)
  (let (a (gensym))
    (setf (symbol-value a) (compile-frame frame-as-cons))
    (symbol-name a)))
i.e. create a new symbol, compile the value and assign it to the symbol,
then return the symbol's name from the macro.

(a bad side effect of this is while in a lisp session, if I re-evaluate
a function several times, new symbols are created for it, and the old
ones just accumulate).
1. Are there other flaws in this method?
2. Will this method work even if I compile my main programs?
3. Does anyone have other methods of doing this?

From: Joe Marshall
Subject: Re: compile-time calculation
Date: 
Message-ID: <uk8i5jx5z.fsf@alum.mit.edu>
Masoud Pirnazar <··········@poboxes.com> writes:

> I have (defun compile-frame (frame-as-cons) ...) which takes a list
> formatted as a property-list and returns an object of class mt-prop
> (internally, it could be hash tables or other data structures).
> 
> Using (compile-frame '(part-of-speech verb    form "book"    tense
> past)) in a program causes the list to be converted to an mt-prop at
> runtime.  I'd like to do this at compile-time, somewhat the way (quote
> ...) can give an already-prepared list.
> 
> So (quote-frame '(part-of-speech verb    form "book"    tense past))
> should return an object of type mt-prop.
> 
> The only way I can think of doing this is with
> (defmacro quote-frame (frame-as-cons)
>   (let (a (gensym))
>     (setf (symbol-value a) (compile-frame frame-as-cons))
>     (symbol-name a)))
> i.e. create a new symbol, compile the value and assign it to the symbol,
> then return the symbol's name from the macro.
> 
> (a bad side effect of this is while in a lisp session, if I re-evaluate
> a function several times, new symbols are created for it, and the old
> ones just accumulate).
> 1. Are there other flaws in this method?

It won't work if you `dump' the compiled file.  QUOTE-FRAME, being a
macro, should return a lisp form.  In your example, it does, it
returns a literal string (the symbol name of a gensym).  If you were
to dump this out to a file, the literal string would be saved, but you 
wouldn't get your compiled frame dumped.

> 2. Will this method work even if I compile my main programs?

See above.

> 3. Does anyone have other methods of doing this?

There are a couple of ways I can think of doing this.  You could
output a call to the constructor for MT-PROP objects:

(defmacro quote-frame (frame-as-cons)
  (let ((compiled (compile-frame frame-as-cons)))
    `(MAKE-INSTANCE 'MT-CLASS :slot-a ,(mt-class-slot-a compiled)
                              :slot-b ,(mt-class-slot-b compiled))))

If MT-PROP has a CREATE-LOAD-FORM method, then you should be able to
dump it directly:

(defmacro quote-frame (frame-as-cons)
  (let ((compiled (compile-frame frame-as-cons)))
    `(QUOTE ,compiled)))
From: Phil Stubblefield
Subject: Re: compile-time calculation
Date: 
Message-ID: <38F4DE06.BDC5013D@rpal.rockwell.com>
Masoud Pirnazar <··········@poboxes.com> wrote:
> 
> I have (defun compile-frame (frame-as-cons) ...) which takes a list
> formatted as a property-list and returns an object of class mt-prop
> (internally, it could be hash tables or other data structures).
> 
> Using (compile-frame '(part-of-speech verb form "book" tense past))
> in a program causes the list to be converted to an mt-prop at
> runtime.  I'd like to do this at compile-time, somewhat the way
> (quote ...) can give an already-prepared list.
> 
> [snipped...]

Look at DEFINE-COMPILER-MACRO, MAKE-LOAD-FORM, and LOAD-TIME-VALUE.

Are the compiled frames stored in such a way that they can be looked
up using a unique ID?  If so, then the following idea may work.
First, define a compiler macro that performs the frame compilation at
compile-time when the argument is a constant.  Don't forget that the
file compiler will call MAKE-LOAD-FORM to determine how to write the
resulting MT-PROP object to a file, so you must also define a method
for MAKE-LOAD-FORM specialized on MT-PROP.

(define-compiler-macro compile-frame (&whole form frame-as-cons)
  "Compiles a constant frame at run-time."
  (if (constantp frame-as-cons)
      (compile-frame (eval frame-as-cons))
    form))

(defmethod make-load-form ((mt-prop mt-prop) &optional environment)
  "Returns a form that performs the lookup at load-time."
  (declare (ignore environment))
  `(find-mt-prop ,(unique-id mt-prop)))

OTOH, you may want a compiler macro that just wraps LOAD-TIME-VALUE
around the whole form when the argument is a constant:

(define-compiler-macro compile-frame (&whole form frame-as-cons)
  "Arranges for load-time evaluate if the frame is constant."
  (if (constantp frame-as-cons)
      ;; You can add T as a second argument here (READ-ONLY-P) if the
      ;; resulting object will never be modified.
      `(load-time-value ,form)
    form))

Any comments from the wizards on the relative merits and drawbacks of
these two approaches?


Phil Stubblefield
Rockwell Palo Alto Laboratory                               206/655-3204
http://www.rpal.rockwell.com/~phil                ····@rpal.rockwell.com