From 771969e57e0cef63febbcd281ec2ed3e81685463 Mon Sep 17 00:00:00 2001 From: Matthias Benkard Date: Sat, 26 Jan 2008 10:51:29 +0100 Subject: Support case-sensitive selector designators. darcs-hash:da29e9f38c99f5a9e558edd20afff7400fced2e4 --- Lisp/libobjcl.lisp | 92 +++++++++++++++++++++++++++++++++++++++------ Lisp/method-invocation.lisp | 38 +++++++++++++++++-- Lisp/name-conversion.lisp | 13 +++++-- Lisp/tests.lisp | 13 ++++++- 4 files changed, 136 insertions(+), 20 deletions(-) diff --git a/Lisp/libobjcl.lisp b/Lisp/libobjcl.lisp index 6c8469a..3d72783 100644 --- a/Lisp/libobjcl.lisp +++ b/Lisp/libobjcl.lisp @@ -394,12 +394,19 @@ If *selector-name* is a **list** of **symbol**s, all **symbol**s are first split into parts separated by hyphens and each part converted into a **string** according to the following rules: -1. The first part is fully converted to **lowercase**. +1. 1. If the keywords' **symbol name**s do contain **lowercase** + **character**s, their case is left intact. -2. Any additional parts are also fully converted to **lowercase** except - for their first letters, which are left intact. + 2. If the keywords' **symbol name**s do not contain any **lowercase** + **character**s, the following steps are taken in order to adjust + their case. -3. If the symbol is a **keyword**, the resulting **string** is suffixed + 1. The first part is fully converted to **lowercase**. + + 2. Any additional parts are also fully converted to **lowercase** + except for their first letters, which are left intact. + +2. If the symbol is a **keyword**, the resulting **string** is suffixed by a **colon** (`:'). After that, all parts are concatenated in order to form a @@ -424,10 +431,27 @@ by which __invoke__ converts its arguments into a *message name*. (find-selector '(:string-with-c-string :encoding)) ;=> # + #.(setq \\*readtable\\* (copy-readtable)) + #.(setf (readtable-case \\*readtable\\*) :invert) + (find-selector '(:stringWithCString :encoding)) + ;=> # + + +## Note: + +Setting the **readtable case** of the **current readtable** to `:INVERT` +is a good way of making the Lisp system behave as traditionally as +possible while making Objective-C method names case-sensitive. + +On the other hand, writing all method names in lower case while +separating parts by hyphens works nicely in all of the `:INVERT`, +`:UPCASE`, `:DOWNCASE`, and `:PRESERVE` modes as well as Allegro CL's +*modern mode*. + ## See also: - __intern-selector__" + __intern-selector__, __selector__" (or (typecase selector-name (string (find-selector-by-name selector-name)) @@ -463,12 +487,19 @@ If *selector-name* is a **list** of **symbol**s, all **symbol**s are first split into parts separated by hyphens and each part converted into a **string** according to the following rules: -1. The first part is fully converted to **lowercase**. +1. 1. If the keywords' **symbol name**s do contain **lowercase** + **character**s, their case is left intact. + + 2. If the keywords' **symbol name**s do not contain any **lowercase** + **character**s, the following steps are taken in order to adjust + their case. -2. Any additional parts are also fully converted to **lowercase** except - for their first letters, which are left intact. + 1. The first part is fully converted to **lowercase**. -3. If the symbol is a **keyword**, the resulting **string** is suffixed + 2. Any additional parts are also fully converted to **lowercase** + except for their first letters, which are left intact. + +2. If the symbol is a **keyword**, the resulting **string** is suffixed by a **colon** (`:'). After that, all parts are concatenated in order to form a @@ -493,10 +524,27 @@ by which __invoke__ converts its arguments into a *message name*. (intern-selector '(:string-with-c-string :encoding)) ;=> # + #.(setq \\*readtable\\* (copy-readtable)) + #.(setf (readtable-case \\*readtable\\*) :invert) + (intern-selector '(:stringWithCString :encoding)) + ;=> # + + +## Note: + +Setting the **readtable case** of the **current readtable** to `:INVERT` +is a good way of making the Lisp system behave as traditionally as +possible while making Objective-C method names case-sensitive. + +On the other hand, writing all method names in lower case while +separating parts by hyphens works nicely in all of the `:INVERT`, +`:UPCASE`, `:DOWNCASE`, and `:PRESERVE` modes as well as Allegro CL's +*modern mode*. + ## See also: - __find-selector__" + __find-selector__, __selector__" (typecase selector-name (string (intern-selector-by-name selector-name)) @@ -581,7 +629,29 @@ If *selector-designator* is a __selector__, it is simply returned. ;=> # (selector '(:string-with-c-string :encoding)) - ;=> #" + ;=> # + + #.(setq \\*readtable\\* (copy-readtable)) + #.(setf (readtable-case \\*readtable\\*) :invert) + (selector '(:stringWithCString :encoding)) + ;=> # + + +## Note: + +Setting the **readtable case** of the **current readtable** to `:INVERT` +is a good way of making the Lisp system behave as traditionally as +possible while making Objective-C method names case-sensitive. + +On the other hand, writing all method names in lower case while +separating parts by hyphens works nicely in all of the `:INVERT`, +`:UPCASE`, `:DOWNCASE`, and `:PRESERVE` modes as well as Allegro CL's +*modern mode*. + + +## See also: + + __find-selector__, __intern-selector__" (etypecase designator (selector designator) diff --git a/Lisp/method-invocation.lisp b/Lisp/method-invocation.lisp index c95a43c..1ff9c74 100644 --- a/Lisp/method-invocation.lisp +++ b/Lisp/method-invocation.lisp @@ -44,12 +44,19 @@ All uneven-numbered *message components*, which must be **symbol**s, are first split into parts separated by hyphens and each part converted into a **string** according to the following rules: -1. The first part is fully converted to **lowercase**. +1. 1. If the keywords' **symbol name**s do contain **lowercase** + **character**s, their case is left intact. -2. Any additional parts are also fully converted to **lowercase** except - for their first letters, which are left intact. + 2. If the keywords' **symbol name**s do not contain any **lowercase** + **character**s, the following steps are taken in order to adjust + their case. -3. If the symbol is a **keyword**, the resulting **string** is suffixed + 1. The first part is fully converted to **lowercase**. + + 2. Any additional parts are also fully converted to **lowercase** + except for their first letters, which are left intact. + +2. If the symbol is a **keyword**, the resulting **string** is suffixed by a **colon** (`:'). After that, all parts are concatenated in order to form a @@ -64,6 +71,10 @@ if as the second **argument** to __invoke-by-name__. :string-with-u-t-f-8-string \"Mulk.\") ;=> # + (invoke (find-objc-class 'ns-string) + '|:stringWithUTF8String| \"Mulk.\") + ;=> # + (invoke (find-objc-class 'ns-object) 'self) ;=> # @@ -77,6 +88,25 @@ if as the second **argument** to __invoke-by-name__. :encoding 4) ;=> # + #.(setq \\*readtable\\* (copy-readtable)) + #.(setf (readtable-case \\*readtable\\*) :invert) + (invoke (find-objc-class 'ns-string) + :stringWithCString \"Mulk.\" + :encoding 4) + ;=> # + + +## Note: + +Setting the **readtable case** of the **current readtable** to `:INVERT` +is a good way of making the Lisp system behave as traditionally as +possible while making Objective-C method names case-sensitive. + +On the other hand, writing all method names in lower case while +separating parts by hyphens works nicely in all of the `:INVERT`, +`:UPCASE`, `:DOWNCASE`, and `:PRESERVE` modes as well as Allegro CL's +*modern mode*. + ## See also: diff --git a/Lisp/name-conversion.lisp b/Lisp/name-conversion.lisp index 767edaa..7a7f476 100644 --- a/Lisp/name-conversion.lisp +++ b/Lisp/name-conversion.lisp @@ -22,14 +22,19 @@ (defun message-component->string (symbol) (let* ((components (split-sequence #\- (symbol-name symbol) :remove-empty-subseqs t)) + (downcasep (notany #'lower-case-p (symbol-name symbol))) (acc-string (reduce #'(lambda (x y) (concatenate 'string x y)) (mapcar #'(lambda (x) - (concatenate 'string - (string (char x 0)) - (string-downcase (subseq x 1)))) + (if downcasep + (concatenate 'string + (string (char x 0)) + (string-downcase (subseq x 1))) + x)) (subseq components 1)) - :initial-value (string-downcase (first components))))) + :initial-value (if downcasep + (string-downcase (first components)) + (first components))))) (if (eql (find-package '#:keyword) (symbol-package symbol)) (concatenate 'string acc-string ":") diff --git a/Lisp/tests.lisp b/Lisp/tests.lisp index beff6f9..f7a6dbb 100644 --- a/Lisp/tests.lisp +++ b/Lisp/tests.lisp @@ -46,6 +46,10 @@ (- (random (abs most-negative-double-float))))) +#.(prog1 nil + (defparameter *readtable-backup* *readtable*) + (setq *readtable* (copy-readtable)) + (setf (readtable-case *readtable*) :invert)) (deftestsuite base-functions (objective-cl) () (:equality-test #'objc-equal) @@ -62,7 +66,14 @@ ((ensure-same (find-selector "stringWithUTF8String:") (find-selector '(:string-with-u-t-f-8-string)))) ((ensure-same (find-selector "stringWithCString:encoding:") - (find-selector '(:string-with-c-string :encoding)))))) + (find-selector '(:string-with-c-string :encoding)))) + ;; Case-sensitivity. + ((ensure-same (find-selector "stringWithCString:encoding:") + (find-selector '(:stringWithCString :encoding)))) + ((ensure-same (find-selector "stringWithUTF8String:") + (find-selector :stringWithUTF8String))))) +#.(prog1 nil + (setq *readtable* *readtable-backup*)) (deftestsuite primitive-method-invocation (objective-cl) -- cgit v1.2.3