1 Commits

Author SHA1 Message Date
Pavel Kulyov
78862cfe4f TMP
All checks were successful
Sex CI / build-linux (pull_request) Successful in 4m45s
2026-09-18 18:42:52 +03:00
3 changed files with 65 additions and 62 deletions

View File

@@ -149,11 +149,11 @@
(and (pair? f) (eq? (car f) 'comment))) (and (pair? f) (eq? (car f) 'comment)))
(define (fn-header-length fn-form) (define (fn-header-length fn-form)
(if (memq (first fn-form) '(pub extern)) 5 4)) (if (memq (car fn-form) '(pub extern)) 5 4))
(define (fn-core form) (define (fn-core form)
;; The (fn name args rettype . body) list, without pub/extern ;; The (fn name args rettype . body) list, without pub/extern
(if (memq (first form) '(pub extern)) (if (memq (car form) '(pub extern))
(cdr form) (cdr form)
form)) form))
@@ -161,42 +161,46 @@
;; If FORMS starts with a string, possibly after comment forms, return ;; If FORMS starts with a string, possibly after comment forms, return
;; that string and FORMS without it. Otherwise #f and FORMS unchanged ;; that string and FORMS without it. Otherwise #f and FORMS unchanged
(let loop ((fs forms) (prefix (list))) (let loop ((fs forms) (prefix (list)))
(match fs (cond
(() (values #f forms)) ((null? fs)
(((and cmt ('comment . _)) . rest) (values #f forms))
(loop rest (cons cmt prefix))) ((comment-form? (car fs))
(((? string? doc) . rest) (loop (cdr fs) (cons (car fs) prefix)))
(values doc (append (reverse prefix) rest))) ((string? (car fs))
(_ (values #f forms))))) (values (car fs) (append (reverse prefix) (cdr fs))))
(else
(values #f forms)))))
(define (extract-fn-docstring fn-form) (define (extract-fn-docstring fn-form)
(let ((lift (let ((n (fn-header-length fn-form)))
(lambda (proto body) (if (< (length fn-form) n)
(let-values (((doc rest) (take-leading-docstring body))) (values #f fn-form)
(if doc (let-values (((doc body) (take-leading-docstring (drop fn-form n))))
(values doc (copy-form-source! fn-form (append proto rest))) (if doc
(values #f fn-form)))))) (values doc
(match fn-form (copy-form-source! fn-form
(('pub 'fn name args ret . body) (append (take fn-form n) body)))
(lift `(pub fn ,name ,args ,ret) body)) (values #f fn-form))))))
(('extern 'fn name args ret . body)
(lift `(extern fn ,name ,args ,ret) body))
(('fn name args ret . body)
(lift `(fn ,name ,args ,ret) body))
(_ (values #f fn-form)))))
(define (extract-aggregate-docstring form) (define (extract-aggregate-docstring form)
;; ([pub] struct|union|enum name "doc" (fields ...) . attrs)
;; A string immediately after the name is the docstring; comments ;; A string immediately after the name is the docstring; comments
;; between name and fields are not skipped, they already confuse the ;; between name and fields are not skipped, they already confuse the
;; writer ;; writer
(match form (let* ((pub? (eq? (car form) 'pub))
(('pub (and kind (or 'struct 'union 'enum)) (core (if pub? (cdr form) form)))
(? symbol? name) (? string? doc) . rest) (if (and (pair? (cdr core))
(values doc (copy-form-source! form `(pub ,kind ,name ,@rest)))) (symbol? (cadr core))
(((and kind (or 'struct 'union 'enum)) (pair? (cddr core))
(? symbol? name) (? string? doc) . rest) (string? (caddr core)))
(values doc (copy-form-source! form `(,kind ,name ,@rest)))) (let ((new-core (cons (car core)
(_ (values #f form)))) (cons (cadr core) (cdddr core)))))
(values (caddr core)
(copy-form-source! form
(if pub?
(cons 'pub new-core)
new-core))))
(values #f form))))
(define (with-docstring doc form acc) (define (with-docstring doc form acc)
;; acc is newest-first; FORM is consed last so the final reverse ;; acc is newest-first; FORM is consed last so the final reverse
@@ -295,28 +299,27 @@
(define (sex-fn? form) (define (sex-fn? form)
"The `form` must be toplevel. "The `form` must be toplevel.
Returns #f if the form is not a function, returns the form otherwise" Returns #f if the form is not a function, returns the form otherwise"
(match form (and (non-empty-list? form)
((fn . _) form) (let ((core (fn-core form)))
((pub fn . _) form) (and (pair? core) (eq? (car core) 'fn) form))))
(else #f)))
(define (sex-fn-public? fn-form) (define (sex-fn-public? fn-form)
(eq? (first fn-form) 'pub)) (eq? (car fn-form) 'pub))
(define (sex-fn-name fn-form) (define (sex-fn-name 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"))
(second (fn-core fn-form))) (cadr (fn-core fn-form)))
(define (sex-fn-arglist fn-form) (define (sex-fn-arglist 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"))
(third (fn-core fn-form))) (caddr (fn-core fn-form)))
(define (sex-fn-return-type fn-form) (define (sex-fn-return-type 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"))
(fourth (fn-core fn-form))) (cadddr (fn-core fn-form)))
(define (sex-fn-prototype fn-form) (define (sex-fn-prototype fn-form)
"Returns all except body" "Returns all except body"

View File

@@ -8,7 +8,6 @@
(chicken process-context) (chicken process-context)
(chicken string) (chicken string)
fmt fmt
matchable
reader reader
srfi-1 srfi-1
utils) utils)
@@ -75,30 +74,31 @@
(define (public-fn-interface form) (define (public-fn-interface form)
;; (pub fn name args ret . body) -> prototype, keeping a docstring so ;; (pub fn name args ret . body) -> prototype, keeping a docstring so
;; the importer can emit it above the declaration ;; the importer can emit it above the declaration
(match form (let ((header (take form 5)))
(('pub 'fn name args ret) (let loop ((body (drop form 5)))
form) (cond
(('pub 'fn name args ret ('comment . _) . rest) ((null? body) header)
(public-fn-interface `(pub fn ,name ,args ,ret ,@rest))) ((and (pair? (car body)) (eq? (caar body) 'comment))
(('pub 'fn name args ret (? string? doc) . _) (loop (cdr body)))
`(pub fn ,name ,args ,ret ,doc)) ((string? (car body)) (append header (list (car body))))
(('pub 'fn name args ret . _) (else header)))))
`(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)
(match form (case (car form)
;; Reduced to a prototype, still `pub', so the importer declares it ((pub)
;; with external linkage (case (cadr form)
(('pub 'fn . _) ;; A function is reduced to a prototype and keeps its `pub', so
(cons (copy-form-source! form (public-fn-interface form)) acc)) ;; the importing unit declares it with external linkage
(('pub 'var name type . _) ((fn)
(cons (copy-form-source! form `(extern var ,name ,type)) acc)) (cons (copy-form-source! form (public-fn-interface form)) acc))
(('pub (or 'define 'defmacro 'enum 'import 'include 'struct 'typedef 'union) . _) ;; A variable becomes an `extern' declaration
(cons (copy-form-source! form (cdr form)) acc)) ((var)
(('pub . _) (cons (copy-form-source! form (cons 'extern (take (cdr form) 3))) acc))
(sex-error form "pub must be followed by a definition" form)) ((define defmacro enum import include struct typedef union)
(_ acc))) (cons (copy-form-source! form (cdr form)) acc))
(else (sex-error form "pub must be followed by a definition" form))))
(else acc)))
(define (load-persistent-module-paths) (define (load-persistent-module-paths)
(let ((sex-module-path-env-var (let ((sex-module-path-env-var