Recently Written · git

defsl

Dependencies from the lisp macro system, not the reader.

git clone https://github.com/equwal/defsl

Log | Files | Refs


README.org (3973 bytes)

1 #+TITLE: SL: A Package Dependency Language
2 #+AUTHOR: Spenser Truex
3 #+EMAIL: web@spensertruex.com
4 
5 Version 1.0 is out!
6 
7 [[https://github.com/equwal/sl][Github]] | [[https://equwal.com/sl--dependency-language][Homepage]]
8 
9 SL is a complex dependency fixer.
10 
11 Use SL to support two wildly different forks of a library like swank
12 and slynk.
13 
14 #+BEGIN_SRC
15 (defsl operator-arglist :fn :eq slynk swank)
16 #+END_SRC
17 
18 SL is a Domain Specific Language (ie. simple programming language) for dealing
19 with ambiguous dependency situations. It is more expressive than the standard
20 method in Common Lisp: the use of reader macros. It provides symbol aliasing
21 based on compile-time rules.
22 
23 Symbols are then defined in the SL package, which is an artifact of the
24 fact that it was designed primarily to allow supporting both the slynk
25 and swank language servers.
26 
27 TODO: allow defining them in other packages
28 
29 * Rationale and Purpose
30 
31 I made this since =asdf= was not enough abstraction for what I needed: to
32 arbitrarily choose dependencies and renames for any symbol. I could write what I
33 am doing twice, or I could write the compiler for =SL= (ie. the first two
34 letters of SLy and SLime). Once I have that, I can bend that fork until I have a
35 coherent set of names for all the functions I need, and which work on both (in
36 principle). You could just intern the symbols (like with #+ reader syntax) but
37 those tend to explode exponentially; since SL is using the compiler,
38 a much more powerful solution is implemented in macros.
39 
40 * Benefits
41 
42 - Symbol aliasing at compile time provides a means of abstracting separate
43 but similar interfaces. Forked projects, or projects that duplicate work.
44 - Far more expressive and concise than reader macros, while still very simple.
45 - There is also the use case of renaming things for import, like
46 =with-gensyms= to =with-unique-names= or similar.
47 
48 * Drawbacks
49 
50 none
51 
52 * Examples
53 
54   The only external macro is =defsl=. There is BNF below, though some examples are in order.
55 
56 ** Simple
57    This defines =operator-arglist= (in the current package) as
58    =slynk:operator-arglist=, unless =slynk= is unavailable, in which case
59    =swank:operator-arglist= is used.
60 
61 #+BEGIN_SRC lisp
62 (defsl operator-arglist :fn :eq slynk swank)
63 #+END_SRC
64 
65 The =:fn= shows that a FUNCTION is being defined, as opposed to a =:sym= symbol;
66 to define another namespace a list is required: =(accessor-fn boundp-fn)=. =:eq=
67 denotes that the packages have the same name for this function.
68 For this simplest of examples, consider the reader macro alternative.
69 
70 #+BEGIN_SRC lisp
71 #+slynk
72 (setf (symbol-function 'operator-arglist)
73       slynk:operator-arglist)
74 #+(and (not slynk) swank)
75 (setf (symbol-function 'operator-arglist)
76       swank:operator-arglist)
77 #+END_SRC
78 
79 ** Complex example
80 
81 #+BEGIN_SRC lisp
82 (defsl gensymmer (macro-function macro-function)
83     utils with-unique-names
84     alexandria with-gensyms)
85 #+END_SRC
86 
87 To break this down:
88 - =sl:gensymmer= is now defined as =utils:with-unique-names=.
89 - =macro-function= was used twice: once as a =setfable= place, and once as a
90 predicate.
91 - If the =utils= package does not exist, then =sl:gensymmer= is defined as =alexanrdia:with-gensyms=.
92 - to define different names for each package, they must be "qualified" with the package name.
93 
94 * Install
95   Use ASDF to install. Usually this should work:
96 #+BEGIN_SRC sh
97 $ cd ~/common-lisp/
98 $ git clone git@github.com:equwal/sl.git
99 CL-USER> (asdf:load-system :sl)
100 #+END_SRC
101 
102 * BNF
103 #+BEGIN_EXAMPLE
104 (defsl <sl-name> <fnsym>  <package spec>)
105 <package spec> ::= <eq>
106                | <packages>
107 <eq> ::= :eq <preferences>
108 <fnsym> ::= :fn
109         | :sym
110         | <fnpair>
111 
112 <fnpair> ::= (setfable-place bound-predicate)
113 <packages> ::= <package> <fn name> <more packages>
114 <package> ::= symbol
115 <fn name> ::= symbol
116 <preferences> ::= <package> <more packages>
117 <more packages> ::= ε
118                 | <package>
119                 | <package> <more packages>
120 #+END_EXAMPLE
121 * Non-issues:
122 - defsl is a hygienic macro