[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 11/25] system/foreign/declarative: new macro
From: |
KAction |
Subject: |
[PATCH 11/25] system/foreign/declarative: new macro |
Date: |
Mon, 18 Jul 2016 18:17:34 +0300 |
From: Dmitry Bogatov <address@hidden>
* module/system/foreign/declarative.scm: new macro
`define-foreign-bitmask' that defines `foreign-type' for bitmask,
with proper encoding, decoding and validation.
---
module/system/foreign/declarative.scm | 46 +++++++++++++++++++++++++++++++
test-suite/tests/foreign-declarative.test | 38 ++++++++++++++++++++++---
2 files changed, 80 insertions(+), 4 deletions(-)
diff --git a/module/system/foreign/declarative.scm
b/module/system/foreign/declarative.scm
index fb949db..b0c31a0 100644
--- a/module/system/foreign/declarative.scm
+++ b/module/system/foreign/declarative.scm
@@ -174,3 +174,49 @@
(set-procedure-property! frontend-function 'name 'function-name)
frontend-function))))))
+(define* (make-foreign-bitmask name #:rest flags)
+ (define-syntax-rule (filter-map-flags (symbol value) stmt stmt* ...)
+ (filter-map (lambda (flag)
+ (match flag
+ ((symbol . value) stmt stmt* ...)))
+ flags))
+ (define (encode-proc obj)
+ (unless (list? obj)
+ (set! obj (list obj)))
+ (apply logior
+ (filter-map-flags (symbol value)
+ (and (member symbol obj)
+ value))))
+ (define (decode-proc int)
+ (filter-map-flags (symbol value)
+ (and (not (zero? (logand int value)))
+ symbol)))
+ (define symbols (map car flags))
+ (define (validate-proc obj)
+ (define (allowed-symbol? x)
+ (member x symbols))
+ (define correct-symbol? (and (symbol? obj)
+ (allowed-symbol? obj)))
+ (define correct-list? (and (list? obj)
+ (every allowed-symbol? obj)))
+ (unless (or correct-list? correct-symbol?)
+ (throw
+ 'wrong-type-arg
+ (*validate-function-name*)
+ "Wrong type argument named `~A'\
+ (expected `~A' bitmask: symbol or list of symbols from ~A): ~S"
+ (list (*validate-argument-name*) name symbols obj)))
+ #t)
+ (make-foreign-type name
+ #:encode-proc encode-proc
+ #:decode-proc decode-proc
+ #:type int
+ #:validate-proc validate-proc))
+
+(export define-foreign-bitmask)
+(define-syntax-rule (define-foreign-bitmask name ((symbol value) ...))
+ (define name (make-foreign-bitmask 'name '(symbol . value) ...)))
+
+;; Local Variables:
+;; eval: (put (quote filter-map-flags) (quote scheme-indent-function) 1)
+;; End:
diff --git a/test-suite/tests/foreign-declarative.test
b/test-suite/tests/foreign-declarative.test
index cf285d4..450c653 100644
--- a/test-suite/tests/foreign-declarative.test
+++ b/test-suite/tests/foreign-declarative.test
@@ -22,10 +22,11 @@
#:use-module (system foreign)
#:use-module (system foreign declarative))
-(define ft-encode-proc (@@ (system foreign declarative) ft-encode-proc))
-(define ft-decode-proc (@@ (system foreign declarative) ft-decode-proc))
-(define ft-clone-proc (@@ (system foreign declarative) ft-clone-proc))
-(define ft-free-proc (@@ (system foreign declarative) ft-free-proc))
+(define ft-encode-proc (@@ (system foreign declarative) ft-encode-proc))
+(define ft-decode-proc (@@ (system foreign declarative) ft-decode-proc))
+(define ft-clone-proc (@@ (system foreign declarative) ft-clone-proc))
+(define ft-validate-proc (@@ (system foreign declarative) ft-validate-proc))
+(define ft-free-proc (@@ (system foreign declarative) ft-free-proc))
(with-test-prefix "foreign-type primitives"
(pass-if "int: encoder is identity"
@@ -61,3 +62,32 @@
(c-sin "string, not number"))
(lambda (key function-name . rest)
(eq? function-name 'c-sin))))))
+
+(define-foreign-bitmask file-permissions:
+ ((read 4) (write 2) (execute 1)))
+
+(with-test-prefix "bitmasks"
+ (pass-if "correctly encodes"
+ (equal? 7 ((ft-encode-proc file-permissions:) '(read write execute))))
+ (pass-if "correctly decodes"
+ (equal? '(read write) ((ft-decode-proc file-permissions:) 6)))
+ (pass-if "validator accepts valid values [1]"
+ ((ft-validate-proc file-permissions:) 'write))
+ (pass-if "validator accepts valid values [2]"
+ ((ft-validate-proc file-permissions:) '(read execute)))
+ (pass-if "validator rejects bogus symbol"
+ (equal?
+ (catch 'wrong-type-arg
+ (lambda ()
+ ((ft-validate-proc file-permissions:) 'bogus)
+ #f)
+ (lambda _args
+ #t))))
+ (pass-if "validator rejects bogus value in list"
+ (equal?
+ (catch 'wrong-type-arg
+ (lambda ()
+ ((ft-validate-proc file-permissions:) '(read write 15))
+ #f)
+ (lambda _args
+ #t)))))
--
I may be not subscribed. Please, keep me in carbon copy.
- Re: [PATCH 02/25] Define <ffi-type> structure, (continued)
- [PATCH 03/25] Mirror types from system/foreign as <foreign-type>, KAction, 2016/07/18
- [PATCH 04/25] Write boilerplate for primitive types, KAction, 2016/07/18
- [PATCH 05/25] Fix bug in `default' macro, KAction, 2016/07/18
- [PATCH 06/25] Basic implementation of `define-foreign-function', KAction, 2016/07/18
- [PATCH 07/25] Introduce foreign-type predicates, KAction, 2016/07/18
- [PATCH 08/25] Add keywords for `define-foreign-function' macro, KAction, 2016/07/18
- [PATCH 10/25] Refactor type validation in `define-foreign-function', KAction, 2016/07/18
- [PATCH 09/25] system/foreign/declarative: rename `predicate' to `validate', KAction, 2016/07/18
- [PATCH 11/25] system/foreign/declarative: new macro,
KAction <=
- [PATCH 13/25] system/foreign/declarative.scm: export string foreign type, KAction, 2016/07/18
- [PATCH 12/25] Improve deriving c symbol name from scheme one, KAction, 2016/07/18
- [PATCH 14/25] foreign/declarative: mirror more primitive types, KAction, 2016/07/18
- [PATCH 15/25] New macro: with-pointer, KAction, 2016/07/18
- [PATCH 16/25] Configure emacs file-local indention, KAction, 2016/07/18
- [PATCH 17/25] system/foreign/declarative: unexport internal macro, KAction, 2016/07/18
- [PATCH 18/25] write documentation for (system foreign declarative), KAction, 2016/07/18