~ chicken-core (chicken-5) eaced6c9bb5209b321543511bd5ce02022498c2f


commit eaced6c9bb5209b321543511bd5ce02022498c2f
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Sat Apr 2 15:15:24 2016 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Sat Apr 2 15:15:24 2016 +0200

    added first experimental code for processing egg-info

diff --git a/egg-info.scm b/egg-info.scm
new file mode 100644
index 00000000..108497dd
--- /dev/null
+++ b/egg-info.scm
@@ -0,0 +1,280 @@
+;;;; egg-info processing and compilation
+
+
+(import (chicken))
+(import (chicken data-structures))
+(import (chicken pretty-print))
+(import (chicken files))
+
+
+(define valid-items
+  '(synopsis authors category license version dependencies files
+    source-file csc-options test-dependencies destination linkage
+    build-dependencies components foreign-dependencies link-options))
+
+(define nested-items 
+  '(components))
+
+(define named-items
+  '(extension program data c-include scheme-include))
+
+(define default-extension-options '())
+(define default-program-options '())
+(define default-static-program-link-options '())
+(define default-dynamic-program-link-options '())
+(define default-static-extension-link-options '())
+(define default-dynamic-extension-link-options '())
+(define default-extension-linkage '(static dynamic))
+(define default-program-linkage '(dynamic))
+(define executable-extension "")
+
+
+(define (validate-egg-info info)
+  (unless (list? info) 
+    (error "egg-information has invalid structure"))
+  (for-each
+    (lambda (item)
+      (cond ((not (and (list? item) (pair? item) (symbol? (car item))))
+              (error "egg-information item has invalid structure" item))
+            ((not (memq (car item) valid-items))
+              (error "invalid item" item))
+            ((and (memq (car item) named-items) (not (symbol? (cadr item))))
+              (error "missing name for item" item))
+            ((memq (car item) nested-items)
+              (validate-egg-info 
+                (if (memq (car item) named-items) (cddr item) (cdr item))))))
+    info))
+
+(define (compile-egg-info info)
+  (let ((exts '())
+        (prgs '())
+        (data '())
+        (cinc '())
+        (scminc '())
+        (target #f)
+        (src #f)
+        (files '())
+        (ifiles '())
+        (link '())
+        (dest #f)
+        (deps '())
+        (lopts '())
+        (opts '()))
+    (define (check-target t lst)
+      (when (member t lst)
+        (error "target multiply defined" t))
+      t)
+    (define (addfiles . files)
+      (set! ifiles (append files ifiles))
+      files)
+    (define (compile-component info)
+      (case (car info)
+        ((extension)
+          (fluid-let ((target (check-target (cadr info) exts))
+                      (deps '())
+                      (src #f)
+                      (link default-extension-linkage)
+                      (lopts '())
+                      (opts '()))
+            (for-each compile-extension/program (cddr info))
+            (addfiles 
+              (if (memq 'static link) (conc target ".o") '())
+              (if (memq 'dynamic link) (conc target ".so") '())
+              (conc target ".import.so")) ; assumes import-lib is always compiled?
+            (set! exts (cons (list target deps src opts lopts link) exts))))
+        ((data)
+          (fluid-let ((target (check-target (cadr info) data))
+                      (dest #f)
+                      (files '()))
+            (for-each compile-data/include (cddr info))
+            (let ((dest (normalize-pathname (conc dest "/"))))
+              (for-each addfiles (map (cut conc dest <>) files)))
+            (set! data (cons (list target '() files dest) data))))
+        ((c-include)
+          (fluid-let ((target (check-target (cadr info) cinc))
+                      (dest #f)
+                      (files '()))
+            (for-each compile-data/include (cddr info))
+            (let ((dest (normalize-pathname (conc dest "/"))))
+              (for-each addfiles (map (cut conc dest <>) files)))
+            (set! cinc (cons (list target '() files dest) cinc))))
+        ((scheme-include)
+          (fluid-let ((target (check-target (cadr info) scminc))
+                      (dest #f))
+                      (files '()))
+            (for-each compile-data/include (cddr info))
+            (let ((dest (normalize-pathname (conc dest "/"))))
+              (for-each addfiles (map (cut conc dest <>) files)))
+            (set! scminc (cons (list target '() files dest) scminc)))
+        ((program)
+          (fluid-let ((target (check-target (cadr info) prgs))
+                      (deps '())
+                      (src #f)
+                      (link default-program-linkage)
+                      (lopts '())
+                      (opts '()))
+            (for-each compile-extension/program (cddr info))
+            (addfiles (conc target executable-extension))
+            (set! prgs (cons (list target deps src opts lopts link) prgs))))))
+    (define (compile-extension/program info)
+      (case (car info)
+        ((linkage) 
+         (set! link (cdr info)))
+        ((csc-options) 
+         (set! opts (append opts (cdr info))))
+        ((link-options)
+         (set! lopts (append lopts (cdr info))))
+        ((source-file)
+         (set! src (->string (arg info 1 name?))))
+        ((dependencies)
+         (set! deps (append deps (map ->dep (cdr info)))))))
+    (define (compile-data/include info)
+      (case (car info)
+        ((destination)
+         (set! dest (->string (arg info 1 name?))))
+        ((files) 
+         (set! files (append files (map ->string (cdr info)))))))
+    (define (->dep x)
+      (if (name? x) x (error "invalid dependency" x)))
+    (define (compile info)
+      (case (car info)
+        ((components) (for-each compile-component (cdr info)))))
+    (define (arg info n #!optional (pred (constantly #t)))
+      (when (< (length info) n)
+        (error "missing argument" info n))
+      (let ((x (list-ref info n)))
+        (unless (pred x)
+          (error "argument has invalid type" x))
+        x))
+    (define (name? x) (or (string? x) (symbol? x)))
+    (define dep=? equal?)
+    (define (filter pred lst)
+      (cond ((null? lst) '())
+            ((pred (car lst)) (cons (car lst) (filter pred (cdr lst))))
+            (else (filter pred (cdr lst)))))
+    (define (filter-deps name deps)
+      (filter (lambda (dep)
+                (and (symbol? dep)
+                     (or (assq dep exts)
+                         (assq dep data)
+                         (assq dep cinc)
+                         (assq dep scminc)
+                         (error "unknown component dependency" dep name))))
+              deps))
+    ;; collect information
+    (for-each compile info)
+    ;; sort topologically, by dependencies
+    (let ((order (reverse 
+                   (topological-sort          
+                     (map (lambda (dep)
+                            (cons (car dep) 
+                                  (filter-deps (car dep) (cadr dep))))
+                          exts)
+                      dep=?))))
+      ;; generate + return build/install commands
+      (values
+        ;; build commands
+        (append 
+          (foldr
+            (lambda (t cmds)
+              (let ((data (assq t exts)))
+                (cons `(compile-extension ,@data) cmds)))
+            '() order)
+          (map (lambda (prg) `(compile-program ,prg)) prgs))
+        ;; installation commands
+        (append
+          (map (lambda (ext) `(install-extension ,@ext)) exts)
+          (map (lambda (prg) `(install-program ,@prg)) prgs)
+          (map (lambda (data) `(install-data ,@data)) data)
+          (map (lambda (cinc) `(install-c-include ,@cinc)) cinc)
+          (map (lambda (scminc) `(install-scheme-include ,@scminc)) scminc))
+        ;; augmented egg-info
+        (cons `(installed-files ,@ifiles) info)))))
+
+
+;;; UNIX shell code generation
+
+(define (gen-compile-unix-extension name deps src opts lopts link)
+  ...)
+
+(define (gen-compile-unix-program name deps src opts lopts link)
+  ...)
+
+(define (gen-install-unix-extension name deps src opts lopts link)
+  ...)
+
+(define (gen-install-unix-program name deps src opts lopts link)
+  ...)
+
+(define (gen-install-unix-data name deps files dest)
+  ...)
+
+(define (gen-install-unix-c-include name deps files dest)
+  ...)
+
+(define (gen-install-unix-scheme-include name deps files dest)
+  ...)
+
+
+;;; Windows batch code generation
+
+(define (gen-compile-windows-extension name deps src opts lopts link)
+  ...)
+
+(define (gen-compile-windows-program name deps src opts lopts link)
+  ...)
+
+(define (gen-install-windows-extension name deps src opts lopts link)
+  ...)
+
+(define (gen-install-windows-program name deps src opts lopts link)
+  ...)
+
+(define (gen-install-windows-data name deps files dest)
+  ...)
+
+(define (gen-install-windows-c-include name deps files dest)
+  ...)
+
+(define (gen-install-windows-scheme-include name deps files dest)
+  ...)
+
+
+;;; platform-independent part of code generation
+
+(define generators
+  `((compile-extension (unix ,gen-compile-unix-extension) 
+                       (windows ,gen-compile-windows-extension))
+    (compile-program (unix ,gen-compile-unix-program) 
+                     (windows ,gen-compile-windows-program))
+    (install-extension (unix ,gen-install-unix-extension)
+                       (windows ,gen-install-windows-extension))
+    (install-program (unix ,gen-install-unix-program)
+                     (windows ,gen-install-windows-program))
+    (install-data (unix ,gen-install-unix-data)
+                  (windows ,gen-install-windows-data))
+    (install-c-include (unix ,gen-install-unix-c-include)
+                       (windows ,gen-install-windows-c-include))
+    (install-scheme-include (unix ,gen-install-unix-scheme-include)
+                            (windows ,gen-install-windows-scheme-include))))
+
+(define (generate-shell-commands platform cmds dest prefix suffix)
+  (with-output-to-file dest
+    (lambda ()
+      (prefix)
+      (for-each
+        (lambda (cmd)
+          (cond ((assq cmd generators) =>
+                  (lambda (gen)
+                    (cond ((assq platform (cdr gen)) =>
+                            (lambda (a) (apply (cdr a) (cdr cmd))))
+                          (else (error "invalid platform" platform)))))
+                (else (error "invalid command" cmd))))
+        cmds)
+      (suffix))))
+                        
+
+;;
+
+(set! hyde (with-input-from-file "hyde.egg" read))
+(pp (receive (compile-egg-info hyde)))
Trap