001: /*
002: * ExprValue.java
003: *
004: * Copyright (c) 1997 Cornell University.
005: * Copyright (c) 1997 Sun Microsystems, Inc.
006: *
007: * See the file "license.terms" for information on usage and
008: * redistribution of this file, and for a DISCLAIMER OF ALL
009: * WARRANTIES.
010: *
011: * RCS: @(#) $Id: ExprValue.java,v 1.12 2006/06/27 21:14:42 mdejong Exp $
012: *
013: */
014:
015: package tcl.lang;
016:
017: /**
018: * Describes an expression value, which can be either an integer (the
019: * usual case), a double-precision floating-point value, or a string.
020: * A number type will typically have a string value that is the number
021: * string before it was parsed into a number. If the number has no
022: * string value then one will be generated by getStringValue().
023: */
024:
025: public final class ExprValue {
026: static final int INT = 0;
027: static final int DOUBLE = 1;
028: static final int STRING = 2;
029:
030: /**
031: * Integer value, if any.
032: */
033: private int intValue;
034:
035: /**
036: * Floating-point value, if any.
037: */
038: private double doubleValue;
039:
040: /**
041: * Used to hold a string value, if any.
042: */
043: private String stringValue;
044:
045: /**
046: * Type of value: INT, DOUBLE, or STRING.
047: */
048: private int type;
049:
050: /**
051: * Extra debug checking
052: */
053: private static final boolean validate = false;
054:
055: public ExprValue(int i, String s) {
056: setIntValue(i, s);
057: }
058:
059: public ExprValue(double d, String s) {
060: setDoubleValue(d, s);
061: }
062:
063: public ExprValue(String s) {
064: setStringValue(s);
065: }
066:
067: public ExprValue(boolean b) {
068: setIntValue(b);
069: }
070:
071: public final int getType() {
072: return type;
073: }
074:
075: public final boolean isIntType() {
076: return type == INT;
077: }
078:
079: public final boolean isDoubleType() {
080: return type == DOUBLE;
081: }
082:
083: public final boolean isStringType() {
084: return type == STRING;
085: }
086:
087: public final boolean isIntOrDoubleType() {
088: return (type == INT) || (type == DOUBLE);
089: }
090:
091: public final int getIntValue() {
092: if (validate) {
093: if (type != INT) {
094: throw new TclRuntimeError(
095: "called getIntValue() on non-INT type");
096: }
097: }
098: return intValue;
099: }
100:
101: public final double getDoubleValue() {
102: if (validate) {
103: if (type != DOUBLE) {
104: throw new TclRuntimeError(
105: "called getDoubleValue() on non-DOUBLE type");
106: }
107: }
108: return doubleValue;
109: }
110:
111: public final String getStringValue() {
112: if (type == STRING) {
113: // No-op
114: } else if (type == INT) {
115: if (stringValue == null) {
116: stringValue = Integer.toString(intValue);
117: }
118: } else if (type == DOUBLE) {
119: if (stringValue == null) {
120: // Generate Tcl string rep for the double.
121: stringValue = Util.printDouble(doubleValue);
122: }
123: }
124: return stringValue;
125: }
126:
127: public final boolean getBooleanValue(Interp interp)
128: throws TclException // Raise TclException if string is not a boolean
129: {
130: switch (type) {
131: case ExprValue.INT:
132: return (intValue != 0);
133: case ExprValue.DOUBLE:
134: return (doubleValue != 0.0);
135: case ExprValue.STRING:
136: return Util.getBoolean(interp, stringValue);
137: default:
138: throw new TclRuntimeError(
139: "internal error: expression, unknown");
140: }
141: }
142:
143: public final void setIntValue(int value) {
144: stringValue = null;
145: intValue = value;
146: type = INT;
147: }
148:
149: public final void setIntValue(int value, String s) {
150: stringValue = s;
151: intValue = value;
152: type = INT;
153: }
154:
155: public final void setIntValue(boolean b) {
156: stringValue = null;
157: intValue = (b ? 1 : 0);
158: type = INT;
159: }
160:
161: public final void setDoubleValue(double value) {
162: stringValue = null;
163: doubleValue = value;
164: type = DOUBLE;
165: }
166:
167: public final void setDoubleValue(double value, String s) {
168: stringValue = s;
169: doubleValue = value;
170: type = DOUBLE;
171: }
172:
173: public final void setStringValue(String s) {
174: if (s == null) {
175: throw new NullPointerException();
176: }
177: stringValue = s;
178: type = STRING;
179: }
180:
181: public final void setValue(ExprValue value2) {
182: // Copy bits over, including any logic based
183: // on type that causes branching make this
184: // method execute 2x slower.
185: type = value2.type;
186: intValue = value2.intValue;
187: doubleValue = value2.doubleValue;
188: stringValue = value2.stringValue;
189: }
190:
191: public final void nullStringValue() {
192: stringValue = null;
193: }
194:
195: final void toStringType() {
196: if (type == STRING) {
197: throw new TclRuntimeError(
198: "called toStringType() on STRING type");
199: }
200: if (stringValue == null) {
201: getStringValue();
202: }
203: type = STRING;
204: }
205:
206: // This method is used only for debugging, it prints a description
207: // of the internal state of a ExprValue object.
208:
209: public String toString() {
210: StringBuffer sb = new StringBuffer(64);
211: if (type == STRING) {
212: sb.append("STRING \"" + stringValue + "\"");
213: } else if (type == INT) {
214: sb.append("INT \"" + intValue + "\"");
215: if (stringValue != null) {
216: String intString = Integer.toString(intValue);
217: if (intString.compareTo(stringValue) != 0) {
218: sb.append(" parsed from \"");
219: sb.append(stringValue);
220: sb.append("\"");
221: }
222: }
223: } else if (type == DOUBLE) {
224: sb.append("DOUBLE \"" + doubleValue + "\"");
225: if (stringValue != null) {
226: String doubleString = Util.printDouble(doubleValue);
227: if (doubleString.compareTo(stringValue) != 0) {
228: sb.append(" parsed from \"");
229: sb.append(stringValue);
230: sb.append("\"");
231: }
232: }
233: }
234: return sb.toString();
235: }
236:
237: // Optimized int multiply operation
238:
239: final void optIntMult(final ExprValue value2) {
240: stringValue = null;
241: intValue *= value2.intValue;
242: }
243:
244: // Optimized double multiply operation
245:
246: final void optDoubleMult(final ExprValue value2) {
247: stringValue = null;
248: doubleValue *= value2.doubleValue;
249: }
250:
251: // Optimized int plus operation
252:
253: final void optIntPlus(final ExprValue value2) {
254: stringValue = null;
255: intValue += value2.intValue;
256: }
257:
258: // Optimized double plus operation
259:
260: final void optDoublePlus(final ExprValue value2) {
261: stringValue = null;
262: doubleValue += value2.doubleValue;
263: }
264:
265: // Optimized int minus operation
266:
267: final void optIntMinus(final ExprValue value2) {
268: stringValue = null;
269: intValue -= value2.intValue;
270: }
271:
272: // Optimized double minus operation
273:
274: final void optDoubleMinus(final ExprValue value2) {
275: stringValue = null;
276: doubleValue -= value2.doubleValue;
277: }
278:
279: // Optimized int less than operation
280:
281: final void optIntLess(final ExprValue value2) {
282: stringValue = null;
283: intValue = ((intValue < value2.intValue) ? 1 : 0);
284: }
285:
286: // Optimized double less than operation
287:
288: final void optDoubleLess(final ExprValue value2) {
289: stringValue = null;
290: intValue = ((doubleValue < value2.doubleValue) ? 1 : 0);
291: type = INT;
292: }
293:
294: // Optimized int greater than operation
295:
296: final void optIntGreater(final ExprValue value2) {
297: stringValue = null;
298: intValue = ((intValue > value2.intValue) ? 1 : 0);
299: }
300:
301: // Optimized double greater than operation
302:
303: final void optDoubleGreater(final ExprValue value2) {
304: stringValue = null;
305: intValue = ((doubleValue > value2.doubleValue) ? 1 : 0);
306: type = INT;
307: }
308:
309: // Optimized int less than or equal to operation
310:
311: final void optIntLessEq(final ExprValue value2) {
312: stringValue = null;
313: intValue = ((intValue <= value2.intValue) ? 1 : 0);
314: }
315:
316: // Optimized int less than or equal to operation
317:
318: final void optDoubleLessEq(final ExprValue value2) {
319: stringValue = null;
320: intValue = ((doubleValue <= value2.doubleValue) ? 1 : 0);
321: type = INT;
322: }
323:
324: // Optimized int greater than or equal to operation
325:
326: final void optIntGreaterEq(final ExprValue value2) {
327: stringValue = null;
328: intValue = ((intValue >= value2.intValue) ? 1 : 0);
329: }
330:
331: // Optimized double greater than or equal to operation
332:
333: final void optDoubleGreaterEq(final ExprValue value2) {
334: stringValue = null;
335: intValue = ((doubleValue >= value2.doubleValue) ? 1 : 0);
336: type = INT;
337: }
338:
339: // Optimized int equal to operation
340:
341: final void optIntEq(final ExprValue value2) {
342: stringValue = null;
343: intValue = ((intValue == value2.intValue) ? 1 : 0);
344: }
345:
346: // Optimized double equal to operation
347:
348: final void optDoubleEq(final ExprValue value2) {
349: stringValue = null;
350: intValue = ((doubleValue == value2.doubleValue) ? 1 : 0);
351: type = INT;
352: }
353:
354: // Optimized int not equal to operation
355:
356: final void optIntNotEq(final ExprValue value2) {
357: stringValue = null;
358: intValue = ((intValue != value2.intValue) ? 1 : 0);
359: }
360:
361: // Optimized double not equal to operation
362:
363: final void optDoubleNotEq(final ExprValue value2) {
364: stringValue = null;
365: intValue = ((doubleValue != value2.doubleValue) ? 1 : 0);
366: type = INT;
367: }
368:
369: // Optimized integer unary logical not operation '!'
370:
371: public final void optIntUnaryNot() {
372: if (validate) {
373: if (type != INT) {
374: throw new TclRuntimeError(
375: "called optIntUnaryNot() on non-INT type");
376: }
377: }
378:
379: stringValue = null;
380: intValue = (intValue == 0) ? 1 : 0;
381: }
382:
383: public final void optIntUnaryNotNstr() {
384: if (validate) {
385: if (type != INT) {
386: throw new TclRuntimeError(
387: "called optIntUnaryNotNstr() on non-INT type");
388: }
389: if (stringValue != null) {
390: throw new TclRuntimeError(
391: "called optIntUnaryNotNstr() with non-null string value");
392: }
393: }
394:
395: intValue = (intValue == 0) ? 1 : 0;
396: }
397:
398: }
|