by Marc Nieper-Wißkirchen
This SRFI is currently in final status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-211@nospamsrfi.schemers.org
. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.
This SRFI describes common syntactic extensions of the syntax-rules
macro facility of R5RS and the base R6RS and R7RS libraries. In particular,
library namespaces are defined where these extensions can be located
and which can be tested against in cond-expand
forms.
This SRFI was in draft state for a very long time. The main reason for that was that the author of this SRFI was torn between getting it finalized or withdrawing it. The main reasons that spoke for withdrawal are summarized below. In spite of this, the author finally decided to ask the SRFI editor for finalization because members of the Scheme community expressed their opinion that this SRFI would serve the community more in finalized instead of withdrawn status.
The abbreviation SRFI stands for Scheme Request for
Implementation. It is, however, probably not a good
idea to implement those parts of this SRFI that haven't
already been specified elsewhere. This SRFI is a proof
of concept that explicit-renaming macros can be made
compatible with syntax-case
and can borrow
the power of the latter to make robust unhygienic macros
possible. The resulting system is, however, slower and
still less comfortable that the syntax-case
system, so implementations should rather be motivated to
implement syntax-case
instead of trying to
patch explicit-renaming macros.
A definition of the syntactic closure macro facility is
still missing in this SRFI. While the author could provide
one, it would still be unclear how to write robust
unhygienic macros with syntactic closures. In particular,
the canonical implementation of syntax-rules
with syntactic closures does not behave well with respect to
unhygienic macros written with syntactic closures. Thus,
the author considers syntactic closures broken and hasn't
found a reason to promote them outside of thinking
academically about them.
It is better to move a facility
like with-ellipsis
into its own SRFI.
Various Scheme implementations define extensions to
the syntax-rules
macro facility that can be found
in R7RS, for
example explicit-renaming macros, syntax-case
,
identifier macros or variable transformers. While different
implementation of the same extension will usually be compatible,
they cannot usually be found under the same namespace.
This SRFI therefore defines a number of standard libraries
under which supporting implementations export the identifiers of
those syntax-rules
extensions they implement so
that portable code can be written without explicitly loading
implementation-specific libraries.
Let us assume that we want to write a library that exports the
macro skip
. The arguments of the skip
macro are a non-negative exact integer n and a number
of body forms. A skip
macro is evaluated by
dropping the first n body forms and evaluating the
rest as a body.
Writing such a macro is not possible
with syntax-rules
, but it is possible both
with er-macro-transformer
and syntax-case
. With the following
R7RS code, the library works on all implementations
that support at least er-macro-transformer
or syntax-case
, and this SRFI, of course.
(define-library (skip) (export skip) (import (scheme base)) (cond-expand ((library (srfi 211 syntax-case)) (import (srfi 211 syntax-case)) (begin (define-syntax skip (lambda (x) (syntax-case x () ((_ n b ...) (with-syntax (((b ...) (list-tail (syntax->datum #'n) #'(b ...)))) #'(letrec* () b ...)))))))) ((library (srfi 211 er-macro-transformer)) (import (srfi 211 er-macro-transformer)) (begin (define-syntax skip (er-macro-transformer (lambda (e r c) `(,(r 'letrec*) () ,@(list-tail (cddr e) (cadr e))))))))))
As a baseline for this specification, we build on the definitions used in the R6RS, especially those described in chapter 12 of the R6RS Standard Libraries.
Syntax objects, wrapped syntax objects, and (syntax objects representing) identifiers are defined as in section 12.2 of the R6RS Standard Libraries.
A presyntax object is a generalization of a syntax object that allows symbols at its leaves. More precisely, a presyntax object is
A preidentifier is a value that is either an identifier or a symbol.
A transformer is a transformation procedure or a variable transformer as in section 12.3 of the R6RS Standard Libraries, or an explicit-renaming transformer, an implicitly renaming transformer, a syntactic closures transformer, or a Lisp transformer.
In the context of a transformer being applied to transcribe a macro use of a keyword, injecting a symbol results in an identifier with the same name that behaves as if it were introduced into the code where the keyword was used.
In the same context, renaming a symbol results in an identifier with the same name that behaves as if it were introduced into the code where the keyword was defined.
In the same context, the injection of a presyntax object is a syntax object recursively built from it by replacing each symbol at the leaves with its injection, and the renaming of presyntax object is a syntax object recursively build from it by replacing each symbol at the leaves with its renaming. Both the injection and the renaming preserve any shared or cyclic structure.
(identifier? obj)
This procedure is defined in section 12.5 of the R6RS Standard Libraries.
(preidentifier? obj)
The preidentifier?
procedure
returns #t
if obj
is either
an identifier or a symbol, and #f
otherwise.
(bound-identifier=? id1 id2)
This procedure is defined in section 12.5 of the R6RS Standard Libraries.
(free-identifier=? id1 id2)
This procedure is defined in section 12.5 of the R6RS Standard Libraries.
(syntax->datum obj)
This procedure is defined in section 12.6 of the R6RS Standard Libraries.
(presyntax->datum obj)
It is an error if obj
is not a presyntax object.
The procedure presyntax->datum
strips all
syntactic information from the presyntax
object obj
and returns the corresponding
Scheme datum. The difference from syntax->datum
is
that symbols at the leaves are explicitly allowed and are
converted to themselves.
(identifier->symbol id)
It is an error if id
is not an identifier.
The procedure identifier->symbol
returns the
symbolic name of the identifier id
,
i.e. the result of applying syntax->datum
to id
.
(preidentifier->symbol id)
It is an error if id
is not a preidentifier.
The procedure preidentifier->symbol
returns
the symbolic name of the identifier id
.
The difference from syntax->datum
is that symbols
are allowed and are converted to their own symbolic names.
(unwrap-syntax
obj
)
It is an error if obj
is not a syntax object.
If obj
is an identifier or an unwrapped
syntax object, the procedure unwrap-syntax
returns obj
unchanged.
If obj
is a wrapped syntax
object, unwrap-syntax
returns the underlying unwrapped syntax object.
(unwrap-presyntax
obj
)
It is an error if obj
is not a presyntax object.
If obj
is a preidentifier or an
unwrapped presyntax object, the procedure unwrap-syntax
returns obj
unchanged.
If obj
is a wrapped syntax
object, unwrap-syntax
returns the underlying
unwrapped syntax object.
(datum->syntax id datum)
This procedure is defined in section 12.6 of the R6RS Standard Libraries.
(construct-identifier id symbol)
It is an error if id
is not an
identifier or if symbol
is not a
symbol.
This procedure returns the result of
applying datum->syntax
to the
arguments id
and symbol
.
(generate-temporaries list)
This procedure is defined in section 12.7 of the R6RS Standard Libraries.
(generate-identifier)
(generate-identifier symbol)
The generate-identifier
procedure returns a new,
unique identifier. The symbolic name of the identifier
is symbol
if provided, and unspecified
otherwise.
(syntax-violation who message form)
(syntax-violation who message form subform)
This procedure is defined in section 12.9 of the R6RS Standard Libraries.
Note: An implementation that does not have condition objects as defined in chapter 7 of the R6RS Standard Libraries should raise an exception with an appropriate native condition object instead.
(make-variable-transformer transformer)
The make-variable-transformer
procedure behaves as
defined in section 12.3 of the R6RS Standard
Libraries, except that transformer
can
be a transformation procedure, an explicit-renaming
transformer, an implicitly renaming transformer,
a syntactic closures transformer, or a Lisp
transformer.
(er-macro-transformer proc)
It is an error if proc
is not a
procedure accepting a single argument.
The er-macro-transformer
procedure returns an
explicit-renaming transformer such that each use of a macro
whose keyword is associated with it is transcribed in the
following way:
At first, the input form is recursively fully unwrapped,
preserving any shared or cyclic structure.
Then proc
is called with three
arguments, the fully unwrapped input form and two
procedures rename
and compare
. It is an error if it does
not return a presyntax object. The symbols at the leaves of
the presyntax object returned are then replaced by their
injections to yield the output form as a syntax object.
The rename
procedure accepts a single
argument expr
. It is an error
if expr
is not a presyntax
object. Rename
returns a syntax object
that is built from expr
by replacing the
symbols at the leaves by their renamings. This syntax object
may share structure with expr
.
The compare
procedure accepts exactly two arguments
id1
and id2
. It is an error if
the ids
are not
preidentifiers. Compare
returns the result of free-identifier=?
applied to the injections of
id1
and id2
.
Note: In the preceding
paragraphs, er-macro-transformer
is defined through
an (informally given) operational semantics. This does not mean
that er-macro-transformer
has to be implemented by
following each step of the operational semantics. Any
implementation is correct as long as it behaves operationally
equivalently. This is like syntax-case
is defined in
the R6RS through Kent Dybvig's, Robert Hieb's, and
Carl Bruggeman's marks and substitutions algorithm but
does not preclude other algorithms like the one implemented by
André van Tonder in Larceny.
(ir-macro-transformer proc)
It is an error if proc
is not a
procedure accepting a single argument.
The ir-macro-transformer
procedure returns an
implicitly renaming transformer such that each use of a macro
whose keyword is associated with it is transcribed in the
following way:
At first, the input form is recursively fully unwrapped,
preserving any shared or cyclic structure.
Then proc
is called with three
arguments, the fully unwrapped input form and two
procedures inject
and compare
. It is an error if it does
not return a presyntax object. The symbols at the leaves of
the presyntax object returned are then replaced by their
renamings to yield the output form as a syntax object.
The inject
procedure accepts a single
argument expr
. It is an error
if expr
is not a presyntax
object. Inject
returns a syntax object
that is built from expr
by replacing the
symbols at the leaves by their injections. This syntax object
may share structure with expr
.
The compare
procedure accepts exactly two arguments
id1
and id2
. It is an error if
the ids
are not
preidentifiers. Compare
returns the
result of free-identifier=?
applied to the
renamings of
id1
and id2
.
(lisp-transformer proc)
It is an error if proc
is not a
procedure accepting a single argument.
The lisp-transformer
procedure returns a Lisp
transformer such that each use of a macro whose keyword is
associated with it replaces the macro use with the injection of
the datum resulting from invoking proc
on the datum representing the macro use.
The following procedures are mentioned without being given any semantics. The reason is that the usual semantics as given in the MIT/GNU Scheme manual doesn't allow the definition of robust unhygienic macros. (The reasons for that are similar to those why the unmodified explicit-renaming system is unsuitable for unhygienic macros.)
However, while it is clear (as this SRFI shows) how to extend
the explicit-renaming facility so that it becomes compatible
with syntax-case
and allows robust unhygienic
macros, a universally accepted solution for syntactic closures
hasn't been proposed yet. The author of this SRFI has
implemented an extended version of syntactic closures compatible
with syntax-case
in his Unsyntax Scheme, but this
extension is incompatible with the canonical
implementation of syntax-rules
with syntactic
closures, which, in turn, is incompatible with robust unhygienic
syntactic closure macros.
Regardless, the names of the procedures forming the syntactic
closures facility are given here so that the exports
of (srfi 211 syntactic-closures)
are fixed.
Despite a missing specification here, a Scheme programmer can
still refer to (srfi 211 syntactic-closures)
to
write programs that will be portable to most implementations of
syntactic closures in practise.
(sc-macro-transformer proc)
(rsc-macro-transformer proc)
(make-syntactic-closure environment free-names form)
(close-syntax form environment)
(capture-syntactic-environment proc)
(sc-identifier=? obj)
(make-synthetic-identifier identifier)
(keyword datum …)
(keyword datum … . datum)
keyword
(set! keyword datum)
These macro uses are defined in section 9.2 of the R6RS.
Note: Every implementation must support the first form
of a macro use and should support all four forms. It must support
the third form if it provides identifier-syntax
, it
must support the third and fourth form if it
provides make-variable-transformer
, and it must
support all four forms if it
provides syntax-case
.
(with-ellipsis ellipsis
identifier expression or
definition …)
Syntax: Ellipsis identifier
is an identifier.
Semantics: The expressions and
definitions
are spliced into the surrounding
lexical context just as if they were contained in
a begin
sequencing construct but expanded in an
extended syntactic environment. In this extended syntactic
environment,
an ellipsis
in a
macro pattern or template is an identifier such that binding
the ellipsis
identifier
would shadow free references to
it.
Note: The normal behavior is that
an ellipsis
in a macro
pattern or template is an identifier that has the same binding
as ...
.
Rationale: In the syntax-case
system,
the syntax-rules
facility is destructured into its
natural components, a pattern matcher (syntax-case
)
and a templating engine (syntax
). Accordingly, in
such a system, syntax-rules
is naturally defined in
terms of syntax-case
and syntax
, and
the R6RS gives an according definition
of syntax-rules
in section 12.8 of its Standard
Libraries.
R7RS adopted all of the syntax-rules
extensions
of SRFI
46: Basic Syntax-rules Extensions, including the
possibility of specifying a custom ellipsis.
The with-ellipsis
form described here gives the same
power to syntax-case
and syntax
and
ensures that syntax-rules
is still a simple derived
form of syntax-case
and syntax
.
The extended form
(syntax-rules ellipsis (pattern literal …) syntax rule …)
of a syntax-rules
transformer is equivalent to
(with-ellipsis ellipsis (syntax-rules (pattern literal …) syntax rule …))
The following example comes from the GNU Guile Reference Manual.
(define-syntax define-quotation-macros (lambda (x) (syntax-case x () ((_ (macro-name head-symbol) ...) #'(begin (define-syntax macro-name (lambda (x) (with-ellipsis ::: (syntax-case x () ((_ x :::) #'(quote (head-symbol x :::))))))) ...))))) (define-quotation-macros (quote-a a) (quote-b b) (quote-c c)) (quote-a 1 2 3) ⟹ (a 1 2 3)
(syntax-case expression (literal …) syntax-case clause)
This syntax is defined in section 12.4 of the R6RS Standard Libraries.
Contrary to that specification, it is not a syntax violation if
the ellipsis or underscore appears
in (literal …)
. If
the ellipsis or underscore appear
in (literal …)
,
they are treated as literal identifiers.
Rationale: This extension to
R6RS's syntax-case
is necessary so that
R7RS's syntax-rules
can be easily defined in
terms of syntax-case
.
Note 1: The author of this SRFI believes that the exclusion of the ellipsis and the underscore in the list of literal identifiers was a mistake of the R6RS.
Note 2: In the lexical scope of an with-ellipsis
form, the meaning of the ellipsis is changed.
(syntax template)
This syntax is defined in section 12.4 of the R6RS Standard Libraries.
Note: In the lexical scope of an with-ellipsis
form, the meaning of the ellipsis is changed.
(with-syntax ((pattern expression) …) body)
This syntax is defined in section 12.8 of the R6RS Standard Libraries.
Note: In the lexical scope of an with-ellipsis
form, the meaning of the ellipsis is changed.
(quasisyntax template)
This syntax is defined in section 12.8 of the R6RS Standard Libraries.
Note: In the lexical scope of an with-ellipsis
form, the meaning of the ellipsis is changed.
unsyntax
This auxiliary syntax is defined in section 12.8 of the R6RS Standard Libraries.
unsyntax-splicing
This auxiliary syntax is defined in section 12.8 of the R6RS Standard Libraries.
(identifier-syntax template)
(identifier-syntax (id1) template1) ((set! id2 pattern) template1))
This syntax is defined in section 11.19 of the R6RS.
(define-macro keyword transformer)
Syntax: Keyword
is an identifier
and transformer
an expression.
Semantics: This syntax definition is equivalent to the syntax definition
(define-syntax keyword (lisp-transformer transformer))
(define-macro (keyword
. formals)
body1 body1 …)
Syntax: Keyword
is an
identifier, formals
a
formal arguments list,
and transformer
an
expression.
Semantics: This syntax definition is equivalent to the syntax definition
(define-syntax keyword (lisp-transformer (lambda (exp) (let-values ((formals (apply values (cdr exp)))) body1 body2 …))))
(define-syntax-parameter keyword expression)
This syntax is defined in SRFI 139.
(syntax-parameterize ((keyword expression) …) body)
This syntax is defined in SRFI 139.
An implementation does not have to provide all the libraries below. If it provides a library, it has to provide it as a whole and not just a subset of it.
(srfi 211)
Exports all identifiers defined in this SRFI.
(srfi 211 low-level)
Exports the identifiers
syntax
,unwrap-syntax
,identifier?
,free-identifier=?
,bound-identifier=?
,identifier->symbol
,generate-identifier
, andconstruct-identifier
.Rationale: Although this thirty-year-old low-level macro
facility is usually not mentioned when talking about macro
systems, it has the advantage that it is on the one hand simple
and abstract enough to serve as a common denominator between
Schemes that have explicit-renaming macro transformers and
Schemes that have syntax-case
and on the other hand
powerful enough so that it can define syntax-rules
as a macro.
In a certain sense, this macro facility
is syntax-case
without syntax-case
.
Compared to the explicit-renaming facility,
which is quite comparable to this low-level macro facility, it
does not assume that abstract syntax objects are Scheme datums
but enforces the use of unwrap-syntax
. While this
can be no-op when implemented on top of explicit-renaming macro
transformers, it is not in the case when implemented on top of
the marks and substitutions implementation
of syntax-case
. Similarly, it does not assume that
identifiers that are bound-identifier=?
are
already eq?
. These further abstractions make the
system compatible to the usual syntax-case
systems.
The system is, in principle, as expressive as
the syntax-case
system (but without all bells and
whistles) and thus more powerful than explicit renaming.
To the explicit-renaming facility, it adds that a macro transformer can also be given by procedure taking a syntax object and returning a syntax object. Thanks to the abstract nature of a syntax object, this can be easily achieved by implementations.
(srfi 211 explicit-renaming)
Exports the identifiers
er-macro-transformer
, andpreidentifier?
as identifier?
.Note 1: In legacy implementations, to test whether
binding one identifier would also bind the other, the
equivalence predicate eqv?
is used in the context
of explicit-renaming macros. In general, however, this
equivalence predicate is too fine as soon as the system is
augmented with a means to capture the syntactic environment of
an identifier as the following code shows:
(let ((x #f)) (let ((x #f)) ...))
In the context of ...
binding one of the two
identifiers named x
would certainly also bind the
other. However, both identifiers cannot be equivalent because
the syntactic environment of the second is extended by the
binding of the first.
Consequently, macro programmers should
use bound-identifier=?
instead of eqv?
whenever one of the libraries (srfi 211 low-level)
or (srfi 211 syntax-case)
is provided as well.
Note 2: In legacy implementations, to implement non-hygienic macros, raw symbols are inserted into the macro output in the context of explicit-renaming macros. In general, however, this cannot lead to robust macros in a typical implementation as the following example shows:
(define-syntax loop (er-macro-transformer (lambda (x r c) (let ((body (cdr x))) `(,(r 'call-with-current-continuation) (,(r 'lambda) (exit) (,(r 'let) ,(r 'f) () ,@body (,(r 'f))))))))) (define-syntax foo (syntax-rules () ((foo x) (loop (exit x))))) (foo 42)
The macro writer may expect that the
expression (foo)
evaluates to 42. Instead, in most
implementations the program will fail because the
identifier exit
in the template of
the foo
macro is effectively renamed and does not
capture the binding of the identifier exit
introduced by the loop
macro.
The following rewrite of foo
will
solve this problem.
(define-syntax foo (er-macro-transformer (lambda (x r c) `(,(r 'loop) (exit ,(cadr x))))))
This rewrite does not solve another problem, however. The expression
(let ((exit 42)) (foo exit))
evaluates to the procedure exit
introduced by
the loop
macro, not to 42, which may have been
expected. The real problem lies in the loop
macro,
which should have renamed exit
in the context of
the macro invoking it.
Consequently, in legacy implementations, macro programmers
should not return raw symbols from their transformers, but
use construct-identifier
from (srfi 211
low-level)
or datum->syntax
from (srfi 211 syntax-case)
when any of these two
libraries is provided as well.
Note 3: In legacy implementations, it may be an error if the rename procedure is applied to a non-symbol. It is an error if the compare procedure is applied to non-preidentifiers.
Note 4: In view of the above, this specification demands
that er-macro-transformer
is implemented in a way
so that raw symbols in the output are closed in the syntactic
environment of the invoking macro keyword. Furthermore, it is
demanded that the rename
procedure accepts
arbitrary datums representing Scheme code and that
the compare
procedure closes raw symbols in the
syntactic environment of the invoking macro keyword.
(srfi 211 implicit-renaming)
Exports the identifier
ir-macro-transformer
.Note: Most of the notes to explicit renaming apply mutatis mutandis here as well.
syntax-case
system(srfi 211 syntax-case)
Exports the identifiers
syntax-case
,syntax
,identifier?
,bound-identifier=?
,free-identifier=?
,syntax->datum
,datum->syntax
,generate-temporaries
,with-syntax
,quasisyntax
,unsyntax
,unsyntax-splicing
, andsyntax-violation
.Note: As syntax-case
must
accept ...
and _
as literal
identifiers, syntax-case
exported by (srfi 211 syntax-case)
cannot be the same as syntax-case
exported by (rnrs syntax-case (6))
.
(srfi 211 identifier-syntax)
Exports the identifier
identifier-syntax
.Note: If this library is present, a macro transformer
will be invoked if its associated keyword is referenced as an
expression. The more general form
of identifier-syntax
that permits the transformer
to determine what happens when set!
is used may not
be supported by legacy implementations unless the (srfi
211 variable-transformer)
library is present as well.
(srfi 211 variable-transformer)
Exports the identifier
make-variable-transformer
.(srfi 211 with-ellipsis)
Exports the identifier
with-ellipsis
.(srfi 211 syntax-parameter)
Exports the identifiers
define-syntax-parameter
and syntax-parameterize
.(srfi 211 define-macro)
Exports the identifiers
define-macro
, andlisp-transformer
.Note: A legacy implementation that does not
support define-syntax
,
let-syntax
, and letrec-syntax
need not
define lisp-transformer
.
Remark: The syntax and procedures defined by the
library (srfi 211 define-macro)
should be
considered deprecated. Their use is only recommended by code
that needs to be compatible with Scheme implementations lacking
a working hygienic macro facility and for demonstration or
educational purposes. Scheme implementations that do have a
working hygienic macro facility are even encouraged not to provide
this library by default.
(srfi 211 syntactic-closures)
Exports the identifiers
sc-macro-transformer
,rsc-macro-transformer
,make-syntactic-closure
,close-syntax
,capture-syntactic-environment
,preidentifier?
as identifier?
,sc-identifier=?
as identifier=?
, andmake-synthetic-identifier
.(srfi 211 presyntax)
Exports the identifiers
preidentifier?
,presyntax->datum
,preidentifier->symbol
, andunwrap-presyntax
.The implementation is necessarily distinct for every Scheme
implementation but in any case almost trivial. The identifiers
of each supported extension of syntax-rules
just
have to be re-exported in the standardized libraries defined
above.
Implementers are highly encouraged to provide an implementation
of the low-level macro facility (srfi 211 low-level)
,
which can serve as a foundation for syntax-rules
and as a common denominator between the different Scheme
implementations.
The Unsyntax implementation
of the Scheme programming language provides all
of the above libraries. Its implementation
of er-macro-transformer
follows all of the above
recommendations.
Thanks to the inventors and implementers of the various
extensions to the syntax-rules
macro facility
that are covered by this SRFI.
The idea for with-ellipsis
comes
from GNU Guile.
Alex Shinn came up with the final title of this SRFI.
Thanks to John Cowan and Alex Shinn for their insistence to make this SRFI as much as independent from non-stable external sources.
Wording has been taken from the R6RS, the R7RS, and R6RS Syntax-Case Macros.
© 2021 Marc Nieper-Wißkirchen.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.