gelisam / klister

an implementation of stuck macros
BSD 3-Clause "New" or "Revised" License
128 stars 11 forks source link

Let macros yield to other macros with the same name #241

Open gelisam opened 1 month ago

gelisam commented 1 month ago

We sometimes define a single macro which checks whether they are in the expression Problem or the type Problem and then behaves accordingly.

(define-macros
  ([m (lambda (stx)
        (>>= (which-problem)
          (lambda (prob)
            (case prob
              [(declaration)  (pure '(example (the (m) (m))))]
              [(type)         (pure 'Bool)]
              [(expression t) (pure 'true)]
              [(pattern)      (pure 'unit)]))))]))

We have discussed the following alternative, in which several macros (perhaps provided by different libraries) cooperate in order to provide the above behaviour. The way in which the cooperate is that each one indicates whether or not they are applicable to the current situation, and if there is only one macro which is applicable, then that's the macro whose returned Syntax object is used.

(define-macros
  ([m (lambda (stx)
        (>>= (which-problem)
          (lambda (prob)
            (case prob
              [(declaration)  (pure '(example (the (m) (m))))]
              [_ (not-applicable)]))))]
   [m (lambda (stx)
        (>>= (which-problem)
          (lambda (prob)
            (case prob
              [(type) (pure 'Bool)]
              [_ (not-applicable)]))))]
   [m (lambda (stx)
        (>>= (which-problem)
          (lambda (prob)
            (case prob
              [(expression t) (pure 'true)]
              [_ (not-applicable)]))))]
   [m (lambda (stx)
        (>>= (which-problem)
          (lambda (prob)
            (case prob
              [(pattern) (pure 'unit)]
              [_ (not-applicable)]))))]))
gelisam commented 1 month ago

Hmm, if there are four distinct bindings to m coming from different libraries, what's the bahaviour of (free-identifier=? 'm my-identifier)? Would it only return true if both identifiers see the same set of m bindings?

gelisam commented 1 month ago

One alternative would be to have one main binding which states that the behaviour of m will obtained that way:

(define-combining-macro m)

And then to have each sub-definition refer to this main m binding, to indicate that it wants to contribute to this combining-macro:

(extend-combining-macro m
  (lambda (stx)
    (>>= (which-problem)
      (lambda (prob)
        (case prob
          [(declaration)  (pure '(example (the (m) (m))))]
          [_ (not-applicable)])))))

This way, free-identifier=? would only have to check whether the two identifiers see the same main m binding. They would behave the same, even if a different set of extend-combining-macro m definitions are in scope for each, because each such definition would affect the behaviour of m calls as a side-effect.