1
0
forked from alex-eg/sex

2 Commits

Author SHA1 Message Date
Pavel Kulyov
8588f5a531 semen: extract counting header length into a function 2026-09-20 15:33:09 +03:00
Pavel Kulyov
05929951cb modules: save fn docstring in prototype 2026-09-20 00:39:05 +03:00
2 changed files with 32 additions and 21 deletions

View File

@@ -144,12 +144,15 @@
(define (comment-form? f) (define (comment-form? f)
(and (pair? f) (eq? (car f) 'comment))) (and (pair? f) (eq? (car f) 'comment)))
(define (fn-header-length fn-form)
(if (memq (first fn-form) '(pub extern)) 5 4))
(define (strip-fn-header-comments fn-form) (define (strip-fn-header-comments fn-form)
;; Remove comment forms from the function header ;; Remove comment forms from the function header
;; ([pub|extern] fn name arglist rettype) so the positional accessors ;; ([pub|extern] fn name arglist rettype) so the positional accessors
;; below are not shifted. Comments in the body are left in place as ;; below are not shifted. Comments in the body are left in place as
;; ordinary statements and preserved into the generated C. ;; ordinary statements and preserved into the generated C.
(let ((header-count (if (memq (car fn-form) '(pub extern)) 5 4))) (let ((header-count (fn-header-length fn-form)))
;; This always rebuilds the list, so the location has to be carried ;; This always rebuilds the list, so the location has to be carried
;; over explicitly -- otherwise every function loses it ;; over explicitly -- otherwise every function loses it
(copy-form-source! (copy-form-source!
@@ -265,13 +268,9 @@ Returns #f if the form is not a function, returns the form otherwise"
"Returns all except body" "Returns all except body"
(assert (sex-fn? fn-form) (assert (sex-fn? fn-form)
(fmt #f "Form " fn-form " is not a function")) (fmt #f "Form " fn-form " is not a function"))
(if (sex-fn-public? fn-form) (take fn-form (fn-header-length fn-form)))
(take fn-form 5)
(take fn-form 4)))
(define (sex-fn-body fn-form) (define (sex-fn-body fn-form)
(assert (sex-fn? fn-form) (assert (sex-fn? fn-form)
(fmt #f "Form " fn-form " is not a function")) (fmt #f "Form " fn-form " is not a function"))
(if (sex-fn-public? fn-form) (drop fn-form (fn-header-length fn-form)))
(drop fn-form 5)
(drop fn-form 4)))

View File

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