- Added stale-when:

syntax:  (stale-when guard-expr e* ...)   ;; in definition context
            (stale-when guard-expr e e* ...) ;; in expression context

   semantics:
     When a stale-when form is encountered while expanding any code
     (expressions, macros, macros in macros, etc.) in a library
     body, the guard-expr is expanded (but not evaluated) and
     serialized along with the library.  When the library is later
     reloaded from fasl and before it is installed, the guard-expr
     is evaluated.  If guard-expr returns true, the fasl content is
     ignored and the library is recompiled afresh from source.
This commit is contained in:
Abdulaziz Ghuloum 2009-05-28 09:02:47 +03:00
parent f759815a8c
commit 24ece86772
5 changed files with 114 additions and 40 deletions

View File

@ -1 +1 @@
1794 1795

View File

@ -126,6 +126,7 @@
[set! (set!)] [set! (set!)]
[let-syntax (let-syntax)] [let-syntax (let-syntax)]
[letrec-syntax (letrec-syntax)] [letrec-syntax (letrec-syntax)]
[stale-when (stale-when)]
[foreign-call (core-macro . foreign-call)] [foreign-call (core-macro . foreign-call)]
[quote (core-macro . quote)] [quote (core-macro . quote)]
[syntax-case (core-macro . syntax-case)] [syntax-case (core-macro . syntax-case)]
@ -296,6 +297,7 @@
[define-struct i] [define-struct i]
[include i] [include i]
[include-into i] [include-into i]
[stale-when i]
[time i] [time i]
[trace-lambda i] [trace-lambda i]
[trace-let i] [trace-let i]
@ -1691,7 +1693,7 @@
'()))]) '()))])
`(install-library `(install-library
',id ',name ',version ',import-libs ',visit-libs ',invoke-libs ',id ',name ',version ',import-libs ',visit-libs ',invoke-libs
',subst ',env void void '#f '#f ',visible? '#f))))) ',subst ',env void void '#f '#f '#f '() ',visible? '#f)))))
(let ([code `(library (ikarus primlocs) (let ([code `(library (ikarus primlocs)
(export) ;;; must be empty (export) ;;; must be empty
(import (import

View File

@ -22,6 +22,7 @@
annotation-stripped annotation-stripped
read-library-source-file read-library-source-file
library-version-mismatch-warning library-version-mismatch-warning
library-stale-warning
file-locator-resolution-error file-locator-resolution-error
label-binding set-label-binding! remove-location label-binding set-label-binding! remove-location
make-source-position-condition) make-source-position-condition)
@ -29,32 +30,37 @@
(only (ikarus.compiler) eval-core) (only (ikarus.compiler) eval-core)
(only (ikarus.reader.annotated) read-library-source-file) (only (ikarus.reader.annotated) read-library-source-file)
(ikarus)) (ikarus))
(define (library-version-mismatch-warning name depname filename) (define (library-version-mismatch-warning name depname filename)
(fprintf (current-error-port) (fprintf (current-error-port)
"WARNING: library ~s has an inconsistent dependency \ "WARNING: library ~s has an inconsistent dependency \
on library ~s; file ~s will be recompiled from \ on library ~s; file ~s will be recompiled from \
source.\n" source.\n"
name depname filename)) name depname filename))
(define (library-stale-warning name filename)
(fprintf (current-error-port)
"WARNING: library ~s is stale; file ~s will be recompiled from source.\n"
name filename))
(define (file-locator-resolution-error libname failed-list pending-list) (define (file-locator-resolution-error libname failed-list pending-list)
(define-condition-type &library-resolution &condition (define-condition-type &library-resolution &condition
make-library-resolution-condition make-library-resolution-condition
library-resolution-condition? library-resolution-condition?
(library condition-library) (library condition-library)
(files condition-files)) (files condition-files))
(define-condition-type &imported-from &condition (define-condition-type &imported-from &condition
make-imported-from-condition imported-from-condition? make-imported-from-condition imported-from-condition?
(importing-library importing-library)) (importing-library importing-library))
(raise (raise
(apply condition (make-error) (apply condition (make-error)
(make-who-condition 'expander) (make-who-condition 'expander)
(make-message-condition (make-message-condition
"cannot locate library in library-path") "cannot locate library in library-path")
(make-library-resolution-condition (make-library-resolution-condition
libname failed-list) libname failed-list)
(map make-imported-from-condition pending-list)))) (map make-imported-from-condition pending-list))))
(define-syntax define-record (define-syntax define-record
(syntax-rules () (syntax-rules ()

View File

@ -704,7 +704,7 @@
macro! local-macro local-macro! global-macro macro! local-macro local-macro! global-macro
global-macro! module library set! let-syntax global-macro! module library set! let-syntax
letrec-syntax import export $core-rtd letrec-syntax import export $core-rtd
ctv local-ctv global-ctv) ctv local-ctv global-ctv stale-when)
(values type (binding-value b) id)) (values type (binding-value b) id))
(else (else
(values 'call #f #f)))) (values 'call #f #f))))
@ -2734,6 +2734,8 @@
rator rator
(chi-expr* rands r mr))))))) (chi-expr* rands r mr)))))))
(define chi-expr (define chi-expr
(lambda (e r mr) (lambda (e r mr)
(let-values (((type value kwd) (syntax-type e r))) (let-values (((type value kwd) (syntax-type e r)))
@ -2766,6 +2768,13 @@
((_ x x* ...) ((_ x x* ...)
(build-sequence no-source (build-sequence no-source
(chi-expr* (cons x x*) r mr))))) (chi-expr* (cons x x*) r mr)))))
((stale-when)
(syntax-match e ()
((_ guard x x* ...)
(begin
(handle-stale-when guard mr)
(build-sequence no-source
(chi-expr* (cons x x*) r mr))))))
((let-syntax letrec-syntax) ((let-syntax letrec-syntax)
(syntax-match e () (syntax-match e ()
((_ ((xlhs* xrhs*) ...) xbody xbody* ...) ((_ ((xlhs* xrhs*) ...) xbody xbody* ...)
@ -3133,6 +3142,14 @@
(chi-body* (append x* (cdr e*)) (chi-body* (append x* (cdr e*))
r mr lex* rhs* mod** kwd* exp* rib r mr lex* rhs* mod** kwd* exp* rib
mix? sd?)))) mix? sd?))))
((stale-when)
(syntax-match e ()
((_ guard x* ...)
(begin
(handle-stale-when guard mr)
(chi-body* (append x* (cdr e*))
r mr lex* rhs* mod** kwd* exp* rib
mix? sd?)))))
((global-macro global-macro!) ((global-macro global-macro!)
(chi-body* (chi-body*
(cons (add-subst rib (chi-global-macro value e r)) (cons (add-subst rib (chi-global-macro value e r))
@ -3545,6 +3562,7 @@
(assertion-violation 'imp-collector "BUG: not a procedure" x)) (assertion-violation 'imp-collector "BUG: not a procedure" x))
x))) x)))
(define chi-library-internal (define chi-library-internal
(lambda (e* rib mix?) (lambda (e* rib mix?)
(let-values (((e* r mr lex* rhs* mod** _kwd* exp*) (let-values (((e* r mr lex* rhs* mod** _kwd* exp*)
@ -3627,18 +3645,44 @@
(list invoke-body))) (list invoke-body)))
macro* export-subst export-env)))))))))))))) macro* export-subst export-env))))))))))))))
(define stale-when-collector (make-parameter #f))
(define (make-stale-collector)
(let ([code (build-data no-source #f)]
[req* '()])
(case-lambda
[() (values code req*)]
[(c r*)
(set! code
(build-conditional no-source
code
(build-data no-source #t)
c))
(set! req* (set-union r* req*))])))
(define (handle-stale-when guard-expr mr)
(let ([stc (make-collector)])
(let ([core-expr (parameterize ([inv-collector stc])
(chi-expr guard-expr mr mr))])
(cond
[(stale-when-collector) =>
(lambda (c) (c core-expr (stc)))]))))
(define core-library-expander (define core-library-expander
(case-lambda (case-lambda
((e verify-name) ((e verify-name)
(let-values (((name* exp* imp* b*) (parse-library e))) (let-values (((name* exp* imp* b*) (parse-library e)))
(let-values (((name ver) (parse-library-name name*))) (let-values (((name ver) (parse-library-name name*)))
(verify-name name) (verify-name name)
(let-values (((imp* invoke-req* visit-req* invoke-code (let ([c (make-stale-collector)])
visit-code export-subst export-env) (let-values (((imp* invoke-req* visit-req* invoke-code
(library-body-expander exp* imp* b* #f))) visit-code export-subst export-env)
(values name ver imp* invoke-req* visit-req* (parameterize ([stale-when-collector c])
invoke-code visit-code export-subst (library-body-expander exp* imp* b* #f))))
export-env))))))) (let-values ([(guard-code guard-req*) (c)])
(values name ver imp* invoke-req* visit-req*
invoke-code visit-code export-subst
export-env guard-code guard-req*)))))))))
(define (parse-top-level-program e*) (define (parse-top-level-program e*)
(syntax-match e* () (syntax-match e* ()
@ -3773,7 +3817,8 @@
(set-symbol-value! loc proc))) (set-symbol-value! loc proc)))
macro*)) macro*))
(let-values (((name ver imp* inv* vis* (let-values (((name ver imp* inv* vis*
invoke-code macro* export-subst export-env) invoke-code macro* export-subst export-env
guard-code guard-req*)
(core-library-expander x verify-name))) (core-library-expander x verify-name)))
(let ((id (gensym)) (let ((id (gensym))
(name name) (name name)
@ -3781,6 +3826,7 @@
(imp* (map library-spec imp*)) (imp* (map library-spec imp*))
(vis* (map library-spec vis*)) (vis* (map library-spec vis*))
(inv* (map library-spec inv*)) (inv* (map library-spec inv*))
(guard-req* (map library-spec guard-req*))
(visit-proc (lambda () (visit! macro*))) (visit-proc (lambda () (visit! macro*)))
(invoke-proc (invoke-proc
(lambda () (eval-core (expanded->core invoke-code)))) (lambda () (eval-core (expanded->core invoke-code))))
@ -3790,10 +3836,12 @@
imp* vis* inv* export-subst export-env imp* vis* inv* export-subst export-env
visit-proc invoke-proc visit-proc invoke-proc
visit-code invoke-code visit-code invoke-code
guard-code guard-req*
#t filename) #t filename)
(values id name ver imp* vis* inv* (values id name ver imp* vis* inv*
invoke-code visit-code invoke-code visit-code
export-subst export-env)))) export-subst export-env
guard-code guard-req*))))
((x filename) ((x filename)
(library-expander x filename (lambda (x) (values)))) (library-expander x filename (lambda (x) (values))))
((x) ((x)
@ -3803,7 +3851,8 @@
;;; be) be used in the "next" system. So, we drop it. ;;; be) be used in the "next" system. So, we drop it.
(define (boot-library-expand x) (define (boot-library-expand x)
(let-values (((id name ver imp* vis* inv* (let-values (((id name ver imp* vis* inv*
invoke-code visit-code export-subst export-env) invoke-code visit-code export-subst export-env
guard-code guard-dep*)
(library-expander x))) (library-expander x)))
(values name invoke-code export-subst export-env))) (values name invoke-code export-subst export-env)))

View File

@ -54,8 +54,8 @@
(define-record library (define-record library
(id name version imp* vis* inv* subst env visit-state (id name version imp* vis* inv* subst env visit-state
invoke-state visit-code invoke-code visible? invoke-state visit-code invoke-code guard-code guard-req*
source-file-name) visible? source-file-name)
(lambda (x p wr) (lambda (x p wr)
(unless (library? x) (unless (library? x)
(assertion-violation 'record-type-printer "not a library")) (assertion-violation 'record-type-printer "not a library"))
@ -177,6 +177,8 @@
(library-env x) (library-env x)
(compile (library-visit-code x)) (compile (library-visit-code x))
(compile (library-invoke-code x)) (compile (library-invoke-code x))
(compile (library-guard-code x))
(map library-desc (library-guard-req* x))
(library-visible? x))))) (library-visible? x)))))
((current-library-collection)))) ((current-library-collection))))
@ -188,18 +190,30 @@
filename filename
(case-lambda (case-lambda
((id name ver imp* vis* inv* exp-subst exp-env ((id name ver imp* vis* inv* exp-subst exp-env
visit-proc invoke-proc visible?) visit-proc invoke-proc guard-proc guard-req* visible?)
;;; make sure all dependencies are met ;;; make sure all dependencies are met
;;; if all is ok, install the library ;;; if all is ok, install the library
;;; otherwise, return #f so that the ;;; otherwise, return #f so that the
;;; library gets recompiled. ;;; library gets recompiled.
(let f ((deps (append imp* vis* inv*))) (let f ((deps (append imp* vis* inv* guard-req*)))
(cond (cond
((null? deps) ((null? deps)
(install-library id name ver imp* vis* inv* ;;; CHECK
exp-subst exp-env visit-proc invoke-proc (for-each
#f #f visible? #f) (lambda (x)
#t) (let ([label (car x)] [dname (cadr x)])
(let ([lib (find-library-by-name dname)])
(invoke-library lib))))
guard-req*)
(cond
[(guard-proc) ;;; stale
(library-stale-warning name filename)
#f]
[else
(install-library id name ver imp* vis* inv*
exp-subst exp-env visit-proc invoke-proc
#f #f ''#f '() visible? #f)
#t]))
(else (else
(let ((d (car deps))) (let ((d (car deps)))
(let ((label (car d)) (dname (cadr d))) (let ((label (car d)) (dname (cadr d)))
@ -333,10 +347,12 @@
(case-lambda (case-lambda
((id name ver imp* vis* inv* exp-subst exp-env ((id name ver imp* vis* inv* exp-subst exp-env
visit-proc invoke-proc visit-code invoke-code visit-proc invoke-proc visit-code invoke-code
guard-code guard-req*
visible? source-file-name) visible? source-file-name)
(let ((imp-lib* (map find-library-by-spec/die imp*)) (let ((imp-lib* (map find-library-by-spec/die imp*))
(vis-lib* (map find-library-by-spec/die vis*)) (vis-lib* (map find-library-by-spec/die vis*))
(inv-lib* (map find-library-by-spec/die inv*))) (inv-lib* (map find-library-by-spec/die inv*))
(guard-lib* (map find-library-by-spec/die guard-req*)))
(unless (and (symbol? id) (list? name) (list? ver)) (unless (and (symbol? id) (list? name) (list? ver))
(assertion-violation 'install-library (assertion-violation 'install-library
"invalid spec with id/name/ver" id name ver)) "invalid spec with id/name/ver" id name ver))
@ -345,7 +361,8 @@
"library is already installed" name)) "library is already installed" name))
(let ((lib (make-library id name ver imp-lib* vis-lib* inv-lib* (let ((lib (make-library id name ver imp-lib* vis-lib* inv-lib*
exp-subst exp-env visit-proc invoke-proc exp-subst exp-env visit-proc invoke-proc
visit-code invoke-code visible? source-file-name))) visit-code invoke-code guard-code guard-lib*
visible? source-file-name)))
(install-library-record lib)))))) (install-library-record lib))))))
(define (imported-label->binding lab) (define (imported-label->binding lab)