Skip to content

Commit a24cafa

Browse files
committed
Manage generic types
1 parent d8e3015 commit a24cafa

5 files changed

Lines changed: 269 additions & 28 deletions

File tree

‎src/FAST-Python-Model-Generator/FASTPythonMetamodelGenerator.class.st‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ FASTPythonMetamodelGenerator >> defineHierarchy [
428428

429429
genericType --|> tTypeContent.
430430
genericType --|> tWithTypeParameters.
431+
genericType --|> tNamedEntity.
431432

432433
globalStatement --|> statement.
433434

@@ -690,6 +691,8 @@ FASTPythonMetamodelGenerator >> defineRelations [
690691

691692
(functionDefinition property: #returnType) <>- (type property: #parentFunctionDefinition).
692693

694+
(genericType property: #arguments) <>-* (type property: #parentGenericTypeArgument).
695+
693696
((globalStatement property: #variables) comment: 'The variables scoped')
694697
<>-* ((variable property: #globalOwner) comment: 'The global statement defining my scope (if it''s the case)').
695698

‎src/FAST-Python-Model/FASTPyGenericType.class.st‎

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,34 @@
55
### Parents
66
| Relation | Origin | Opposite | Type | Comment |
77
|---|
8+
| `invokedIn` | `FASTTNamedEntity` | `invoked` | `FASTTInvocation` | Optional invocation where this name is used|
89
| `parentType` | `FASTPyTTypeContent` | `content` | `FASTPyType` | |
910
1011
### Children
1112
| Relation | Origin | Opposite | Type | Comment |
1213
|---|
14+
| `arguments` | `FASTPyGenericType` | `parentGenericTypeArgument` | `FASTPyType` | |
1315
| `typeParameters` | `FASTPyTWithTypeParameters` | `parentWithTypeParameters` | `FASTPyType` | |
1416
1517
18+
## Properties
19+
======================
20+
21+
| Name | Type | Default value | Comment |
22+
|---|
23+
| `endPos` | `Number` | nil | |
24+
| `name` | `String` | nil | |
25+
| `startPos` | `Number` | nil | |
1626
1727
"
1828
Class {
1929
#name : 'FASTPyGenericType',
2030
#superclass : 'FASTPyEntity',
21-
#traits : 'FASTPyTTypeContent + FASTPyTWithTypeParameters',
22-
#classTraits : 'FASTPyTTypeContent classTrait + FASTPyTWithTypeParameters classTrait',
31+
#traits : 'FASTPyTTypeContent + FASTPyTWithTypeParameters + FASTTNamedEntity',
32+
#classTraits : 'FASTPyTTypeContent classTrait + FASTPyTWithTypeParameters classTrait + FASTTNamedEntity classTrait',
33+
#instVars : [
34+
'#arguments => FMMany type: #FASTPyType opposite: #parentGenericTypeArgument'
35+
],
2336
#category : 'FAST-Python-Model-Entities',
2437
#package : 'FAST-Python-Model',
2538
#tag : 'Entities'
@@ -33,3 +46,32 @@ FASTPyGenericType class >> annotation [
3346
<generated>
3447
^ self
3548
]
49+
50+
{ #category : 'adding' }
51+
FASTPyGenericType >> addArgument: anObject [
52+
<generated>
53+
^ self arguments add: anObject
54+
]
55+
56+
{ #category : 'accessing' }
57+
FASTPyGenericType >> arguments [
58+
"Relation named: #arguments type: #FASTPyType opposite: #parentGenericTypeArgument"
59+
60+
<generated>
61+
<derived>
62+
^ arguments
63+
]
64+
65+
{ #category : 'accessing' }
66+
FASTPyGenericType >> arguments: anObject [
67+
68+
<generated>
69+
arguments value: anObject
70+
]
71+
72+
{ #category : 'navigation' }
73+
FASTPyGenericType >> argumentsGroup [
74+
<generated>
75+
<navigation: 'Arguments'>
76+
^ MooseSpecializedGroup withAll: self arguments asSet
77+
]

‎src/FAST-Python-Model/FASTPyType.class.st‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
| `parentContrainedType` | `FASTPyType` | `type` | `FASTPyConstrainedType` | |
1010
| `parentContrainedTypeBound` | `FASTPyType` | `bound` | `FASTPyConstrainedType` | |
1111
| `parentFunctionDefinition` | `FASTPyType` | `returnType` | `FASTPyFunctionDefinition` | |
12+
| `parentGenericTypeArgument` | `FASTPyType` | `arguments` | `FASTPyGenericType` | |
1213
| `parentParameter` | `FASTPyType` | `type` | `FASTPyParameter` | |
1314
| `parentWithTypeParameters` | `FASTPyType` | `typeParameters` | `FASTPyTWithTypeParameters` | |
1415
| `parentyTypeAliasStatementAlias` | `FASTPyType` | `left` | `FASTPyTypeAliasStatement` | |
@@ -31,6 +32,7 @@ Class {
3132
'#parentContrainedType => FMOne type: #FASTPyConstrainedType opposite: #type',
3233
'#parentContrainedTypeBound => FMOne type: #FASTPyConstrainedType opposite: #bound',
3334
'#parentFunctionDefinition => FMOne type: #FASTPyFunctionDefinition opposite: #returnType',
35+
'#parentGenericTypeArgument => FMOne type: #FASTPyGenericType opposite: #arguments',
3436
'#parentParameter => FMOne type: #FASTPyParameter opposite: #type',
3537
'#parentWithTypeParameters => FMOne type: #FASTPyTWithTypeParameters opposite: #typeParameters',
3638
'#parentyTypeAliasStatementAlias => FMOne type: #FASTPyTypeAliasStatement opposite: #left',
@@ -168,6 +170,29 @@ FASTPyType >> parentFunctionDefinitionGroup [
168170
^ MooseSpecializedGroup with: self parentFunctionDefinition
169171
]
170172

173+
{ #category : 'accessing' }
174+
FASTPyType >> parentGenericTypeArgument [
175+
"Relation named: #parentGenericTypeArgument type: #FASTPyGenericType opposite: #arguments"
176+
177+
<generated>
178+
<container>
179+
^ parentGenericTypeArgument
180+
]
181+
182+
{ #category : 'accessing' }
183+
FASTPyType >> parentGenericTypeArgument: anObject [
184+
185+
<generated>
186+
parentGenericTypeArgument := anObject
187+
]
188+
189+
{ #category : 'navigation' }
190+
FASTPyType >> parentGenericTypeArgumentGroup [
191+
<generated>
192+
<navigation: 'ParentGenericTypeArgument'>
193+
^ MooseSpecializedGroup with: self parentGenericTypeArgument
194+
]
195+
171196
{ #category : 'accessing' }
172197
FASTPyType >> parentParameter [
173198
"Relation named: #parentParameter type: #FASTPyParameter opposite: #type"

‎src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st‎

Lines changed: 163 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9791,30 +9791,179 @@ FASTPythonImporterTest >> testGenericType [
97919791
"Generated as regression test by FASTPyImporterTestGenerator>>#generateTestNamed:fromCode:protocol:
97929792
Regenerate executing: self regenerateTest: #testGenericType "
97939793

9794-
self parse: 'list[Path]'.
9794+
self parse: 'def f(items: List[T]): pass'.
97959795

9796+
self assert: (fast allWithType: FASTPyBlock) size equals: 1.
9797+
self assert: (fast allWithType: FASTPyFunctionDefinition) size equals: 1.
9798+
self assert: (fast allWithType: FASTPyGenericType) size equals: 1.
9799+
self assert: (fast allWithType: FASTPyIdentifier) size equals: 1.
9800+
self assert: (fast allWithType: FASTPyModule) size equals: 1.
9801+
self assert: (fast allWithType: FASTPyParameter) size equals: 1.
9802+
self assert: (fast allWithType: FASTPyPassStatement) size equals: 1.
9803+
self assert: (fast allWithType: FASTPyType) size equals: 2.
9804+
9805+
stack push: fast rootEntities anyOne containedEntities first.
9806+
self assert: self topEntity sourceCode equals: 'def f(items: List[T]): pass'.
9807+
self assert: (self topEntity isOfType: FASTPyFunctionDefinition).
9808+
self assert: (self topEntity isOfType: FASTPyTDefinition).
9809+
self assert: (self topEntity isOfType: FASTTWithParameters).
9810+
self assert: (self topEntity isOfType: FASTTWithStatements).
9811+
self assert: self topEntity name equals: 'f'.
9812+
9813+
"Testing value of multivalued relation parameters"
9814+
self assert: self topEntity parameters size equals: 1.
9815+
9816+
stack push: (stack top parameters at: 1).
9817+
self assert: self topEntity sourceCode equals: 'items: List[T]'.
9818+
self assert: (self topEntity isOfType: FASTPyParameter).
9819+
self assert: (self topEntity isOfType: FASTTVariableEntity).
9820+
self assert: self topEntity name equals: 'items'.
9821+
9822+
"Testing value of monovalue relation type"
9823+
self assert: self topEntity type isNotNil.
9824+
9825+
stack push: self topEntity type.
9826+
self assert: self topEntity sourceCode equals: 'List[T]'.
9827+
self assert: (self topEntity isOfType: FASTPyType).
9828+
9829+
"Testing value of monovalue relation content"
9830+
self assert: self topEntity content isNotNil.
9831+
9832+
stack push: self topEntity content.
9833+
self assert: self topEntity sourceCode equals: 'List[T]'.
9834+
self assert: (self topEntity isOfType: FASTPyGenericType).
9835+
self assert: self topEntity name equals: 'List'.
9836+
9837+
"Testing value of multivalued relation typeParameters"
9838+
self assert: self topEntity typeParameters size equals: 1.
9839+
9840+
stack push: (stack top typeParameters at: 1).
9841+
self assert: self topEntity sourceCode equals: 'T'.
9842+
self assert: (self topEntity isOfType: FASTPyType).
9843+
9844+
"Testing value of monovalue relation content"
9845+
self assert: self topEntity content isNotNil.
9846+
9847+
stack push: self topEntity content.
9848+
self assert: self topEntity sourceCode equals: 'T'.
9849+
self assert: (self topEntity isOfType: FASTPyIdentifier).
9850+
stack pop.
9851+
stack pop.
9852+
stack pop.
9853+
stack pop.
9854+
stack pop.
9855+
9856+
"Testing value of monovalue relation statementBlock"
9857+
self assert: self topEntity statementBlock isNotNil.
9858+
9859+
stack push: self topEntity statementBlock.
9860+
self assert: self topEntity sourceCode equals: 'pass'.
9861+
self assert: (self topEntity isOfType: FASTPyBlock).
9862+
self assert: (self topEntity isOfType: FASTTStatementBlock).
9863+
9864+
"Testing value of multivalued relation statements"
9865+
self assert: self topEntity statements size equals: 1.
9866+
9867+
stack push: (stack top statements at: 1).
9868+
self assert: self topEntity sourceCode equals: 'pass'.
9869+
self assert: (self topEntity isOfType: FASTPyPassStatement)
9870+
]
9871+
9872+
{ #category : 'tests - types' }
9873+
FASTPythonImporterTest >> testGenericTypeWithMultipleParameters [
9874+
<generated>
9875+
"Generated as regression test by FASTPyImporterTestGenerator>>#generateTestNamed:fromCode:protocol:
9876+
Regenerate executing: self regenerateTest: #testGenericTypeWithMultipleParameters "
9877+
9878+
self parse: 'def f(items: Dictionary[str, T]): pass'.
9879+
9880+
self assert: (fast allWithType: FASTPyBlock) size equals: 1.
9881+
self assert: (fast allWithType: FASTPyFunctionDefinition) size equals: 1.
9882+
self assert: (fast allWithType: FASTPyGenericType) size equals: 1.
97969883
self assert: (fast allWithType: FASTPyIdentifier) size equals: 2.
97979884
self assert: (fast allWithType: FASTPyModule) size equals: 1.
9798-
self assert: (fast allWithType: FASTPySubscript) size equals: 1.
9885+
self assert: (fast allWithType: FASTPyParameter) size equals: 1.
9886+
self assert: (fast allWithType: FASTPyPassStatement) size equals: 1.
9887+
self assert: (fast allWithType: FASTPyType) size equals: 3.
97999888

98009889
stack push: fast rootEntities anyOne containedEntities first.
9801-
self assert: self topEntity sourceCode equals: 'list[Path]'.
9802-
self assert: (self topEntity isOfType: FASTPySubscript).
9890+
self assert: self topEntity sourceCode equals: 'def f(items: Dictionary[str, T]): pass'.
9891+
self assert: (self topEntity isOfType: FASTPyFunctionDefinition).
9892+
self assert: (self topEntity isOfType: FASTPyTDefinition).
9893+
self assert: (self topEntity isOfType: FASTTWithParameters).
9894+
self assert: (self topEntity isOfType: FASTTWithStatements).
9895+
self assert: self topEntity name equals: 'f'.
98039896

9804-
"Testing value of multivalued relation indices"
9805-
self assert: self topEntity indices size equals: 1.
9897+
"Testing value of multivalued relation parameters"
9898+
self assert: self topEntity parameters size equals: 1.
98069899

9807-
stack push: (stack top indices at: 1).
9808-
self assert: self topEntity sourceCode equals: 'Path'.
9809-
self assert: (self topEntity isOfType: FASTPyIdentifier).
9900+
stack push: (stack top parameters at: 1).
9901+
self assert: self topEntity sourceCode equals: 'items: Dictionary[str, T]'.
9902+
self assert: (self topEntity isOfType: FASTPyParameter).
9903+
self assert: (self topEntity isOfType: FASTTVariableEntity).
9904+
self assert: self topEntity name equals: 'items'.
9905+
9906+
"Testing value of monovalue relation type"
9907+
self assert: self topEntity type isNotNil.
9908+
9909+
stack push: self topEntity type.
9910+
self assert: self topEntity sourceCode equals: 'Dictionary[str, T]'.
9911+
self assert: (self topEntity isOfType: FASTPyType).
9912+
9913+
"Testing value of monovalue relation content"
9914+
self assert: self topEntity content isNotNil.
9915+
9916+
stack push: self topEntity content.
9917+
self assert: self topEntity sourceCode equals: 'Dictionary[str, T]'.
9918+
self assert: (self topEntity isOfType: FASTPyGenericType).
9919+
self assert: self topEntity name equals: 'Dictionary'.
9920+
9921+
"Testing value of multivalued relation typeParameters"
9922+
self assert: self topEntity typeParameters size equals: 2.
9923+
9924+
stack push: (stack top typeParameters at: 1).
9925+
self assert: self topEntity sourceCode equals: 'str'.
9926+
self assert: (self topEntity isOfType: FASTPyType).
9927+
9928+
"Testing value of monovalue relation content"
9929+
self assert: self topEntity content isNotNil.
9930+
9931+
stack push: self topEntity content.
9932+
self assert: self topEntity sourceCode equals: 'str'.
9933+
self assert: (self topEntity isOfType: FASTPyIdentifier).
9934+
stack pop.
9935+
stack pop.
9936+
9937+
stack push: (stack top typeParameters at: 2).
9938+
self assert: self topEntity sourceCode equals: 'T'.
9939+
self assert: (self topEntity isOfType: FASTPyType).
9940+
9941+
"Testing value of monovalue relation content"
9942+
self assert: self topEntity content isNotNil.
9943+
9944+
stack push: self topEntity content.
9945+
self assert: self topEntity sourceCode equals: 'T'.
9946+
self assert: (self topEntity isOfType: FASTPyIdentifier).
9947+
stack pop.
9948+
stack pop.
9949+
stack pop.
9950+
stack pop.
98109951
stack pop.
98119952

9812-
"Testing value of monovalue relation value"
9813-
self assert: self topEntity value isNotNil.
9953+
"Testing value of monovalue relation statementBlock"
9954+
self assert: self topEntity statementBlock isNotNil.
98149955

9815-
stack push: self topEntity value.
9816-
self assert: self topEntity sourceCode equals: 'list'.
9817-
self assert: (self topEntity isOfType: FASTPyIdentifier)
9956+
stack push: self topEntity statementBlock.
9957+
self assert: self topEntity sourceCode equals: 'pass'.
9958+
self assert: (self topEntity isOfType: FASTPyBlock).
9959+
self assert: (self topEntity isOfType: FASTTStatementBlock).
9960+
9961+
"Testing value of multivalued relation statements"
9962+
self assert: self topEntity statements size equals: 1.
9963+
9964+
stack push: (stack top statements at: 1).
9965+
self assert: self topEntity sourceCode equals: 'pass'.
9966+
self assert: (self topEntity isOfType: FASTPyPassStatement)
98189967
]
98199968

98209969
{ #category : 'tests - statements' }

‎src/FAST-Python-Tools/TSFASTPythonImporter.class.st‎

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ TSFASTPythonImporter >> isInParameter: aNode [
6767
^ (#( typed_default_parameter default_parameter ) includes: type) and: [ context top field ~= #defaultValue ]
6868
]
6969

70+
{ #category : 'testing' }
71+
TSFASTPythonImporter >> shouldIdentifierSetNameProperty [
72+
73+
(context top isOfFASTType: FASTPyGenericType) ifTrue: [ ^ true ].
74+
75+
^ context top field = #name and: [
76+
{
77+
FASTPyMethodDefinition.
78+
FASTPyClassDefinition.
79+
FASTPyFunctionDefinition.
80+
FASTPyKeywordArgument } anySatisfy: [ :class | context top isOfFASTType: class ] ]
81+
]
82+
7083
{ #category : 'visiting - skip' }
7184
TSFASTPythonImporter >> visitAliasedImport: aTSNode [
7285
"Nothing to do. The visit of my children will take care of things. I use the #raw version since it is what should be used to skip a context level."
@@ -575,6 +588,14 @@ TSFASTPythonImporter >> visitGeneratorExpression: aTSNode [
575588
^ self visitComprehension: aTSNode
576589
]
577590

591+
{ #category : 'visiting - alias' }
592+
TSFASTPythonImporter >> visitGenericType: aTSNode [
593+
594+
self onNextContextDo: [ :entry | entry aliasUnnamedFieldAs: #typeConstructor ].
595+
596+
^ self handleNode: aTSNode kind: FASTPyGenericType
597+
]
598+
578599
{ #category : 'visiting - alias' }
579600
TSFASTPythonImporter >> visitGlobalStatement: aTSNode [
580601

@@ -586,18 +607,19 @@ TSFASTPythonImporter >> visitGlobalStatement: aTSNode [
586607
{ #category : 'visiting' }
587608
TSFASTPythonImporter >> visitIdentifier: aNode [
588609

589-
(self isInParameter: aNode) ifTrue: [ ^ self handleParameterNode: aNode name: (self sourceCodeOf: aNode) ]. "If we are in a field `name` then we are probably in a definition of an entity and we set my content as a name."
590-
(context anySatisfy: [ :entry |
591-
entry field = #name and: [
592-
{
593-
FASTPyMethodDefinition.
594-
FASTPyClassDefinition.
595-
FASTPyFunctionDefinition.
596-
FASTPyKeywordArgument } anySatisfy: [ :class | entry isOfFASTType: class ] ] ]) ifTrue: [ ^ self topFastEntity name: (self sourceCodeOf: aNode) ]. "If I am on the left side of an assignation then I am a variable."
597-
(context top field = #left and: [ context top isOfFASTType: FASTPyAssignment ]) ifTrue: [ ^ self handleNode: aNode kind: FASTPyVariable ]. "In case we are in an alias, we edit the property alias of the last imported entity"
598-
aNode parent type = #aliased_import ifTrue: [ ^ self topFastEntity importedEntities last alias: (self sourceCodeOf: aNode) ]. "Those statements points a variable"
599-
((context top isOfFASTType: FASTPyGlobalStatement) or: [ context top isOfFASTType: FASTPyNonlocalStatement ]) ifTrue: [
600-
^ self handleNode: aNode kind: FASTPyVariable ].
610+
(self isInParameter: aNode) ifTrue: [ ^ self handleParameterNode: aNode name: (self sourceCodeOf: aNode) ].
611+
612+
"If we are in a field `name` then we are probably in a definition of an entity and we set my content as a name."
613+
self shouldIdentifierSetNameProperty ifTrue: [ ^ self topFastEntity name: (self sourceCodeOf: aNode) ].
614+
615+
"If I am on the left side of an assignation then I am a variable."
616+
(context top field = #left and: [ context top isOfFASTType: FASTPyAssignment ]) ifTrue: [ ^ self handleNode: aNode kind: FASTPyVariable ].
617+
618+
"In case we are in an alias, we edit the property alias of the last imported entity"
619+
aNode parent type = #aliased_import ifTrue: [ ^ self topFastEntity importedEntities last alias: (self sourceCodeOf: aNode) ].
620+
621+
"Those statements points a variable"
622+
((context top isOfFASTType: FASTPyGlobalStatement) or: [ context top isOfFASTType: FASTPyNonlocalStatement ]) ifTrue: [ ^ self handleNode: aNode kind: FASTPyVariable ].
601623

602624
^ self handleNode: aNode
603625
]

0 commit comments

Comments
 (0)