Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type guided '&' translation #683

Open
wants to merge 10 commits into
base: pharo-12
Choose a base branch
from
6 changes: 3 additions & 3 deletions smalltalksrc/Melchor/MLVMCCodeGenerator.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -300,16 +300,16 @@ MLVMCCodeGenerator >> harmonizeReturnTypesIn: aSetOfTypes [
constantIntegers := aSetOfTypes select: [:element| element isInteger].
aSetOfTypes removeAll: constantIntegers.
"N.B. Because of LP64 vs LLP64 issues do *not* rename #long to #sqInt or #'unsigned long' to #usqInt"
#(char short int #'long long' #'unsigned char' #'unsigned short' #'unsigned int' #'unsigned long long')
with: #(sqInt sqInt sqInt sqLong usqInt usqInt usqInt usqLong)
{#char. #short. #int. #'long long' .#'unsigned char'. #'unsigned short'. #'unsigned int'. #'unsigned long long'. TType int}
with: #(sqInt sqInt sqInt sqLong usqInt usqInt usqInt usqLong sqInt)
do: [:type :replacement|
(aSetOfTypes includes: type) ifTrue:
[aSetOfTypes remove: type; add: replacement]].
sqs := aSetOfTypes select: [:t| t beginsWith: 'sq'].
usqs := aSetOfTypes select: [:t| t beginsWith: 'usq'].
^(sqs size + usqs size = aSetOfTypes size
and: [sqs notEmpty
and: [sqs allSatisfy: [:t| usqs includes: 'u', t]]])
and: [sqs allSatisfy: [:t| usqs includes: 'u', t asString]]])
ifTrue: [sqs]
ifFalse: [(aSetOfTypes isEmpty and: [constantIntegers notEmpty])
ifTrue: [Set with: self defaultType]
Expand Down
2 changes: 1 addition & 1 deletion smalltalksrc/Slang-Tests/SlangAbstractTestCase.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ SlangAbstractTestCase >> assertReturnTypeOf: aMethod equalsHarmonized: expectedT
| harmonizedTypes |
harmonizedTypes := ccg harmonizeReturnTypesIn: { expectedType } asSet.
self assert: harmonizedTypes size = 1 description: 'There seems to be a type conflict'.
self assert: aMethod returnType equals: harmonizedTypes anyOne.
self assert: aMethod returnType asString equals: harmonizedTypes anyOne.
]
100 changes: 58 additions & 42 deletions smalltalksrc/Slang-Tests/SlangBasicTranslationTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,35 @@ SlangBasicTranslationTest >> testGoto [
self assert: translation equals: 'goto lab'
]

