[<<][meta][>>][..]
Thu Jan 17 16:34:56 CET 2013

Racket compile-time bindings

Basic mechanism is:

   (require (for-syntax scheme/base))
   (define-syntax <id> <val>)

Syntax identifiers are only accessible during transformation.
E.g. the `slv' macro below lifts the value 123 from compile time to
syntax through `datum->syntax'.


(define-syntax foo 123)

(define-syntax (slv stx)
  (syntax-case stx ()
    ((_ id) (datum->syntax stx (syntax-local-value #'id)))))


After that, the level reasoning gets difficult.  Needs some rehash..
Ok, I got it:

;; Define a compile time entity representing a siso system.
(define-syntax (define-system stx)
  (syntax-case stx ()
    ((_ name (si i) (so o) b)
     #`(define-syntax name
         (list
          #,(length (syntax->datum #'si))
          #'(lambda-system (si i) (so o) b))))))

;; Expand compile time siso entity to function.
(define-syntax (system-function stx)
  (syntax-case stx ()
    ((_ id)
     (match (syntax-local-value #'id)
            ((list narg spec) spec)))))

This allows definitions of compile-time entities (state size and body
syntax) that contain structural information that can be used by other
macros, such as `system-function'.

This should be enough to build a composition macro that builds such a
compile time object (size + syntax) from a specification syntax.

In the examples above, it's not even necessary to cache the lenght as
it can be recomputed from the system syntax:

(define-syntax (define-system stx)
  (syntax-case stx ()
    ((_ name (si i) (so o) b)
     #`(define-syntax name #'((si i) (so o) b)))))

(begin-for-syntax
 (define (system-num-state id)
   (length (syntax->datum (syntax-local-value id))))
 (define (system-body-def id)
   #`(lambda-system #,@(syntax-local-value id))))

(define-syntax (system-function stx)
  (syntax-case stx ()
    ((_ id) (system-body-def #'id))))
(define-syntax (system-arity stx)
 (syntax-case stx ()
    ((_ id) (system-num-state #'id))))



So the idea is now to make a `system' form containing a collection of
bindings, which expands to a lambda form derived from the systems that
are present in the body.

Note this requires distinction between primitive and composite
systems.

(compose-system (in ...) (out ...) (bindings ...))

Since we're binding syntax to an identifier, there will be no code
reuse if we're not being careful, so this might be added later:
instead of expanding the body inline, record the references.  This
would allow generation of inline functions in C, where the C compiler
decides on performing the inlining.  For now, just inline.

Ok, works.  Minimal config:

(begin-for-syntax
 (define (thread-state vdefs)
   (let*
       ((vs
         (for/list ((vdef vdefs))
           (syntax-case vdef ()
             (((var ...) (op arg ...))
              ;; If it's a processor, generate state variables.
              (let-values (((si so) (system-state #'op)))
                (let ((g-si (generate-temporaries si))
                      (g-so (generate-temporaries so))
                      (l-op (system-body-def #'op)))
                  
                  (list g-si g-so
                        #`((#,@g-so var ...) (#,l-op #,@g-si arg ...))))))
             ;(else (list '() vdef))
             )))
        (g-sis (apply append (map car vs)))
        (g-sos (apply append (map cadr vs)))
        (state-vdefs (map caddr vs)))
             
     (values g-sis g-sos state-vdefs)))
 )



(define-syntax (define-system-comp stx)
  (syntax-case stx ()
    ((_ name in out (vdef ...))
     (let-values (((si so vdefs) (thread-state (syntax->list #'(vdef ...)))))
       #`(define-system-prim name (#,si in) (#,so out) #,vdefs)))))
 )
(define-syntax (define-system-comp stx)
  (syntax-case stx ()
    ((_ name in out (vdef ...))
     (let-values (((si so vdefs) (thread-state (syntax->list #'(vdef ...)))))
       #`(define-system-prim name (#,si in) (#,so out) #,vdefs)))))

(define-system-comp foo (i) (o3)
  (((o1) (integrator i))
   ((o2) (integrator o1))
   ((o3) (integrator o2))
   ))
 

Next: should the form support only composition of siso systems, or
should it lift pure functions too?  Pure functions are useful as glue,
but automatic lifting can be confusing...



[Reply][About]
[<<][meta][>>][..]