"File : rules" "SCCS : '@(#)2010/09/22 rules 1.6'" "Author : Richard A. O'Keefe" "Purpose: protocol consistency rules for ASTC" rule: '== is sacred' defines: #== -> is: Object rule: '~~ is sacred' defines: #~~ -> is: Object rule: '~= is sacred' defines: #~= -> is: Object rule: 'class is sacred' defines: #class -> is: Object rule: 'identityHash is sacred' defines: #identityHash -> is: Object rule: '= and hash must be consistent (A)' defines: #= -> defines: #hash rule: '= and hash must be consistent (B)' defines: #hash -> defines: #= rule: 'isKindOf: is sacred' defines: #isKindOf: -> is: Object rule: 'isMemberOf: is sacred' defines: #isMemberOf: -> is: Object rule: 'isNil is sacred' defines: #isNil -> is: Object | is: UndefinedObject rule: 'notNil is sacred' defines: #notNil -> is: Object | is: UndefinedObject rule: 'ifNil: is sacred' defines: #ifNil: -> is: Object | is: UndefinedObject rule: 'ifNotNil: is sacred' defines: #ifNotNil: -> is: Object | is: UndefinedObject rule: 'ifNil:ifNotNil: is sacred' defines: #ifNil:ifNotNil: -> is: Object | is: UndefinedObject rule: 'ifNotNil:ifNil: is sacred' defines: #ifNotNil:ifNil: -> is: Object | is: UndefinedObject "Maybe #perform... can be overridden." rule: 'respondsTo: is sacred' "but SHOULD it be?" defines: #respondsTo: -> is: Object rule: 'yourself is sacred' defines: #yourself -> is: Object rule: 'UndefinedObject may have no subclasses' descendsFrom: UndefinedObject -> false rule: 'Boolean may have no subclasses' descendsFrom: Boolean -> false rule: 'Character may have no subclasses' descendsFrom: Character -> false rule: 'SmallInteger may have no subclasses' descendsFrom: SmallInteger -> false rule: 'ifTrue: is sacred' defines: #ifTrue -> is: Boolean rule: 'ifFalse: is sacred' defines: #ifFalse -> is: Boolean rule: 'ifTrue:ifFalse: is sacred' defines: #ifTrue:ifFalse: -> is: Boolean rule: 'ifFalse:ifTrue: is sacred' defines: #ifFalse:ifTrue -> is: Boolean rule: 'full comparison set (1)' provides: #< -> provides: #<= rule: 'full comparison set (2)' provides: #<= -> provides: #>= rule: 'full comparison set (3)' provides: #>= -> provides: #> rule: 'full comparison set (4)' provides: #> -> provides: #max: rule: 'full comparison set (5)' provides: #max: -> provides: #min: rule: 'full comparison set (6)' provides: #min: -> provides: #between:and: rule: 'full comparison set (7)' provides: #between:and: -> provides: #< rule: 'full comparison set (8)' "The #comparedWith:[ignoringCase:] methods are non-ANSI." "If you have the version with a Boolean argument," "you can certainly have the other, but not vice versa." "#comparedWith: is not in the cycle; you may provide" "the other (standard) methods without this one -- though" "it is better to have it -- but if you do have it you" "must have the others." provides: #comparedWith:ignoringCase: -> provides: #comparedWith: rule: 'full comparison set (9)' provides: #comparedWith: -> provides: #< "While we are at it, let's have a few more rules about ignoringCase:" rule: 'sameAs: is missing' provides: #sameAs:ignoringCase: -> provides: #sameAs: rule: 'beginsWith: is missing' provides: #beginsWith:ignoringCase: -> provides: #beginsWith: rule: 'endsWith: is missing' provides: #endsWith:ignoringCase: -> provides: #endsWith: rule: 'complete support of withAll:collect:' provides: #withAll: -> provides: #withAll:collect: rule: 'sequences support withAll:from:to:' kindOf: SequencedReadableCollection -> class provides: #withAll:from:to: "The 'with' rules should not apply to Lazy*** collections." rule: 'all the with:s (4)' "This SHOULD apply to Sorted{Set,Bag}, but NOT Sorted{SetOrBagOr,}Dictionary" provides: #withAll: & ~ kindOf: AbstractDictionary class & ~ kindOf: SortedSetOrBagOrDictionary class -> provides: #with:with:with:with: rule: 'all the with:s (3)' provides: #with:with:with:with: -> provides: #with:with:with: rule: 'all the with:s (2)' provides: #with:with:with: -> provides: #with:with: rule: 'all the with:s (1)' provides: #with:with: -> provides: #with: rule: 'to:do: is sacred' defines: #to:do: -> is: Number rule: 'to:do:by: is sacred' defines: #to:do:by: -> is: Number rule: 'nobody changes Float' sets: Float -> is: FloatD class rule: 'nobody changes Transcript' sets: Transcript -> is: ChannelLatin1OutputStream class rule: 'full adding set (1)' provides: #+ & provides: #negated -> provides: #- rule: 'full adding set (2)' "x + y = x - ((y - y) - y)" provides: #- -> provides: #+ "I wanted the following rule." "It makes sense that if you can do x-x you SHOULD be able to do x class zero." "However, in ANSI Smalltalk this is only true for Duration," "and in Squeak it's only true for Duration and ScaledDecimal." """rule: 'class zero if subtraction'" """ provides: #- -> class provides: #zero" rule: 'full adding set (4)' "x negated = (x - x) - x" "Of course, that presumes that (x - x) - x is allowed." "For a Date, x - x is an Integer 0, and 0 - aDate is NOT allowed." """provides: #- -> provides: #negated" "But since x * (-1) is the same as #negated, this should work:" provides: #* -> provides: #negated rule: 'full adding set (5)' provides: #+ & provides: #negated -> provides: #- rule: 'full adding set (6)' provides: #negated & provides: #negative -> provides: #abs rule: 'both parts of integer division (A)' provides: #// -> provides: #\\ rule: 'both parts of integer division (B)' provides: #\\ -> provides: #// rule: 'remainder if quotient' provides: #quo: -> provides: #rem: rule: 'quotient if remainder' provides: #rem: -> provides: #quo: rule: 'division if reciprocal' "x / y = x * y reciprocal" provides: #reciprocal & provides: #* -> provides: #/ "There is no converse rule because we could support both" "x * scalar and x / scalar without supporting x reciprocal." rule: 'integerPart and fractionPart go together (A)' "x integerPart = x - x fractionPart" provides: #fractionPart -> provides: #integerPart rule: 'integerPart and fractionPart go together (B)' provides: #integerPart -> provides: #fractionPart rule: 'rounded is a special case of roundTo:' provides: #roundTo: -> provides: #rounded rule: 'truncated is a special case of truncateTo:' provides: #truncateTo: -> provides: #truncated rule: 'zero' class provides: #zero -> provides: #isZero "It makes sense that if you can ask whether x isZero then" "you should be able to ask for x class zero as well." "But in ANSI Smalltalk this is only true for Duration," "and in Squeak only for Duration and ScaledDecimal." """provides: #isZero -> class provides: #zero" rule: 'sign tests (1)' provides: #negative -> provides: #positive rule: 'sign tests (2)' provides: #positive -> provides: #strictlyPositive rule: 'sign tests (3)' provides: #strictlyPositive -> provides: #sign rule: 'sign tests (4)' provides: #sign -> provides: #negative | is: Point rule: 'conversion to integer (1)' provides: #ceiling -> provides: #floor rule: 'conversion to integer (2)' provides: #floor -> provides: #truncated rule: 'conversion to integer (3)' provides: #truncated -> provides: #ceiling rule: 'squared' "x squared = x * x; but we might support x * scalar without supporting" "x * x. As a probe for the latter, we check for reciprocal; if 1/x is" "allowed then x*x should be." provides: #* & provides: #reciprocal -> provides: #squared rule: 'raisedToInteger:' "raisedToInteger: needs * and reciprocal and squared, but we don't" "need to check for squared beause of the previous rule." provides: #* & provides: #reciprocal -> provides: #raisedToInteger: rule: 'whileFalse is sacred' defines: #whileFalse -> is: NiladicBlock rule: 'whileTrue is sacred' defines: #whileTrue -> is: NiladicBlock rule: 'assert is sacred' defines: #assert -> is: NiladicBlock rule: 'whileFalse: is sacred' defines: #whileFalse: -> is: NiladicBlock rule: 'whileTrue: is sacred' defines: #whileTrue: -> is: NiladicBlock rule: 'assert: is sacred' defines: #assert: -> is: NiladicBlock rule: 'blocks must define argumentCount' kindOf: Block -> defines: #argumentCount rule: 'size is easier than empty' provides: #size -> provides: #isEmpty rule: 'isEmpty/notEmpty go together (1)' provides: #isEmpty -> provides: #notEmpty rule: 'isEmpty/notEmpty go together (2)' provides: #notEmpty -> provides: #isEmpty rule: 'atEnd/next go together (1)' provides: #atEnd -> provides: #next rule: 'atEnd/next go together (2)' provides: #next & ~ provides: #previous -> provides: #atEnd rule: 'at:put: requires at:' provides: #at:put: -> provides: #at: rule: 'float conversion (A)' provides: #asFloatE -> provides: #asFloatD rule: 'float conversion (B)' provides: #asFloatD -> provides: #asFloatQ rule: 'float conversion (C)' provides: #asFloatQ -> provides: #asFloatE rule: 'division implies multiplication' "(x * y) = (x / (1 / y))." "However, FileName uses / for directory/child, so we need to" "pin it down a bit, and #- is good for that." provides: #/ & provides: #- -> provides: #* rule: 'quantifiers : allSatisfy:' provides: #noneSatisfy: -> provides: #allSatisfy: rule: 'quantifiers : anySatisfy:' provides: #allSatisfy: -> provides: #anySatisfy: rule: 'quantifiers : count:' provides: #anySatisfy: -> provides: #count: rule: 'quantifiers : noneSatisfy:' provides: #count: -> provides: #noneSatisfy: rule: 'reject if select' "We want select$X: -> reject$X:" provides: #select: -> provides: #reject: rule: 'select if reject' "We want reject$X: -> select$X:" provides: #reject: -> provides: #select: rule: 'collections have copyEmpty' "I'm still looking for a good way to say 'is a collection'" provides: #printElementsOn: -> provides: #copyEmpty "EXTENSIONS" "I want Encoders and Decoders to support at: and at:put:" "but that is ALL I want them to have." rule: 'should provide atAllPut:' provides: #atAll:put: -> provides: #atAllPut: rule: 'should provide #swap:with:' provides: #at:put: & provides: #size -> provides: #swap:with: rule: 'should provide #at:exchange:' provides: #swap:with: -> provides: #at:exchange: rule: 'should provide atAll:put:' provides: #at:exchange: -> provides: #atAll:put: rule: 'should provide at:put:' provides: #atAll:put: -> provides: #at:put: rule: 'addAll:' provides: #add: & ~ provides: #subtract: -> provides: #addAll: provides: #addFirst: -> provides: #addAllFirst: provides: #addLast: -> provides: #addAllLast: rule: 'remove if add' provides: #add: & ~ provides: #subtract: -> provides: #remove: provides: #addFirst: -> provides: #removeFirst provides: #addLast: -> provides: #removeLast rule: '#remove: without #includes:' provides: #remove: -> provides: #includes: rule: '#removeFirst without #isEmpty' provides: #removeFirst -> provides: #isEmpty rule: '#removeLast without #isEmpty' provides: #removeLast -> provides: #isEmpty rule: 'removeAll:' provides: #remove: -> provides: #removeAll: rule: 'removeAll' provides: #remove: -> provides: #removeAll provides: #removeFirst -> provides: #removeAll provides: #removeLast -> provides: #removeAll rule: 'from:to:do:' "x from: p to: q do: b === (x copyFrom: p to: q) do: b" provides: #copyFrom:to: & provides: #do: -> provides: #from:to:do: rule: 'from:to:keysAndValuesDo:' provides: #copyFrom:to: & provides: #keysAndValuesDo: -> provides: #from:to:keysAndValuesDo: rule: 'from:to:runsDo:' provides: #copyFrom:to: & provides: #runsDo: -> provides: #from:to:runsDo: rule: 'from:to:valuesDo:' provides: #copyFrom:to: & provides: #valuesDo: -> provides: #from:to:valuesDo: "I want Encoders and Decoders to support at: and at:put:" "but that is ALL I want them to have." rule: 'at:ifAbsent:' provides: #at: & provides: #size -> provides: #at:ifAbsent: rule: 'after:ifAbsent:' provides: #after: -> provides: #after:ifAbsent: rule: 'after:' provides: #after:ifAbsent: -> provides: #after: rule: 'at:' provides: #at:ifAbsent: -> provides: #at: rule: 'before:ifAbsent:' provides: #before: -> provides: #before:ifAbsent: rule: 'before:' provides: #before:ifAbsent: -> provides: #before: rule: 'findFirst:ifAbsent:' provides: #findFirst: -> provides: #findFirst:ifAbsent: rule: 'findFirst:' provides: #findFirst:ifAbsent: -> provides: #findFirst: rule: 'findLast:ifAbsent:' provides: #findLast: -> provides: #findLast:ifAbsent: rule: 'findLast:' provides: #findLast:ifAbsent: -> provides: #findLast: rule: 'indexOf:ifAbsent:' provides: #indexOf: -> provides: #indexOf:ifAbsent: rule: 'indexOf:' provides: #indexOf:ifAbsent: -> provides: #indexOf: rule: 'indexOfSubcollection:ifAbsent:' provides: #indexOfSubcollection: -> provides: #indexOfSubcollection:ifAbsent: rule: 'indexOfSubcollection:' provides: #indexOfSubcollection:ifAbsent: -> provides: #indexOfSubcollection: rule: 'keyAtIdentityValue:ifAbsent: provides: #keyAtIdentityValue: -> provides: #keyAtIdentityValue:ifAbsent: rule: 'keyAtIdentityValue: provides: #keyAtIdentityValue:ifAbsent: -> provides: #keyAtIdentityValue: rule: 'keyAtValue:ifAbsent: provides: #keyAtValue: -> provides: #keyAtValue:ifAbsent: rule: 'keyAtValue: provides: #keyAtValue:ifAbsent: -> provides: #keyAtValue: rule: 'remove:ifAbsent:' provides: #remove: -> provides: #remove:ifAbsent: rule: 'remove:' provides: #remove:ifAbsent: -> provides: #remove: rule: 'first is missing' "x first = x from: 1 to: x size do: [:each | ^each]" provides: #from:to:do: -> provides: #first rule: 'last is missing' "x last = |t| x isEmpty ifTrue: [x error: ' last']." " x from: 1 to: x size do: [:each | t := each]. ^t" provides: #from:to:do: -> provides: #last rule: 'subStrings and subStrings: should both be offered' provides: #subStrings -> provides: #subStrings: provides: #subStrings: -> provides: #subStrings rule: 'input streams should have do:' provides: #atEnd & provides: #next -> provides: #do: rule: 'input streams should have next:' provides: #atEnd & provides: #next -> provides: #next: rule: 'input streams should have skip:' provides: #atEnd & provides: #next -> provides: #skip: rule: 'input streams should have skipTo:' provides: #atEnd & provides: #next -> provides: #skipTo: rule: 'peek and peekFor: go together' provides: #peek -> provides: #peekFor: provides: #peekFor: -> provides: #peek rule: 'peekFor: is a special case of peekForAny:' provides: #peekForAny: -> provides: #peekFor: rule: 'if you can set the position you should be able to read it' provides: #position: -> provides: #position rule: 'if you can set the position you can set it to the beginning' provides: #position: -> provides: #reset rule: 'if you can set the position you can set it to the end' provides: #position: -> provides: #setToEnd rule: 'if you can set the position you can skip over input' kindOf: inputStream & provides: #position: -> provides: #skip: rule: 'if you can find the contents you can test if they would be empty' kindOf: Stream & provides: #contents -> provides: #isEmpty rule: 'output streams should have close' provides: #nextPut: -> provides: #close rule: 'closed requires close' provides: #closed -> provides: #close rule: 'how can you read a line if you can't read a character?' provides: #nextLine -> provides: #next rule: 'nextPut:/nextPutAll: go together' provides: #nextPut: -> provides: #nextPutAll: provides: #nextPutAll: -> provides: #nextPut: rule: 'basicNew may only be defined by the compiler defines: #basicNew -> false rule: 'basicNew: may only be defined by the compiler defines: #basicNew: -> false rule: 'basicSize may only be defined by the compiler defines: #basicSize -> false rule: 'basicAt: may only be defined by the compiler' defines: #basicAt: -> false rule: 'basicAt:put: may only be defined by the compiler' defines: #basicAt:put: -> false rule: 'reverse applies to sequences' defines: #reverse -> provides: #do: rule: 'reverseDo: is a composition' provides: #reverse & provides: #do: -> provides: #reverseDo: rule: 'reverseDo: is a special case' provides: #reverseDo: -> provides: #reverse & provides: #do: rule: 'inPlaceReverse is a special case of #reverse' provides: #inPlaceReverse -> provides: #reverse rule: 'inPlaceReverse applies to mutable sequences' provides: #inPlaceReverse -> provides: #at:put: | provides: #removeLast "Some more compounds" rule: 'collect:thenDo: is a compound' provides: #collect:thenDo: -> provides: #collect: & provides: #do: rule: 'collect:thenReject: is a compound' provides: #collect:thenReject: -> provides: #collect: & provides: #reject: rule: 'collect:thenSelect: is a compound' provides: #collect:thenSelect: -> provides: #collect: & provides: #select: rule: 'collect:thenReject: and collect:thenSelect: go together' provides: #collect:thenReject: -> provides: #collect:thenSelect: rule: 'collect:thenSelect: and collect:thenReject: go together' provides: #collect:thenSelect: -> provides: #collect:thenReject: rule: 'reject:thencollect: is a compound' provides: #reject:thencollect: -> provides: #collect: & provides: #reject: rule: 'select:thencollect: is a compound' provides: #select:thencollect: -> provides: #collect: & provides: #select: rule: 'reject:thencollect: and select:thencollect: go together' provides: #reject:thencollect: -> provides: #select:thencollect: rule: 'select:thencollect: and reject:thencollect: go together' provides: #select:thencollect: -> provides: #reject:thencollect: rule: 'do:without: is derived' provides: #do:without: -> provides: #do: rule: 'exclusion is derived from inclusion (1)' provides: #excludes: -> provides: #includes: rule: 'exclusion is derived from inclusion (2)' provides: #excludesAllOf: -> provides: #includesAnyOf: rule: 'exclusion is derived from inclusion (3)' provides: #excludesAnyOf: -> provides: #includesAllOf: rule: 'exclusion is derived from inclusion (4)' provides: #excludesNoneOf -> provides: #includesAnyOf: rule: 'includesAllOf: is missing' provides: #allSatisfy: & provides: #includes: -> provides: #includesAllOf: rule: 'includesAnyOf: is missing' provides: #anySatisfy: & provides: #includes: -> provides: #includesAnyOf: rule: 'includesNoneOf: is missing' provides: #noneSatisfy: & provides: #includes: -> provides: #includesNoneOf: rule: 'identityIncludes: is missing' provides: #anySatisfy: -> provides: #identityIncludes: rule: 'identityOccurrencesOf: is missing' provides: #count: -> provides: #identityOccurrencesOf: rule: 'addAll:/collect: fusion is a good idea' kindOf: Collection & provides: #addAll: -> provides: #addAll:collect: rule: 'addAll:/copyFrom:to: fusion is a good idea' kindOf: Collection & provides: #addAll: &~ kindOf: AbstractDictionary -> provides: #addAll:from:to: rule: 'keyed assignment -> batched assignment (1)' provides: #at:put: & provides: #do: -> provides: #atAll:put: rule: 'keyed assignment -> batched assignment (2)' provides: #at:put: & provides: #do: -> provides: #atAllPut: rule: 'whichSatisfy:' provides: #keysAndValuesDo: -> provides: #whichSatisfy: rule: 'self batch update/inPlaceCollect:' provides: #at:put: & provides: #collect: -> provides: #inPlaceCollect: rule: 'self batch update/inPlaceReject:' provides: #removeAll: & provides: #reject: -> provides: #inPlaceReject: rule: 'self batch update/inPlaceSelect:' provides: #removeAll: & provides: #select: -> provides: #inPlaceSelect: rule: 'self batch update/inPlaceReverse' provides: #at:put: & provides: #reverse: -> provides: #inPlaceReverse rule: 'numbers are values' kindOf: Number -> isAbstract | isValue rule: 'blocks are values' kindOf: Block -> isAbstract | isValue rule: 'dates are values' kindOf: AbstractDate -> isAbstract | isValue rule: 'dates and times are values' is: Date | is: Time | is: DateAndTime -> isValue rule: 'intervals are values' kindOf: AbstractInterval -> isAbstract | isValue rule: 'network addresses are values' kindOf: NetworkAddress -> isAbstract | isValue rule: 'streams are NOT values' kindOf: InputStream | kindOf: outputStream -> isAbstract | isMutable "Squeak 4.1 Collection has #add:withOccurrences: as well as #add:." "This makes no sense for Collection, but we'd like to ensure that" "any Collection with either has both." rule: 'add: <-> add:withOccurrences: (missing #add:)' provides: #add:withOccurrences: -> provides: #add: rule: 'add: <-> add:withOccurrences: (missing #add:withOccurrences:)' provides: #add: & ~ kindOf: AbstractDictionary -> provides: #add:withOccurrences: rule: 'add: <-> addAll: (missing add:)' provides: #addAll: & ~ kindOf: AbstractDictionary -> provides: #add: rule: 'add: <-> addAll: (missing addAll:)' provides: #add: -> provides: #addAll: rule: 'missing addIfNotPresent:' provides: #add: & provides: #includes: & ~ kindOf: AbstractDictionary -> provides: #addIfNotPresent: