diff --git a/sex-modules.scm b/sex-modules.scm index c524df4..fd07f6e 100644 --- a/sex-modules.scm +++ b/sex-modules.scm @@ -8,6 +8,7 @@ (chicken process-context) (chicken string) fmt + matchable reader srfi-1 utils) @@ -71,22 +72,33 @@ (list) raw-forms))) +(define (public-fn-interface form) + ;; (pub fn name args ret . body) -> prototype, keeping a docstring so + ;; the importer can emit it above the declaration + (match form + (('pub 'fn name args ret) + form) + (('pub 'fn name args ret ('comment . _) . rest) + (public-fn-interface `(pub fn ,name ,args ,ret ,@rest))) + (('pub 'fn name args ret (? string? doc) . _) + `(pub fn ,name ,args ,ret ,doc)) + (('pub 'fn name args ret . _) + `(pub fn ,name ,args ,ret)))) + ;;; TODO: use semen facilities to analyze modules (define (process-public-interface-form form acc) - (case (car form) - ((pub) - (case (cadr form) - ;; A function is reduced to a prototype and keeps its `pub', so - ;; the importing unit declares it with external linkage - ((fn) - (cons (copy-form-source! form (take form 5)) acc)) - ;; A variable becomes an `extern' declaration - ((var) - (cons (copy-form-source! form (cons 'extern (take (cdr form) 3))) acc)) - ((define defmacro enum import include struct typedef union) - (cons (copy-form-source! form (cdr form)) acc)) - (else (sex-error form "pub must be followed by a definition" form)))) - (else acc))) + (match form + ;; Reduced to a prototype, still `pub', so the importer declares it + ;; with external linkage + (('pub 'fn . _) + (cons (copy-form-source! form (public-fn-interface form)) acc)) + (('pub 'var name type . _) + (cons (copy-form-source! form `(extern var ,name ,type)) acc)) + (('pub (or 'define 'defmacro 'enum 'import 'include 'struct 'typedef 'union) . _) + (cons (copy-form-source! form (cdr form)) acc)) + (('pub . _) + (sex-error form "pub must be followed by a definition" form)) + (_ acc))) (define (load-persistent-module-paths) (let ((sex-module-path-env-var