forked from alex-eg/sex
read-time feature expressions
'#+' and '#-' introduce conditional compilation: the form that follows is kept only when the feature expression is true, and otherwise is read and thrown away. An expression is a feature name, or and / or / not of them. They are read time, not compile time. Default features are the host's software-version, software-type and machine-type as CHICKEN reports them, plus what --features flag adds.
This commit is contained in:
45
reader.scm
45
reader.scm
@@ -7,6 +7,8 @@
|
||||
;;; - a leading `.' rewritten to the symbol `dot-access'
|
||||
;;; - `;' comments preserved as (comment "...") forms, so they can be
|
||||
;;; re-emitted into the generated C (keeping the source mapping)
|
||||
;;; - #+ / #- feature expressions, which decide at read time what the
|
||||
;;; compiler gets to see at all
|
||||
;;; It also records the source location of every form it reads (see
|
||||
;;; utils' form-source), so the C writer can emit #line directives.
|
||||
|
||||
@@ -15,6 +17,8 @@
|
||||
(scheme base) ; make-parameter
|
||||
(chicken base)
|
||||
(chicken pathname)
|
||||
(chicken platform) ; software-version, machine-type
|
||||
(only srfi-1 every any) ; srfi-1 also has an append-reverse
|
||||
utils)
|
||||
|
||||
;;; Sentinels for structural tokens
|
||||
@@ -160,7 +164,8 @@
|
||||
((string->number s) => identity)
|
||||
(else (string->symbol s))))
|
||||
|
||||
;;; #-dispatch: booleans, characters, vectors, block/datum comments
|
||||
;;; #-dispatch: booleans, characters, vectors, block/datum comments,
|
||||
;;; feature expressions
|
||||
(define (read-hash port)
|
||||
(let ((c (get-ch port)))
|
||||
(cond
|
||||
@@ -171,8 +176,46 @@
|
||||
((char=? c #\() (list->vector (read-list port close-paren)))
|
||||
((char=? c #\|) (skip-block-comment port 1) (next-token port))
|
||||
((char=? c #\;) (read-datum port) (next-token port)) ; datum comment
|
||||
((char=? c #\+) (read-conditional port #t))
|
||||
((char=? c #\-) (read-conditional port #f))
|
||||
(else (error "Unsupported # syntax" c)))))
|
||||
|
||||
;;; Feature expressions
|
||||
;;;
|
||||
;;; #+linux (include GL/gl.h) kept on Linux
|
||||
;;; #-macosx (foo) kept only on other than macOS
|
||||
;;; #+(and unix (not macosx)) (bar) and / or / not combine them
|
||||
;;;
|
||||
(define (platform-features)
|
||||
(list (software-version) (software-type) (machine-type)))
|
||||
|
||||
;;; The host's features are the default, so anything reading Sex sees
|
||||
;;; what the compiler would. sexc rebinds this to add --features
|
||||
(define current-features (make-parameter (platform-features)))
|
||||
|
||||
(define (feature-true? test)
|
||||
(cond
|
||||
((symbol? test) (and (memq test (current-features)) #t))
|
||||
((pair? test)
|
||||
(case (car test)
|
||||
((and) (every feature-true? (cdr test)))
|
||||
((or) (any feature-true? (cdr test)))
|
||||
((not)
|
||||
(if (and (pair? (cdr test)) (null? (cddr test)))
|
||||
(not (feature-true? (cadr test)))
|
||||
(error "Feature expression `not' takes exactly one operand" test)))
|
||||
(else (error "Unknown operator in feature expression" (car test)))))
|
||||
(else (error "Malformed feature expression" test))))
|
||||
|
||||
;;; The #-/#+ preceded datum is always read -- there is no other way
|
||||
;;; to know where it ends -- and then either returned or dropped
|
||||
(define (read-conditional port keep-when)
|
||||
(let ((keep (eq? keep-when (feature-true? (read-datum port)))))
|
||||
(if keep
|
||||
(read-datum port)
|
||||
(begin (read-datum port)
|
||||
(next-token port)))))
|
||||
|
||||
;;; #t / #true / #f / #false. `val' is the boolean; consume any
|
||||
;;; trailing name characters and validate
|
||||
(define (read-bool port val)
|
||||
|
||||
Reference in New Issue
Block a user