-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrule.tex
81 lines (78 loc) · 3.41 KB
/
rule.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
% #1: kept_head
% #2: removed_head
% #3: guard
% #4: body
% #5: name (afterthought)
% returns a solver (stored in \chr@toreturn)
\def\chr@rule#1#2#3#4#5{%
% takes the name of the constraint list to work on
% add it to the list of rules
\chr@list@append{chr@rules}{%
\chr@verbose{Running rule '#5' -------------------------------------------------------}%
% first, let's match
\chr@list@concat{chr@all}{#2}{#1}% we want r + k, why? this way i can just remove the first 'r' elements, instead of having to keep the first k
\chr@match{chr@all}{\chr@input@constraints}%
% iterate and check if the guards like them.
% we pass in the list getter to the guard as \cs, so it can use \cs1, \cs2, ...
\let\chr@constraints@to@fire=\chr@empty
% todo: just iter directly?
\chr@list{chr@guard@tries}{\chr@match@result}%
\chr@list@iter\chr@try:=chr@guard@tries\do{%
\expandafter\chr@list\expandafter{\expandafter c\expandafter s\expandafter}\expandafter{\chr@try}%
\chr@exec@guard{#3}%
{\global\let\chr@constraints@to@fire=\chr@try\relax \chr@break}%
{}% just continue in the other case
}%
\ifx\chr@constraints@to@fire\chr@empty
\chr@verbose{No guard matched.}%
\def\chr@toreturn{}%
\else % here, we have a matched head and guard, and we can actually apply the rule!
% we have the length of the kept head in #1, now we shorten the list to only contain it!
\chr@log{Firing rule '#5' with constraints: \chr@constraints@to@fire}%
% we copy this way, ugly? yes. nice? i dunno
\chr@list{chr@list@tmp}{\chr@constraints@to@fire}%
% we remove the first length elements
\chr@list@to@string\chr@constraints@remains{chr@list@tmp}{\csname#2length\endcsname}%
\chr@list{chr@c@rem}{\chr@constraints@remains}% these are those to remove
\def\chr@constraints@name{chr@constraints}%
% the body should return a new list named... result! which we now simply concat, it can still access c for a new list
\let\c=\chr@list@tmp
\chr@list{chr@result}{}%
#4
\chr@list@iter\chr@elem:=chr@c@rem\do{%
\expandafter\chr@list@remove\expandafter{\expandafter\chr@constraints@name\expandafter}\expandafter{\chr@elem}% these are those to keep
}%
% body output:
\chr@list@log{chr@result}%
\chr@list@iter\chr@elem:=chr@result\do{%
\expandafter\chr@list@append\expandafter{\expandafter\chr@constraints@name\expandafter}\expandafter{\chr@elem}%
}%
\chr@list@log{chr@constraints}%
\fi
}
}
\def\chr@body#1{% copy-pasta
\def\chr@tmp{#1}\def\chr@listname{chr@result}%
\expandafter\chr@list@append\expandafter{\expandafter\chr@listname\expandafter}\expandafter{\chr@tmp}%
}
\def\chr@ebody#1{%
\chr@list@eappend{chr@result}{#1}%
}
% variant of \chr@rule, which allows for a name as #1 (which must be unique)
% and uses it to construct lists in-place
\def\chr@rule@inline#1#2#3#4#5{%
\chr@list{#1@kept}{#2}%
\chr@list{#1@rem}{#3}%
\chr@rule{#1@kept}{#1@rem}{#4}{#5}{#1}%
}
% #2 if matches, #3 otherwise
\def\chr@exec@guard#1{% we have to hide the \else from early execute
#1
\let\chr@guard@result=\chr@ns
\chr@verbose{Guard matches.}%
\expandafter\chr@firstoftwo
\else
\chr@verbose{Guard does not match.}%
\expandafter\chr@secondoftwo
\fi
}