1
0
فهرست منبع

Merge branch 'master' into newcompiler

Nicolas Petton 13 سال پیش
والد
کامیت
82de082072
10فایلهای تغییر یافته به همراه243 افزوده شده و 37 حذف شده
  1. 11 0
      js/Kernel-Collections.deploy.js
  2. 16 0
      js/Kernel-Collections.js
  3. 18 1
      js/Kernel-Objects.deploy.js
  4. 24 2
      js/Kernel-Objects.js
  5. 37 0
      js/Kernel-Tests.deploy.js
  6. 49 2
      js/Kernel-Tests.js
  7. 41 30
      js/boot.js
  8. 4 0
      st/Kernel-Collections.st
  9. 11 1
      st/Kernel-Objects.st
  10. 32 1
      st/Kernel-Tests.st

+ 11 - 0
js/Kernel-Collections.deploy.js

@@ -1760,6 +1760,17 @@ return self;
 }),
 smalltalk.String);
 
+smalltalk.addMethod(
+"__eq_eq",
+smalltalk.method({
+selector: "==",
+fn: function (aString){
+var self=this;
+return smalltalk.send(self, "__eq", [aString]);
+return self;}
+}),
+smalltalk.String);
+
 smalltalk.addMethod(
 "__gt",
 smalltalk.method({

+ 16 - 0
js/Kernel-Collections.js

@@ -2486,6 +2486,22 @@ referencedClasses: []
 }),
 smalltalk.String);
 
+smalltalk.addMethod(
+"__eq_eq",
+smalltalk.method({
+selector: "==",
+category: 'comparing',
+fn: function (aString){
+var self=this;
+return smalltalk.send(self, "__eq", [aString]);
+return self;},
+args: ["aString"],
+source: "== aString\x0a\x09^self = aString",
+messageSends: ["="],
+referencedClasses: []
+}),
+smalltalk.String);
+
 smalltalk.addMethod(
 "__gt",
 smalltalk.method({

+ 18 - 1
js/Kernel-Objects.deploy.js

@@ -226,7 +226,13 @@ smalltalk.method({
 selector: "identityHash",
 fn: function (){
 var self=this;
-return self.identityHash || (self.identityHash = smalltalk.nextId());;
+
+	var hash=self.identityHash;
+	if (hash) return hash;
+	hash=smalltalk.nextId();
+	Object.defineProperty(self, 'identityHash', {value:hash});
+	return hash;
+	;
 return self;}
 }),
 smalltalk.Object);
@@ -667,6 +673,17 @@ return self;
 }),
 smalltalk.Boolean);
 
+smalltalk.addMethod(
+"__eq_eq",
+smalltalk.method({
+selector: "==",
+fn: function (aBoolean){
+var self=this;
+return smalltalk.send(self, "__eq", [aBoolean]);
+return self;}
+}),
+smalltalk.Boolean);
+
 smalltalk.addMethod(
 "_and_",
 smalltalk.method({

+ 24 - 2
js/Kernel-Objects.js

@@ -323,10 +323,16 @@ selector: "identityHash",
 category: 'accessing',
 fn: function (){
 var self=this;
-return self.identityHash || (self.identityHash = smalltalk.nextId());;
+
+	var hash=self.identityHash;
+	if (hash) return hash;
+	hash=smalltalk.nextId();
+	Object.defineProperty(self, 'identityHash', {value:hash});
+	return hash;
+	;
 return self;},
 args: [],
-source: "identityHash\x0a\x09<return self.identityHash || (self.identityHash = smalltalk.nextId());>",
+source: "identityHash\x0a\x09<\x0a\x09var hash=self.identityHash;\x0a\x09if (hash) return hash;\x0a\x09hash=smalltalk.nextId();\x0a\x09Object.defineProperty(self, 'identityHash', {value:hash});\x0a\x09return hash;\x0a\x09>",
 messageSends: [],
 referencedClasses: []
 }),
@@ -954,6 +960,22 @@ referencedClasses: []
 }),
 smalltalk.Boolean);
 
+smalltalk.addMethod(
+"__eq_eq",
+smalltalk.method({
+selector: "==",
+category: 'comparing',
+fn: function (aBoolean){
+var self=this;
+return smalltalk.send(self, "__eq", [aBoolean]);
+return self;},
+args: ["aBoolean"],
+source: "== aBoolean\x0a\x09^self = aBoolean",
+messageSends: ["="],
+referencedClasses: []
+}),
+smalltalk.Boolean);
+
 smalltalk.addMethod(
 "_and_",
 smalltalk.method({

+ 37 - 0
js/Kernel-Tests.deploy.js

@@ -172,6 +172,26 @@ return self;}
 }),
 smalltalk.BooleanTest);
 
