This repository has been archived on 2024-06-20. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
coffee.pygments/external/scheme-builtins-generator.scm
Jean Abou Samra 93d4cce817 Scheme: autogenerate lists of builtins
This enriches the space of recognized builtins.

Note that this also fixes the space after a builtin being included in
the token.
2022-02-08 16:36:49 +01:00

116 lines
3.4 KiB
Scheme

;; Autogenerate a list of Scheme keywords (i.e., macros) and built-in
;; functions. This is written for the Guile implementation. The
;; principle of autogenerating this has the advantage of catching many
;; builtins that would be tedious to maintain by hand, and the
;; disadvantage that some builtins very specific to Guile and not
;; relevant to other implementations are caught as well. However,
;; since Scheme builtin function names tend to be rather specific,
;; this should not be a significant problem.
(define port (open-output-file "../pygments/lexers/_scheme_builtins.py"))
(display
"\"\"\"
pygments.lexers._scheme_builtins
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Scheme builtins.
:copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
:license: BSD, see LICENSE for details.
\"\"\"
"
port)
(format port
"\n# Autogenerated by external/scheme-builtins-generator.scm\n\
# using Guile ~a.\n\n"
(version))
(use-modules (srfi srfi-1)
(ice-9 match))
(define relevant-modules
;; This is a nightmare. Scheme builtins are split in
;; gazillions of standards, SRFIs and implementation
;; extensions. With so many sources, it's hard to define
;; what is really a Scheme builtin. This is a rather
;; conservative list of Guile modules that might be used
;; the most frequently (somewhat subjective, admittedly).
'(
;; The real builtins.
(guile)
;; Let's include the fundamental list library.
(srfi srfi-1)
;; define-record-type
(srfi srfi-9)
;; let-values, let*-values
(srfi srfi-11)
;; case-lambda
(srfi srfi-16)
;; Pattern matching
(ice-9 match)
;; Included for compatibility with files written for R5RS
(rnrs r5rs)))
(define (get-all-bindings module)
;; Need to recurse to find all public bindings. module-map
;; only considers the module's own bindings.
(let* ((own (module-map cons module))
(uses (module-uses module)))
(append own (append-map get-all-bindings uses))))
(define all-bindings
(append-map
;; Need to use module-public-interface to restrict to
;; public bindings. Note that module-uses already
;; returns public interfaces.
(lambda (mod-path)
(let* ((mod-object (resolve-module mod-path))
(iface (module-public-interface mod-object)))
(get-all-bindings iface)))
relevant-modules))
(define (filter-for pred)
(filter-map
(match-lambda
((key . variable)
(and (variable-bound? variable)
(let ((value (variable-ref variable)))
(and (pred value)
key)))))
all-bindings))
(define (sort-and-uniq lst pred)
(let loop ((lst (sort lst pred))
(acc '()))
(match lst
(() (reverse! acc))
((one . rest)
(loop (drop-while (lambda (elt)
(equal? elt one))
rest)
(cons one acc))))))
(define (dump-py-list lst)
(string-join
(map
(lambda (name)
(format #f " \"~a\"," name))
(sort-and-uniq
(map symbol->string lst)
string<?))
"\n"))
(define (dump-builtins name pred extra)
(format port
"~a = {\n~a\n}\n\n"
name
(dump-py-list (append extra (filter-for pred)))))
(define extra-procedures
;; These are found in RnRS but not implemented by Guile.
'(load transcript-off transcript-on))
(dump-builtins 'scheme_keywords macro? '())
(dump-builtins 'scheme_builtins procedure? extra-procedures)