Exports of InterpretingTools
evaluate: (ExpressionTree, List LabelSpecies) -> LabelSpecies
Usage
s: String
== "Plus(SingletonSpecies, SingletonSpecies, Self(0))";
S: LabelSpecies
== evaluate(parse s, [coerce SingletonSpecies]);
Description
evaluate evaluates the given ExpressionTree, replacing Self(i) with the ith element of the given list. Instead of Self(1) the shorthand Self is also allowed.
Remarks
Note that the correspondence between leaves and species like SingletonSpecies and operators and operations on species like Plus is hardcoded in the function. If necessary, this could be done differently, namely passing evaluate additionally a table that describes the correspondence.
interpret: List ExpressionTree -> List LabelSpecies
Usage
T23: List LabelSpecies == interpret
[parse "Plus(SingletonSpecies, Times(Self(2), Self(2)))",
parse "Plus(SingletonSpecies, Times(Self,Times(Self,Self)))"];
Description
Translates a grammar into a list of combinatorial species.
interpret translates a list of ExpressionTree’s into a list of combinatorial species. The list of ExpressionTree’s [s_1, s_2, \dots, s_n] is interpreted as a system of equations as follows:
Self(1) | = s1 | ||
Self(2) | = s2 | ||
Self(n) | = sn. |
In the following we explain why interpret works in Aldor versions 1.0.2 and 1.0.3. Before doing so we have to stress however that very likely this depends on the current implementation. The code is probably not conforming to the specification in the Aldor user guide.
In principle the reason is that the compiler evaluates (coerce evaluate(p.i, res))(L) lazily – although it wouldn’t have to. Consider, for example, what happens when we call
C == interpret([parse "Plus(SingletonSpecies, Times(Self, Self))"]);
g := generatingSeries$C;
First res is initialized with a list of combinatorial species. For simplicity we use EmptySetSpecies, but any other would do.
Then E(1) is called. However, note that (coerce evaluate(p.i, res))(L) is an expression in type context, as explained in the Aldor user guide, Section 7.3. Thus, Aldor is – a priori – free to choose when it evaluates it. In fact, it seems that Aldor evaluates it only much later, namely at the point when for the first time on operation from the formed domain is called.
Thus, in the next step, res.1 is assigned the result of coerce E(1). Note that (coerce evaluate(p.i, res))(L) is still not being evaluated. At this point the operation interpret is left and Aldor commences the evaluation of g := generatingSeries$C.
Of course, now it is truly necessary to evaluate (coerce evaluate(p.i, res))(L), and this is exactly what happens. Meanwhile the list res contains as first member the result of coerce E(1). Thus, res.1 is indeed defined recursively, as we were hoping.
Previously we said that Aldor would be free to choose when to evaluate (coerce evaluate(p.i, res))(L). However, there is another paragraph in the Aldor user guide, Section 7.9, that might apply:
The bodies of with and add expressions are evaluated in such a way that they will be evaluated after the expressions they depend on. If mutually recursive type-forming expressions are found within the body of either with or add expressions, the expressions are computed as a xed point, rather than evaluated in strict sequence. This xed point computation uses a technique from functional programming to create self-referential data structures. |
A: C; B: C;
A == f(A, B) add;
B == g(A, B) add;
One can argue that the situation in the code in interpret is very similar, indeed, why should
l: List C == [someC, someC];
l.1 == f(l) add;
l.2 == g(l) add;
produce a different result?
for i in 1..#p repeat res.i := {evaluate(parse(p.i), res) add};
Usage
T := Interpret([parse "Plus(SingletonSpecies, Times(Self, Self))"], ACInteger);
s := structures([1,2,3,4,5])$T;
partialNext! s
Description
A domain function that returns a CombinatorialSpecies.
This domain is mainly useful within the Axiom environment. It returns the CombinatorialSpecies corresponding to the expression Self within the given grammar p.
Remarks
Note that the add within the body is necessary. Otherwise Axiom would, in the above usage example, complain about a missing function partialNext!.