source: project/wiki/eggref/5/srfi-105 @ 37971

Last change on this file since 37971 was 37971, checked in by dieggsy, 12 months ago

Document more recent versions

File size: 9.4 KB
Line 
1[[tags: egg]]
2
3[[toc:]]
4
5== srfi-105
6
7Curly infix expressions. For more information, see
8[[http://srfi.schemers.org/srfi-105/srfi-105.html|SRFI-105]].
9
10=== Modules
11==== srfi-105
12
13The core srfi as specified in
14[[http://srfi.schemers.org/srfi-105/srfi-105.html|SRFI-105]]. Note that the
15srfi does not on its own handle mixed operators or square-bracket neoteric
16expressions.
17
18===== Notes
19====== Dot notation
20
21The special dot notation described in the original srfi is not supported,
22meaning the following examples do not work with this implemenation:
23
24* {{ {read(. options)} ⇒ (read . options) }}
25* {{ {a . z} ⇒ ($nfx$ a . z) }}
26
27This is because chicken reserves the {{.}} symbol for special use, and I didn't
28feel it would be consistent (or worth jumping through hoops) to support it
29inside curly braces.
30
31====== Neoteric expressions
32
33In part due to the way that Chicken's reader {{##sys#read}} is implemented, and
34in part becasue of the way neoteric-expression (n-expression) support is
35implemented, n-expressions inside curly braces (e.g. {{f(x)}}) are only
36partially supported. In particular, they will work as long as the n-expression
37is not nested directly within a lisp expression. However, this can be worked
38around by adding curly brackets directly around the n-expression.
39
40To show what this means, here are some (non-exhaustive) examples:
41
42DOES work - simple n-expressions:
43
44* {{{f(x)} ⇒ (f x)}}
45* {{{f(x) + 1} ⇒ (+ (f x) 1)}}
46* {{{3 + f(x) + g(x)} ⇒ (+ 3 (f x) (g x))}}
47
48DOES work - nested/chained n-expressions:
49
50* DOES work: {{{f(x)(y)(z)} ⇒ (((f x) y) z)}}
51* DOES work: {{{3 + 4 + f(x)(y)(z)} ⇒ (+ 3 4 (((f x) y) z))}}
52* DOES work: {{{f(g(h(x)))} ⇒ (f (g (h x)))}}
53* DOES work: {{{f(g(h(x))) * 5 * 3} ⇒ (* 5 3 (f (g (h x))))}}
54* DOES work: {{{f(g(h(x)))(y)} ⇒ ((f (g (h x))) y)}}
55* DOES work: {{{f(g{h(x) + 1})} ⇒ (f (g (+ (h x) 1)))}}
56
57DOES NOT work - n-expressions nested inside lisp syntax:
58
59* {{{ (f (g h(x))) } ⇒ (f (g (h x)))}} - use {{{ (f (g {h(x)})) }}} instead
60* {{{#(1 2 f(a) 4)} ⇒ #(1 2 (f a) 4)}} - use  {{{#(1 2 {f(a)} 4)}}} instead
61* {{{(f #;g(x) h(x))} ⇒ (f (h x))}} - no workaround available
62* Any of the above working neoteric expressions within any lisp syntax - enclose them with additional curly brackets instead.
63
64===== Further details
65
66n-expression support is implemented by locally modifying the internal
67{{##sys#read}} procedure which is not itself recursive, but rather uses an
68internal (and inaccesible) recursive read procedure. This means any
69modifications made to {{##sys#read}} procedure cannot take effect inside lisp
70expressions, as the internal recursive read handles those and has no knowledge
71of the modifications.
72
73The internal read procedure does however have knowledge of special read syntax,
74which is why this limitation can be 'escaped' with more curly bracket
75expressions.
76
77This could potentially be worked around with a solid parser, but is a little
78out of the scope of this extension.
79
80==== srfi-105.extra
81
82Adds support for mixed operators and square bracket neoteric expressions.
83Importing this implies {{(import srfi-105)}}, so one should not have to import
84both. {{$nfx$}} as specified in the original SRFI document is implemented as
85syntax in order to be able to handle syntax operators like {{and}}, {{or}}, and
86some of the aliases defined in this module.
87
88===== Usage
89
90Upon importing this module, curly infix expressions with mixed operators as
91well as neoteric calls of the form {{x[a]}} should just work. Certain operators
92are handled specially by default. See {{mixed-operator-precedence}} for more
93information.
94
95===== Notes
96====== Unary operators in mixed expressions
97
98"Loose" unary operators in mixed expressions are not supported. That is,
99something like {{ {#t and not #f} }} should result in an error. To use unary
100operators, use lisp syntax ({{ {#t and (not #f)} }}) or n-expressions {{ {#t
101and not(#f)} }}.
102
103====== Neoteric square bracket expressions
104
105Square bracket n-expressions such as {{a[x]}} are handled using SRFI-123's
106{{ref*}}. See [[https://wiki.call-cc.org/eggref/5/srfi-123|srfi-123]] for more
107information.
108
109===== Precedence
110
111<parameter>(mixed-operator-precedence)</parameter>
112
113Defines the order of operations, or operator precedence, for supported
114operations. This should be a list of lists of symbols, each specifying a
115precedence group, ordered from highest to lowest precedence. Symbols are
116grouped with left-associativity by default. Instead of a symbol, {{(#:right
117symbol)}} can be used instead, indicating that {{symbol}} is an operator with
118right associativity.
119
120If the first element of a group is the keyword {{#:comparison}}, the following
121members of that group should be treated as comparison operators that return a
122boolean, and are grouped as non-associative operators with {{and}}. For
123example, the group {{(#:comparison < >)}} implies that {{ {1 > 3 < 4} }} will
124be grouped as {{ (and (1 > 3) (3 > 4)) }}
125
126The special group {{(#:other)}} is a placeholder for any operators not present
127in (mixed-operator-precedence). These are grouped with left associativity. The
128parameter should contain at least this group, and is properly guarded as such.
129
130The default roughly matches
131[[https://docs.python.org/3/reference/expressions.html#operator-precedence|python's
132operator precedence]]:
133
134<enscript highlight=scheme>
135'(((right: expt) (right: **))
136  (* / modulo % quotient remainder
137     fx* fx/ fxmod fxrem
138     fp* fp/)
139  (+ - fx+ fx- fp+ fp-)
140  (arithmetic-shift << >> fxshl fxshr)
141  (bitwise-and & fxand)
142  (bitwise-xor ^ fxxor)
143  (bitwise-ior ior fxior)
144  (other:)
145  (comparison: < <= > >= =
146               fx< fx<= fx> fx>= fx=
147               fp< fp<= fp> fp>= fp=)
148  (and)
149  (or))
150</enscript>
151
152===== Aliases
153
154These are provided because of the way the core srfi (unmixed operators) works.
155By default, something like {{ {1 expt 3 expt 4} }} will not work. Since the
156srfi is associativity and precedence neutral, it will simply expand this to {{
157(expt 1 3 4) }}, which will result in an error since the {{ expt }} procedure
158only takes 2 arguments.
159
160Thus, most of the following are syntax wrappers for common infix operators
161whose chicken scheme implementation only takes two arguments. The macros handle
162more than two arguments with the correct associativity, and are fit for use in
163'simple' (unmixed) curly infix expressions.
164
165The procedure aliases simply provide common shorthand for some unary operators.
166
167<syntax>(** . rest)</syntax>
168
169Applies {{expt}} on all arguments right-associatively.
170
171<syntax>(% . rest)</syntax>
172
173Applies {{modulo}} on all arguments left-associatively.
174
175<syntax>(<< . rest)</syntax>
176
177Applies {{arithmetic-shift}} on all arguments left-associatively. Equivalent to
178a left shift if shift is positive, right shift if shift is negative.
179
180<syntax>(>> . rest)</syntax>
181
182Applies {{arithmetic-shift}} (with inverted direction) on all arguments
183left-associatively. Equivalent to a right shift if shift is positive, left
184shift if shift is negative.
185
186<syntax>(^ . rest)</syntax>
187
188Applies {{bitwise-xor}} on all arguments left-associatively.
189
190<syntax>(ior . rest)</syntax>
191
192Applies {{bitwise-ior}} on all arguments left-associatively.
193
194<syntax>(& . rest)</syntax>
195
196Applies {{bitwise-and}} on all arguments left-associatively.
197
198<procedure>(~ arg)</procedure>
199
200An alias for {{bitwise-not}}.
201
202<procedure>(~ arg)</procedure>
203An alias for boolean {{not}}.
204
205===== Special symbols
206
207In general, you shouldn't need to use the following directly, as curly
208expressions containing mixed operators or neoteric calls of the form {{x[a]}}
209will simply automatically expand into {{($nfx$ ...)}} or {{($bracket-apply$
210x a)}}, respectively.
211
212<syntax>($nfx$ . rest)</syntax>
213
214Group the infix expression specified by the elements of {{rest}} according to
215{{mixed-operator-precedence}}.
216
217<procedure>($bracket-apply$ obj i)</procedure>
218An alias for SRFI-123's {{ref*}}.
219
220=== Author
221
222Reference implementation by David A. Wheeler and Alan Manual K. Gloria,
223Chicken-specific implementation and extras by Diego A. Mundo.
224
225=== License
226
227Copyright (C) 2012 David A. Wheeler and Alan Manuel K. Gloria. All Rights
228Reserved.
229Copyright (C) 2019 Diego A. Mundo
230
231Permission is hereby granted, free of charge, to any person obtaining a copy of
232this software and associated documentation files (the "Software"), to deal in
233the Software without restriction, including without limitation the rights to
234use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
235of the Software, and to permit persons to whom the Software is furnished to do
236so, subject to the following conditions:
237
238The above copyright notice and this permission notice shall be included in all
239copies or substantial portions of the Software.
240
241THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
242IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
243FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
244AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
245LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
246OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
247SOFTWARE.
248
249=== Version History
250
251; 0.1.6 : Add simpler and more robust neoteric expression support
252; 0.1.5 : Rewrite curly expression reader more in accordance with reference
253; 0.1.5 : Rewrite curly expression reader more in accordance with reference
254; 0.1.4 : Temporarily drop neoteric expression support
255; 0.1.3 : Rename extras module to srfi-105.extra
256; 0.1.2 : Use standard keyword syntax, properly check for (#:other) group
257; 0.1.1 : Initial implementation of base srfi + extras
Note: See TracBrowser for help on using the repository browser.