aboutsummaryrefslogtreecommitdiff
path: root/module/c/preprocessor2.scm
diff options
context:
space:
mode:
Diffstat (limited to 'module/c/preprocessor2.scm')
-rw-r--r--module/c/preprocessor2.scm188
1 files changed, 126 insertions, 62 deletions
diff --git a/module/c/preprocessor2.scm b/module/c/preprocessor2.scm
index 3f9552c5..b9b11d0a 100644
--- a/module/c/preprocessor2.scm
+++ b/module/c/preprocessor2.scm
@@ -4,17 +4,20 @@
:use-module (srfi srfi-88)
:use-module (c cpp-environment)
- :use-module (c eval2)
+ :use-module ((c eval2) :select (c-boolean->boolean))
+ :use-module ((c eval-basic) :select (eval-basic-c))
:use-module ((c cpp-environment function-like-macro)
- :select (function-like-macro variadic? identifier-list))
- :use-module ((c cpp-environment object-like-macro) :select (object-like-macro object-like-macro?))
+ :select (function-like-macro variadic?))
+ :use-module ((c cpp-environment object-like-macro)
+ :select (object-like-macro object-like-macro?))
:use-module ((c cpp-environment internal-macro) :select (internal-macro))
- :use-module ((hnh util) :select (-> ->> intersperse aif swap unless unval break/all))
+ :use-module ((hnh util) :select (-> ->> intersperse swap unless unval break/all))
:use-module ((hnh util lens) :select (set modify cdr*))
:use-module (hnh util path)
:use-module (hnh util type)
:use-module (hnh util object)
:use-module ((hnh util values) :select (abort* on-fst on-snd apply/values))
+ :use-module ((hnh util io) :select (read-file))
:use-module ((c lex2)
:select (lex
placemaker
@@ -27,15 +30,16 @@
:use-module (c unlex)
:use-module (c cpp-types)
:use-module (c cpp-util)
+ :use-module ((c ast) :select (build-ast))
:export (_Pragma-macro
- defined-macro
+ ;; defined-macro
c-search-path
- handle-preprocessing-tokens))
+ handle-preprocessing-tokens
+ preprocess-string
+ make-default-environment
+ ))
-(define (read-file path)
- (call-with-input-file path (@ (ice-9 rdelim) read-string)))
-
(define-syntax-rule (alist-of variable key-type value-type)
@@ -55,12 +59,6 @@
(define (ellipsis-token? token) (equal? "..." (punctuator-token? token)))
-;; TODO
-;; > #if defined X
-;; is equivalent to
-;; > #if defined(X)
-
-
;; parameters is a lexeme list, as returned by parse-parameter-list
(define (build-parameter-map macro parameters)
(typecheck macro cpp-macro?)
@@ -201,15 +199,6 @@
expand##))))
-
-;; Expand object-like macro
-
-;; #define VALUE 10
-;; #define str(x) #x
-;; #define OTHER str(VALUE)
-;; OTHER
-;; ⇒ "VALUE"
-
;; remaining-tokens should be the token stream just after the name of the macro
(define (expand-macro environment macro noexpand-list remaining-tokens)
(typecheck environment cpp-environment?)
@@ -378,19 +367,6 @@
body: (lex (number->string (current-line environment)))))))
-(define defined-macro
- (internal-macro
- identifier: "defined"
- body: (lambda (environment arguments)
- (typecheck arguments (and (list-of (list-of lexeme?))
- (not null?)))
- (aif (identifier-token? (car (list-ref arguments 0)))
- (let ((in-env (boolean->c-boolean (in-environment? environment it))))
- (values environment (lex (number->string in-env))))
- (scm-error 'cpp-error "defined"
- "Invalid parameter list to `defined': ~s"
- (list arguments) #f)))))
-
(define _Pragma-macro
(internal-macro
identifier: "_Pragma"
@@ -436,21 +412,65 @@
environment))))
-;; 6.10.1 p. 4
-(define (resolve-constant-expression cpp-tokens)
- ;; (typecheck tokens (list-of lexeme?))
+;; (next-token-or-group (lex " x y")
+;; => (car (lex "x"))
+;; => (lex " y")
+;; next-token-or-group (lex " (x) y")
+;; => (lex "(x)")
+;; => (lex " y")
+(define (next-token-or-group tokens)
+ (let loop ((tokens (drop-whitespace tokens)))
+ (cond ((null? tokens)
+ ;; TODO error here?
+ '())
+ ((left-parenthesis-token? (car tokens))
+ (parse-group tokens))
+ ((preprocessing-token? (car tokens))
+ (car+cdr tokens))
+ (else
+ (loop (cdr tokens))))))
+
+
+
+(define (parse-if-line environment cpp-tokens)
(define zero (car (lex "0")))
- #;
- (define tokens
- (map preprocessing-token->token
- (map (lambda (token)
- (cond ((identifier-token? token) zero)
- (else token)))
- (remove whitespace-token? tokens))))
+ (define one (car (lex "1")))
+
+ (define (drop-identifiers tokens)
+ (map (lambda (x) (if (identifier-token? x)
+ zero x))
+ tokens))
+
+ (drop-identifiers
+ (let ((environment (join-file-line environment)))
+ (let loop ((tokens cpp-tokens))
+ (cond ((null? tokens) '())
+ ((identifier-token? (car tokens))
+ (lambda (s) (and s (string=? s "defined")))
+ => (lambda _
+ (let ((next rest (next-token-or-group (cdr tokens))))
+ (cons (if (and=> (identifier-token? (if (parenthesis-group? next)
+ ;; TODO empty group
+ (car (drop-whitespace (parenthesis-group-tokens next)))
+ next))
+ (lambda (it) (in-environment? environment it)))
+ one zero)
+ (loop rest)))))
+
+ ((and (identifier-token? (car tokens))
+ (not (marked-noexpand? (car tokens))))
+ (let ((_ tokens
+ (maybe-extend-identifier environment
+ (identifier-token? (car tokens))
+ (lexeme-noexpand (car tokens))
+ (cdr tokens))))
+ (loop tokens)))
+
+ (else (cons (car tokens)
+ (loop (cdr tokens)))))))))
+
+
- 'TODO
- ;; eval as per 6.6
- )
@@ -498,13 +518,16 @@
(typecheck environment cpp-environment?)
;; (typecheck tokens (list-of lexeme?))
- (-> (extend-environment environment (list defined-macro))
- ;; no newlines in #if line
- ((unval resolve-token-stream 1) tokens)
- resolve-constant-expression
- c-boolean->boolean
- (if (enter-active-if environment)
- (enter-inactive-if environment))))
+ (if (->> tokens
+ (parse-if-line environment)
+ (remove whitespace-token?)
+ merge-string-literals
+ build-ast
+ ;; 6.10.1 p. 4
+ eval-basic-c
+ c-boolean->boolean)
+ (enter-active-if environment)
+ (enter-inactive-if environment)))
;; environment, string, (list token) → environment, (list token)
(define (maybe-extend-identifier environment identifier noexpand-list remaining-tokens)
@@ -719,11 +742,10 @@
(unless (in-conditional? env)
(err "#endif outside conditional"))
(leave-if env)))
- ((else) (lambda (env _)
- (unless (in-conditional? env)
- (err "#else outside conditional"))
- (flip-flop-if env)))
- ;; ((elif) (lambda ))
+ ((else elif) (lambda (env _)
+ (unless (in-conditional? env)
+ (err "#else outside conditional"))
+ (flip-flop-if env)))
((define) resolve-define)
((undef) (lambda (env body) (remove-identifier env (identifier-token? (car body)))))
((line) handle-line-directive)
@@ -750,3 +772,45 @@
(else (err "Unexpected middle of line, (near ~s)"
(unlex tokens))))))
+
+
+
+
+(define* (make-default-environment key: (now (localtime (current-time))))
+ (call-with-values
+ (lambda ()
+ (preprocess-string
+ (format
+ #f
+ "
+#define __STDC__ 1
+#define __STDC_HOSTED__ 1
+#define __STDC_VERSION__ 201112L
+#define __DATE__ \"~a\"
+#define __TIME__ \"~a\"
+"
+ ;; TODO format should always be in
+ ;; english, and not tranlated
+ (strftime "\"%b %_d %Y\"" now)
+ (strftime "\"%H:%M:%S\"" now))
+ (make-environment)))
+ (lambda (env _) env)))
+
+
+(define* (preprocess-string str optional: (environment (make-default-environment)))
+ (on-snd
+ (->>
+ (abort*
+ (->> str
+;;; Phase 1-3
+ tokenize
+;;; 4. Execution of preprocessing directives, all preprocessing directives are then deleted
+ (handle-preprocessing-tokens environment)))
+
+;;; 5. (something with character sets)
+;;; 7. Whitespace tokens are discarded, each preprocessing token is converted into a token
+ (remove whitespace-token?)
+;;; 6. concatenation of string literals
+;;; Should be done before removal of whitespace, but I don't understand why
+ merge-string-literals
+ )))