1 |
root |
1.1 |
/* |
2 |
|
|
* l-system representation and evaluation |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#include "config.h" |
6 |
|
|
|
7 |
|
|
#include <algorithm> |
8 |
|
|
#include <iterator> |
9 |
|
|
#include <iostream> |
10 |
|
|
#include <sstream> |
11 |
|
|
|
12 |
|
|
#include <cstdlib> |
13 |
|
|
#include <cmath> |
14 |
|
|
|
15 |
|
|
#include "tokens.h" |
16 |
|
|
#include "DLGLexer.h" |
17 |
|
|
#include "Parser.h" |
18 |
|
|
|
19 |
|
|
#include "lsys.h" |
20 |
|
|
|
21 |
|
|
#ifndef M_PI |
22 |
|
|
# define M_PI 3.14159265358979323846 /* pi */ |
23 |
|
|
#endif |
24 |
|
|
|
25 |
|
|
bool operator <(const lsys::arg_spec &a, const lsys::arg_spec &b) t_no |
26 |
|
|
{ |
27 |
|
|
return a.nargs < b.nargs |
28 |
|
|
|| (a.nargs == b.nargs && a.arg < b.arg) |
29 |
|
|
|| (a.arg == b.arg && a.str < b.str); |
30 |
|
|
} |
31 |
|
|
|
32 |
|
|
ostream &operator <<(ostream &o, const file_pos &p) t_no |
33 |
|
|
{ |
34 |
|
|
return o << p.path << ":" << p.line << ", column " << p.col; |
35 |
|
|
} |
36 |
|
|
|
37 |
|
|
ostream &operator <<(ostream &o, const module_vec &v) t_no |
38 |
|
|
{ |
39 |
|
|
// o << "[" << hex << (long)&v << " " << (long)v.s << dec << "|";//D |
40 |
|
|
|
41 |
|
|
for (module_pos i = v.begin (); i != v.end (); ++i) |
42 |
|
|
o << *i << " "; |
43 |
|
|
|
44 |
|
|
// o << "]"; |
45 |
|
|
|
46 |
|
|
return o; |
47 |
|
|
} |
48 |
|
|
|
49 |
|
|
ostream &operator <<(ostream &o, const module &m) t_no |
50 |
|
|
{ |
51 |
|
|
static const char *delim[2][2] = { |
52 |
|
|
{ ",", ")" }, |
53 |
|
|
{ " ", "" } |
54 |
|
|
}; |
55 |
|
|
|
56 |
|
|
// if (m.is_expr) o << "E:"; |
57 |
|
|
// if (m.is_num) o << "N:"; |
58 |
|
|
|
59 |
|
|
o << m.str; |
60 |
|
|
|
61 |
|
|
if (!m.empty ()) |
62 |
|
|
{ |
63 |
|
|
o << (m.str.size () ? "(" : "'"); |
64 |
|
|
|
65 |
|
|
for (module_pos i = m.begin (); i != m.end (); ) |
66 |
|
|
{ |
67 |
|
|
o << *i; |
68 |
|
|
o << delim[!m.str.size ()][++i == m.end ()]; |
69 |
|
|
} |
70 |
|
|
} |
71 |
|
|
|
72 |
|
|
return o; |
73 |
|
|
} |
74 |
|
|
|
75 |
|
|
ostream &operator <<(ostream &o, const rule &r) t_no |
76 |
|
|
{ |
77 |
|
|
if (r.pre.size ()) |
78 |
|
|
o << r.pre << " < "; |
79 |
|
|
|
80 |
|
|
o << (module)r << " "; |
81 |
|
|
if (r.post.size ()) |
82 |
|
|
o << "> " << r.post << " "; |
83 |
|
|
|
84 |
|
|
if (r.constraint.is_expr) |
85 |
|
|
o << " '" << r.constraint << "' "; |
86 |
|
|
|
87 |
|
|
o << "=> " << r.repl; |
88 |
|
|
o << ", " << r.iterations; |
89 |
|
|
return o; |
90 |
|
|
} |
91 |
|
|
|
92 |
|
|
static ostream &operator <<(ostream &o, const lsys::arg_spec &a) t_no |
93 |
|
|
{ |
94 |
|
|
return o << "<" << a.str << "/" << a.nargs << ", " << a.arg << ">"; |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
ostream &operator <<(ostream &o, const lsys &l) t_no |
98 |
|
|
{ |
99 |
|
|
for (module_map::const_iterator i = l.defines.begin (); i != l.defines.end (); ++i) |
100 |
|
|
o << "DEFINE: " << i->first << " = " << i->second << endl; |
101 |
|
|
|
102 |
|
|
o << "PARENT: " << (l.parent ? l.parent->str : "(none)") << endl; |
103 |
|
|
|
104 |
|
|
o << "CHILDREN:"; |
105 |
|
|
for (hash_map<string, lsys *>::const_iterator i = l.sub_lsys.begin (); i != l.sub_lsys.end (); ++i) |
106 |
|
|
o << " " << i->second->str; |
107 |
|
|
o << endl; |
108 |
|
|
|
109 |
|
|
o << "IGNORE: "; |
110 |
|
|
copy (l.ignore_module.begin (), l.ignore_module.end (), ostream_iterator<const string>(o, " ")); |
111 |
|
|
o << endl; |
112 |
|
|
|
113 |
|
|
for (rule_map::const_iterator i = l.rules.begin (); i != l.rules.end (); ++i) |
114 |
|
|
for (rule_map::mapped_type::const_iterator j = i->second.begin (); j != i->second.end (); ++j) |
115 |
|
|
o << "RULE " << i->first << "/" << j->size () << ": " << *j << endl; |
116 |
|
|
|
117 |
|
|
o << "ARG_IS_NUMERIC:"; |
118 |
|
|
for (set<lsys::arg_spec>::const_iterator i = l.arg_is_numeric.begin (); |
119 |
|
|
i != l.arg_is_numeric.end (); |
120 |
|
|
++i) |
121 |
|
|
o << " " << *i; |
122 |
|
|
o << endl; |
123 |
|
|
|
124 |
|
|
return o; |
125 |
|
|
} |
126 |
|
|
|
127 |
|
|
lsys::lsys () t_no |
128 |
|
|
{ |
129 |
|
|
parent = 0; |
130 |
|
|
|
131 |
|
|
arg_spec s; |
132 |
|
|
s.str = "f"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
133 |
|
|
s.str = "F"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
134 |
|
|
s.str = "+"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
135 |
|
|
s.str = "-"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
136 |
|
|
s.str = "^"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
137 |
|
|
s.str = "&"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
138 |
|
|
s.str = "/"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
139 |
|
|
s.str = "\\"; s.nargs = 1; s.arg = 0; arg_is_numeric.insert (s); |
140 |
|
|
|
141 |
|
|
ignore_module.insert ("attr"); |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
lsys::~lsys () t_no |
145 |
|
|
{ |
146 |
|
|
hash_map<string, lsys*>::iterator i; |
147 |
|
|
|
148 |
|
|
while ((i = sub_lsys.begin ()) != sub_lsys.end ()) |
149 |
|
|
{ |
150 |
|
|
delete i->second; |
151 |
|
|
sub_lsys.erase (i); |
152 |
|
|
} |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
void lsys::mark_numeric (const map<string, arg_spec> &which, const module &v) t_no |
156 |
|
|
{ |
157 |
|
|
for (module_pos i = v.begin (); i != v.end (); ++i) |
158 |
|
|
{ |
159 |
|
|
map<string,arg_spec>::const_iterator d = which.find (i->str); |
160 |
|
|
|
161 |
|
|
if (d != which.end ()) |
162 |
|
|
arg_is_numeric.insert (d->second); |
163 |
|
|
else |
164 |
|
|
for (module_pos a = i->begin (); a != i->end (); a++) |
165 |
|
|
mark_numeric (which, *a); |
166 |
|
|
} |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
void lsys::add_lsys (lsys *l) t_err |
170 |
|
|
{ |
171 |
|
|
if (!l->str.size ()) |
172 |
|
|
{ |
173 |
|
|
delete l; |
174 |
|
|
throw error ("unable to determine ruleset name", *l); |
175 |
|
|
} |
176 |
|
|
|
177 |
|
|
l->parent = this; |
178 |
|
|
sub_lsys [l->str] = l; |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
void lsys::add_rule (rule r) t_err |
182 |
|
|
{ |
183 |
|
|
map<string,arg_spec> which; |
184 |
|
|
arg_spec spec; |
185 |
|
|
|
186 |
|
|
spec.str = r.str; |
187 |
|
|
spec.nargs = r.size (); |
188 |
|
|
spec.arg = 0; |
189 |
|
|
|
190 |
|
|
for (rule::iterator i = r.begin (); i != r.end (); ++i, spec.arg++) |
191 |
|
|
if (i->size () != 0) |
192 |
|
|
throw error("rule parameter too complex", *i); |
193 |
|
|
else if (i->is_expr) |
194 |
|
|
{ |
195 |
|
|
if (i->is_num) |
196 |
|
|
{ |
197 |
|
|
char arg[30]; |
198 |
|
|
sprintf (arg, "_arg%d", spec.arg); |
199 |
|
|
|
200 |
|
|
module m(arg); m.is_expr = 1; |
201 |
|
|
module eq("==", m, *i); eq.is_expr = 1; |
202 |
|
|
|
203 |
|
|
r.constraint = r.constraint.empty () |
204 |
|
|
? eq |
205 |
|
|
: module ("&&", r.constraint, eq); |
206 |
|
|
*i = m; |
207 |
|
|
} |
208 |
|
|
which.insert (pair<string, arg_spec>(i->str, spec)); |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
mark_numeric (which, r.constraint); |
212 |
|
|
|
213 |
|
|
if (rules.size () == 0) |
214 |
|
|
module::operator =((module)r); |
215 |
|
|
|
216 |
|
|
rules[r.str].push_back (r); |
217 |
|
|
} |
218 |
|
|
|
219 |
|
|
static double eval_expr_2 (const module &m, const module_map &l, const module_map &g) t_err |
220 |
|
|
{ |
221 |
|
|
switch (m.size ()) |
222 |
|
|
{ |
223 |
|
|
case 0: |
224 |
|
|
{ |
225 |
|
|
if (m.is_num) |
226 |
|
|
return m.num; |
227 |
|
|
else |
228 |
|
|
{ |
229 |
|
|
module_map::const_iterator i; |
230 |
|
|
|
231 |
|
|
if ((i = l.find (m.str)) != l.end () |
232 |
|
|
|| (i = g.find (m.str)) != g.end ()) |
233 |
|
|
return eval_expr (i->second, g, module_map ()); |
234 |
|
|
|
235 |
|
|
throw error ("undefined identifier in expression", m); |
236 |
|
|
} |
237 |
|
|
} |
238 |
|
|
|
239 |
|
|
case 1: |
240 |
|
|
if (m.str == "!" ) return !eval_expr_2 (m.first (), l, g); |
241 |
|
|
if (m.str == "sin" ) return sin (eval_expr_2 (m.first (), l, g)); |
242 |
|
|
if (m.str == "cos" ) return cos (eval_expr_2 (m.first (), l, g)); |
243 |
|
|
if (m.str == "tan" ) return tan (eval_expr_2 (m.first (), l, g)); |
244 |
|
|
if (m.str == "asin" ) return asin (eval_expr_2 (m.first (), l, g)); |
245 |
|
|
if (m.str == "acos" ) return acos (eval_expr_2 (m.first (), l, g)); |
246 |
|
|
if (m.str == "atan" ) return atan (eval_expr_2 (m.first (), l, g)); |
247 |
|
|
if (m.str == "int" ) return int (eval_expr_2 (m.first (), l, g)); |
248 |
|
|
if (m.str == "ceil" ) return ceil (eval_expr_2 (m.first (), l, g)); |
249 |
|
|
if (m.str == "floor" ) return floor(eval_expr_2 (m.first (), l, g)); |
250 |
|
|
if (m.str == "rand" ) return (eval_expr_2 (m.first (), l, g)) * rand () / RAND_MAX; |
251 |
|
|
if (m.str == "irand" ) return int ((eval_expr_2 (m.first (), l, g)) * rand () / RAND_MAX); |
252 |
|
|
if (m.str == "log" ) return log (eval_expr_2 (m.first (), l, g)); |
253 |
|
|
if (m.str == "abs" ) return abs (eval_expr_2 (m.first (), l, g)); |
254 |
|
|
if (m.str == "deg" ) return (eval_expr_2 (m.first (), l, g)) * 180.0 / M_PI; |
255 |
|
|
if (m.str == "rad" ) return (eval_expr_2 (m.first (), l, g)) * M_PI / 180.0; |
256 |
|
|
if (m.str == "sqrt" ) return sqrt (eval_expr_2 (m.first (), l, g)); |
257 |
|
|
|
258 |
|
|
throw error ("unknown unary function in expression", m); |
259 |
|
|
|
260 |
|
|
case 2: |
261 |
|
|
if (m.str == "+" ) return eval_expr_2 (m.first (), l, g) + eval_expr_2 (m.second (), l, g); |
262 |
|
|
if (m.str == "-" ) return eval_expr_2 (m.first (), l, g) - eval_expr_2 (m.second (), l, g); |
263 |
|
|
if (m.str == "*" ) return eval_expr_2 (m.first (), l, g) * eval_expr_2 (m.second (), l, g); |
264 |
|
|
if (m.str == "/" ) return eval_expr_2 (m.first (), l, g) / eval_expr_2 (m.second (), l, g); |
265 |
|
|
if (m.str == "<" ) return eval_expr_2 (m.first (), l, g) < eval_expr_2 (m.second (), l, g); |
266 |
|
|
if (m.str == "<=") return eval_expr_2 (m.first (), l, g) <= eval_expr_2 (m.second (), l, g); |
267 |
|
|
if (m.str == "==") return equal (eval_expr_2 (m.first (), l, g), eval_expr_2 (m.second (), l, g)); |
268 |
|
|
if (m.str == "!=") return eval_expr_2 (m.first (), l, g) != eval_expr_2 (m.second (), l, g); |
269 |
|
|
if (m.str == ">" ) return eval_expr_2 (m.first (), l, g) > eval_expr_2 (m.second (), l, g); |
270 |
|
|
if (m.str == ">=") return eval_expr_2 (m.first (), l, g) >= eval_expr_2 (m.second (), l, g); |
271 |
|
|
if (m.str == "&&") return eval_expr_2 (m.first (), l, g) && eval_expr_2 (m.second (), l, g); |
272 |
|
|
if (m.str == "||") return eval_expr_2 (m.first (), l, g) || eval_expr_2 (m.second (), l, g); |
273 |
|
|
if (m.str == "%" ) return fmod (eval_expr_2 (m.first (), l, g), eval_expr_2 (m.second (), l, g)); |
274 |
|
|
if (m.str == "^" ) return pow (eval_expr_2 (m.first (), l, g), eval_expr_2 (m.second (), l, g)); |
275 |
|
|
|
276 |
|
|
throw error ("unknown binary function in expression", m); |
277 |
|
|
|
278 |
|
|
default: |
279 |
|
|
throw error ("can only evaluate modules with 0, 1 or 2 arguments", m); |
280 |
|
|
} |
281 |
|
|
|
282 |
|
|
throw error("reached end of non-void function eval_expr_2", m); |
283 |
|
|
} |
284 |
|
|
|
285 |
|
|
double eval_expr (const module &expr, const module_map &locals, const module_map &globals) t_err |
286 |
|
|
{ |
287 |
|
|
return eval_expr_2 (expr, locals, globals); |
288 |
|
|
} |
289 |
|
|
|
290 |
|
|
double lsys::eval_numeric (const module &expr, module_map context) const t_err |
291 |
|
|
{ |
292 |
|
|
return eval_expr (expr, context, defines); |
293 |
|
|
} |
294 |
|
|
|
295 |
|
|
static void get_vars (const module_vec &par, const module_vec &arg, module_map &vars) t_no |
296 |
|
|
{ |
297 |
|
|
for (module_pos a = arg.begin (), b = par.begin (); |
298 |
|
|
a != arg.end (); |
299 |
|
|
++a, ++b) |
300 |
|
|
vars [b->str] = *a; |
301 |
|
|
} |
302 |
|
|
|
303 |
|
|
bool lsys::match_rule (const rule &r, const module_vec &v, module_pos i, module_map &vars) const t_err |
304 |
|
|
{ |
305 |
|
|
int nested = 0; |
306 |
|
|
|
307 |
|
|
if (r.module::match (*i)) |
308 |
|
|
{ |
309 |
|
|
module_pos j; |
310 |
|
|
|
311 |
|
|
// match heading context |
312 |
|
|
j = i; |
313 |
|
|
for (module_pos z = r.pre.end (); |
314 |
|
|
z != r.pre.begin (); |
315 |
|
|
) |
316 |
|
|
{ |
317 |
|
|
if (j == v.begin ()) |
318 |
|
|
return false; |
319 |
|
|
|
320 |
|
|
--j; |
321 |
|
|
if (j->str == "]") |
322 |
|
|
nested++; |
323 |
|
|
else if (j->str == "[") |
324 |
|
|
nested = nested ? nested-1 : nested; |
325 |
|
|
else if (!nested && ignore_module.find (j->str) == ignore_module.end ()) |
326 |
|
|
{ |
327 |
|
|
--z; |
328 |
|
|
if (!z->match (*j)) |
329 |
|
|
return false; |
330 |
|
|
|
331 |
|
|
get_vars (*z, *j, vars); |
332 |
|
|
} |
333 |
|
|
} |
334 |
|
|
|
335 |
|
|
// match trailing context |
336 |
|
|
j = i; |
337 |
|
|
for (module_pos z = r.post.begin (); |
338 |
|
|
z != r.post.end (); |
339 |
|
|
) |
340 |
|
|
{ |
341 |
|
|
++j; |
342 |
|
|
if (j == v.end ()) |
343 |
|
|
return false; |
344 |
|
|
|
345 |
|
|
if (j->str == "[") |
346 |
|
|
nested++; |
347 |
|
|
else if (j->str == "]") |
348 |
|
|
nested = nested ? nested-1 : nested; |
349 |
|
|
else if (!nested && ignore_module.find (j->str) == ignore_module.end ()) |
350 |
|
|
{ |
351 |
|
|
if (!z->match (*j)) |
352 |
|
|
return false; |
353 |
|
|
|
354 |
|
|
get_vars (*z, *j, vars); |
355 |
|
|
++z; |
356 |
|
|
} |
357 |
|
|
} |
358 |
|
|
|
359 |
|
|
get_vars (r, *i, vars); |
360 |
|
|
//FIXME: add pattern matching ??? |
361 |
|
|
return eval_numeric (r.constraint, vars); |
362 |
|
|
} |
363 |
|
|
|
364 |
|
|
return false; |
365 |
|
|
} |
366 |
|
|
|
367 |
|
|
module lsys::expand (const module_map &c, const module &m) const t_err |
368 |
|
|
{ |
369 |
|
|
module_map::const_iterator n; |
370 |
|
|
|
371 |
|
|
if ((n = c.find (m.str)) != c.end ()) |
372 |
|
|
return n->second; |
373 |
|
|
else |
374 |
|
|
{ |
375 |
|
|
arg_spec spec; |
376 |
|
|
spec.str = m.str; |
377 |
|
|
spec.nargs = m.size (); |
378 |
|
|
spec.arg = 0; |
379 |
|
|
|
380 |
|
|
module k; |
381 |
|
|
k.str = m.str; |
382 |
|
|
k.num = m.num; |
383 |
|
|
k.is_num = m.is_num; |
384 |
|
|
k.is_expr = m.is_expr; |
385 |
|
|
k.where = m.where; |
386 |
|
|
|
387 |
|
|
for (module_pos i = m.begin (); i != m.end (); ++i, spec.arg++) |
388 |
|
|
if (arg_is_numeric.find (spec) != arg_is_numeric.end ()) |
389 |
|
|
k.push_back (eval_numeric (*i, c)); |
390 |
|
|
else |
391 |
|
|
k.push_back (expand (c, *i)); |
392 |
|
|
|
393 |
|
|
return k; |
394 |
|
|
} |
395 |
|
|
} |
396 |
|
|
|
397 |
|
|
static void replace_modules(module_vec &v, const module_map &m) t_no |
398 |
|
|
{ |
399 |
|
|
module_map::const_iterator c; |
400 |
|
|
|
401 |
|
|
for (module::iterator i = v.begin (); i != v.end (); ++i) |
402 |
|
|
if (i->empty () && (c = m.find (i->str)) != m.end ()) |
403 |
|
|
*i = c->second; |
404 |
|
|
else |
405 |
|
|
replace_modules (*i, m); |
406 |
|
|
} |
407 |
|
|
|
408 |
|
|
bool operator <(const module &a, const module &b) t_no |
409 |
|
|
{ |
410 |
|
|
if ((module_vec)a < (module_vec)b) |
411 |
|
|
return true; |
412 |
|
|
else |
413 |
|
|
return a.str < b.str; |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
struct lsys_module { |
417 |
|
|
const lsys *sys; |
418 |
|
|
module_vec v; |
419 |
|
|
}; |
420 |
|
|
|
421 |
|
|
static bool operator <(const lsys_module &a, const lsys_module &b) |
422 |
|
|
{ |
423 |
|
|
if (a.v < b.v) |
424 |
|
|
return true; |
425 |
|
|
else |
426 |
|
|
return (long)a.sys < (long)b.sys; |
427 |
|
|
} |
428 |
|
|
|
429 |
|
|
bool lsys::eval (module_vec &v) const t_err |
430 |
|
|
{ |
431 |
|
|
#if 0 |
432 |
|
|
typedef map<lsys_module, pair<bool, module_vec> > eval_cache; |
433 |
|
|
static eval_cache cache; |
434 |
|
|
|
435 |
|
|
eval_cache::iterator ci; |
436 |
|
|
|
437 |
|
|
{ //FIXME, why can't I just re-use "ck" later?? |
438 |
|
|
lsys_module ck; |
439 |
|
|
ck.sys = this; |
440 |
|
|
ck.v = v; |
441 |
|
|
|
442 |
|
|
if ((ci = cache.find (ck)) != cache.end ()) |
443 |
|
|
{ |
444 |
|
|
if (ci->second.first) |
445 |
|
|
v = ci->second.second; |
446 |
|
|
|
447 |
|
|
return ci->second.first; |
448 |
|
|
} |
449 |
|
|
} |
450 |
|
|
#endif |
451 |
|
|
|
452 |
|
|
bool changed = false; |
453 |
|
|
module_vec res; |
454 |
|
|
module_map vars; |
455 |
|
|
|
456 |
|
|
for (module_pos i = v.begin (); i != v.end (); ++i) |
457 |
|
|
{ |
458 |
|
|
rule_map::const_iterator r = rules.find (i->str); |
459 |
|
|
|
460 |
|
|
if (r != rules.end ()) |
461 |
|
|
for (rule_map::mapped_type::const_iterator j = r->second.begin (); j != r->second.end (); ++j) |
462 |
|
|
{ |
463 |
|
|
vars.erase (vars.begin (), vars.end ()); |
464 |
|
|
|
465 |
|
|
if (match_rule (*j, v, i, vars)) |
466 |
|
|
{ |
467 |
|
|
double it = eval_numeric (j->iterations, vars); |
468 |
|
|
|
469 |
|
|
changed = true; |
470 |
|
|
|
471 |
|
|
if (it >= 1.0) |
472 |
|
|
{ |
473 |
|
|
module_vec x; |
474 |
|
|
|
475 |
|
|
for (module_pos i = j->repl.begin (); i != j->repl.end (); ++i) |
476 |
|
|
x.push_back (expand (vars, *i)); |
477 |
|
|
|
478 |
|
|
do { |
479 |
|
|
eval (x); |
480 |
|
|
it--; |
481 |
|
|
} while (it > 0); |
482 |
|
|
|
483 |
|
|
res.insert (res.end (), x.begin (), x.end ()); |
484 |
|
|
} |
485 |
|
|
else |
486 |
|
|
for (module_pos i = j->repl.begin (); i != j->repl.end (); ++i) |
487 |
|
|
res.push_back (expand (vars, *i)); |
488 |
|
|
|
489 |
|
|
goto skip; |
490 |
|
|
} |
491 |
|
|
} |
492 |
|
|
|
493 |
|
|
// no rule matched.. |
494 |
|
|
res.push_back (*i); |
495 |
|
|
skip:; |
496 |
|
|
} |
497 |
|
|
|
498 |
|
|
replace_modules (res, defines); |
499 |
|
|
#if 0 |
500 |
|
|
if ((!changed && v.size () < 10) || res.size () < 20) |
501 |
|
|
{ |
502 |
|
|
eval_cache::mapped_type ce(changed, changed ? res : module_vec ()); |
503 |
|
|
lsys_module ck; |
504 |
|
|
ck.sys = this; |
505 |
|
|
ck.v = v; //FIXME not even this works |
506 |
|
|
cache.insert (ci, eval_cache::value_type (ck, ce)); |
507 |
|
|
} |
508 |
|
|
#endif |
509 |
|
|
|
510 |
|
|
v.erase (); |
511 |
|
|
|
512 |
|
|
for (module_pos i = res.begin (); i != res.end (); ) |
513 |
|
|
{ |
514 |
|
|
if (i->str == "%") |
515 |
|
|
{ |
516 |
|
|
int nested = 1; |
517 |
|
|
|
518 |
|
|
while (++i != res.end ()) |
519 |
|
|
if (i->str == "[") |
520 |
|
|
nested++; |
521 |
|
|
else if (i->str == "]" && !(--nested)) |
522 |
|
|
break; |
523 |
|
|
} |
524 |
|
|
else |
525 |
|
|
v.push_back (*i++); |
526 |
|
|
} |
527 |
|
|
|
528 |
|
|
return changed; |
529 |
|
|
} |
530 |
|
|
|
531 |
|
|
bool module::is_func (const string &func) const t_no |
532 |
|
|
{ |
533 |
|
|
return str == func && size () == 0; |
534 |
|
|
} |
535 |
|
|
|
536 |
|
|
bool module::is_func (const string &func, double &arg1) const t_no |
537 |
|
|
{ |
538 |
|
|
if (str == func && size () == 1) |
539 |
|
|
{ |
540 |
|
|
arg1 = eval_expr (first ()); |
541 |
|
|
return true; |
542 |
|
|
} |
543 |
|
|
return false; |
544 |
|
|
} |
545 |
|
|
|
546 |
|
|
bool module::is_func (const string &func, string &arg1, module &arg2) const t_no |
547 |
|
|
{ |
548 |
|
|
if (str == func && size () == 2 && first().is_expr) |
549 |
|
|
{ |
550 |
|
|
arg1 = first ().str; |
551 |
|
|
arg2 = second (); |
552 |
|
|
return true; |
553 |
|
|
} |
554 |
|
|
|
555 |
|
|
return false; |
556 |
|
|
} |
557 |
|
|
|
558 |
|
|
bool module::is_func (const string &func, string &arg1, double &arg2) const t_no |
559 |
|
|
{ |
560 |
|
|
if (str == func && size () == 2 && first().is_expr) |
561 |
|
|
{ |
562 |
|
|
arg1 = first ().str; |
563 |
|
|
arg2 = eval_expr (second ()); |
564 |
|
|
return true; |
565 |
|
|
} |
566 |
|
|
|
567 |
|
|
return false; |
568 |
|
|
} |
569 |
|
|
|
570 |
|
|
bool module::is_func (const string &func, string &arg1, string &arg2) const t_no |
571 |
|
|
{ |
572 |
|
|
if (str == func && size () == 2 && first().is_expr) |
573 |
|
|
{ |
574 |
|
|
arg1 = first ().str; |
575 |
|
|
arg2 = (string) second (); |
576 |
|
|
return true; |
577 |
|
|
} |
578 |
|
|
|
579 |
|
|
return false; |
580 |
|
|
} |
581 |
|
|
|
582 |
|
|
|
583 |
|
|
|
584 |
|
|
|
585 |
|
|
|