1 //
2 // aegis - project change supervisor
3 // Copyright (C) 1997, 1999, 2002-2008 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see
17 // <http://www.gnu.org/licenses/>.
18 //
19
20 #include <common/error.h>
21 #include <common/trace.h>
22 #include <libaegis/aer/value/error.h>
23 #include <libaegis/aer/value/integer.h>
24 #include <libaegis/sub.h>
25
26 #include <aefind/function/needs.h>
27 #include <aefind/tree/bitwise.h>
28 #include <aefind/tree/diadic.h>
29 #include <aefind/tree/list.h>
30 #include <aefind/tree/monadic.h>
31
32
~tree_bitwise_and()33 tree_bitwise_and::~tree_bitwise_and()
34 {
35 }
36
37
tree_bitwise_and(const tree::pointer & a1,const tree::pointer & a2)38 tree_bitwise_and::tree_bitwise_and(const tree::pointer &a1,
39 const tree::pointer &a2) :
40 tree_diadic(a1, a2)
41 {
42 }
43
44
45 tree::pointer
create(const tree::pointer & a1,const tree::pointer & a2)46 tree_bitwise_and::create(const tree::pointer &a1, const tree::pointer &a2)
47 {
48 return pointer(new tree_bitwise_and(a1, a2));
49 }
50
51
52 tree::pointer
create_l(const tree_list & args)53 tree_bitwise_and::create_l(const tree_list &args)
54 {
55 function_needs_two("&", args);
56 return create(args[0], args[1]);
57 }
58
59
60 rpt_value::pointer
evaluate(string_ty * path_unres,string_ty * path,string_ty * path_res,struct stat * st) const61 tree_bitwise_and::evaluate(string_ty *path_unres, string_ty *path,
62 string_ty *path_res, struct stat *st) const
63 {
64 rpt_value::pointer v1 =
65 get_left()->evaluate(path_unres, path, path_res, st);
66 if (v1->is_an_error())
67 return v1;
68 rpt_value::pointer v1i = rpt_value::integerize(v1);
69 rpt_value_integer *v1ip = dynamic_cast<rpt_value_integer *>(v1i.get());
70 if (!v1ip)
71 {
72 sub_context_ty sc;
73 sc.var_set_charstar("Name", v1->name());
74 nstring s
75 (
76 sc.subst_intl
77 (
78 i18n("integer value required for bit and (was given $name)")
79 )
80 );
81 return rpt_value_error::create(s);
82 }
83
84 rpt_value::pointer v2 =
85 get_right()->evaluate(path_unres, path, path_res, st);
86 if (v2->is_an_error())
87 return v2;
88 rpt_value::pointer v2i = rpt_value::integerize(v2);
89 rpt_value_integer *v2ip = dynamic_cast<rpt_value_integer *>(v2i.get());
90 if (!v2ip)
91 {
92 sub_context_ty sc;
93 sc.var_set_charstar("Name", v2->name());
94 nstring s
95 (
96 sc.subst_intl
97 (
98 i18n("integer value required for bit and (was given $name)")
99 )
100 );
101 return rpt_value_error::create(s);
102 }
103
104 return rpt_value_integer::create(v1ip->query() & v2ip->query());
105 }
106
107
108 tree::pointer
optimize() const109 tree_bitwise_and::optimize()
110 const
111 {
112 tree::pointer tp = create(get_left()->optimize(), get_right()->optimize());
113 if (tp->constant())
114 tp = tp->optimize_constant();
115 return tp;
116 }
117
118
119 const char *
name() const120 tree_bitwise_and::name()
121 const
122 {
123 return "&";
124 }
125
126
~tree_bitwise_xor()127 tree_bitwise_xor::~tree_bitwise_xor()
128 {
129 }
130
131
tree_bitwise_xor(const tree::pointer & a1,const tree::pointer & a2)132 tree_bitwise_xor::tree_bitwise_xor(const tree::pointer &a1,
133 const tree::pointer &a2) :
134 tree_diadic(a1, a2)
135 {
136 }
137
138
139 tree::pointer
create(const tree::pointer & a1,const tree::pointer & a2)140 tree_bitwise_xor::create(const tree::pointer &a1, const tree::pointer &a2)
141 {
142 return pointer(new tree_bitwise_xor(a1, a2));
143 }
144
145
146 tree::pointer
create_l(const tree_list & args)147 tree_bitwise_xor::create_l(const tree_list &args)
148 {
149 function_needs_two("^", args);
150 return create(args[0], args[1]);
151 }
152
153
154 rpt_value::pointer
evaluate(string_ty * path_unres,string_ty * path,string_ty * path_res,struct stat * st) const155 tree_bitwise_xor::evaluate(string_ty *path_unres, string_ty *path,
156 string_ty *path_res, struct stat *st) const
157 {
158 rpt_value::pointer v1 =
159 get_left()->evaluate(path_unres, path, path_res, st);
160 if (v1->is_an_error())
161 return v1;
162 rpt_value::pointer v1i = rpt_value::integerize(v1);
163 rpt_value_integer *v1ip = dynamic_cast<rpt_value_integer *>(v1i.get());
164 if (!v1ip)
165 {
166 sub_context_ty sc;
167 sc.var_set_charstar("Name", v1->name());
168 nstring s
169 (
170 sc.subst_intl
171 (
172 i18n("integer value required for bit xor (was given $name)")
173 )
174 );
175 return rpt_value_error::create(s);
176 }
177
178 rpt_value::pointer v2 =
179 get_right()->evaluate(path_unres, path, path_res, st);
180 if (v2->is_an_error())
181 return v2;
182 rpt_value::pointer v2i = rpt_value::integerize(v2);
183 rpt_value_integer *v2ip = dynamic_cast<rpt_value_integer *>(v2i.get());
184 if (!v2ip)
185 {
186 sub_context_ty sc;
187 sc.var_set_charstar("Name", v2->name());
188 nstring s
189 (
190 sc.subst_intl
191 (
192 i18n("integer value required for bit xor (was given $name)")
193 )
194 );
195 return rpt_value_error::create(s);
196 }
197
198 return rpt_value_integer::create(v1ip->query() ^ v2ip->query());
199 }
200
201
202 tree::pointer
optimize() const203 tree_bitwise_xor::optimize()
204 const
205 {
206 tree::pointer tp = create(get_left()->optimize(), get_right()->optimize());
207 if (tp->constant())
208 tp = tp->optimize_constant();
209 return tp;
210 }
211
212
213 const char *
name() const214 tree_bitwise_xor::name()
215 const
216 {
217 return "^";
218 }
219
220
~tree_bitwise_or()221 tree_bitwise_or::~tree_bitwise_or()
222 {
223 }
224
225
tree_bitwise_or(const tree::pointer & a1,const tree::pointer & a2)226 tree_bitwise_or::tree_bitwise_or(const tree::pointer &a1,
227 const tree::pointer &a2) :
228 tree_diadic(a1, a2)
229 {
230 }
231
232
233 tree::pointer
create(const tree::pointer & a1,const tree::pointer & a2)234 tree_bitwise_or::create(const tree::pointer &a1, const tree::pointer &a2)
235 {
236 return pointer(new tree_bitwise_or(a1, a2));
237 }
238
239
240 tree::pointer
create_l(const tree_list & args)241 tree_bitwise_or::create_l(const tree_list &args)
242 {
243 function_needs_two("|", args);
244 return create(args[0], args[1]);
245 }
246
247
248 rpt_value::pointer
evaluate(string_ty * path_unres,string_ty * path,string_ty * path_res,struct stat * st) const249 tree_bitwise_or::evaluate(string_ty *path_unres, string_ty *path,
250 string_ty *path_res, struct stat *st) const
251 {
252 rpt_value::pointer v1 =
253 get_left()->evaluate(path_unres, path, path_res, st);
254 if (v1->is_an_error())
255 return v1;
256 rpt_value::pointer v1i = rpt_value::integerize(v1);
257 rpt_value_integer *v1ip = dynamic_cast<rpt_value_integer *>(v1i.get());
258 if (!v1ip)
259 {
260 sub_context_ty sc;
261 sc.var_set_charstar("Name", v1->name());
262 nstring s
263 (
264 sc.subst_intl
265 (
266 i18n("integer value required for bit or (was given $name)")
267 )
268 );
269 return rpt_value_error::create(s);
270 }
271
272 rpt_value::pointer v2 =
273 get_right()->evaluate(path_unres, path, path_res, st);
274 if (v2->is_an_error())
275 return v2;
276 rpt_value::pointer v2i = rpt_value::integerize(v2);
277 rpt_value_integer *v2ip = dynamic_cast<rpt_value_integer *>(v2i.get());
278 if (!v2ip)
279 {
280 sub_context_ty sc;
281 sc.var_set_charstar("Name", v2->name());
282 nstring s
283 (
284 sc.subst_intl
285 (
286 i18n("integer value required for bit or (was given $name)")
287 )
288 );
289 return rpt_value_error::create(s);
290 }
291
292 return rpt_value_integer::create(v1ip->query() | v2ip->query());
293 }
294
295
296 tree::pointer
optimize() const297 tree_bitwise_or::optimize()
298 const
299 {
300 tree::pointer tp = create(get_left()->optimize(), get_right()->optimize());
301 if (tp->constant())
302 tp = tp->optimize_constant();
303 return tp;
304 }
305
306
307 const char *
name() const308 tree_bitwise_or::name()
309 const
310 {
311 return "|";
312 }
313
314
~tree_bitwise_not()315 tree_bitwise_not::~tree_bitwise_not()
316 {
317 }
318
319
tree_bitwise_not(const tree::pointer & a_arg)320 tree_bitwise_not::tree_bitwise_not(const tree::pointer &a_arg) :
321 tree_monadic(a_arg)
322 {
323 }
324
325
326 tree::pointer
create(const tree::pointer & a_arg)327 tree_bitwise_not::create(const tree::pointer &a_arg)
328 {
329 return pointer(new tree_bitwise_not(a_arg));
330 }
331
332
333 tree::pointer
create_l(const tree_list & args)334 tree_bitwise_not::create_l(const tree_list &args)
335 {
336 function_needs_one("~", args);
337 return create(args[0]);
338 }
339
340
341 rpt_value::pointer
evaluate(string_ty * path_unres,string_ty * path,string_ty * path_res,struct stat * st) const342 tree_bitwise_not::evaluate(string_ty *path_unres, string_ty *path,
343 string_ty *path_res, struct stat *st) const
344 {
345 //
346 // evaluate the argument
347 //
348 trace(("not::evaluate()\n"));
349 rpt_value::pointer v1 = get_arg()->evaluate(path_unres, path, path_res, st);
350 if (v1->is_an_error())
351 return v1;
352
353 //
354 // coerce the argument to an arithmetic type
355 // (will not give error if can't, will copy instead)
356 //
357 rpt_value::pointer v2 = rpt_value::integerize(v1);
358
359 //
360 // the type of the result depends on
361 // the types of the argument
362 //
363 rpt_value_integer *v2ip = dynamic_cast<rpt_value_integer *>(v2.get());
364 if (!v2ip)
365 {
366 sub_context_ty sc;
367 sc.var_set_charstar("Name", v1->name());
368 nstring s(sc.subst_intl(i18n("illegal bit not ($name)")));
369 return rpt_value_error::create(s);
370 }
371
372 return rpt_value_integer::create(~v2ip->query());
373 }
374
375
376 tree::pointer
optimize() const377 tree_bitwise_not::optimize()
378 const
379 {
380 tree::pointer tp = create(get_arg()->optimize());
381 if (tp->constant())
382 tp = tp->optimize_constant();
383 return tp;
384 }
385
386
387 const char *
name() const388 tree_bitwise_not::name()
389 const
390 {
391 return "~";
392 }
393
394
~tree_shift_left()395 tree_shift_left::~tree_shift_left()
396 {
397 }
398
399
tree_shift_left(const tree::pointer & a1,const tree::pointer & a2)400 tree_shift_left::tree_shift_left(const tree::pointer &a1,
401 const tree::pointer &a2) :
402 tree_diadic(a1, a2)
403 {
404 }
405
406
407 tree::pointer
create(const tree::pointer & a1,const tree::pointer & a2)408 tree_shift_left::create(const tree::pointer &a1, const tree::pointer &a2)
409 {
410 return pointer(new tree_shift_left(a1, a2));
411 }
412
413
414 tree::pointer
create_l(const tree_list & args)415 tree_shift_left::create_l(const tree_list &args)
416 {
417 function_needs_two("<<", args);
418 return create(args[0], args[1]);
419 }
420
421
422 rpt_value::pointer
evaluate(string_ty * path_unres,string_ty * path,string_ty * path_res,struct stat * st) const423 tree_shift_left::evaluate(string_ty *path_unres, string_ty *path,
424 string_ty *path_res, struct stat *st) const
425 {
426 rpt_value::pointer v1 =
427 get_left()->evaluate(path_unres, path, path_res, st);
428 if (v1->is_an_error())
429 return v1;
430 rpt_value::pointer v1i = rpt_value::integerize(v1);
431 rpt_value_integer *v1ip = dynamic_cast<rpt_value_integer *>(v1i.get());
432
433 rpt_value::pointer v2 =
434 get_right()->evaluate(path_unres, path, path_res, st);
435 if (v2->is_an_error())
436 return v2;
437 rpt_value::pointer v2i = rpt_value::integerize(v2);
438 rpt_value_integer *v2ip = dynamic_cast<rpt_value_integer *>(v2i.get());
439
440 if (!v1ip || !v2ip)
441 {
442 sub_context_ty sc;
443 sc.var_set_charstar("Name1", v1->name());
444 sc.var_set_charstar("Name2", v2->name());
445 nstring s(sc.subst_intl(i18n("illegal shift ($name1 << $name2)")));
446 return rpt_value_error::create(s);
447 }
448
449 long v1n = v1ip->query();
450 long v2n = v2ip->query();
451 return rpt_value_integer::create(v1n << v2n);
452 }
453
454
455 tree::pointer
optimize() const456 tree_shift_left::optimize()
457 const
458 {
459 tree::pointer tp = create(get_left()->optimize(), get_right()->optimize());
460 if (tp->constant())
461 tp = tp->optimize_constant();
462 return tp;
463 }
464
465
466 const char *
name() const467 tree_shift_left::name()
468 const
469 {
470 return "<<";
471 }
472
473
~tree_shift_right()474 tree_shift_right::~tree_shift_right()
475 {
476 }
477
478
tree_shift_right(const tree::pointer & a1,const tree::pointer & a2)479 tree_shift_right::tree_shift_right(const tree::pointer &a1,
480 const tree::pointer &a2) :
481 tree_diadic(a1, a2)
482 {
483 }
484
485
486 tree::pointer
create(const tree::pointer & a1,const tree::pointer & a2)487 tree_shift_right::create(const tree::pointer &a1, const tree::pointer &a2)
488 {
489 return pointer(new tree_shift_right(a1, a2));
490 }
491
492
493 tree::pointer
create_l(const tree_list & args)494 tree_shift_right::create_l(const tree_list &args)
495 {
496 function_needs_two(">>", args);
497 return create(args[0], args[1]);
498 }
499
500
501 rpt_value::pointer
evaluate(string_ty * path_unres,string_ty * path,string_ty * path_res,struct stat * st) const502 tree_shift_right::evaluate(string_ty *path_unres, string_ty *path,
503 string_ty *path_res, struct stat *st) const
504 {
505 rpt_value::pointer v1 =
506 get_left()->evaluate(path_unres, path, path_res, st);
507 if (v1->is_an_error())
508 return v1;
509 rpt_value::pointer v1i = rpt_value::integerize(v1);
510 rpt_value_integer *v1ip = dynamic_cast<rpt_value_integer *>(v1i.get());
511
512 rpt_value::pointer v2 =
513 get_right()->evaluate(path_unres, path, path_res, st);
514 if (v2->is_an_error())
515 return v2;
516 rpt_value::pointer v2i = rpt_value::integerize(v2);
517 rpt_value_integer *v2ip = dynamic_cast<rpt_value_integer *>(v2i.get());
518
519 if (!v1ip || !v2ip)
520 {
521 sub_context_ty sc;
522 sc.var_set_charstar("Name1", v1->name());
523 sc.var_set_charstar("Name2", v2->name());
524 nstring s(sc.subst_intl(i18n("illegal shift ($name1 >> $name2)")));
525 return rpt_value_error::create(s);
526 }
527
528 long v1n = v1ip->query();
529 long v2n = v2ip->query();
530 return rpt_value_integer::create(v1n >> v2n);
531 }
532
533
534 tree::pointer
optimize() const535 tree_shift_right::optimize()
536 const
537 {
538 tree::pointer tp = create(get_left()->optimize(), get_right()->optimize());
539 if (tp->constant())
540 tp = tp->optimize_constant();
541 return tp;
542 }
543
544
545 const char *
name() const546 tree_shift_right::name()
547 const
548 {
549 return ">>";
550 }
551