| Index: compiler/lib/implementation/rtt.js
|
| diff --git a/compiler/lib/implementation/rtt.js b/compiler/lib/implementation/rtt.js
|
| index daea1603a37a7ad39eb8f5847f152b6ffefd17c6..c2d3cb1ecca23b766b9f54e44673a515f773f907 100644
|
| --- a/compiler/lib/implementation/rtt.js
|
| +++ b/compiler/lib/implementation/rtt.js
|
| @@ -10,16 +10,20 @@
|
| * @param {string} classkey
|
| * @param {string=} typekey
|
| * @param {Array.<RTT>=} typeargs
|
| + * @param {RTT} returnType
|
| + * @param {bool} functionType
|
| */
|
| -function RTT(classkey, typekey, typeargs) {
|
| +function RTT(classkey, typekey, typeargs, returnType, functionType) {
|
| this.classKey = classkey;
|
| this.typeKey = typekey ? typekey : classkey;
|
| this.typeArgs = typeargs;
|
| + this.returnType = returnType; // key for the return type
|
| this.implementedTypes = {};
|
| + this.functionType = functionType;
|
| // Add self
|
| this.implementedTypes[classkey] = this;
|
| // Add Object
|
| - if (classkey != $cls('Object')) {
|
| + if (!functionType && classkey != $cls('Object')) {
|
| this.implementedTypes[$cls('Object')] = RTT.objectType;
|
| }
|
| }
|
| @@ -39,6 +43,7 @@ RTT.prototype.toString = function() { return this.typeKey; }
|
| */
|
| RTT.prototype.implementedBy = function(value){
|
| return (value == null) ? RTT.nullInstanceOf(this) :
|
| + this.functionType ? this.implementedByTypeFunc(value) :
|
| this.implementedByType(RTT.getTypeInfo(value));
|
| };
|
|
|
| @@ -53,6 +58,11 @@ function $mapLookup(map, key) {
|
| return map.hasOwnProperty(key) ? map[key] : null;
|
| }
|
|
|
| +RTT.prototype.implementedByTypeSwitch = function(value){
|
| + return this.functionType ? this.implementedByTypeFunc(value) :
|
| + this.implementedByType(value);
|
| +};
|
| +
|
| /**
|
| * @param {!RTT} other
|
| * @return {boolean} Whether this type is implement by other
|
| @@ -67,7 +77,7 @@ RTT.prototype.implementedByType = function(otherType) {
|
| }
|
| if (targetTypeInfo.typeArgs && this.typeArgs) {
|
| for(var i = this.typeArgs.length - 1; i >= 0; i--) {
|
| - if (!this.typeArgs[i].implementedByType(targetTypeInfo.typeArgs[i])) {
|
| + if (!this.typeArgs[i].implementedByTypeSwitch(targetTypeInfo.typeArgs[i])) {
|
| return false;
|
| }
|
| }
|
| @@ -76,6 +86,69 @@ RTT.prototype.implementedByType = function(otherType) {
|
| };
|
|
|
| /**
|
| + * @param {!RTT} other
|
| + * @return {boolean} Whether this type is assignable by other
|
| + */
|
| +RTT.prototype.assignableByType = function(otherType) {
|
| + if (otherType === this || otherType === RTT.dynamicType || this === RTT.dynamicType) {
|
| + return true;
|
| + }
|
| + var targetTypeInfo = $mapLookup(otherType.implementedTypes, this.classKey);
|
| + if (targetTypeInfo == null) {
|
| + targetTypeInfo = $mapLookup(this.implementedTypes, otherType.classKey);
|
| + if (targetTypeInfo == null) {
|
| + return false;
|
| + }
|
| + }
|
| + if (targetTypeInfo.typeArgs && this.typeArgs) {
|
| + for(var i = this.typeArgs.length - 1; i >= 0; i--) {
|
| + if (!this.typeArgs[i].assignableByType(targetTypeInfo.typeArgs[i])) {
|
| + return false;
|
| + }
|
| + }
|
| + }
|
| + return true;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * @param {!RTT} other
|
| + * @return {boolean} Whether this type is implemented by other
|
| + */
|
| +RTT.prototype.implementedByTypeFunc = function(otherType) {
|
| + if (otherType.$lookupRTT) {
|
| + otherType = otherType.$lookupRTT();
|
| + } else if (!(otherType instanceof RTT)) {
|
| + return false;
|
| + }
|
| + if (otherType === this || otherType === RTT.dynamicType) {
|
| + return true;
|
| + }
|
| + var props = Object.getOwnPropertyNames(otherType.implementedTypes);
|
| + NEXT_PROPERTY: for (var i = 0 ; i < props.length; i++) {
|
| + var mapped = otherType.implementedTypes[props[i]];
|
| + if (mapped.returnType && this.returnType &&
|
| + !this.returnType.assignableByType(mapped.returnType)) {
|
| + continue;
|
| + }
|
| + if (mapped.typeArgs && this.typeArgs) {
|
| + if (this.typeArgs.length != mapped.typeArgs.length) {
|
| + continue;
|
| + }
|
| + for (var x = this.typeArgs.length - 1; x >= 0; x--) {
|
| + if (!this.typeArgs[x].assignableByType(mapped.typeArgs[x])) {
|
| + continue NEXT_PROPERTY;
|
| + }
|
| + }
|
| + } else if (mapped.typeArgs || this.typeArgs) {
|
| + return false;
|
| + }
|
| + return true;
|
| + }
|
| + return false;
|
| +};
|
| +
|
| +/**
|
| * @return {string} the class name associated with this type
|
| */
|
| RTT.prototype.getClassName = function() {
|
| @@ -134,15 +207,37 @@ RTT.create = function(name, implementsSupplier, typeArgs) {
|
| };
|
|
|
| /**
|
| + * @param {Array.<RTT>=} typeArgs
|
| + * @param {<RTT>=} returnType (if defined)
|
| + * @return {RTT} The RTT information object
|
| + */
|
| +RTT.createFunction = function(typeArgs, returnType) {
|
| + var name = $cls("Function");
|
| + var typekey = RTT.getTypeKey(name, typeArgs, returnType);
|
| + var rtt = $mapLookup(RTT.types, typekey);
|
| + if (rtt) {
|
| + return rtt;
|
| + }
|
| + var classkey = RTT.getTypeKey(name);
|
| + rtt = new RTT(classkey, typekey, typeArgs, returnType, true);
|
| + RTT.types[typekey] = rtt;
|
| + return rtt;
|
| +};
|
| +
|
| +/**
|
| * @param {string} classkey
|
| * @param {Array.<(RTT|string)>=} typeargs
|
| + * @param {string} returntype
|
| * @return {string}
|
| */
|
| -RTT.getTypeKey = function(classkey, typeargs) {
|
| +RTT.getTypeKey = function(classkey, typeargs, returntype) {
|
| var key = classkey;
|
| if (typeargs) {
|
| key += "<" + typeargs.join(",") + ">";
|
| }
|
| + if (returntype) {
|
| + key += "-><" + returntype + ">";
|
| + }
|
| return key;
|
| };
|
|
|
|
|