~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to src/Data/Drd/drd_info.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
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
******************************************************************************/
 
12
 
 
13
#include "drd_info.hpp"
 
14
#include "iterator.hpp"
 
15
#include "analyze.hpp"
 
16
 
 
17
/******************************************************************************
 
18
* Constructors and basic operations
 
19
******************************************************************************/
 
20
 
 
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)) {}
 
29
 
 
30
tree
 
31
drd_info_rep::get_locals () {
 
32
  tree t (COLLECTION);
 
33
  iterator<tree_label> it= iterate (info->item);
 
34
  while (it->busy()) {
 
35
    tree_label l= it->next();
 
36
    tree v= (tree) info->item[l];
 
37
    t << tree (ASSOCIATE, as_string (l), v);
 
38
  }
 
39
  return t;
 
40
}
 
41
 
 
42
bool
 
43
drd_info_rep::set_locals (tree t) {
 
44
  if (!is_func (t, COLLECTION))
 
45
    return false;
 
46
  int i, n= N(t);
 
47
  for (i=0; i<n; i++)
 
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]);
 
50
  return true;
 
51
}
 
52
 
 
53
bool
 
54
drd_info_rep::contains (string l) {
 
55
  return existing_tree_label (l) && info->contains (as_tree_label (l));
 
56
}
 
57
 
 
58
ostream&
 
59
operator << (ostream& out, drd_info drd) {
 
60
  return out << "drd [" << drd->name << "]";
 
61
}
 
62
 
 
63
/******************************************************************************
 
64
* Arity related methods
 
65
******************************************************************************/
 
66
 
 
67
void
 
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;
 
77
  }
 
78
  else {
 
79
    ti->pi.arity_base = extra;
 
80
    ti->pi.arity_extra= arity;
 
81
  }
 
82
  int n;
 
83
  if (arity+extra == 0) n= 0;
 
84
  else if (cm == CHILD_UNIFORM) n= 1;
 
85
  else if (cm == CHILD_BIFORM) n= 2;
 
86
  else n= arity+extra;
 
87
  if (N(ti->ci) != n) ti->ci= array<child_info> (n);
 
88
}
 
89
 
 
90
int
 
91
drd_info_rep::get_arity_mode (tree_label l) {
 
92
  return info[l]->pi.arity_mode;
 
93
}
 
94
 
 
95
int
 
96
drd_info_rep::get_child_mode (tree_label l) {
 
97
  return info[l]->pi.child_mode;
 
98
}
 
99
 
 
100
int
 
101
drd_info_rep::get_arity_base (tree_label l) {
 
102
  return info[l]->pi.arity_base;
 
103
}
 
104
 
 
105
int
 
106
drd_info_rep::get_arity_extra (tree_label l) {
 
107
  return info[l]->pi.arity_extra;
 
108
}
 
109
 
 
110
int
 
111
drd_info_rep::get_nr_indices (tree_label l) {
 
112
  return N(info[l]->ci);
 
113
}
 
114
 
 
115
void
 
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;
 
120
}
 
121
 
 
122
int
 
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);
 
127
}
 
128
 
 
129
bool
 
130
drd_info_rep::correct_arity (tree_label l, int i) {
 
131
  parent_info pi= info[l]->pi;
 
132
  switch (pi.arity_mode) {
 
133
  case ARITY_NORMAL:
 
134
    return i == ((int) pi.arity_base) + ((int) pi.arity_extra);
 
135
  case ARITY_OPTIONS:
 
136
    return (i >= ((int) pi.arity_base)) &&
 
137
           (i <= ((int) pi.arity_base) + ((int) pi.arity_extra));
 
138
  case ARITY_REPEAT:
 
139
  case ARITY_VAR_REPEAT:
 
140
    return (i >= ((int) pi.arity_base)) &&
 
141
           (((i-pi.arity_base) % pi.arity_extra) == 0);
 
142
  }
 
143
}
 
144
 
 
145
bool
 
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) {
 
149
  case ARITY_NORMAL:
 
150
    return false;
 
151
  case ARITY_OPTIONS:
 
152
    return (i >= ((int) pi.arity_base)) && (i <= n) &&
 
153
           (n < ((int) pi.arity_base) + ((int) pi.arity_extra));
 
154
  case ARITY_REPEAT:
 
155
    return (i >= 0) &&
 
156
           ((i < ((int) pi.arity_base)) ||
 
157
            ((i - pi.arity_base) % pi.arity_extra) == 0);
 
158
  case ARITY_VAR_REPEAT:
 
159
    return (i >= 0) &&
 
160
           ((i > (n - ((int) pi.arity_base))) ||
 
161
            (i % pi.arity_extra == 0));
 
162
  }
 
