|  | @@ -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) {
 | 
	
		
			
				|  |  | -            // assert(Object.getOwnProperties(obj).length === 0)
 | 
	
		
			
				|  |  | -            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);
 | 
	
		
			
				|  |  | -                    // else delete obj[aliasSelector]; // semantically correct; optimized away
 | 
	
		
			
				|  |  | +            function fillTraitTransformation (traitTransformation, obj) {
 | 
	
		
			
				|  |  | +                // assert(Object.getOwnProperties(obj).length === 0)
 | 
	
		
			
				|  |  | +                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);
 | 
	
		
			
				|  |  | +                        // else delete obj[aliasSelector]; // semantically correct; optimized away
 | 
	
		
			
				|  |  | +                    });
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                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));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                // assert(chain === null);
 | 
	
		
			
				|  |  | +                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 () {
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            // assert(chain === null);
 | 
	
		
			
				|  |  | -            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 () {
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +            // Fake root class of the system.
 | 
	
		
			
				|  |  | +            // Effective superclass of all classes created with `nil subclass: ...`.
 | 
	
		
			
				|  |  | +            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;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        // Fake root class of the system.
 | 
	
		
			
				|  |  | -        // Effective superclass of all classes created with `nil subclass: ...`.
 | 
	
		
			
				|  |  | -        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;
 | 
	
		
			
				|  |  | +            // TODO remove, ["@foo"] backward compatibility
 | 
	
		
			
				|  |  | +            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;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        // TODO remove, ["@foo"] backward compatibility
 | 
	
		
			
				|  |  | -        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);
 | 
	
		
			
				|  |  | +            // TODO remove, .iVarNames backward compatibility
 | 
	
		
			
				|  |  | +            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;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // TODO remove, .iVarNames backward compatibility
 | 
	
		
			
				|  |  | -        Object.defineProperty(SmalltalkBehavior.prototype, "iVarNames", {
 | 
	
		
			
				|  |  | -            enumerable: true,
 | 
	
		
			
				|  |  | -            configurable: true,
 | 
	
		
			
				|  |  | -            get: function () {
 | 
	
		
			
				|  |  | -                return this.slots;
 | 
	
		
			
				|  |  | -            },
 | 
	
		
			
				|  |  | -            set: function (instanceVariableNames) {
 | 
	
		
			
				|  |  | -                setSlots(this, instanceVariableNames);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        });
 | 
	
		
			
				|  |  | +            /* Smalltalk class creation. A class is an instance of an automatically
 | 
	
		
			
				|  |  | +             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);
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /* Smalltalk class creation. A class is an instance of an automatically
 | 
	
		
			
				|  |  | -         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);
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            /* Add a class to the system, creating a new one if needed.
 | 
	
		
			
				|  |  | +             A Package is lazily created if one with given name does not exist. */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            st.addClass = function (className, superclass, category) {
 | 
	
		
			
				|  |  | +                // TODO remove, backward compatibility
 | 
	
		
			
				|  |  | +                if (arguments[3]) {
 | 
	
		
			
				|  |  | +                    var added = st.addClass(className, superclass, arguments[3]);
 | 
	
		
			
				|  |  | +                    setSlots(added, category);
 | 
	
		
			
				|  |  | +                    return added;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // While subclassing nil is allowed, it might be an error, so
 | 
	
		
			
				|  |  | +                // warn about it.
 | 
	
		
			
				|  |  | +                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);
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /* Add a class to the system, creating a new one if needed.
 | 
	
		
			
				|  |  | -         A Package is lazily created if one with given name does not exist. */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        st.addClass = function (className, superclass, category) {
 | 
	
		
			
				|  |  | -            // TODO remove, backward compatibility
 | 
	
		
			
				|  |  | -            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);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // While subclassing nil is allowed, it might be an error, so
 | 
	
		
			
				|  |  | -            // warn about it.
 | 
	
		
			
				|  |  | -            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;
 | 
	
		
			
				|  |  | +        /* Making smalltalk that can load */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        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);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /* Making smalltalk that can load */
 | 
	
		
			
				|  |  | +        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;
 | 
	
		
			
				|  |  |  });
 |