Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PKG: Lexicons-killer read macro.

8 views
Skip to first unread message

Kaz Kylheku

unread,
Dec 12, 2008, 2:49:58 AM12/12/08
to
;;; provides #@ read macro
(load "pkg")

;;; some test packages

(defpackage :p1
(:use :cl)
(:export :e0 :e1 :e2)
(:intern :i0 :i1 :i2))

(defpackage :p2
(:use :cl)
(:export :e1 :e2 :e3)
(:intern :i1 :i2 :i3))

;;;
;;; Syntax:
;;;
;;; syntax ::= #@ directive form
;;; | #@ ( {directive}* ) form
;;;
;;; directive := (use {package-spec}*)
;;; (from package-spec import {symbol-spec}*)
;;;

Exploration:


;; Scoped to following form; USE takes only exported symbols.
'(#@(use p1) (e1 i1) #@(use p2) (e1 i1)) -> ((P1:E1 I1) (P2:E1 I1))

;; Right supersedes left (P2 over P1), no conflicts:
#@((use p1) (use p2)) '(e0 e1 e2 e3) -> (P1:E0 P2:E1 P2:E2 P2:E3)

;; Reversed order: P1 takes P2
#@((use p2) (use p1)) '(e0 e1 e2 e3) -> (P1:E0 P1:E1 P1:E2 P2:E3)

;; from-package-import demo:
#@((from p1 import i0 i1)
(from p2 import i1 i2)) '(i0 i1 i2 i3) -> (P1::I0 P2::I1 P2::I2 I3)

;; no effect on surrounding package:
'(e0 e1 e2 e3 i0 i1 i2 i3) -> (E0 E1 E2 E3 I0 I1 I2 I3)

;; symbols interned in surrounding package overriden, no conflicts:
#@((use p1) (from p2 import i1))
'(e0 e1 i0 i1) -> (P1:E0 P1:E1 I0 P2::I1)


;; punch in symbol from surrounding package:
#@((use p1) (from cl-user import e0))
'(e0 e1) -> (E0 P1:E1)

;; nesting:

#@(use p1)
'(e1 #@(use p2)
(e1 #@(from cl-user import e1)
e1)) -> (P1:E1 (P2:E1 E1))


Code to be released on paste server Real Soon.

Ron Garret

unread,
Dec 12, 2008, 3:58:57 AM12/12/08
to
In article <200812271...@gmail.com>,
Kaz Kylheku <kkyl...@gmail.com> wrote:

Wow, lexicons must be getting traction if you feel the need to write a
lexicon-killer :-)

rg

Kaz Kylheku

unread,
Dec 12, 2008, 4:56:21 AM12/12/08
to
On 2008-12-12, Kaz Kylheku <kkyl...@gmail.com> wrote:
> ;;; provides #@ read macro
> (load "pkg")
>
> ;;; some test packages
>
> (defpackage :p1
> (:use :cl)
> (:export :e0 :e1 :e2)
> (:intern :i0 :i1 :i2))
>
> (defpackage :p2
> (:use :cl)
> (:export :e1 :e2 :e3)
> (:intern :i1 :i2 :i3))
>
> ;;;
> ;;; Syntax:
> ;;;
> ;;; syntax ::= #@ directive form
> ;;; | #@ ( {directive}* ) form
> ;;;
> ;;; directive := (use {package-spec}*)
> ;;; (from package-spec import {symbol-spec}*)
> ;;;

More syntax:


;;; directive := (use {package-spec}*)
;;; (from package-spec import {symbol-spec}*)

;;; (keep {symbol-spec}*)
;;; (inherit {symbol-spec}*)
;;; (top)

The KEEP directive specifies which symbols newly interned during
the reading of FORM should be retained, i.e. propagated
to the enclosing package. Keep with no arguments (keep)
means do not propagate any new symbols. This means
that any symbols newly created in FORM turn into gensyms
automagically. The default behavior if no (KEEP) form is specified is that all
of the symbols newly interned are propagated to the outer package.
KEEP also causes the specified symbols to be inherited
from the surrounding package, if they are visible there,
to prevent conflicts.

INHERIT means that only the following symbols, which must exist in the
surrounding package, are to be visible to FORM. Overrides anything to the left.
Must be followed by suitable KEEP to prevent conflicts,
since INHERIT will cause any symbols not on the list to be
freshly interned, and by default they will all be propagated
into the surrounding package.

The TOP directive resets the visibility to the top-level
package which was in effect when the reader was invoked.


Examples:

Write a simplified DEFPACKAGE, without using #: on symbols. Let's quote it so
we see the form as it is read. Note treatment of LIST.

#@(keep)
'(defpackage foo (:use cl) (:export xyzzy quux) (:shadow list))

--> (DEFPACKAGE FOO (:USE CL) (:EXPORT #:XYZZY #:QUUX) (:SHADOW LIST))

Propagate the symbol FOO from the form, but let others
lapse into gensyms. Show that the symbols are interned,
first before becoming homeless, using *print-circle*:

(setf *print-circle* t)

#@(keep foo)
'(defun foo (x y z) (+ x y z))

--> (DEFUN FOO (#1=#:X #2=#:Y #3=#:Z) (+ #1# #2# #3#))

Reset visibility to top without having to know explicitly
what that package is called:

#@(from p1 import e1) '(e1 #@(top) e1)

--> (P1:E1 E1)

Demonstrate inherit and keep: LIST symbol is not inherited
this time:

#@((inherit defpackage)
(keep))
'(defpackage foo (:use cl) (:shadow list))

--> (DEFPACKAGE #:FOO (:USE #:CL) (:SHADOW #:LIST))

Kaz Kylheku

unread,
Dec 12, 2008, 5:48:39 PM12/12/08
to
On 2008-12-12, Kaz Kylheku <kkyl...@gmail.com> wrote:
> Code to be released on paste server Real Soon.

As promised:

http://paste.lisp.org/display/72068

Cheers ...

Kaz Kylheku

unread,
Dec 12, 2008, 6:34:33 PM12/12/08
to

Look ma, no : keywords:

#@((keep)(use keyword))
(defpackage my-package
(use cl)
(export my-symbol))

The form is interned in an anonymous package which uses the
keyword package. If :use and :export have been previously
interned as keywords, this will just use them.

Probably not wise to rely on that, but neat anyway. :)

;;
;; New feature idea just occured to me: INTERN directive.
;; Specifies that these symbols are locally interned, and
;; thus hide anything that was previously imported
;; or inherited
;;
;; Voila: macro hygiene! Multiple occurences
;; of SYM in the form are the same SYM, but
;; it's not known outside of the form, so
;; we can introduce it into the macro expansion.
;;
@((intern sym) ;; overrides any outside SYM
(keep)) ;; keep nothing, so SYM will become a gensym.

(defmacro macro-a (param &body body)
`(let ((sym ,param)) (prog1 sym ,@body)))

;; must implement!

0 new messages