163
}
 
164
 
 
165
bool
 
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;
 
172
}
 
173
 
 
174
/******************************************************************************
 
175
* Border accessability related methods
 
176
******************************************************************************/
 
177
 
 
178
void
 
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;
 
184
}
 
185
 
 
186
bool
 
187
drd_info_rep::get_no_border (tree_label l) {
 
188
  return info[l]->pi.no_border;
 
189
}
 
190
 
 
191
void
 
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;
 
196
}
 
197
 
 
198
bool
 
199
drd_info_rep::is_child_enforcing (tree t) {
 
200
  return info[L(t)]->pi.no_border && (N(t) != 0);
 
201
}
 
202
 
 
203
/******************************************************************************
 
204
* Other attributes
 
205
******************************************************************************/
 
206
 
 
207
void
 
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);
 
213
}
 
214
 
 
215
tree
 
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);
 
220
  return val;
 
221
}
 
222
 
 
223
void
 
224
drd_info_rep::set_name (tree_label l, string val) {
 
225
  set_attribute (l, "name", val);
 
226
}
 
227
 
 
228
string
 
229
drd_info_rep::get_name (tree_label l) {
 
230
  return as_string (get_attribute (l, "name"));
 
231
}
 
232
 
 
233
/******************************************************************************
 
234
* Children's accessability related methods
 
235
******************************************************************************/
 
236
 
 
237
void
 
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;
 
244
}
 
245
 
 
246
bool
 
247
drd_info_rep::get_accessible (tree_label l, int nr) {
 
248
  return info[l]->ci[nr].accessible;
 
249
}
 
250
 
 
251
bool
 
252
drd_info_rep::all_accessible (tree_label l) {
 
253
  int i, n= N(info[l]->ci);
 
254
  for (i=0; i<n; i++)
 
255
    if (!info[l]->ci[i].accessible)
 
256
      return false;
 
257
  return n>0;
 
258
}
 
259
 
 
260
void
 
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;
 
266
}
 
267
 
 
268
bool
 
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;
 
274
}
 
275
 
 
276
/******************************************************************************
 
277
* Heuristic initialization of DRD
 
278
******************************************************************************/
 
279
 
 
280
static bool
 
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])))
 
286
      return false;
 
287
    if ((N(t) == 5) && (N(arg) >= 2) && (as_int (t[3]) <= as_int (arg[1])))
 
288
      return false;
 
289
    tree_label inner= make_tree_label (as_string (t[0]));
 
290
    tree_label outer= make_tree_label (as_string (t[1]));
 
291
    return
 
292
      (drd->get_nr_indices (inner) > 0) &&
 
293
      drd->get_accessible (inner, 0) &&
 
294
      drd->all_accessible (outer);
 
295
  }
 
296
  else if (is_func (t, MACRO)) return false;
 
297
  else {
 
298
    int i, n= N(t);
 
299
    for (i=0; i<n; i++)
 
300
      if (drd->is_accessible_child (t, i))
 
301
        if (accessible_arg (drd, t[i], arg))
 
302
          return true;
 
303
    return false;
 
304
  }
 
305
}
 
306
 
 
307
bool
 
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));
 
316
  }
 
317
  // if (old_ti != info[l])
 
318
  //   cout << var << ": " << old_ti << " -> " << info[l] << "\n";
 
319
  return (old_ti != info[l]);
 
320
}
 
321
 
 
322
static int
 
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]);
 
329
  else {
 
330
    int i, n= N(t), m= 0;
 
331
    for (i=0; i<n; i++)
 
332
      m= max (m, minimal_arity (t[i], var));
 
333
    return m;
 
334
  }
 
335
}
 
336
 
 
337
bool
 
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));
 
346
  }
 
347
  // if (old_ti != info[l])
 
348
  //   cout << var << ": " << old_ti << " -> " << info[l] << "\n";
 
349
  return (old_ti != info[l]);
 
350
}
 
351
 
 
352
void
 
353
drd_info_rep::heuristic_init (hashmap<string,tree> env) {
 
354
  // int tt= texmacs_time ();
 
355
  bool flag= true;
 
356
  int round= 0;
 
357
  while (flag) {
 
358
    // cout << HRULE;
 
359
    flag= false;
 
360
    iterator<string> it= iterate (env);
 
361
    while (it->busy()) {
 
362
      string var= it->next();
 
363
      tree   val= env[var];
 
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;
 
368
    }
 
369
    if ((round++) == 10) {
 
370
      cout << "TeXmacs] Warning: bad heuristic drd convergence\n";
 
371
      flag= false;
 
372
    }
 
373
  }
 
374
  // cout << "--> " << (texmacs_time ()-tt) << "ms\n";
 
375
}