-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwstack.sty
114 lines (102 loc) · 3.37 KB
/
wstack.sty
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
\RequirePackage{expl3}[2014/11/25]
\ProvidesExplPackage
{lt3wstack}
{2015/03/01}
{0.1}
{a weighted-stack data-structure for expl3}
%% The weighted stack is just a stack that associates nodes with
%% weights (or priorities, depending on how you look at it). When a
%% node is pushed onto the stack, it will pop all those nodes with a
%% weight greater than or equal to its own.
% { \csnameA } = { 4,2,1 }
% { \csnameB } = { 4,3,2,0 }
%
% seq is always monotonically decreasing
\prop_new:N \g__wstack_weights_prop
% aligned with above
\prop_new:N \g__wstack_data_prop
% temporary sequence for reporting
\seq_new:N \l_wstack_tmp_data_seq
% \wstack_show:N :: output data to terminal (no weights yet)
% \wstack_use:Nn :: interface to \seq_use:
% \wstack_use:Nnnn :: interface to \seq_use:
% \wstack_remove:N :: removes stack from data model
% \wstack_clear:N :: clears content of stack
% \wstack_new:N :: create new stack
% \wstack_push:Nnn :: push #3 to #1 with weight=#2
% \wstack_pop_to:Nn :: pop #1 down past weight #2
% @todo
%
% The weighted stack \test_wstack contains the items (without outer braces):
% > (200) {hello-200}
% > ( 12) {hello-12}
% > ( 2) {hello-2}
% > ( 1) {hello-1}.
% <recently read> }
%
% l.??? \wstack_show:N \test_wstack
\cs_new:Npn \wstack_show:N #1 {
\group_begin:
\prop_get:NnN \g__wstack_data_prop #1 \l_wstack_tmp_data_seq
\seq_show:N \l_wstack_tmp_data_seq
\group_end:
}
\cs_new:Npn \wstack_use:Nn #1 #2 {
\group_begin:
\prop_get:NnN \g__wstack_data_prop #1 \l_wstack_tmp_data_seq
\seq_use:Nn \l_wstack_tmp_data_seq {#2}
\group_end:
}
\cs_new:Npn \wstack_use:Nnnn #1 #2 #3 #4 {
\group_begin:
\prop_get:NnN \g__wstack_data_prop #1 \l_wstack_tmp_data_seq
\seq_use:Nnnn \l_wstack_tmp_data_seq {#2} {#3} {#4}
\group_end:
}
\cs_new:Npn \wstack_remove:N #1 {
\prop_remove:Nn \g__wstack_weight_prop #1
\prop_remove:Nn \g__wstack_data_prop #1
}
\cs_new:Npn \wstack_clear:N #1 {
\wstack_remove:N #1
\wstack_new:N #1
}
\cs_new:Npn \wstack_new:N #1 {
\prop_put:NnV \g__wstack_weights_prop #1 \c_empty_clist
\prop_put:NnV \g__wstack_data_prop #1 \c_empty_seq
}
% \wstack_push:Nnn \stack {weight} {value}
\cs_new:Npn \wstack_push:Nnn #1 #2 #3 {
\group_begin:
\wstack_pop_to:Nn #1 {#2}
\prop_get:NnN \g__wstack_weights_prop #1 \l_tmpa_clist
\prop_get:NnN \g__wstack_data_prop #1 \l_tmpa_seq
\clist_push:Nn \l_tmpa_clist {#2}
\seq_push:Nn \l_tmpa_seq {#3}
\prop_gput:NnV \g__wstack_weights_prop #1 \l_tmpa_clist
\prop_gput:NnV \g__wstack_data_prop #1 \l_tmpa_seq
\group_end:
}
% With the appropriate weights global for #1, strip off all those
% weight entries that are greater than or equal to #2. Store the
% number of removals in #3. When this function completes, an item
% with weight #2 may be added to the stack for #1.
%
% \wstack_pop_to:Nn \stack {weight}
\cs_new:Npn \wstack_pop_to:Nn #1 #2 {
\group_begin:
\prop_get:NnN \g__wstack_weights_prop #1 \l_tmpa_clist
\prop_get:NnN \g__wstack_data_prop #1 \l_tmpa_seq
\clist_get:NN \l_tmpa_clist \l_tmpa_tl
\bool_until_do:nn {
\quark_if_no_value_p:N \l_tmpa_tl ||
\int_compare_p:nNn \l_tmpa_tl < {#2}
} {
\clist_pop:NN \l_tmpa_clist \l_tmpa_tl
\seq_pop:NN \l_tmpa_seq \l_tmpa_tl
\clist_get:NN \l_tmpa_clist \l_tmpa_tl
}
\prop_gput:NnV \g__wstack_weights_prop #1 \l_tmpa_clist
\prop_gput:NnV \g__wstack_data_prop #1 \l_tmpa_seq
\group_end:
}