+smalltalk.addMethod(
+"_testIdentity",
+smalltalk.method({
+selector: "testIdentity",
+fn: function (){
+var self=this;
+smalltalk.send(self, "_deny_", [smalltalk.send((0), "__eq_eq", [false])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(false, "__eq_eq", [(0)])]);
+smalltalk.send(self, "_deny_", [smalltalk.send("", "__eq_eq", [false])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(false, "__eq_eq", [""])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(true, "__eq_eq", [true])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(false, "__eq_eq", [true])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(true, "__eq_eq", [false])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(false, "__eq_eq", [false])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send(true, "_yourself", []), "__eq_eq", [true])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send(true, "_yourself", []), "__eq_eq", [smalltalk.send(true, "_yourself", [])])]);
+return self;}
+}),
+smalltalk.BooleanTest);
+
 smalltalk.addMethod(
 "_testIfTrueIfFalse",
 smalltalk.method({
@@ -852,6 +872,8 @@ var o=nil;
 (o=smalltalk.send((smalltalk.Object || Object), "_new", []));
 smalltalk.send(self, "_deny_", [smalltalk.send(o, "__eq_eq", [smalltalk.send((smalltalk.Object || Object), "_new", [])])]);
 smalltalk.send(self, "_assert_", [smalltalk.send(o, "__eq_eq", [o])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send(o, "_yourself", []), "__eq_eq", [o])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(o, "__eq_eq", [smalltalk.send(o, "_yourself", [])])]);
 return self;}
 }),
 smalltalk.ObjectTest);
@@ -1295,6 +1317,21 @@ return self;}
 }),
 smalltalk.StringTest);
 
+smalltalk.addMethod(
+"_testIdentity",
+smalltalk.method({
+selector: "testIdentity",
+fn: function (){
+var self=this;
+smalltalk.send(self, "_assert_", [smalltalk.send("hello", "__eq_eq", ["hello"])]);
+smalltalk.send(self, "_deny_", [smalltalk.send("hello", "__eq_eq", ["world"])]);
+smalltalk.send(self, "_assert_", [smalltalk.send("hello", "__eq_eq", [smalltalk.send("hello", "_yourself", [])])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send("hello", "_yourself", []), "__eq_eq", ["hello"])]);
+smalltalk.send(self, "_deny_", [smalltalk.send("", "__eq_eq", [(0)])]);
+return self;}
+}),
+smalltalk.StringTest);
+
 smalltalk.addMethod(
 "_testIncludesSubString",
 smalltalk.method({

+ 49 - 2
js/Kernel-Tests.js

@@ -232,6 +232,31 @@ referencedClasses: []
 }),
 smalltalk.BooleanTest);
 
+smalltalk.addMethod(
+"_testIdentity",
+smalltalk.method({
+selector: "testIdentity",
+category: 'tests',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_deny_", [smalltalk.send((0), "__eq_eq", [false])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(false, "__eq_eq", [(0)])]);
+smalltalk.send(self, "_deny_", [smalltalk.send("", "__eq_eq", [false])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(false, "__eq_eq", [""])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(true, "__eq_eq", [true])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(false, "__eq_eq", [true])]);
+smalltalk.send(self, "_deny_", [smalltalk.send(true, "__eq_eq", [false])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(false, "__eq_eq", [false])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send(true, "_yourself", []), "__eq_eq", [true])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send(true, "_yourself", []), "__eq_eq", [smalltalk.send(true, "_yourself", [])])]);
+return self;},
+args: [],
+source: "testIdentity\x0a\x09\x22We're on top of JS...just be sure to check the basics!\x22\x0a\x0a\x09self deny: 0 == false. \x0a\x09self deny: false == 0.\x0a\x09self deny: '' == false.\x0a\x09self deny: false == ''.\x0a\x0a\x09self assert: true == true.\x0a\x09self deny: false == true.\x0a\x09self deny: true == false.\x0a\x09self assert: false == false.\x0a\x0a\x09\x22JS may do some type coercing after sending a message\x22\x0a\x09self assert: true yourself == true.\x0a\x09self assert: true yourself == true yourself",
+messageSends: ["deny:", "==", "assert:", "yourself"],
+referencedClasses: []
+}),
+smalltalk.BooleanTest);
+
 smalltalk.addMethod(
 "_testIfTrueIfFalse",
 smalltalk.method({
@@ -1138,10 +1163,12 @@ var o=nil;
 (o=smalltalk.send((smalltalk.Object || Object), "_new", []));
 smalltalk.send(self, "_deny_", [smalltalk.send(o, "__eq_eq", [smalltalk.send((smalltalk.Object || Object), "_new", [])])]);
 smalltalk.send(self, "_assert_", [smalltalk.send(o, "__eq_eq", [o])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send(o, "_yourself", []), "__eq_eq", [o])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(o, "__eq_eq", [smalltalk.send(o, "_yourself", [])])]);
 return self;},
 args: [],
-source: "testIdentity\x0a\x09| o |\x0a\x09o := Object new.\x0a\x09self deny: o == Object new.\x0a\x09self assert: o == o",
-messageSends: ["new", "deny:", "==", "assert:"],
+source: "testIdentity\x0a\x09| o |\x0a\x09o := Object new.\x0a\x09self deny: o == Object new.\x0a\x09self assert: o == o.\x0a\x09self assert: o yourself == o.\x0a\x09self assert: o == o yourself",
+messageSends: ["new", "deny:", "==", "assert:", "yourself"],
 referencedClasses: ["Object"]
 }),
 smalltalk.ObjectTest);
