|
@@ -20,441 +20,444 @@ define(function () {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- TraitsBrik.deps = ["event", "behaviors", "methods", "composition", "root"];
|
|
|
- function TraitsBrik (brikz, st) {
|
|
|
- var specialConstructors = brikz.commonSpecialConstructors;
|
|
|
- var SmalltalkObject = brikz.root.Object;
|
|
|
- var setupMethods = brikz.methods.setupMethods;
|
|
|
- var traitMethodChanged = brikz.composition.traitMethodChanged;
|
|
|
- var buildTraitOrClass = brikz.behaviors.buildTraitOrClass;
|
|
|
- var emit = brikz.commonEmit;
|
|
|
- var declareEvent = brikz.event.declareEvent;
|
|
|
-
|
|
|
- function SmalltalkTrait () {
|
|
|
- }
|
|
|
+ function LanguageFactory (specialConstructors, emit) {
|
|
|
+ TraitsBrik.deps = ["event", "behaviors", "methods", "composition", "root"];
|
|
|
|
|
|
- specialConstructors.Trait = inherits(SmalltalkTrait, SmalltalkObject);
|
|
|
+ function TraitsBrik (brikz, st) {
|
|
|
+ var SmalltalkObject = brikz.root.Object;
|
|
|
+ var setupMethods = brikz.methods.setupMethods;
|
|
|
+ var traitMethodChanged = brikz.composition.traitMethodChanged;
|
|
|
+ var buildTraitOrClass = brikz.behaviors.buildTraitOrClass;
|
|
|
+ var declareEvent = brikz.event.declareEvent;
|
|
|
|
|
|
- SmalltalkTrait.prototype.trait = true;
|
|
|
+ function SmalltalkTrait () {
|
|
|
+ }
|
|
|
|
|
|
- defineMethod(SmalltalkTrait, "toString", function () {
|
|
|
- return 'Smalltalk Trait ' + this.name;
|
|
|
- });
|
|
|
- declareEvent("traitAdded");
|
|
|
- defineMethod(SmalltalkTrait, "added", function () {
|
|
|
- emit.traitAdded(this);
|
|
|
- });
|
|
|
- declareEvent("traitRemoved");
|
|
|
- defineMethod(SmalltalkTrait, "removed", function () {
|
|
|
- emit.traitRemoved(this);
|
|
|
- });
|
|
|
- declareEvent("traitMethodAdded");
|
|
|
- defineMethod(SmalltalkTrait, "methodAdded", function (method) {
|
|
|
- var self = this;
|
|
|
- this.traitUsers.forEach(function (each) {
|
|
|
- traitMethodChanged(method.selector, method, self, each);
|
|
|
+ specialConstructors.Trait = inherits(SmalltalkTrait, SmalltalkObject);
|
|
|
+
|
|
|
+ SmalltalkTrait.prototype.trait = true;
|
|
|
+
|
|
|
+ defineMethod(SmalltalkTrait, "toString", function () {
|
|
|
+ return 'Smalltalk Trait ' + this.name;
|
|
|
});
|
|
|
- emit.traitMethodAdded(method, this);
|
|
|
- });
|
|
|
- declareEvent("traitMethodRemoved");
|
|
|
- defineMethod(SmalltalkTrait, "methodRemoved", function (method) {
|
|
|
- var self = this;
|
|
|
- this.traitUsers.forEach(function (each) {
|
|
|
- traitMethodChanged(method.selector, null, self, each);
|
|
|
+ declareEvent("traitAdded");
|
|
|
+ defineMethod(SmalltalkTrait, "added", function () {
|
|
|
+ emit.traitAdded(this);
|
|
|
+ });
|
|
|
+ declareEvent("traitRemoved");
|
|
|
+ defineMethod(SmalltalkTrait, "removed", function () {
|
|
|
+ emit.traitRemoved(this);
|
|
|
+ });
|
|
|
+ declareEvent("traitMethodAdded");
|
|
|
+ defineMethod(SmalltalkTrait, "methodAdded", function (method) {
|
|
|
+ var self = this;
|
|
|
+ this.traitUsers.forEach(function (each) {
|
|
|
+ traitMethodChanged(method.selector, method, self, each);
|
|
|
+ });
|
|
|
+ emit.traitMethodAdded(method, this);
|
|
|
+ });
|
|
|
+ declareEvent("traitMethodRemoved");
|
|
|
+ defineMethod(SmalltalkTrait, "methodRemoved", function (method) {
|
|
|
+ var self = this;
|
|
|
+ this.traitUsers.forEach(function (each) {
|
|
|
+ traitMethodChanged(method.selector, null, self, each);
|
|
|
+ });
|
|
|
+ emit.traitMethodRemoved(method, this);
|
|
|
});
|
|
|
- emit.traitMethodRemoved(method, this);
|
|
|
- });
|
|
|
|
|
|
- function traitBuilder (traitName) {
|
|
|
- return {
|
|
|
- name: traitName,
|
|
|
- make: function () {
|
|
|
- var that = new SmalltalkTrait();
|
|
|
- that.name = traitName;
|
|
|
- that.traitUsers = [];
|
|
|
- setupMethods(that);
|
|
|
- return that;
|
|
|
- },
|
|
|
- updateExisting: function (trait) {
|
|
|
- }
|
|
|
+ function traitBuilder (traitName) {
|
|
|
+ return {
|
|
|
+ name: traitName,
|
|
|
+ make: function () {
|
|
|
+ var that = new SmalltalkTrait();
|
|
|
+ that.name = traitName;
|
|
|
+ that.traitUsers = [];
|
|
|
+ setupMethods(that);
|
|
|
+ return that;
|
|
|
+ },
|
|
|
+ updateExisting: function (trait) {
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ st.addTrait = function (className, category) {
|
|
|
+ return buildTraitOrClass(category, traitBuilder(className));
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- st.addTrait = function (className, category) {
|
|
|
- return buildTraitOrClass(category, traitBuilder(className));
|
|
|
- };
|
|
|
- }
|
|
|
+ MethodCompositionBrik.deps = ["methods", "arraySet"];
|
|
|
|
|
|
- MethodCompositionBrik.deps = ["methods", "arraySet"];
|
|
|
- function MethodCompositionBrik (brikz, st) {
|
|
|
- var updateMethod = brikz.methods.updateMethod;
|
|
|
- var addElement = brikz.arraySet.addElement;
|
|
|
- var removeElement = brikz.arraySet.removeElement;
|
|
|
-
|
|
|
- function aliased (selector, method) {
|
|
|
- var result = st.method(method, method.instantiateFn);
|
|
|
- if (method.selector !== selector) {
|
|
|
- result.selector = selector;
|
|
|
- result.source = '"Aliased as ' + selector + '"\n' + method.source;
|
|
|
+ function MethodCompositionBrik (brikz, st) {
|
|
|
+ var updateMethod = brikz.methods.updateMethod;
|
|
|
+ var addElement = brikz.arraySet.addElement;
|
|
|
+ var removeElement = brikz.arraySet.removeElement;
|
|
|
+
|
|
|
+ function aliased (selector, method) {
|
|
|
+ var result = st.method(method, method.instantiateFn);
|
|
|
+ if (method.selector !== selector) {
|
|
|
+ result.selector = selector;
|
|
|
+ result.source = '"Aliased as ' + selector + '"\n' + method.source;
|
|
|
+ }
|
|
|
+ result.owner = method.owner;
|
|
|
+ return result;
|
|
|
}
|
|
|
- result.owner = method.owner;
|
|
|
- return result;
|
|
|
- }
|
|
|
|
|
|
- function deleteKeysFrom (keys, obj) {
|
|
|
- keys.forEach(function (each) {
|
|
|
- delete obj[each];
|
|
|
- });
|
|
|
- }
|
|
|
+ function deleteKeysFrom (keys, obj) {
|
|
|
+ keys.forEach(function (each) {
|
|
|
+ delete obj[each];
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- function fillTraitTransformation (traitTransformation, obj) {
|
|
|
-
|
|
|
- var traitMethods = traitTransformation.trait.methods;
|
|
|
- Object.keys(traitMethods).forEach(function (selector) {
|
|
|
- obj[selector] = aliased(selector, traitMethods[selector]);
|
|
|
- });
|
|
|
- var traitAliases = traitTransformation.aliases;
|
|
|
- if (traitAliases) {
|
|
|
- Object.keys(traitAliases).forEach(function (aliasSelector) {
|
|
|
- var aliasedMethod = traitMethods[traitAliases[aliasSelector]];
|
|
|
- if (aliasedMethod) obj[aliasSelector] = aliased(aliasSelector, aliasedMethod);
|
|
|
-
|
|
|
+ function fillTraitTransformation (traitTransformation, obj) {
|
|
|
+
|
|
|
+ var traitMethods = traitTransformation.trait.methods;
|
|
|
+ Object.keys(traitMethods).forEach(function (selector) {
|
|
|
+ obj[selector] = aliased(selector, traitMethods[selector]);
|
|
|
});
|
|
|
+ var traitAliases = traitTransformation.aliases;
|
|
|
+ if (traitAliases) {
|
|
|
+ Object.keys(traitAliases).forEach(function (aliasSelector) {
|
|
|
+ var aliasedMethod = traitMethods[traitAliases[aliasSelector]];
|
|
|
+ if (aliasedMethod) obj[aliasSelector] = aliased(aliasSelector, aliasedMethod);
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+ var traitExclusions = traitTransformation.exclusions;
|
|
|
+ if (traitExclusions) {
|
|
|
+ deleteKeysFrom(traitExclusions, obj);
|
|
|
+ }
|
|
|
+ return obj;
|
|
|
}
|
|
|
- var traitExclusions = traitTransformation.exclusions;
|
|
|
- if (traitExclusions) {
|
|
|
- deleteKeysFrom(traitExclusions, obj);
|
|
|
+
|
|
|
+ function buildCompositionChain (traitComposition) {
|
|
|
+ return traitComposition.reduce(function (soFar, each) {
|
|
|
+ return fillTraitTransformation(each, Object.create(soFar));
|
|
|
+ }, null);
|
|
|
}
|
|
|
- return obj;
|
|
|
- }
|
|
|
|
|
|
- function buildCompositionChain (traitComposition) {
|
|
|
- return traitComposition.reduce(function (soFar, each) {
|
|
|
- return fillTraitTransformation(each, Object.create(soFar));
|
|
|
- }, null);
|
|
|
- }
|
|
|
+ st.setTraitComposition = function (traitComposition, traitOrBehavior) {
|
|
|
+ var oldLocalMethods = traitOrBehavior.localMethods,
|
|
|
+ newLocalMethods = Object.create(buildCompositionChain(traitComposition));
|
|
|
+ Object.keys(oldLocalMethods).forEach(function (selector) {
|
|
|
+ newLocalMethods[selector] = oldLocalMethods[selector];
|
|
|
+ });
|
|
|
+ var selector;
|
|
|
+ traitOrBehavior.localMethods = newLocalMethods;
|
|
|
+ for (selector in newLocalMethods) {
|
|
|
+ updateMethod(selector, traitOrBehavior);
|
|
|
+ }
|
|
|
+ for (selector in oldLocalMethods) {
|
|
|
+ updateMethod(selector, traitOrBehavior);
|
|
|
+ }
|
|
|
+ (traitOrBehavior.traitComposition || []).forEach(function (each) {
|
|
|
+ removeElement(each.trait.traitUsers, traitOrBehavior);
|
|
|
+ });
|
|
|
+ traitOrBehavior.traitComposition = traitComposition && traitComposition.length ? traitComposition : null;
|
|
|
+ (traitOrBehavior.traitComposition || []).forEach(function (each) {
|
|
|
+ addElement(each.trait.traitUsers, traitOrBehavior);
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
- st.setTraitComposition = function (traitComposition, traitOrBehavior) {
|
|
|
- var oldLocalMethods = traitOrBehavior.localMethods,
|
|
|
- newLocalMethods = Object.create(buildCompositionChain(traitComposition));
|
|
|
- Object.keys(oldLocalMethods).forEach(function (selector) {
|
|
|
- newLocalMethods[selector] = oldLocalMethods[selector];
|
|
|
- });
|
|
|
- var selector;
|
|
|
- traitOrBehavior.localMethods = newLocalMethods;
|
|
|
- for (selector in newLocalMethods) {
|
|
|
- updateMethod(selector, traitOrBehavior);
|
|
|
+ function aliasesOfSelector (selector, traitAliases) {
|
|
|
+ if (!traitAliases) return [selector];
|
|
|
+ var result = Object.keys(traitAliases).filter(function (aliasSelector) {
|
|
|
+ return traitAliases[aliasSelector] === selector
|
|
|
+ });
|
|
|
+ if (!traitAliases[selector]) result.push(selector);
|
|
|
+ return result;
|
|
|
}
|
|
|
- for (selector in oldLocalMethods) {
|
|
|
- updateMethod(selector, traitOrBehavior);
|
|
|
+
|
|
|
+ function applyTraitMethodAddition (selector, method, traitTransformation, obj) {
|
|
|
+ var changes = aliasesOfSelector(selector, traitTransformation.aliases);
|
|
|
+ changes.forEach(function (aliasSelector) {
|
|
|
+ obj[aliasSelector] = aliased(aliasSelector, method);
|
|
|
+ });
|
|
|
+ var traitExclusions = traitTransformation.exclusions;
|
|
|
+ if (traitExclusions) {
|
|
|
+ deleteKeysFrom(traitExclusions, obj);
|
|
|
+ }
|
|
|
+ return changes;
|
|
|
}
|
|
|
- (traitOrBehavior.traitComposition || []).forEach(function (each) {
|
|
|
- removeElement(each.trait.traitUsers, traitOrBehavior);
|
|
|
- });
|
|
|
- traitOrBehavior.traitComposition = traitComposition && traitComposition.length ? traitComposition : null;
|
|
|
- (traitOrBehavior.traitComposition || []).forEach(function (each) {
|
|
|
- addElement(each.trait.traitUsers, traitOrBehavior);
|
|
|
- });
|
|
|
- };
|
|
|
|
|
|
- function aliasesOfSelector (selector, traitAliases) {
|
|
|
- if (!traitAliases) return [selector];
|
|
|
- var result = Object.keys(traitAliases).filter(function (aliasSelector) {
|
|
|
- return traitAliases[aliasSelector] === selector
|
|
|
- });
|
|
|
- if (!traitAliases[selector]) result.push(selector);
|
|
|
- return result;
|
|
|
- }
|
|
|
+ function applyTraitMethodDeletion (selector, traitTransformation, obj) {
|
|
|
+ var changes = aliasesOfSelector(selector, traitTransformation.aliases);
|
|
|
+ deleteKeysFrom(changes, obj);
|
|
|
+ return changes;
|
|
|
+ }
|
|
|
|
|
|
- function applyTraitMethodAddition (selector, method, traitTransformation, obj) {
|
|
|
- var changes = aliasesOfSelector(selector, traitTransformation.aliases);
|
|
|
- changes.forEach(function (aliasSelector) {
|
|
|
- obj[aliasSelector] = aliased(aliasSelector, method);
|
|
|
- });
|
|
|
- var traitExclusions = traitTransformation.exclusions;
|
|
|
- if (traitExclusions) {
|
|
|
- deleteKeysFrom(traitExclusions, obj);
|
|
|
+ function traitMethodChanged (selector, method, trait, traitOrBehavior) {
|
|
|
+ var traitComposition = traitOrBehavior.traitComposition,
|
|
|
+ chain = traitOrBehavior.localMethods,
|
|
|
+ changes = [];
|
|
|
+ for (var i = traitComposition.length - 1; i >= 0; --i) {
|
|
|
+ chain = Object.getPrototypeOf(chain);
|
|
|
+ var traitTransformation = traitComposition[i];
|
|
|
+ if (traitTransformation.trait !== trait) continue;
|
|
|
+ changes.push.apply(changes, method ?
|
|
|
+ applyTraitMethodAddition(selector, method, traitTransformation, chain) :
|
|
|
+ applyTraitMethodDeletion(selector, traitTransformation, chain));
|
|
|
+ }
|
|
|
+
|
|
|
+ changes.forEach(function (each) {
|
|
|
+ updateMethod(each, traitOrBehavior);
|
|
|
+ });
|
|
|
}
|
|
|
- return changes;
|
|
|
- }
|
|
|
|
|
|
- function applyTraitMethodDeletion (selector, traitTransformation, obj) {
|
|
|
- var changes = aliasesOfSelector(selector, traitTransformation.aliases);
|
|
|
- deleteKeysFrom(changes, obj);
|
|
|
- return changes;
|
|
|
+ this.traitMethodChanged = traitMethodChanged;
|
|
|
}
|
|
|
|
|
|
- function traitMethodChanged (selector, method, trait, traitOrBehavior) {
|
|
|
- var traitComposition = traitOrBehavior.traitComposition,
|
|
|
- chain = traitOrBehavior.localMethods,
|
|
|
- changes = [];
|
|
|
- for (var i = traitComposition.length - 1; i >= 0; --i) {
|
|
|
- chain = Object.getPrototypeOf(chain);
|
|
|
- var traitTransformation = traitComposition[i];
|
|
|
- if (traitTransformation.trait !== trait) continue;
|
|
|
- changes.push.apply(changes, method ?
|
|
|
- applyTraitMethodAddition(selector, method, traitTransformation, chain) :
|
|
|
- applyTraitMethodDeletion(selector, traitTransformation, chain));
|
|
|
+ ClassesBrik.deps = ["root", "event", "behaviors", "methods", "arraySet", "nil"];
|
|
|
+
|
|
|
+ function ClassesBrik (brikz, st) {
|
|
|
+ var SmalltalkRoot = brikz.root.Root;
|
|
|
+ var SmalltalkObject = brikz.root.Object;
|
|
|
+ var buildTraitOrClass = brikz.behaviors.buildTraitOrClass;
|
|
|
+ var setupMethods = brikz.methods.setupMethods;
|
|
|
+ var removeTraitOrClass = brikz.behaviors.removeTraitOrClass;
|
|
|
+ var addElement = brikz.arraySet.addElement;
|
|
|
+ var removeElement = brikz.arraySet.removeElement;
|
|
|
+ var declareEvent = brikz.event.declareEvent;
|
|
|
+ var nilAsReceiver = brikz.nil.nilAsReceiver;
|
|
|
+
|
|
|
+ function SmalltalkBehavior () {
|
|
|
}
|
|
|
-
|
|
|
- changes.forEach(function (each) {
|
|
|
- updateMethod(each, traitOrBehavior);
|
|
|
- });
|
|
|
- }
|
|
|
|
|
|
- this.traitMethodChanged = traitMethodChanged;
|
|
|
- }
|
|
|
+ function SmalltalkClass () {
|
|
|
+ }
|
|
|
|
|
|
- ClassesBrik.deps = ["root", "event", "behaviors", "methods", "arraySet", "nil"];
|
|
|
- function ClassesBrik (brikz, st) {
|
|
|
- var SmalltalkRoot = brikz.root.Root;
|
|
|
- var specialConstructors = brikz.commonSpecialConstructors;
|
|
|
- var SmalltalkObject = brikz.root.Object;
|
|
|
- var buildTraitOrClass = brikz.behaviors.buildTraitOrClass;
|
|
|
- var setupMethods = brikz.methods.setupMethods;
|
|
|
- var removeTraitOrClass = brikz.behaviors.removeTraitOrClass;
|
|
|
- var addElement = brikz.arraySet.addElement;
|
|
|
- var removeElement = brikz.arraySet.removeElement;
|
|
|
- var emit = brikz.commonEmit;
|
|
|
- var declareEvent = brikz.event.declareEvent;
|
|
|
- var nilAsReceiver = brikz.nil.nilAsReceiver;
|
|
|
-
|
|
|
- function SmalltalkBehavior () {
|
|
|
- }
|
|
|
+ function SmalltalkMetaclass () {
|
|
|
+ }
|
|
|
|
|
|
- function SmalltalkClass () {
|
|
|
- }
|
|
|
+ specialConstructors.Behavior = inherits(SmalltalkBehavior, SmalltalkObject);
|
|
|
+ specialConstructors.Class = inherits(SmalltalkClass, SmalltalkBehavior);
|
|
|
+ specialConstructors.Metaclass = inherits(SmalltalkMetaclass, SmalltalkBehavior);
|
|
|
|
|
|
- function SmalltalkMetaclass () {
|
|
|
- }
|
|
|
+
|
|
|
+
|
|
|
+ var nilAsClass = this.nilAsClass = {
|
|
|
+ fn: SmalltalkRoot,
|
|
|
+ subclasses: [],
|
|
|
+ a$cls: {fn: SmalltalkClass}
|
|
|
+ };
|
|
|
|
|
|
- specialConstructors.Behavior = inherits(SmalltalkBehavior, SmalltalkObject);
|
|
|
- specialConstructors.Class = inherits(SmalltalkClass, SmalltalkBehavior);
|
|
|
- specialConstructors.Metaclass = inherits(SmalltalkMetaclass, SmalltalkBehavior);
|
|
|
+ SmalltalkMetaclass.prototype.meta = true;
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- var nilAsClass = this.nilAsClass = {
|
|
|
- fn: SmalltalkRoot,
|
|
|
- subclasses: [],
|
|
|
- a$cls: {fn: SmalltalkClass}
|
|
|
- };
|
|
|
+ defineMethod(SmalltalkClass, "toString", function () {
|
|
|
+ return 'Smalltalk ' + this.name;
|
|
|
+ });
|
|
|
+ defineMethod(SmalltalkMetaclass, "toString", function () {
|
|
|
+ return 'Smalltalk Metaclass ' + this.instanceClass.name;
|
|
|
+ });
|
|
|
+ declareEvent("classAdded");
|
|
|
+ defineMethod(SmalltalkClass, "added", function () {
|
|
|
+ addSubclass(this);
|
|
|
+ emit.classAdded(this);
|
|
|
+ });
|
|
|
+ declareEvent("classRemoved");
|
|
|
+ defineMethod(SmalltalkClass, "removed", function () {
|
|
|
+ emit.classRemoved(this);
|
|
|
+ removeSubclass(this);
|
|
|
+ });
|
|
|
+ declareEvent("behaviorMethodAdded");
|
|
|
+ defineMethod(SmalltalkBehavior, "methodAdded", function (method) {
|
|
|
+ emit.behaviorMethodAdded(method, this);
|
|
|
+ });
|
|
|
+ declareEvent("behaviorMethodRemove");
|
|
|
+ defineMethod(SmalltalkBehavior, "methodRemoved", function (method) {
|
|
|
+ emit.behaviorMethodRemoved(method, this);
|
|
|
+ });
|
|
|
|
|
|
- SmalltalkMetaclass.prototype.meta = true;
|
|
|
+
|
|
|
+ function installIvarCompat (klass) {
|
|
|
+ var ivars = klass.slots;
|
|
|
+ ivars.forEach(function (ivar) {
|
|
|
+ Object.defineProperty(klass.fn.prototype, "@" + ivar, {
|
|
|
+ get: function () {
|
|
|
+ return this[ivar];
|
|
|
+ },
|
|
|
+ set: function (value) {
|
|
|
+ return this[ivar] = value;
|
|
|
+ },
|
|
|
+ enumerable: false,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- defineMethod(SmalltalkClass, "toString", function () {
|
|
|
- return 'Smalltalk ' + this.name;
|
|
|
- });
|
|
|
- defineMethod(SmalltalkMetaclass, "toString", function () {
|
|
|
- return 'Smalltalk Metaclass ' + this.instanceClass.name;
|
|
|
- });
|
|
|
- declareEvent("classAdded");
|
|
|
- defineMethod(SmalltalkClass, "added", function () {
|
|
|
- addSubclass(this);
|
|
|
- emit.classAdded(this);
|
|
|
- });
|
|
|
- declareEvent("classRemoved");
|
|
|
- defineMethod(SmalltalkClass, "removed", function () {
|
|
|
- emit.classRemoved(this);
|
|
|
- removeSubclass(this);
|
|
|
- });
|
|
|
- declareEvent("behaviorMethodAdded");
|
|
|
- defineMethod(SmalltalkBehavior, "methodAdded", function (method) {
|
|
|
- emit.behaviorMethodAdded(method, this);
|
|
|
- });
|
|
|
- declareEvent("behaviorMethodRemove");
|
|
|
- defineMethod(SmalltalkBehavior, "methodRemoved", function (method) {
|
|
|
- emit.behaviorMethodRemoved(method, this);
|
|
|
- });
|
|
|
+ this.installIvarCompat = installIvarCompat;
|
|
|
|
|
|
-
|
|
|
- function installIvarCompat (klass) {
|
|
|
- var ivars = klass.slots;
|
|
|
- ivars.forEach(function (ivar) {
|
|
|
- Object.defineProperty(klass.fn.prototype, "@" + ivar, {
|
|
|
- get: function () {
|
|
|
- return this[ivar];
|
|
|
- },
|
|
|
- set: function (value) {
|
|
|
- return this[ivar] = value;
|
|
|
- },
|
|
|
- enumerable: false,
|
|
|
- configurable: true
|
|
|
+ function setSlots (klass, slots) {
|
|
|
+ slots.forEach(function (name) {
|
|
|
+ if (!name.match(/^[a-zA-Z][a-zA-Z0-9]*$/))
|
|
|
+ throw new Error("Wrong identifier name: " + name);
|
|
|
});
|
|
|
- });
|
|
|
- }
|
|
|
|
|
|
- this.installIvarCompat = installIvarCompat;
|
|
|
+ klass.slots = slots;
|
|
|
+ installIvarCompat(klass);
|
|
|
+ }
|
|
|
+
|
|
|
+ st.setSlots = setSlots;
|
|
|
|
|
|
- function setSlots (klass, slots) {
|
|
|
- slots.forEach(function (name) {
|
|
|
- if (!name.match(/^[a-zA-Z][a-zA-Z0-9]*$/))
|
|
|
- throw new Error("Wrong identifier name: " + name);
|
|
|
+
|
|
|
+ Object.defineProperty(SmalltalkBehavior.prototype, "iVarNames", {
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true,
|
|
|
+ get: function () {
|
|
|
+ return this.slots;
|
|
|
+ },
|
|
|
+ set: function (instanceVariableNames) {
|
|
|
+ setSlots(this, instanceVariableNames);
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
- klass.slots = slots;
|
|
|
- installIvarCompat(klass);
|
|
|
- }
|
|
|
+ this.bootstrapHierarchy = function (realClass) {
|
|
|
+ nilAsClass.a$cls = realClass;
|
|
|
+ nilAsClass.subclasses.forEach(function (each) {
|
|
|
+ each.a$cls.superclass = realClass;
|
|
|
+ addSubclass(each.a$cls);
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
- st.setSlots = setSlots;
|
|
|
-
|
|
|
-
|
|
|
- Object.defineProperty(SmalltalkBehavior.prototype, "iVarNames", {
|
|
|
- enumerable: true,
|
|
|
- configurable: true,
|
|
|
- get: function () {
|
|
|
- return this.slots;
|
|
|
- },
|
|
|
- set: function (instanceVariableNames) {
|
|
|
- setSlots(this, instanceVariableNames);
|
|
|
- }
|
|
|
- });
|
|
|
+
|
|
|
+ created metaclass object. Newly created classes (not their metaclass)
|
|
|
+ should be added to the system, see smalltalk.addClass().
|
|
|
+ Superclass linking is *not* handled here, see api.initialize() */
|
|
|
|
|
|
- this.bootstrapHierarchy = function (realClass) {
|
|
|
- nilAsClass.a$cls = realClass;
|
|
|
- nilAsClass.subclasses.forEach(function (each) {
|
|
|
- each.a$cls.superclass = realClass;
|
|
|
- addSubclass(each.a$cls);
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
- created metaclass object. Newly created classes (not their metaclass)
|
|
|
- should be added to the system, see smalltalk.addClass().
|
|
|
- Superclass linking is *not* handled here, see api.initialize() */
|
|
|
-
|
|
|
- function classBuilder (className, superclass, fn) {
|
|
|
- var logicalSuperclass = superclass;
|
|
|
- if (superclass == null || superclass.a$nil) {
|
|
|
- superclass = nilAsClass;
|
|
|
- logicalSuperclass = null;
|
|
|
- }
|
|
|
+ function classBuilder (className, superclass, fn) {
|
|
|
+ var logicalSuperclass = superclass;
|
|
|
+ if (superclass == null || superclass.a$nil) {
|
|
|
+ superclass = nilAsClass;
|
|
|
+ logicalSuperclass = null;
|
|
|
+ }
|
|
|
|
|
|
- function klass () {
|
|
|
- var that = metaclass().instanceClass;
|
|
|
+ function klass () {
|
|
|
+ var that = metaclass().instanceClass;
|
|
|
|
|
|
- that.superclass = logicalSuperclass;
|
|
|
- that.fn = fn || inherits(function () {
|
|
|
+ that.superclass = logicalSuperclass;
|
|
|
+ that.fn = fn || inherits(function () {
|
|
|
}, superclass.fn);
|
|
|
- that.slots = [];
|
|
|
+ that.slots = [];
|
|
|
|
|
|
- that.name = className;
|
|
|
- that.subclasses = [];
|
|
|
+ that.name = className;
|
|
|
+ that.subclasses = [];
|
|
|
|
|
|
- setupMethods(that);
|
|
|
- return that;
|
|
|
- }
|
|
|
+ setupMethods(that);
|
|
|
+ return that;
|
|
|
+ }
|
|
|
|
|
|
- function metaclass () {
|
|
|
- var that = new SmalltalkMetaclass();
|
|
|
+ function metaclass () {
|
|
|
+ var that = new SmalltalkMetaclass();
|
|
|
|
|
|
- that.superclass = superclass.a$cls;
|
|
|
- that.fn = inherits(function () {
|
|
|
- }, that.superclass.fn);
|
|
|
- that.slots = [];
|
|
|
+ that.superclass = superclass.a$cls;
|
|
|
+ that.fn = inherits(function () {
|
|
|
+ }, that.superclass.fn);
|
|
|
+ that.slots = [];
|
|
|
+
|
|
|
+ that.instanceClass = new that.fn();
|
|
|
+
|
|
|
+ wireKlass(that);
|
|
|
+ setupMethods(that);
|
|
|
+ return that;
|
|
|
+ }
|
|
|
|
|
|
- that.instanceClass = new that.fn();
|
|
|
+ return {
|
|
|
+ name: className,
|
|
|
+ make: klass,
|
|
|
+ updateExisting: function (klass) {
|
|
|
+ if (klass.superclass != logicalSuperclass || fn && fn !== klass.fn)
|
|
|
+ throw new Error("Incompatible change of class: " + klass.name);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
|
|
|
- wireKlass(that);
|
|
|
- setupMethods(that);
|
|
|
- return that;
|
|
|
+ function wireKlass (klass) {
|
|
|
+ Object.defineProperty(klass.fn.prototype, "a$cls", {
|
|
|
+ value: klass,
|
|
|
+ enumerable: false, configurable: true, writable: true
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- return {
|
|
|
- name: className,
|
|
|
- make: klass,
|
|
|
- updateExisting: function (klass) {
|
|
|
- if (klass.superclass != logicalSuperclass || fn && fn !== klass.fn)
|
|
|
- throw new Error("Incompatible change of class: " + klass.name);
|
|
|
+ this.wireKlass = wireKlass;
|
|
|
+
|
|
|
+
|
|
|
+ * This function is used all over the compiled amber code.
|
|
|
+ * It takes any value (JavaScript or Smalltalk)
|
|
|
+ * and returns a proper Amber Smalltalk receiver.
|
|
|
+ *
|
|
|
+ * null or undefined -> nilAsReceiver,
|
|
|
+ * object having Smalltalk signature -> unchanged,
|
|
|
+ * otherwise wrapped foreign (JS) object
|
|
|
+ */
|
|
|
+ this.asReceiver = function (o) {
|
|
|
+ if (o == null) return nilAsReceiver;
|
|
|
+ else if (o.a$cls != null) return o;
|
|
|
+ else return st.wrapJavaScript(o);
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ A Package is lazily created if one with given name does not exist. */
|
|
|
+
|
|
|
+ st.addClass = function (className, superclass, category) {
|
|
|
+
|
|
|
+ if (arguments[3]) {
|
|
|
+ var added = st.addClass(className, superclass, arguments[3]);
|
|
|
+ setSlots(added, category);
|
|
|
+ return added;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (typeof superclass === 'undefined' || superclass && superclass.a$nil) {
|
|
|
+ console.warn('Compiling ' + className + ' as a subclass of `nil`. A dependency might be missing.');
|
|
|
}
|
|
|
+ return buildTraitOrClass(category, classBuilder(className, superclass, specialConstructors[className]));
|
|
|
};
|
|
|
- }
|
|
|
|
|
|
- function wireKlass (klass) {
|
|
|
- Object.defineProperty(klass.fn.prototype, "a$cls", {
|
|
|
- value: klass,
|
|
|
- enumerable: false, configurable: true, writable: true
|
|
|
- });
|
|
|
- }
|
|
|
+ st.removeClass = removeTraitOrClass;
|
|
|
|
|
|
- this.wireKlass = wireKlass;
|
|
|
-
|
|
|
-
|
|
|
- * This function is used all over the compiled amber code.
|
|
|
- * It takes any value (JavaScript or Smalltalk)
|
|
|
- * and returns a proper Amber Smalltalk receiver.
|
|
|
- *
|
|
|
- * null or undefined -> nilAsReceiver,
|
|
|
- * object having Smalltalk signature -> unchanged,
|
|
|
- * otherwise wrapped foreign (JS) object
|
|
|
- */
|
|
|
- this.asReceiver = function (o) {
|
|
|
- if (o == null) return nilAsReceiver;
|
|
|
- else if (o.a$cls != null) return o;
|
|
|
- else return st.wrapJavaScript(o);
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
- A Package is lazily created if one with given name does not exist. */
|
|
|
-
|
|
|
- st.addClass = function (className, superclass, category) {
|
|
|
-
|
|
|
- if (arguments[3]) {
|
|
|
- var added = st.addClass(className, superclass, arguments[3]);
|
|
|
- setSlots(added, category);
|
|
|
- return added;
|
|
|
+ function addSubclass (klass) {
|
|
|
+ addElement((klass.superclass || nilAsClass).subclasses, klass);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- if (typeof superclass === 'undefined' || superclass && superclass.a$nil) {
|
|
|
- console.warn('Compiling ' + className + ' as a subclass of `nil`. A dependency might be missing.');
|
|
|
+ function removeSubclass (klass) {
|
|
|
+ removeElement((klass.superclass || nilAsClass).subclasses, klass);
|
|
|
}
|
|
|
- return buildTraitOrClass(category, classBuilder(className, superclass, specialConstructors[className]));
|
|
|
- };
|
|
|
|
|
|
- st.removeClass = removeTraitOrClass;
|
|
|
-
|
|
|
- function addSubclass (klass) {
|
|
|
- addElement((klass.superclass || nilAsClass).subclasses, klass);
|
|
|
- }
|
|
|
+ function metaSubclasses (metaclass) {
|
|
|
+ return metaclass.instanceClass.subclasses
|
|
|
+ .filter(function (each) {
|
|
|
+ return !each.meta;
|
|
|
+ })
|
|
|
+ .map(function (each) {
|
|
|
+ return each.a$cls;
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- function removeSubclass (klass) {
|
|
|
- removeElement((klass.superclass || nilAsClass).subclasses, klass);
|
|
|
- }
|
|
|
+ st.metaSubclasses = metaSubclasses;
|
|
|
|
|
|
- function metaSubclasses (metaclass) {
|
|
|
- return metaclass.instanceClass.subclasses
|
|
|
- .filter(function (each) {
|
|
|
- return !each.meta;
|
|
|
- })
|
|
|
- .map(function (each) {
|
|
|
- return each.a$cls;
|
|
|
- });
|
|
|
+ st.traverseClassTree = function (klass, fn) {
|
|
|
+ var queue = [klass], sentinel = {};
|
|
|
+ for (var i = 0; i < queue.length; ++i) {
|
|
|
+ var item = queue[i];
|
|
|
+ if (fn(item, sentinel) === sentinel) continue;
|
|
|
+ var subclasses = item.meta ? metaSubclasses(item) : item.subclasses;
|
|
|
+ queue.push.apply(queue, subclasses);
|
|
|
+ }
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
- st.metaSubclasses = metaSubclasses;
|
|
|
+
|
|
|
|
|
|
- st.traverseClassTree = function (klass, fn) {
|
|
|
- var queue = [klass], sentinel = {};
|
|
|
- for (var i = 0; i < queue.length; ++i) {
|
|
|
- var item = queue[i];
|
|
|
- if (fn(item, sentinel) === sentinel) continue;
|
|
|
- var subclasses = item.meta ? metaSubclasses(item) : item.subclasses;
|
|
|
- queue.push.apply(queue, subclasses);
|
|
|
- }
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
+ function configure (brikz) {
|
|
|
+ brikz.traits = TraitsBrik;
|
|
|
+ brikz.composition = MethodCompositionBrik;
|
|
|
+ brikz.classes = ClassesBrik;
|
|
|
|
|
|
- function configure (brikz) {
|
|
|
- brikz.traits = TraitsBrik;
|
|
|
- brikz.composition = MethodCompositionBrik;
|
|
|
- brikz.classes = ClassesBrik;
|
|
|
+ brikz();
|
|
|
+ }
|
|
|
|
|
|
- brikz();
|
|
|
+ return {configure: configure};
|
|
|
}
|
|
|
|
|
|
- return {configure: configure};
|
|
|
+ return LanguageFactory;
|
|
|
});
|