[gambit-list] Re --enable-auto-forcing: Scope, how/where implemented, how build (with) it properly?

Marc Feeley feeley at iro.umontreal.ca
Fri Jun 16 01:52:13 EDT 2017

Here is the definition of + from lib/_num.scm:

(define-prim-nary (+ x y)
  (if (##number? x) x '(1))
  (##+ x y)
  (##pair? ##fail-check-number))

The define-prim-nary macro will expand this to an n-ary procedure definition where the 0 argument case returns 0, the 1 argument case returns the argument if it is a number otherwise it raises a type error (by calling ##fail-check-number), and the general >= 2 argument case calls ##+ to fold the argument list. All arguments are passed to macro-force-vars to force the argument if it is a promise (and --enable-auto-forcing is used).

Using set! to “short-circuit” promises is not a good idea because it introduces a cell for the variable (if local and not previously assigned) and this slows things down.  In early versions of Gambit (on Motorola 68K), the garbage collector did this short-circuiting (i.e. a reference to a promise was replaced with the value of the promise if it was previously forced).  This isn’t done currently but probably easy to add.


> On Jun 15, 2017, at 11:04 PM, Adam <adam.mlmb at gmail.com> wrote:
> 2017-06-13 5:30 GMT+07:00 Bradley Lucier <lucier at math.purdue.edu>:
> > On Jun 11, 2017, at 5:08 AM, Adam <adam.mlmb at gmail.com> wrote:
> >
> > Possibly the "macro-force-vars", which is used all over the runtime and compiler, would have something to do with this, but I don't find its definition anywhere.
> >
> In _gambit#.scm:
> (macro-define-syntax macro-force-vars
>   (lambda (stx)
>     (syntax-case stx ()
>       ((_ vars expr)
>        (if (let* ((co
>                    (##global-var-ref
>                     (##make-global-var '##compilation-options)))
>                   (comp-opts
>                    (if (##unbound? co) '() co)))
>              (assq 'force comp-opts))
>            (syntax-case (datum->syntax
>                          #'vars
>                          (map (lambda (x) `(,x (##force ,x)))
>                               (syntax->list #'vars)))
>                ()
>              (bindings #'(let bindings expr)))
>            #'expr)))))
> Ah right, https://github.com/gambit/gambit/blob/9c3dcbdc322a10673370c0880696ba131144251d/lib/_gambit%23.scm#L316 , and used to be a define-macro, https://github.com/gambit/gambit/blob/29103e6a29b8fbbf7d6fc772a344b814be3f1c1a/lib/_gambit%23.scm#L492 , and all the rest of the code is meticulously padded with its use.
> This also sheds a bit of light on why the slot containing the promise is not replaced with the forced value. Maybe that would be possible in some situations though.. When |x| is a symbol, it could be |set!| with the forced value?
> That would cover standard variable slots and not typedef, vector, pair etc. slots though, I guess I'd need to dig in a bit more to understand how this one actually works out. If you have any spontaneous ideas, feel free to share.
> Any idea where in the sources fundamental primitives like |+| , |if| , |or| autoforce?

More information about the Gambit-list mailing list