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