@@ -1750,6 +1777,26 @@ referencedClasses: []
 }),
 smalltalk.StringTest);
 
+smalltalk.addMethod(
+"_testIdentity",
+smalltalk.method({
+selector: "testIdentity",
+category: 'tests',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_assert_", [smalltalk.send("hello", "__eq_eq", ["hello"])]);
+smalltalk.send(self, "_deny_", [smalltalk.send("hello", "__eq_eq", ["world"])]);
+smalltalk.send(self, "_assert_", [smalltalk.send("hello", "__eq_eq", [smalltalk.send("hello", "_yourself", [])])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send("hello", "_yourself", []), "__eq_eq", ["hello"])]);
+smalltalk.send(self, "_deny_", [smalltalk.send("", "__eq_eq", [(0)])]);
+return self;},
+args: [],
+source: "testIdentity\x0a\x09self assert: 'hello' == 'hello'.\x0a\x09self deny: 'hello' == 'world'.\x0a\x0a\x09self assert: 'hello' == 'hello' yourself.\x0a\x09self assert: 'hello' yourself == 'hello'.\x0a\x0a\x09\x22test JS falsy value\x22\x0a\x09self deny: '' == 0",
+messageSends: ["assert:", "==", "deny:", "yourself"],
+referencedClasses: []
+}),
+smalltalk.StringTest);
+
 smalltalk.addMethod(
 "_testIncludesSubString",
 smalltalk.method({

+ 41 - 30
js/boot.js

@@ -45,22 +45,21 @@ if (typeof console === "undefined") {
 	};
 }
 
-
 /* Smalltalk constructors definition */
 
 function SmalltalkObject(){}
-function SmalltalkBehavior(){};
+function SmalltalkBehavior(){}
 function SmalltalkClass(){}
-function SmalltalkPackage(){};
+function SmalltalkPackage(){}
 function SmalltalkMetaclass(){
 	this.meta = true;
-};
-function SmalltalkMethod(){};
-function SmalltalkNil(){};
+}
+function SmalltalkMethod(){}
+function SmalltalkNil(){}
 
 function SmalltalkSymbol(string){
 	this.value = string;
-};
+}
 
 function Smalltalk(){
 
@@ -107,8 +106,8 @@ function Smalltalk(){
 	/* Smalltalk package creation. To add a Package, use smalltalk.addPackage() */
 
 	function pkg(spec) {
-		var that      = new SmalltalkPackage();
-		that.pkgName  = spec.pkgName;
+		var that = new SmalltalkPackage();
+		that.pkgName = spec.pkgName;
 		that.properties = spec.properties || {};
 		return that;
 	};
@@ -120,28 +119,36 @@ function Smalltalk(){
 
 	function klass(spec) {
 		var spec = spec || {};
-		var that;
-		if(spec.meta) {
-			that = new SmalltalkMetaclass();
-		} else {
-			that = new (klass({meta: true})).fn;
-			that.klass.instanceClass = that;
-			that.className = spec.className;
-			that.klass.className = that.className + ' class';
+		var meta = metaclass();
+		var that = setupClass(meta.instanceClass, spec);
+		that.className = spec.className;
+		meta.className = spec.className + ' class';
+		if(spec.superclass) {
+			that.superclass = spec.superclass;
+			meta.superclass = spec.superclass.klass;
 		}
-
+		return that;
+	}
+	
+	function metaclass() {
+		var meta = setupClass(new SmalltalkMetaclass(), {});
+		meta.instanceClass = new meta.fn;
+		return meta;
+	}
+	
+	function setupClass(that, spec) {
 		that.fn = spec.fn || function(){};
-		that.superclass = spec.superclass;
 		that.iVarNames = spec.iVarNames || [];
-        that.toString = function() {return 'Smalltalk ' + that.className};
-		if(that.superclass) {
-			that.klass.superclass = that.superclass.klass;
-		}
+		Object.defineProperty(that, "toString", {
+			value: function() { return 'Smalltalk ' + this.className; }, 
+            configurable: true // no writable - in par with ES6 methods
+		});
 		that.pkg = spec.pkg;
-		that.fn.prototype.methods = {};
-		that.fn.prototype.inheritedMethods = {};
-		that.fn.prototype.klass = that;
-
+		Object.defineProperties(that.fn.prototype, {
+			methods: { value: {}, enumerable: false, configurable: true, writable: true },
+			inheritedMethods: { value: {}, enumerable: false, configurable: true, writable: true },
+			klass: { value: that, enumerable: false, configurable: true, writable: true }
+		});
 		return that;
 	};
 
@@ -158,7 +165,7 @@ function Smalltalk(){
 		that.messageSends      = spec.messageSends || [];
 		that.referencedClasses = spec.referencedClasses || [];
 		that.fn                = spec.fn;
-		return that
+		return that;
 	};
 
 	/* Initialize a class in its class hierarchy. Handle both class and
@@ -183,7 +190,9 @@ function Smalltalk(){
 				var k = keys[i]
 				if(!proto.methods[k]) {
 					proto.inheritedMethods[k] = methods[k];
-					proto[methods[k].jsSelector] = methods[k].fn;
+					Object.defineProperty(proto, methods[k].jsSelector, {
+						value: methods[k].fn, configurable: true // no writable - in par with ES6 methods
+					});
 				}
 			}
 		}
@@ -316,7 +325,9 @@ function Smalltalk(){
 	/* Add a method to a class */
 
 	st.addMethod = function(jsSelector, method, klass) {
-		klass.fn.prototype[jsSelector] = method.fn;
+		Object.defineProperty(klass.fn.prototype, jsSelector, {
+			value: method.fn, configurable: true // not writable - in par with ES6 methods
+		});
 		klass.fn.prototype.methods[method.selector] = method;
 		method.methodClass = klass;
 		method.jsSelector = jsSelector;

+ 4 - 0
st/Kernel-Collections.st

@@ -951,6 +951,10 @@ unescaped
 	<return String(self) === String(aString)>
 !
 
+== aString
+	^self = aString
+!
+
 > aString
 	<return String(self) >> aString._asString()>
 !

+ 11 - 1
st/Kernel-Objects.st

@@ -58,7 +58,13 @@ class
 !
 
 identityHash
-	<return self.identityHash || (self.identityHash = smalltalk.nextId());>
+	<
+	var hash=self.identityHash;
+	if (hash) return hash;
+	hash=smalltalk.nextId();
+	Object.defineProperty(self, 'identityHash', {value:hash});
+	return hash;
+	>
 !
 
 instVarAt: aSymbol
@@ -336,6 +342,10 @@ Boolean instances are weither `true` or `false`.!
 = aBoolean
 	aBoolean class = self class ifFalse: [^false].
 	<return Boolean(self == true) == aBoolean>
+!
+
+== aBoolean
+	^self = aBoolean
 ! !
 
 !Boolean methodsFor: 'controlling'!

+ 32 - 1
st/Kernel-Tests.st

@@ -109,6 +109,24 @@ testEquality
 	self assert: true yourself = true yourself
 !
 
+testIdentity
+	"We're on top of JS...just be sure to check the basics!!"
+
+	self deny: 0 == false. 
+	self deny: false == 0.
+	self deny: '' == false.
+	self deny: false == ''.
+
+	self assert: true == true.
+	self deny: false == true.
+	self deny: true == false.
+	self assert: false == false.
+
+	"JS may do some type coercing after sending a message"
+	self assert: true yourself == true.
+	self assert: true yourself == true yourself
+!
+
 testIfTrueIfFalse
  
 	self assert: (true ifTrue: ['alternative block']) = 'alternative block'.
@@ -570,7 +588,9 @@ testIdentity
 	| o |
 	o := Object new.
 	self deny: o == Object new.
-	self assert: o == o
+	self assert: o == o.
+	self assert: o yourself == o.
+	self assert: o == o yourself
 !
 
 testIfNil
@@ -839,6 +859,17 @@ testEquality
 	self deny: '' = 0
 !
 
+testIdentity
+	self assert: 'hello' == 'hello'.
+	self deny: 'hello' == 'world'.
+
+	self assert: 'hello' == 'hello' yourself.
+	self assert: 'hello' yourself == 'hello'.
+
+	"test JS falsy value"
+	self deny: '' == 0
+!
+
 testIncludesSubString
 	self assert: ('amber' includesSubString: 'ber').
 	self deny: ('amber' includesSubString: 'zork').