2
/******************************************************************************
3
* MODULE : drd_info.cpp
4
* DESCRIPTION: data relation descriptions
5
* COPYRIGHT : (C) 2003 Joris van der Hoeven
6
*******************************************************************************
7
* This software falls under the GNU general public license and comes WITHOUT
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
11
******************************************************************************/
13
#include "drd_info.hpp"
14
#include "iterator.hpp"
15
#include "analyze.hpp"
17
/******************************************************************************
18
* Constructors and basic operations
19
******************************************************************************/
21
drd_info_rep::drd_info_rep (string name2):
22
name (name2), info (tag_info ()) {}
23
drd_info_rep::drd_info_rep (string name2, drd_info base):
24
name (name2), info (tag_info (), base->info) {}
25
drd_info::drd_info (string name):
26
rep (new drd_info_rep (name)) {}
27
drd_info::drd_info (string name, drd_info base):
28
rep (new drd_info_rep (name, base)) {}
31
drd_info_rep::get_locals () {
33
iterator<tree_label> it= iterate (info->item);
35
tree_label l= it->next();
36
tree v= (tree) info->item[l];
37
t << tree (ASSOCIATE, as_string (l), v);
43
drd_info_rep::set_locals (tree t) {
44
if (!is_func (t, COLLECTION))
48
if (is_func (t[i], ASSOCIATE, 2) && is_atomic (t[i][0]))
49
info (make_tree_label (t[i][0]->label))= tag_info (t[i][1]);
54
drd_info_rep::contains (string l) {
55
return existing_tree_label (l) && info->contains (as_tree_label (l));
59
operator << (ostream& out, drd_info drd) {
60
return out << "drd [" << drd->name << "]";
63
/******************************************************************************
64
* Arity related methods
65
******************************************************************************/
68
drd_info_rep::set_arity (tree_label l, int arity, int extra, int am, int cm) {
69
if (info[l]->pi.freeze_arity) return;
70
if (!info->contains (l)) info(l)= copy (info[l]);
71
tag_info& ti= info(l);
72
ti->pi.arity_mode= am;
73
ti->pi.child_mode= cm;
74
if (am != ARITY_VAR_REPEAT) {
75
ti->pi.arity_base = arity;
76
ti->pi.arity_extra= extra;
79
ti->pi.arity_base = extra;
80
ti->pi.arity_extra= arity;
83
if (arity+extra == 0) n= 0;
84
else if (cm == CHILD_UNIFORM) n= 1;
85
else if (cm == CHILD_BIFORM) n= 2;
87
if (N(ti->ci) != n) ti->ci= array<child_info> (n);
91
drd_info_rep::get_arity_mode (tree_label l) {
92
return info[l]->pi.arity_mode;
96
drd_info_rep::get_child_mode (tree_label l) {
97
return info[l]->pi.child_mode;
101
drd_info_rep::get_arity_base (tree_label l) {
102
return info[l]->pi.arity_base;
106
drd_info_rep::get_arity_extra (tree_label l) {
107
return info[l]->pi.arity_extra;
111
drd_info_rep::get_nr_indices (tree_label l) {
112
return N(info[l]->ci);
116
drd_info_rep::freeze_arity (tree_label l) {
117
if (!info->contains (l)) info(l)= copy (info[l]);
118
tag_info& ti= info(l);
119
ti->pi.freeze_arity= true;
123
drd_info_rep::get_old_arity (tree_label l) {
124
tag_info ti= info[l];
125
if (ti->pi.arity_mode != ARITY_NORMAL) return -1;
126
else return ((int) ti->pi.arity_base) + ((int) ti->pi.arity_extra);
130
drd_info_rep::correct_arity (tree_label l, int i) {
131
parent_info pi= info[l]->pi;
132
switch (pi.arity_mode) {
134
return i == ((int) pi.arity_base) + ((int) pi.arity_extra);
136
return (i >= ((int) pi.arity_base)) &&
137
(i <= ((int) pi.arity_base) + ((int) pi.arity_extra));
139
case ARITY_VAR_REPEAT:
140
return (i >= ((int) pi.arity_base)) &&
141
(((i-pi.arity_base) % pi.arity_extra) == 0);
146
drd_info_rep::insert_point (tree_label l, int i, int n) {
147
parent_info pi= info[l]->pi;
148
switch (pi.arity_mode) {
152
return (i >= ((int) pi.arity_base)) && (i <= n) &&
153
(n < ((int) pi.arity_base) + ((int) pi.arity_extra));
156
((i < ((int) pi.arity_base)) ||
157
((i - pi.arity_base) % pi.arity_extra) == 0);
158
case ARITY_VAR_REPEAT:
160
((i > (n - ((int) pi.arity_base))) ||
161
(i % pi.arity_extra == 0));
166
drd_info_rep::is_dynamic (tree t) {
167
if (L(t) >= START_EXTENSIONS) return true; // FIXME: temporary fix
168
if (is_atomic (t)) return false;
169
if (is_func (t, DOCUMENT) || is_func (t, PARA) || is_func (t, CONCAT) ||
170
is_func (t, TABLE) || is_func (t, ROW)) return false;
171
return info[L(t)]->pi.arity_mode != ARITY_NORMAL;
174
/******************************************************************************
175
* Border accessability related methods
176
******************************************************************************/
179
drd_info_rep::set_no_border (tree_label l, bool has_no_border) {
180
if (info[l]->pi.freeze_no_border) return;
181
if (!info->contains (l)) info(l)= copy (info[l]);
182
tag_info& ti= info(l);
183
ti->pi.no_border= has_no_border;
187
drd_info_rep::get_no_border (tree_label l) {
188
return info[l]->pi.no_border;
192
drd_info_rep::freeze_no_border (tree_label l) {
193
if (!info->contains (l)) info(l)= copy (info[l]);
194
tag_info& ti= info(l);
195
ti->pi.freeze_no_border= true;
199
drd_info_rep::is_child_enforcing (tree t) {
200
return info[L(t)]->pi.no_border && (N(t) != 0);
203
/******************************************************************************
205
******************************************************************************/
208
drd_info_rep::set_attribute (tree_label l, string which, tree val) {
209
if (info[l]->pi.freeze_no_border) return;
210
if (!info->contains (l)) info(l)= copy (info[l]);
211
tag_info& ti= info(l);
212
ti->set_attribute (which, val);
216
drd_info_rep::get_attribute (tree_label l, string which) {
217
tree val= info[l]->get_attribute (which);
218
if ((which == "name") && (val == ""))
219
return as_string (l);
224
drd_info_rep::set_name (tree_label l, string val) {
225
set_attribute (l, "name", val);
229
drd_info_rep::get_name (tree_label l) {
230
return as_string (get_attribute (l, "name"));
233
/******************************************************************************
234
* Children's accessability related methods
235
******************************************************************************/
238
drd_info_rep::set_accessible (tree_label l, int nr, bool is_accessible) {
239
if (!info->contains (l)) info(l)= copy (info[l]);
240
tag_info & ti= info(l);
241
child_info& ci= ti->ci[nr];
242
if (ci.freeze_accessible) return;
243
ci.accessible= is_accessible;
247
drd_info_rep::get_accessible (tree_label l, int nr) {
248
return info[l]->ci[nr].accessible;
252
drd_info_rep::all_accessible (tree_label l) {
253
int i, n= N(info[l]->ci);
255
if (!info[l]->ci[i].accessible)
261
drd_info_rep::freeze_accessible (tree_label l, int nr) {
262
if (!info->contains (l)) info(l)= copy (info[l]);
263
tag_info & ti= info(l);
264
child_info& ci= ti->ci[nr];
265
ci.freeze_accessible= true;
269
drd_info_rep::is_accessible_child (tree t, int i) {
270
tag_info ti= info[L(t)];
271
int index= ti->get_index (i, N(t));
272
if ((index<0) || (index>=N(ti->ci))) return false;
273
return ti->ci[index].accessible;
276
/******************************************************************************
277
* Heuristic initialization of DRD
278
******************************************************************************/
281
accessible_arg (drd_info_rep* drd, tree t, tree arg) {
282
if (is_atomic (t)) return false;
283
else if (t == arg) return true;
284
else if (is_func (t, MAP_ARGS) && (t[2] == arg[0])) {
285
if ((N(t) >= 4) && (N(arg) >= 2) && (as_int (t[3]) > as_int (arg[1])))
287
if ((N(t) == 5) && (N(arg) >= 2) && (as_int (t[3]) <= as_int (arg[1])))
289
tree_label inner= make_tree_label (as_string (t[0]));
290
tree_label outer= make_tree_label (as_string (t[1]));
292
(drd->get_nr_indices (inner) > 0) &&
293
drd->get_accessible (inner, 0) &&
294
drd->all_accessible (outer);
296
else if (is_func (t, MACRO)) return false;
300
if (drd->is_accessible_child (t, i))
301
if (accessible_arg (drd, t[i], arg))
308
drd_info_rep::heuristic_init_macro (string var, tree macro) {
309
tree_label l = make_tree_label (var);
310
tag_info old_ti= copy (info[l]);
311
int i, n= N(macro)-1;
312
set_arity (l, n, 0, ARITY_NORMAL, CHILD_DETAILED);
313
for (i=0; i<n; i++) {
314
tree arg (ARG, macro[i]);
315
set_accessible (l, i, accessible_arg (this, macro[n], arg));
317
// if (old_ti != info[l])
318
// cout << var << ": " << old_ti << " -> " << info[l] << "\n";
319
return (old_ti != info[l]);
323
minimal_arity (tree t, tree var) {
324
if (is_atomic (t)) return 0;
325
else if (is_func (t, ARG, 2) && (t[0] == var))
326
return as_int (t[1]) + 1;
327
else if (is_func (t, MAP_ARGS) && (N(t)>=4) && (t[2] == var))
328
return as_int (t[3]);
330
int i, n= N(t), m= 0;
332
m= max (m, minimal_arity (t[i], var));
338
drd_info_rep::heuristic_init_xmacro (string var, tree xmacro) {
339
tree_label l = make_tree_label (var);
340
tag_info old_ti= copy (info[l]);
341
int i, m= minimal_arity (xmacro[1], xmacro[0]);
342
set_arity (l, m, 1, ARITY_REPEAT, CHILD_DETAILED);
343
for (i=0; i<=m; i++) {
344
tree arg (ARG, xmacro[0], as_string (i));
345
set_accessible (l, i, accessible_arg (this, xmacro[1], arg));
347
// if (old_ti != info[l])
348
// cout << var << ": " << old_ti << " -> " << info[l] << "\n";
349
return (old_ti != info[l]);
353
drd_info_rep::heuristic_init (hashmap<string,tree> env) {
354
// int tt= texmacs_time ();
360
iterator<string> it= iterate (env);
362
string var= it->next();
364
if (is_func (val, MACRO))
365
flag= heuristic_init_macro (var, val) | flag;
366
if (is_func (val, XMACRO))
367
flag= heuristic_init_xmacro (var, val) | flag;
369
if ((round++) == 10) {
370
cout << "TeXmacs] Warning: bad heuristic drd convergence\n";
374
// cout << "--> " << (texmacs_time ()-tt) << "ms\n";