001: /*
002: * Copyright 2006 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.lang;
017:
018: import com.google.gwt.core.client.JavaScriptObject;
019:
020: // CHECKSTYLE_NAMING_OFF: Uses legacy conventions of underscore prefixes.
021:
022: /**
023: * This is a magic class the compiler uses to perform any cast operations that
024: * require code.
025: */
026: final class Cast {
027:
028: // magic magic magic
029: protected static Object typeIdArray;
030:
031: protected static native boolean canCast(int srcId, int dstId) /*-{
032: // Force to boolean.
033: return !!(srcId && @com.google.gwt.lang.Cast::typeIdArray[srcId][dstId]);
034: }-*/;
035:
036: static native String charToString(char x) /*-{
037: return String.fromCharCode(x);
038: }-*/;
039:
040: static native Object dynamicCast(Object src, int dstId) /*-{
041: if (src != null)
042: @com.google.gwt.lang.Cast::canCast(II)(src.@java.lang.Object::typeId,dstId)
043: || @com.google.gwt.lang.Cast::throwClassCastException()();
044:
045: return src;
046: }-*/;
047:
048: static native boolean instanceOf(Object src, int dstId) /*-{
049: return (src != null) &&
050: @com.google.gwt.lang.Cast::canCast(II)(src.@java.lang.Object::typeId,dstId);
051: }-*/;
052:
053: /**
054: * See JLS 5.1.3.
055: */
056: static native byte narrow_byte(Object x) /*-{
057: return x << 24 >> 24;
058: }-*/;
059:
060: /**
061: * See JLS 5.1.3.
062: */
063: static native char narrow_char(Object x) /*-{
064: return x & 0xFFFF;
065: }-*/;
066:
067: /**
068: * See JLS 5.1.3.
069: */
070: static native int narrow_int(Object x) /*-{
071: return ~~x;
072: }-*/;
073:
074: /**
075: * See JLS 5.1.3.
076: */
077: static native short narrow_short(Object x) /*-{
078: return x << 16 >> 16;
079: }-*/;
080:
081: /**
082: * See JLS 5.1.3 for why we do a two-step cast. First we round to int, then
083: * narrow to byte.
084: */
085: static byte round_byte(Object x) {
086: return narrow_byte(round_int(x));
087: }
088:
089: /**
090: * See JLS 5.1.3 for why we do a two-step cast. First we round to int, then
091: * narrow to char.
092: */
093: static char round_char(Object x) {
094: return narrow_char(round_int(x));
095: }
096:
097: /**
098: * See JLS 5.1.3.
099: */
100: static native int round_int(Object x) /*-{
101: // TODO: reference java.lang.Integer::MAX_VALUE when we get clinits fixed
102: return ~~Math.max(Math.min(x, 2147483647), -2147483648);
103: }-*/;
104:
105: /**
106: * See JLS 5.1.3.
107: */
108: static native long round_long(Object x) /*-{
109: // TODO: reference java.lang.Long::MAX_VALUE when we get clinits fixed
110: x = Math.max(Math.min(x, 9223372036854775807), -9223372036854775808);
111: return (x >= 0) ? Math.floor(x) : Math.ceil(x);
112: }-*/;
113:
114: /**
115: * See JLS 5.1.3 for why we do a two-step cast. First we rount to int, then
116: * narrow to short.
117: */
118: static short round_short(Object x) {
119: return narrow_short(round_int(x));
120: }
121:
122: /**
123: * Unconditionally throw a {@link ClassCastException}. Called from {#link
124: * {@link #dynamicCast(Object, int)}.
125: */
126: static Object throwClassCastException() throws ClassCastException {
127: throw new ClassCastException();
128: }
129:
130: /**
131: * Check a statically false cast, which can succeed if the argument is null.
132: * Called by compiler-generated code based on static type information.
133: */
134: static Object throwClassCastExceptionUnlessNull(Object o)
135: throws ClassCastException {
136: if (o != null) {
137: throw new ClassCastException();
138: }
139: return o;
140: }
141:
142: static native JavaScriptObject wrapJSO(JavaScriptObject jso,
143: Object seed) /*-{
144: _ = seed.prototype;
145:
146: // WEIRD: The inequality below represents the fact that superclasses always
147: // have typeId < any subclass typeId. This code lets us wrap the same JSO
148: // "tighter" but never "looser". This would break if the compiler did not
149: // ensure that superclass ids are less than subclass ids.
150: //
151: // Note also that the inequality is false (and thus allows wrapping) if
152: // jso's typeId is undefined, because (undefined < positive int).
153:
154: if (jso && !(jso.@java.lang.Object::typeId >= _.@java.lang.Object::typeId)) {
155: for (var i in _) {
156: // don't clobber toString
157: if (i != 'toString' ) {
158: jso[i] = _[i];
159: }
160: }
161: }
162: return jso;
163: }-*/;
164:
165: }
166:
167: // CHECKSTYLE_NAMING_ON
|