forked from alex-eg/sex
Compare commits
2 Commits
feature/pr
...
8588f5a531
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8588f5a531 | ||
|
|
05929951cb |
13
semen.scm
13
semen.scm
@@ -144,12 +144,15 @@
|
||||
(define (comment-form? f)
|
||||
(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)
|
||||
;; Remove comment forms from the function header
|
||||
;; ([pub|extern] fn name arglist rettype) so the positional accessors
|
||||
;; below are not shifted. Comments in the body are left in place as
|
||||
;; 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
|
||||
;; over explicitly -- otherwise every function loses it
|
||||
(copy-form-source!
|
||||
@@ -265,13 +268,9 @@ Returns #f if the form is not a function, returns the form otherwise"
|
||||
"Returns all except body"
|
||||
(assert (sex-fn? fn-form)
|
||||
(fmt #f "Form " fn-form " is not a function"))
|
||||
(if (sex-fn-public? fn-form)
|
||||
(take fn-form 5)
|
||||
(take fn-form 4)))
|
||||
(take fn-form (fn-header-length fn-form)))
|
||||
|
||||
(define (sex-fn-body fn-form)
|
||||
(assert (sex-fn? fn-form)
|
||||
(fmt #f "Form " fn-form " is not a function"))
|
||||
(if (sex-fn-public? fn-form)
|
||||
(drop fn-form 5)
|
||||
(drop fn-form 4)))
|
||||
(drop fn-form (fn-header-length fn-form)))
|
||||
|
||||
@@ -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)
|
||||
(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))
|
||||
(else (sex-error form "pub must be followed by a definition" form))))
|
||||
(else 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
|
||||
|
||||
Reference in New Issue
Block a user