1
0
Fork 0

Reorganization of contextual overloading system, part I

This commit is contained in:
Joris van der Hoeven 2012-02-16 20:49:50 +00:00
parent ea66b07bac
commit 0f698d9a42
3 changed files with 55 additions and 140 deletions

View File

@ -1,4 +1,4 @@
<TeXmacs|1.0.7.11>
<TeXmacs|1.0.7.14>
<style|tmdoc>
@ -30,99 +30,52 @@
<\scm-code>
(tm-define (hello) (insert "Hello"))
(tm-define (hello) (:mode in-math?) (insert-go-to "hello()" '(6)))
(tm-define (hello) (:require (in-math?)) (insert-go-to "hello()" '(6)))
</scm-code>
Here we recall that the two definitions may be put inside different
modules. Notice also that the contextual overloading system considers the
implementation of <scm|hello> inside math mode to be more <em|particular>
than the default implementation. In case when several implementations match
their respective conditions, the most particular implementation will be
chosen.
Currently, <TeXmacs> supports two major types of conditions:
<\description>
<item*|Conditions on the mode>
A <em|<TeXmacs> mode> corresponds to a simple predicate without
arguments, together with a finite number of other, less particular, modes
which are implied by it. New modes can be defined using the instruction
<\scm-code>
(texmacs-modes <em|mode>% <em|cond> <em|submode-1> ... <em|submode-n>)
</scm-code>
For instance, we might define a new mode <scm|inside-theorem?> as follows
<\scm-code>
(texmacs-modes inside-theorem% (inside? 'theorem) in-text%)
</scm-code>
Some standard modes are <scm|always?>, <scm|in-source?>, <scm|in-text?>,
<scm|in-math?>, <scm|in-prog?>. There is also a special mode
<scm|prevail?> which is always satisfied, but nevertheless considered as
more particular than all other modes.
<\remark>
Currently, modes necessarily terminate by the <verbatim|?> character.
However, in the <scm|texmacs-modes> instruction, the <verbatim|?> has
to be replaced by a <verbatim|%>. This may change in a future version
of <TeXmacs>.
</remark>
<item*|Conditions on the arguments of the function>
This type of contextual overloading is closest to the more classical
concept of overloading used by languages like <name|C++>. Although one
may overload on the types of the arguments, it is also possible to impose
more general conditions on the arguments. For instance, one may sometimes
wish to write the following kind of code:
<\scm-code>
(tm-define (my-replace what by)
\ \ <em|default-implementation>)
\;
(tm-define (my-replace what by)
\ \ (:require (== what by))
\ \ (noop))
</scm-code>
</description>
\;
In cases of conflict, we notice that the contextual overloading system
first dispatches on mode and then on the arguments on the function. For
instance, consider a routine <scm|foo> defined<nbsp>by
The order in which routines are overloaded is important. <TeXmacs> first
tries the latest (re)definition. If this definition does not satisfy the
requirements (<scm|(in-math?)>, in our case), then it tries the before last
(re)definition, and so on until an implementation is found which matches
the requirements. For example, if we invert the two declarations in the
above example, then the general unconditional definition of <scm|hello>
will always prevail. If the two declarations are made inside different
modules, then it is up to the user to ensure that the modules are loaded in
an appropriate order.
Inside a redefinition, it is also possible to access the former definition
using the keyword <scm|former>. In particular, the code
<\scm-code>
(tm-define (foo t) (:mode in-math?) <em|implementation-1>)
(tm-define (hello)
(tm-define (foo t) (:require (tree-is? t 'frac)) <em|implementation-2>)
\ \ (if (in-math?) (insert-go-to "hello()" '(6)) (former)))
</scm-code>
Then the first implementation will be used when <scm|foo> is called for a
fraction in math mode. In cases of conflict when no implementation is
preferrable <em|a priori>, the last implementation prevails. For instance,
consider a predicate <scm|(gnu? t)> which implies another predicate
<scm|(hairy? t)>, and assume that we want to overload a function <scm|(foo
t)> for both predicates. Then we may use something such as
is equivalent to the second declaration in our example.
Contextual overloading generalizes more classical overloading on the types
of the arguments, such as <name|C++> style polymorphism. Although one may
overload on the types of the arguments, it is also possible to impose more
general conditions on the arguments. For instance, one may sometimes wish
to write the following kind of code:
<\scm-code>
(tm-define (foo t) (:require (hairy? t) <em|implementation-1>)
(tm-define (my-replace what by)
(tm-define (foo t) (:require (gnu? t)) <em|implementation-2>)
\ \ <em|default-implementation>)
\;
(tm-define (my-replace what by)
\ \ (:require (== what by))
\ \ (noop))
</scm-code>
Indeed, the most particular implementation should be declared last. In the
case when both implementations are in different files, the file with the
definition when <scm|(gnu? t)> should include the other<nbsp>one.
Besides <scm|tm-define>, several other added language primitives support
the contextual overloading mechanism. For instance, <scm|kbd-map> and
<scm|menu-bind> support overloading on mode. The <scm|tm-define-macro> and

View File

@ -47,7 +47,7 @@
<\scm-code>
(menu-bind insert-menu
\ \ (next)
\ \ (former)
\ \ ---

View File

@ -1,4 +1,4 @@
<TeXmacs|1.0.7.7>
<TeXmacs|1.0.7.14>
<style|tmdoc>
@ -31,37 +31,9 @@
<paragraph*|Contextual overloading>
We will first describe the various options for overloading. If several
definitions are given for the same function (or macro) <scm|foo> and
several definitions satisfy the corresponding overloading conditions, when
applying <scm|foo> to some arguments, then the <em|most particular>
definition will prevail. For any of the overloading options, we will
therefore have to specify what we mean my ``most particular''. When trying
to find out the most particular set of options, we first sort on mode, next
on context and finally on function arguments. Notice that sorting on
function arguments is not yet fully implemented, so we will not discuss
this yet.
<\explain>
<scm|(:mode <scm-arg|mode>)><explain-synopsis|mode-based overloading>
<|explain>
This option specifies that the definition is only valid when we are in a
given <scm-arg|mode>. New modes are defined using <scm|texmacs-modes> and
modes can inherit from other modes. A mode <math|m<rsub|1>> is understood
to be more particular than another mode <math|m<rsub|2>> if
<math|m<rsub|1>> inherits from <math|m<rsub|2>>.
</explain>
<\explain>
<scm|(:match <scm-arg|pattern>)><explain-synopsis|argument based
overloading>
<|explain>
This option specifies that one necessary condition for the declaration to
be valid valid is that the arguments match the specified pattern
according to the primitive <scm|match?>. We have not yet implemented a
function to test whether a pattern is a restriction of another pattern,
so ambiguous overloads cannot be resolved.
</explain>
We will first describe the most important <scm|:require> option for
contextual overloading, which was already discussed
<hlink|before|../overview/overview-overloading.en.tm>.
<\explain>
<scm|(:require <scm-arg|cond>)><explain-synopsis|argument based
@ -69,12 +41,11 @@
<|explain>
This option specifies that one necessary condition for the declaration to
be valid is that the condition <scm-arg|cond> is met. This condition may
involve the arguments of the function. Again, ambiguous overloads cannot
be resolved.
involve the arguments of the function.
As an example, let us consider the following definitions:
<\scm-fragment>
<\scm-code>
(tm-define (special t)
\ \ (and-with p (tree-outer t)
@ -96,7 +67,7 @@
\ \ (:require (tree-is? t 'rsub))
\ \ (tree-set! t `(rsup ,(tree-ref t 0))))
</scm-fragment>
</scm-code>
The default implementation of <scm|special> is to apply <scm|special> to
the parent <scm|p> of <scm|t> as long as <scm|t> is not the entire
@ -107,29 +78,20 @@
calling <scm|special> will swap the numerator and the denominator. On the
other hand, if your cursor is inside a subscript inside a fraction, then
calling <scm|special> will change the subscript into a superscript.
</explain>
<\explain>
<scm|(:case <scm-arg|label-1> ... <scm-arg|label-n>)><explain-synopsis|argument
based dispatching>
<|explain>
This is a very special case of the <scm|:match> option, where we require
the first argument to be a compound hybrid tree whose root label is
amongst <scm-arg|label-1> until <scm-arg|label-n>. Besides a simplified
syntax, the implementation of <scm|:case> is done using a dispatch via a
hash table. When appropriate, you should therefore priviledge <scm|:case>
over the general form of <scm|:match>. A typical situation when
<scm|:case> is useful is when writing a converter <scm|tm-\<gtr\>foo> of
<TeXmacs> trees into your own foormat: specific converters for given tags
can be added using
When the conditions of several (re)declarations are met, then the last
redeclaration will be used. Inside a redeclaration, one may also use the
<scm|former> keyword in order to explicitly access the former value of
the redefined symbol.
<\scm-fragment>
(tm-define (tm-\<gtr\>foo t)
\ \ (:case frac)
\ \ <with|prog-font-shape|italic|tm-to-foo-converter-for-frac>)
</scm-fragment>
<\explain>
<scm|(:mode <scm-arg|mode>)><explain-synopsis|mode-based overloading>
<|explain>
This option is equivalent to <scm|(:require (<scm-arg|mode>))> and
specifies that the definition is only valid when we are in a given
<scm-arg|mode>. New modes are defined using <scm|texmacs-modes> and
modes can inherit from other modes.
</explain>
</explain>
<paragraph*|Other options for function and macro declarations>
@ -149,13 +111,13 @@
expressions may be encoded inside this string by using the
<verbatim|@>-prefix. For instance:
<\scm-fragment>
<\scm-code>
(tm-define (list-square l)
\ \ (:synopsis "Appends the list @l to itself")
\ \ (append l l))
</scm-fragment>
</scm-code>
The synopsis of a function is used for instance in order to provide a
short help string for the function. In the future, we might also use it