From: Vladimir Zolotykh
Subject: Checking recursive calls
Date: 
Message-ID: <3F867C5D.9000900@eurocom.od.ua>
Hi,

Here is the definition of a rather simple WITH-TRANSACTION macro to be
used with Allegro Odbc.

   (defvar *transaction-level* 0)

   (defmacro with-transaction ((db) &body body)
     (let ((abort (gensym)))
       `(let ((,abort t)
	     (*transaction-level* (1+ *transaction-level*))
	     (dbi:*default-database* ,db))
	 (if (= 1 *transaction-level*)
	     (unwind-protect
		 (progn
		   (dbi:set-autocommit nil)
		   (multiple-value-prog1
		       (progn ,@body)
		     (mp:without-scheduling
		       (dbi:end-transaction :commit)
		       (setq ,abort nil))))
	       (when ,abort
		 (dbi:end-transaction :rollback))
	       (dbi:set-autocommit t))
            (error "Nested transaction.")))))

The recursiveness (nesting) of a transaction is tested (and prevented)
at run time.

Is it possible to do that at macro-expansion time ? And if it
possible, do you think it is worth doing that?

thanks in advance

-- 
Vladimir Zolotykh

From: james anderson
Subject: Re: Checking recursive calls
Date: 
Message-ID: <3F869962.259F108A@setf.de>
it is possible to add definitions to the compilation environment and enquire
as to their nature and existence by expding forms in the resulting
environment, but, following the principle, that dynamic compiler state ==
lexical contours, that would be limited to lexical relations while appear to
desire constraints on dynamic relations.

it is not clear what additional constraints one would have to make on the use
of the operator in order to recognize dependancies through a global analysis
of the source code. otherwise every time some function which contained the
form anywhere within its body invoked another such function you would have a
suspect dependancy.

Vladimir Zolotykh wrote:
> 
> Hi,
> 
> Here is the definition of a rather simple WITH-TRANSACTION macro to be
> used with Allegro Odbc.
> 
>    (defvar *transaction-level* 0)
> 
>    (defmacro with-transaction ((db) &body body)
>      (let ((abort (gensym)))
>        `(let ((,abort t)
>              (*transaction-level* (1+ *transaction-level*))
>              (dbi:*default-database* ,db))
as you are permitteg one level only, another option is to start with an
unbound variable, bind it if it is not, and signal an error if it is.
>          (if (= 1 *transaction-level*)
>              (unwind-protect
>                  (progn
>                    (dbi:set-autocommit nil)
>                    (multiple-value-prog1
>                        (progn ,@body)
>                      (mp:without-scheduling
>                        (dbi:end-transaction :commit)
>                        (setq ,abort nil))))
>                (when ,abort
>                  (dbi:end-transaction :rollback))
>                (dbi:set-autocommit t))
>             (error "Nested transaction.")))))
> 
> The recursiveness (nesting) of a transaction is tested (and prevented)
> at run time.
> 
> Is it possible to do that at macro-expansion time ? And if it
> possible, do you think it is worth doing that?
> 
> thanks in advance
> 
> --
> Vladimir Zolotykh
From: Barry Margolin
Subject: Re: Checking recursive calls
Date: 
Message-ID: <4iAhb.275$pd.70@news.level3.com>
In article <················@eurocom.od.ua>,
Vladimir Zolotykh  <······@eurocom.od.ua> wrote:
>The recursiveness (nesting) of a transaction is tested (and prevented)
>at run time.
>
>Is it possible to do that at macro-expansion time ? And if it
>possible, do you think it is worth doing that?

You can do it at macro-expansion time by having your macro expand into a
MACROLET that shadows the global WITH-TRANSACTION macro:

(defmacro with-transaction ((db) &body body)
  (let ((abort (gensym)))
    `(let ((,abort t)
           (*transaction-level* (1+ *transaction-level*))
           (dbi:*default-database* ,db))
       (macrolet ((with-transaction ((db) &body body)
                    (declare (ignore db body))
                    (error "Nested transaction.")))
         ...))))

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Frode Vatvedt Fjeld
Subject: Re: Checking recursive calls
Date: 
Message-ID: <2hu16humuw.fsf@vserver.cs.uit.no>
Barry Margolin <··············@level3.com> writes:

> You can do it at macro-expansion time by having your macro expand into a
> MACROLET that shadows the global WITH-TRANSACTION macro:

This will only work for lexically apparent with-transactions,
though. Anything that is not lexically apparent, may be re-defined at
any time, so your only option is to check at run-time if you want to
catch such a situation.

-- 
Frode Vatvedt Fjeld
From: Barry Margolin
Subject: Re: Checking recursive calls
Date: 
Message-ID: <4UAhb.282$pd.207@news.level3.com>
In article <··············@vserver.cs.uit.no>,
Frode Vatvedt Fjeld  <······@cs.uit.no> wrote:
>Barry Margolin <··············@level3.com> writes:
>
>> You can do it at macro-expansion time by having your macro expand into a
>> MACROLET that shadows the global WITH-TRANSACTION macro:
>
>This will only work for lexically apparent with-transactions,
>though. Anything that is not lexically apparent, may be re-defined at
>any time, so your only option is to check at run-time if you want to
>catch such a situation.

If you noticed, my suggested macro still incremented the
*TRANSACTION-LEVEL* variable.  I intended that the "..." part of my code be
identical to the rest of his original macro body, which checks this.

Actually, now that I think of it, *TRANSACTION-LEVEL* shouldn't be a
counter, it should just be a boolean *IN-TRANSACTION-P*.  Since an error is
signalled in the first recursive level, you can never get to level 2, so
there's no need to count that high.

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Frode Vatvedt Fjeld
Subject: Re: Checking recursive calls
Date: 
Message-ID: <2hzng9rr9m.fsf@vserver.cs.uit.no>
Barry Margolin <··············@level3.com> writes:

> If you noticed, my suggested macro still incremented the
> *TRANSACTION-LEVEL* variable.  I intended that the "..." part of my
> code be identical to the rest of his original macro body, which
> checks this.

Yes. What I meant to say was that you didn't change from checking at
run-time to checking at macro-expansion-time, rather you added the
check at macro-expansion time. Which is fine, but perhaps not
tremendously useful, at least not in the sense that you can remove any
run-time checks.

-- 
Frode Vatvedt Fjeld