{ #category : #'tests-inlinemethod' }
SlangBasicTranslationTest >> testInlineMethodIfExpressionWithShiftRight [

| translation codeGenerator inlinedMethod cast printedString |
translation := (self getTMethodFrom: #methodToBeTranslatedWithIfAndShiftRight).
inlinedMethod := ((SlangBasicTranslationTestClass >> #methodWithIfAndShiftRight:) asTranslationMethodOfClass: TMethod).

codeGenerator := CCodeGeneratorGlobalStructure new.
codeGenerator
addMethod: translation;
addMethod: inlinedMethod;
doInlining: true.

cast := translation asCASTIn: codeGenerator.
printedString := String streamContents: [ :str | cast prettyPrintOn: str ].
self assert: cast isCompoundStatement.
self assert: printedString equals: '/* SlangBasicTranslationTestClass>>#methodToBeTranslatedWithIfAndShiftRight */
static sqInt
methodToBeTranslatedWithIfAndShiftRight(void)
{
/* begin methodWithIfAndShiftRight: */
((usqInt) (((2 < 0)
? 0
: 2)) ) >> ((2 - 1) * 32);
return 0;
}
'.
]

{ #category : #'tests-inline-builtins' }
SlangBasicTranslationTest >> testInlineMethodSumArgumentsWithAnnotations [
| tMethod translation |
Expand Down Expand Up @@ -1246,35 +1275,6 @@ methodUseParametersWithAnnotationsBuiltIntowith(unsigned int *pFrom, unsigned in
}'
]

{ #category : #'tests-inlinemethod' }
SlangBasicTranslationTest >> testInlineMethodIfExpressionWithShiftRight [

| translation codeGenerator inlinedMethod cast printedString |
translation := (self getTMethodFrom: #methodToBeTranslatedWithIfAndShiftRight).
inlinedMethod := ((SlangBasicTranslationTestClass >> #methodWithIfAndShiftRight:) asTranslationMethodOfClass: TMethod).

codeGenerator := CCodeGeneratorGlobalStructure new.
codeGenerator
addMethod: translation;
addMethod: inlinedMethod;
doInlining: true.

cast := translation asCASTIn: codeGenerator.
printedString := String streamContents: [ :str | cast prettyPrintOn: str ].
self assert: cast isCompoundStatement.
self assert: printedString equals: '/* SlangBasicTranslationTestClass>>#methodToBeTranslatedWithIfAndShiftRight */
static sqInt
methodToBeTranslatedWithIfAndShiftRight(void)
{
/* begin methodWithIfAndShiftRight: */
((usqInt) (((2 < 0)
? 0
: 2)) ) >> ((2 - 1) * 32);
return 0;
}
'.
]

{ #category : #'tests-inlinenode' }
SlangBasicTranslationTest >> testInlineNodeDoesNotInitializeReadBeforeWrittenArrayTemp [

Expand Down Expand Up @@ -2187,19 +2187,6 @@ SlangBasicTranslationTest >> testSendAllMask [
self assert: translation equals: '(a & 7) == 7'
]

{ #category : #'tests-builtins' }
SlangBasicTranslationTest >> testSendAnd [

| send |

send := TSendNode new
setSelector: #&
receiver: (TConstantNode value: false)
arguments: { TConstantNode value: true }.
self should: [ self translate: send ] raise: TranslationError.

]

{ #category : #'tests-builtins' }
SlangBasicTranslationTest >> testSendAsFloat [

Expand Down Expand Up @@ -6604,6 +6591,35 @@ SlangBasicTranslationTest >> testTranslateNormalVariable [
self assert: translation equals: 'someVar'
]

{ #category : #'tests-send' }
SlangBasicTranslationTest >> testTypeGuidedAnd [

| tMethod translation |
tMethod := self getTMethodFrom: #methodWithAndBooleanReceiver.
translation := self translate: tMethod.

self assert: (translation includesSubstring: 'receiver && 1')
]

{ #category : #'tests-send' }
SlangBasicTranslationTest >> testTypeGuidedbitAnd [

| tMethod translation |
tMethod := self getTMethodFrom: #methodWithAndIntegerReceiver.
translation := self translate: tMethod.

self assert: (translation includesSubstring: 'receiver & 1')
]

{ #category : #'tests-send' }
SlangBasicTranslationTest >> testTypeMismatchedAnd [

| method |
method := self getTMethodFrom:
#methodWithAndIntegerReceiverAndBooleanArgument.
self should: [ self translate: method ] raise: TypeError
]

{ #category : #'tests-assignment' }
SlangBasicTranslationTest >> testVariableAssignment [

Expand Down
39 changes: 33 additions & 6 deletions smalltalksrc/Slang-Tests/SlangBasicTranslationTestClass.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ SlangBasicTranslationTestClass >> methodFromWithAnnotations: pFrom to: pTo len:
^ 0
]

{ #category : #inline }
SlangBasicTranslationTestClass >> methodToBeTranslatedWithIfAndShiftRight [

self methodWithIfAndShiftRight: 2
]

{ #category : #'generation-targets' }
SlangBasicTranslationTestClass >> methodUseParametersWithAnnotations: pFrom to: pTo with: anInteger [

Expand All @@ -125,12 +131,6 @@ SlangBasicTranslationTestClass >> methodUseParametersWithAnnotationsBuiltIn: pFr
to: pTo
]

{ #category : #inline }
SlangBasicTranslationTestClass >> methodToBeTranslatedWithIfAndShiftRight [

self methodWithIfAndShiftRight: 2
]

{ #category : #inline }
SlangBasicTranslationTestClass >> methodUsingSingleArrayVariable [

Expand Down Expand Up @@ -177,6 +177,33 @@ SlangBasicTranslationTestClass >> methodWithAnOptionPragma [

]

{ #category : #'as yet unclassified' }
SlangBasicTranslationTestClass >> methodWithAndBooleanReceiver [

| receiver result |

receiver := true.
result := receiver & true
]

{ #category : #'as yet unclassified' }
SlangBasicTranslationTestClass >> methodWithAndIntegerReceiver [

| receiver result |

receiver := 1000.
result := receiver & 1
]

{ #category : #'as yet unclassified' }
SlangBasicTranslationTestClass >> methodWithAndIntegerReceiverAndBooleanArgument [

| receiver result |

receiver := 1000.
result := receiver & false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the boolean is an argument?

methodWithAndIntegerReceiverAndBooleanArgument: arg [

	| receiver result |

	receiver := 1000.
	result := receiver & arg

and all variantas :)

  • boolean & boolean
  • boolean & int
  • int & boolean
  • int & int

Copy link
Collaborator Author

@ivojawer ivojawer Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cases where both (arg and receiver) are boolean/int are covered with methodWithAndBooleanReceiver and methodWithAndIntegerReceiver. Maybe the name should reference the argument 馃槄

The other cases I considered them all the same test case (covered by this method), as they fall under the "if they are different types then throw an error" logic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but my point is that those tests are on literal booleans/integers!!!
What if the receiver are the result of a more complex expression, say a variable? Do we need a type annotation for booleans?

]

{ #category : #inline }
SlangBasicTranslationTestClass >> methodWithIfAndShiftRight: var [

Expand Down
68 changes: 34 additions & 34 deletions smalltalksrc/Slang-Tests/SlangBasicTypeInferenceTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ SlangBasicTypeInferenceTest >> testAFalseConstantNode [
tMethod := ccg methodNamed: #aFalseConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #int
]

{ #category : #constant }
Expand All @@ -71,7 +71,7 @@ SlangBasicTypeInferenceTest >> testANilConstantNode [
tMethod := ccg methodNamed: #aNilConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt
]

{ #category : #constant }
Expand All @@ -98,7 +98,7 @@ SlangBasicTypeInferenceTest >> testATrueConstantNode [
tMethod := ccg methodNamed: #aTrueConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #int
]

{ #category : #constant }
Expand Down Expand Up @@ -166,8 +166,8 @@ SlangBasicTypeInferenceTest >> testReturnAFalseConstantNode [
tMethod := ccg methodNamed: #returnAFalseConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int.
self assert: tMethod returnType equals: #sqInt
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #int.
self assert: tMethod returnType asString equals: #sqInt
]

{ #category : #'return-message-send' }
Expand All @@ -176,9 +176,9 @@ SlangBasicTypeInferenceTest >> testReturnAFalseMessageSend [
tMethod := ccg methodNamed: #returnAFalseMessageSend.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first expression in: tMethod) equals: #sqInt.
self assert: tMethod returnType equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first expression in: tMethod) asString equals: #sqInt.
self assert: tMethod returnType asString equals: #sqInt.
]

{ #category : #'return-message-send' }
Expand All @@ -198,7 +198,7 @@ SlangBasicTypeInferenceTest >> testReturnANilConstantNode [
tMethod := ccg methodNamed: #returnANilConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int.
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt.
self assert: tMethod returnType equals: #sqInt
]

Expand Down Expand Up @@ -261,8 +261,8 @@ SlangBasicTypeInferenceTest >> testReturnATrueConstantNode [
tMethod := ccg methodNamed: #returnATrueConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int.
self assert: tMethod returnType equals: #sqInt
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #int.
self assert: tMethod returnType asString equals: #sqInt
]

{ #category : #'return-message-send' }
Expand All @@ -271,9 +271,9 @@ SlangBasicTypeInferenceTest >> testReturnATrueMessageSend [
tMethod := ccg methodNamed: #returnATrueMessageSend.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first expression in: tMethod) equals: #sqInt.
self assert: tMethod returnType equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first expression in: tMethod) asString equals: #sqInt.
self assert: tMethod returnType asString equals: #sqInt.
]

{ #category : #'return-constant' }
Expand Down Expand Up @@ -576,9 +576,9 @@ SlangBasicTypeInferenceTest >> testReturnTempFalseConstantNode [
tMethod := ccg methodNamed: #returnTempFalseConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #int. " variable, temporaryNode "
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #int. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) asString equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) asString equals: #int. " variable, temporaryNode "

self assertReturnTypeOf: tMethod equalsHarmonized: #int
]
Expand All @@ -589,8 +589,8 @@ SlangBasicTypeInferenceTest >> testReturnTempFalseMessageNode [
tMethod := ccg methodNamed: #returnTempFalseMessageNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) asString equals: #sqInt.
self assert: tMethod returnType equals: #sqInt.
]

Expand Down Expand Up @@ -697,7 +697,7 @@ SlangBasicTypeInferenceTest >> testReturnTempIntLesser32ConstantNode [
self assert: (ccg typeFor: tMethod statements first value in: tMethod) equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #int. " variable, temporaryNode "

self assertReturnTypeOf: tMethod equalsHarmonized: #'int'
self assertReturnTypeOf: tMethod equalsHarmonized: #int
]

{ #category : #'return-temp-assigned-message' }
Expand All @@ -717,11 +717,11 @@ SlangBasicTypeInferenceTest >> testReturnTempNilConstantNode [
tMethod := ccg methodNamed: #returnTempNilConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #int. " variable, temporaryNode "
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) asString equals: #sqInt. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) asString equals: #sqInt. " variable, temporaryNode "

self assertReturnTypeOf: tMethod equalsHarmonized: #int
self assertReturnTypeOf: tMethod equalsHarmonized: #sqInt
]

{ #category : #'return-temp-assigned-message' }
Expand All @@ -741,9 +741,9 @@ SlangBasicTypeInferenceTest >> testReturnTempSmallNegativeIntegerConstantNode [
tMethod := ccg methodNamed: #returnTempSmallNegativeIntegerConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #int. " variable, temporaryNode "
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #int. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) asString equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) asString equals: #int. " variable, temporaryNode "

self assertReturnTypeOf: tMethod equalsHarmonized: #int
]
Expand All @@ -754,8 +754,8 @@ SlangBasicTypeInferenceTest >> testReturnTempSmallNegativeIntegerMessageNode [
tMethod := ccg methodNamed: #returnTempSmallNegativeIntegerMessageNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) asString equals: #sqInt.
self assert: tMethod returnType equals: #sqInt.
]

Expand Down Expand Up @@ -788,9 +788,9 @@ SlangBasicTypeInferenceTest >> testReturnTempTrueConstantNode [
tMethod := ccg methodNamed: #returnTempTrueConstantNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #int. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #int. " variable, temporaryNode "
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #int. " assignementNode "
self assert: (ccg typeFor: tMethod statements first value in: tMethod) asString equals: #int. " value, constantNode "
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) asString equals: #int. " variable, temporaryNode "

self assertReturnTypeOf: tMethod equalsHarmonized: #int
]
Expand All @@ -801,7 +801,7 @@ SlangBasicTypeInferenceTest >> testReturnTempTrueMessageNode [
tMethod := ccg methodNamed: #returnTempTrueMessageNode.

self assert: tMethod isNotNil.
self assert: (ccg typeFor: tMethod statements first in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first in: tMethod) asString equals: #sqInt.
self assert: (ccg typeFor: tMethod statements first variable in: tMethod) asString equals: #sqInt.
self assert: tMethod returnType equals: #sqInt.
]