1 /*
2 * The contents of this file are subject to the Mozilla Public License
3 * Version 1.0 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
9 * License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Initial Developer of this code is David Baum.
13 * Portions created by David Baum are Copyright (C) 1999 David Baum.
14 * All Rights Reserved.
15 *
16 * Portions created by John Hansen are Copyright (C) 2005 John Hansen.
17 * All Rights Reserved.
18 *
19 */
20
21 #include "RelExpr.h"
22 #include "Bytecode.h"
23 /*
24 #include "parser.h"
25 #include "RCX_Constants.h"
26 */
27
28 // these are VERY dependent on RCX_Constants
29 static int sReversed[] = {
30 RelExpr::kGreaterOrEqual, RelExpr::kLessOrEqual, RelExpr::kNotEqualTo,
31 RelExpr::kEqualTo, RelExpr::kLessThan, RelExpr::kGreaterThan
32 };
33
34 static int sInverted[] = {
35 RelExpr::kGreaterThan, RelExpr::kLessThan, RelExpr::kEqualTo,
36 RelExpr::kNotEqualTo, RelExpr::kLessOrEqual, RelExpr::kGreaterOrEqual
37 };
38
39 static RCX_Relation sRCX_Codes[] = {
40 kRCX_LessOrEqual, kRCX_GreaterOrEqual, kRCX_NotEqualTo, kRCX_EqualTo
41 };
42
43
RelExpr(Expr * lhs,int relation,Expr * rhs)44 RelExpr::RelExpr (Expr *lhs, int relation, Expr *rhs)
45 : NodeExpr(lhs, rhs), fRelation(relation)
46 {
47 }
48
49
50
Clone(Mapping * b) const51 Expr* RelExpr::Clone(Mapping *b) const
52 {
53 return new RelExpr(Get(0)->Clone(b), fRelation, Get(1)->Clone(b));
54 }
55
56
Evaluate(int & v) const57 bool RelExpr::Evaluate(int &v) const
58 {
59 int v1, v2;
60 bool b;
61
62 if (!Get(0)->Evaluate(v1)) return false;
63 if (!Get(1)->Evaluate(v2)) return false;
64
65 switch(fRelation)
66 {
67 case kLessOrEqual:
68 b = (v1 <= v2);
69 break;
70 case kGreaterOrEqual:
71 b = (v1 >= v2);
72 break;
73 case kNotEqualTo:
74 b = (v1 != v2);
75 break;
76 case kEqualTo:
77 b = (v1 == v2);
78 break;
79 case kGreaterThan:
80 b = (v1 > v2);
81 break;
82 case kLessThan:
83 b = (v1 < v2);
84 break;
85 default:
86 return false;
87
88 }
89
90 v = b ? 1 : 0;
91
92 return true;
93 }
94
95
EmitBranch_(Bytecode & b,int label,bool condition) const96 bool RelExpr::EmitBranch_(Bytecode &b, int label, bool condition) const
97 {
98 bool ok = true;
99 int r = fRelation;
100 RCX_Value ea1 = Get(0)->EmitConstrained(b, TEST_MASK);
101 RCX_Value ea2 = Get(1)->EmitConstrained(b, TEST_MASK);
102
103 // if value 2 is constant, swap with value 1
104 if (RCX_VALUE_TYPE(ea2) == kRCX_ConstantType)
105 {
106 RCX_Value t = ea1;
107 ea1 = ea2;
108 ea2 = t;
109 r = sReversed[r];
110 }
111
112 // invert if emitting false branch
113 if (!condition)
114 r = sInverted[r];
115
116 switch(r)
117 {
118 case kLessOrEqual:
119 case kGreaterOrEqual:
120 case kNotEqualTo:
121 case kEqualTo:
122 b.AddTest(ea1, sRCX_Codes[r], ea2, label);
123 break;
124 case kGreaterThan:
125 case kLessThan:
126 if (RCX_VALUE_TYPE(ea1) == kRCX_ConstantType)
127 {
128 RCX_Relation rel;
129 short adjust;
130 short limit;
131 short c;
132
133 if (r == kGreaterThan)
134 {
135 rel = kRCX_GreaterOrEqual;
136 adjust = -1;
137 limit = -32768;
138 }
139 else
140 {
141 rel = kRCX_LessOrEqual;
142 adjust = 1;
143 limit = 32767;
144 }
145
146 c = RCX_VALUE_DATA(ea1);
147
148 // check for impossible range
149 if (c == limit)
150 {
151 ok = false;
152 break;
153 }
154
155 // test for adjusted range
156 b.AddTest(RCX_VALUE(kRCX_ConstantType, c+adjust), rel, ea2, label);
157 }
158 else
159 {
160 int around = b.NewLabel();
161 b.AddTest(ea1, sRCX_Codes[sInverted[r]], ea2, around);
162 b.AddJump(label);
163 b.SetLabel(around);
164 }
165 break;
166 }
167
168 b.ReleaseTempEA(ea1);
169 b.ReleaseTempEA(ea2);
170 return ok;
171 }
172