From 43d50645243c8eebbed721c59de6224d904fa92e Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Fri, 18 Sep 2026 15:14:18 +0200 Subject: [PATCH 01/15] Add parametric tests exporting and importing the model --- .../FASTPythonAbstractTestCase.class.st | 43 ++++++++++++++++++- .../FASTPythonLocalResolverTest.class.st | 5 ++- .../FASTPythonSSATest.class.st | 5 ++- .../FASTPythonVariablesAnalysisTest.class.st | 5 ++- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st b/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st index 6bb6733..c152de7 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st @@ -1,8 +1,9 @@ Class { #name : 'FASTPythonAbstractTestCase', - #superclass : 'TestCase', + #superclass : 'ParametrizedTestCase', #instVars : [ - 'model' + 'model', + 'persist' ], #category : 'FAST-Python-Tools-Tests-Core', #package : 'FAST-Python-Tools-Tests', @@ -15,8 +16,46 @@ FASTPythonAbstractTestCase class >> isAbstract [ ^ self = FASTPythonAbstractTestCase ] +{ #category : 'building suites' } +FASTPythonAbstractTestCase class >> testParameters [ + + ^ ParametrizedTestMatrix new forSelector: #persist addOptions: { false. true } +] + +{ #category : 'running' } +FASTPythonAbstractTestCase >> exportAndImportModelIfNeeded [ + + | json | + self persist ifFalse: [ ^ self ]. + + json := model asJSONString. + + model := json readStreamDo: [ :stream | FASTPyModel new importFromJSONStream: stream ] +] + { #category : 'running' } FASTPythonAbstractTestCase >> parse: aString [ + "I import a FAST Python model from a string and if #persist is true, I export and reimport the model to test that export/import works fine." + + self privateParse: aString. + self exportAndImportModelIfNeeded +] + +{ #category : 'accessing' } +FASTPythonAbstractTestCase >> persist [ + + ^ persist +] + +{ #category : 'accessing' } +FASTPythonAbstractTestCase >> persist: anObject [ + + persist := anObject +] + +{ #category : 'running' } +FASTPythonAbstractTestCase >> privateParse: aString [ + "I parse a string and return a FAST Python model" ^ model := FASTPythonImporter new errorReportBlock: [ :i | i errors ifNotEmpty: [ self fail: 'Errors happened during parsing. Errors: ' , i errors printString ] ]; diff --git a/src/FAST-Python-Tools-Tests/FASTPythonLocalResolverTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonLocalResolverTest.class.st index b4d374d..727324c 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonLocalResolverTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonLocalResolverTest.class.st @@ -9,8 +9,9 @@ Class { { #category : 'resolving' } FASTPythonLocalResolverTest >> parseAndResolve: aString [ - self parse: aString. - FASTPythonLocalResolverVisitor resolve: model module + self privateParse: aString. + FASTPythonLocalResolverVisitor resolve: model module. + self exportAndImportModelIfNeeded ] { #category : 'tests - if' } diff --git a/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st index 0ca3c78..6c04f54 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st @@ -9,8 +9,9 @@ Class { { #category : 'parsing' } FASTPythonSSATest >> parseAndResolve: aString [ - self parse: aString. - FASTPythonSSAVisitor resolve: model module + self privateParse: aString. + FASTPythonSSAVisitor resolve: model module. + self exportAndImportModelIfNeeded ] { #category : 'tests - assignments' } diff --git a/src/FAST-Python-Tools-Tests/FASTPythonVariablesAnalysisTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonVariablesAnalysisTest.class.st index 91e228e..bf44c66 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonVariablesAnalysisTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonVariablesAnalysisTest.class.st @@ -12,8 +12,9 @@ Class { { #category : 'parsing' } FASTPythonVariablesAnalysisTest >> parseAndResolve: aString [ - self parse: aString. - FASTPythonSSAVisitor resolve: model module + self privateParse: aString. + FASTPythonSSAVisitor resolve: model module. + self exportAndImportModelIfNeeded ] { #category : 'tests' } From 7636d475db79e7129706af2677cf17ca4e04bac0 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Fri, 18 Sep 2026 15:50:54 +0200 Subject: [PATCH 02/15] Start by testing the importer for export/import --- .../FASTPythonAbstractTestCase.class.st | 9 +++-- .../FASTPythonImporterTest.class.st | 39 +++++++++++++++++++ .../FASTPythonMetamodelTest.class.st | 2 +- .../FASTPythonPersistedModelTest.class.st | 12 ++++++ 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 src/FAST-Python-Tools-Tests/FASTPythonPersistedModelTest.class.st diff --git a/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st b/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st index c152de7..f885e51 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st @@ -19,7 +19,9 @@ FASTPythonAbstractTestCase class >> isAbstract [ { #category : 'building suites' } FASTPythonAbstractTestCase class >> testParameters [ - ^ ParametrizedTestMatrix new forSelector: #persist addOptions: { false. true } + self flag: #todo. "enable once the tests of FASTPythonImporterTest will all be green with the parametric tests." + "^ ParametrizedTestMatrix new forSelector: #persist addOptions: { false. true }" + ^ super testParameters ] { #category : 'running' } @@ -29,7 +31,7 @@ FASTPythonAbstractTestCase >> exportAndImportModelIfNeeded [ self persist ifFalse: [ ^ self ]. json := model asJSONString. - + self halt. model := json readStreamDo: [ :stream | FASTPyModel new importFromJSONStream: stream ] ] @@ -38,7 +40,8 @@ FASTPythonAbstractTestCase >> parse: aString [ "I import a FAST Python model from a string and if #persist is true, I export and reimport the model to test that export/import works fine." self privateParse: aString. - self exportAndImportModelIfNeeded + self exportAndImportModelIfNeeded. + ^ model ] { #category : 'accessing' } diff --git a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st index a35ddf7..094c31f 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st @@ -37,6 +37,9 @@ Dictionary new Class { #name : 'FASTPythonImporterTest', #superclass : 'TSFASTAbstractImporterTest', + #instVars : [ + 'persist' + ], #category : 'FAST-Python-Tools-Tests-Importer', #package : 'FAST-Python-Tools-Tests', #tag : 'Importer' @@ -49,6 +52,12 @@ FASTPythonImporterTest class >> regenerateAllTests [ super regenerateAllTests ] +{ #category : 'building suites' } +FASTPythonImporterTest class >> testParameters [ + + ^ ParametrizedTestMatrix new forSelector: #persist addOptions: { false. true } +] + { #category : 'test generation' } FASTPythonImporterTest class >> traitsToTest [ "Return a collection of traits to test in generated tests." @@ -75,6 +84,36 @@ FASTPythonImporterTest class >> traitsToTest [ FamixTSourceAnchor } ] +{ #category : 'running' } +FASTPythonImporterTest >> exportAndImportModelIfNeeded [ + + | json | + self persist ifFalse: [ ^ self ]. + + json := fast asJSONString. + + fast := json readStreamDo: [ :stream | FASTPyModel new importFromJSONStream: stream ] +] + +{ #category : 'running' } +FASTPythonImporterTest >> parse: aString [ + + super parse: aString. + self exportAndImportModelIfNeeded. + + ^ fast +] + +{ #category : 'accessing' } +FASTPythonImporterTest >> persist [ + ^ persist +] + +{ #category : 'accessing' } +FASTPythonImporterTest >> persist: anObject [ + persist := anObject +] + { #category : 'tests - with statements' } FASTPythonImporterTest >> testAsPatternWithAttribute [ diff --git a/src/FAST-Python-Tools-Tests/FASTPythonMetamodelTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonMetamodelTest.class.st index 983fc53..3ec3234 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonMetamodelTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonMetamodelTest.class.st @@ -1,6 +1,6 @@ Class { #name : 'FASTPythonMetamodelTest', - #superclass : 'TSFASTAbstractImporterTest', + #superclass : 'TestCase', #category : 'FAST-Python-Tools-Tests-Core', #package : 'FAST-Python-Tools-Tests', #tag : 'Core' diff --git a/src/FAST-Python-Tools-Tests/FASTPythonPersistedModelTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonPersistedModelTest.class.st new file mode 100644 index 0000000..9643f18 --- /dev/null +++ b/src/FAST-Python-Tools-Tests/FASTPythonPersistedModelTest.class.st @@ -0,0 +1,12 @@ +" +All tests cases subclassing `FASTPythonAbstractTestCase` are parametric and run on an imported model, and also on the same model that has been exported and imported again. + +I am here to hold some tests specific to the export and import. When bugs are discovered in the import/export but the tests in the other classes are too complex to find easily the problem, a minimal version producing the problem is added to me. +" +Class { + #name : 'FASTPythonPersistedModelTest', + #superclass : 'FASTPythonAbstractTestCase', + #category : 'FAST-Python-Tools-Tests-Importer', + #package : 'FAST-Python-Tools-Tests', + #tag : 'Importer' +} From 2ea9d6a7ebb938685564671f8c1900c7e2f885f7 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Wed, 23 Sep 2026 14:38:49 +0200 Subject: [PATCH 03/15] Regenerate tests after https://github.com/Evref-BL/Pharo-Tree-Sitter/pull/62 --- .../FASTPythonImporterTest.class.st | 271 +++++++++--------- 1 file changed, 136 insertions(+), 135 deletions(-) diff --git a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st index 094c31f..b91869e 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st @@ -106,7 +106,8 @@ FASTPythonImporterTest >> parse: aString [ { #category : 'accessing' } FASTPythonImporterTest >> persist [ - ^ persist + + ^ persist ifNil: [ ^ false ] ] { #category : 'accessing' } @@ -771,7 +772,7 @@ FASTPythonImporterTest >> testAssertStatement [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('!=') + self assert: self topEntity operators asArray equals: #('!=') asArray ] { #category : 'tests - statements' } @@ -1444,7 +1445,7 @@ FASTPythonImporterTest >> testAssignmentToComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - assignments' } @@ -2877,7 +2878,7 @@ FASTPythonImporterTest >> testAttributeAccessOnComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - attributes' } @@ -5021,7 +5022,7 @@ FASTPythonImporterTest >> testBinaryOperatorWithComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>' '>') + self assert: self topEntity operators asArray equals: #('>' '>') asArray ] { #category : 'tests - operators' } @@ -6639,7 +6640,7 @@ FASTPythonImporterTest >> testBooleanOperatorWithComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. self assert: self topEntity operator equals: 'and'. @@ -6666,7 +6667,7 @@ FASTPythonImporterTest >> testBooleanOperatorWithComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - operators' } @@ -7787,7 +7788,7 @@ FASTPythonImporterTest >> testCalWithArgumentComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation callee" @@ -9320,7 +9321,7 @@ FASTPythonImporterTest >> testCallArgumentWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'resize'. stack pop. - self assert: self topEntity operators equals: #('!='). + self assert: self topEntity operators asArray equals: #('!=') asArray. stack pop. "Testing value of monovalue relation callee" @@ -9697,7 +9698,7 @@ FASTPythonImporterTest >> testCallLambda [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of multivalued relation parameters" @@ -10864,7 +10865,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithAttribute [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -10920,7 +10921,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithBinaryOperator [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -10973,7 +10974,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithBooleanOperator [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11018,7 +11019,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithCall [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11053,7 +11054,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithComplexe [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11107,7 +11108,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithConditionalExpression [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is'). + self assert: self topEntity operators asArray equals: #('is') asArray. stack pop. "Testing value of monovalue relation thenExpression" @@ -11179,7 +11180,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithDictionary [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11213,7 +11214,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithEllipsis [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11248,7 +11249,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithFalse [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11283,7 +11284,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithFloat [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11317,7 +11318,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithIdentifier [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11352,7 +11353,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithInteger [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11385,7 +11386,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithList [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11419,7 +11420,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithNone [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11462,7 +11463,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithNotOperator [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11506,7 +11507,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithSet [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11541,7 +11542,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithString [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11595,7 +11596,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithSubscript [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11630,7 +11631,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithTrue [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11679,7 +11680,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithTuple [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - operators' } @@ -11725,7 +11726,7 @@ FASTPythonImporterTest >> testComparisonOperatorWithUnaryOperator [ self assert: (self topEntity isOfType: FASTPyEllipsis). self assert: (self topEntity isOfType: FASTTLiteral). stack pop. - self assert: self topEntity operators equals: #('is') + self assert: self topEntity operators asArray equals: #('is') asArray ] { #category : 'tests - literals' } @@ -11861,7 +11862,7 @@ FASTPythonImporterTest >> testConditionalExpression [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of monovalue relation elseExpression" @@ -12232,7 +12233,7 @@ FASTPythonImporterTest >> testConditionalExpressionWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation thenExpression" @@ -12256,7 +12257,7 @@ FASTPythonImporterTest >> testConditionalExpressionWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - conditional expressions' } @@ -12592,7 +12593,7 @@ FASTPythonImporterTest >> testConditionalExpressionWithConditionComparisonOperat self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation elseExpression" @@ -15969,7 +15970,7 @@ FASTPythonImporterTest >> testDefaultParameterWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. self assert: self topEntity name equals: 'x'. stack pop. @@ -17909,7 +17910,7 @@ FASTPythonImporterTest >> testDefaultTypedParameterWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. self assert: self topEntity name equals: 'x'. @@ -20225,7 +20226,7 @@ FASTPythonImporterTest >> testDictionaryComprehensionWithIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -21209,7 +21210,7 @@ FASTPythonImporterTest >> testDictionaryWithComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - collections' } @@ -22738,7 +22739,7 @@ except Exception if n > 1 else Error: pass' withPlatformLineEndings. self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation elseExpression" @@ -23635,7 +23636,7 @@ FASTPythonImporterTest >> testFromImport [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'datetime'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('datetime'). + self assert: self topEntity segments asArray equals: #('datetime') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23644,7 +23645,7 @@ FASTPythonImporterTest >> testFromImport [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'date'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('date') + self assert: self topEntity segments asArray equals: #('date') asArray ] { #category : 'tests - imports' } @@ -23670,7 +23671,7 @@ FASTPythonImporterTest >> testFromImportMultiple [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'collections'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('collections'). + self assert: self topEntity segments asArray equals: #('collections') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23679,13 +23680,13 @@ FASTPythonImporterTest >> testFromImportMultiple [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'Counter'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('Counter'). + self assert: self topEntity segments asArray equals: #('Counter') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'defaultdic'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('defaultdic') + self assert: self topEntity segments asArray equals: #('defaultdic') asArray ] { #category : 'tests - imports' } @@ -23711,7 +23712,7 @@ FASTPythonImporterTest >> testFromImportMultipleWithAlias [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'math'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('math'). + self assert: self topEntity segments asArray equals: #('math') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23720,20 +23721,20 @@ FASTPythonImporterTest >> testFromImportMultipleWithAlias [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'sin'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('sin'). + self assert: self topEntity segments asArray equals: #('sin') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'cos as cosinus'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'cosinus'. - self assert: self topEntity segments equals: #('cos'). + self assert: self topEntity segments asArray equals: #('cos') asArray. stack pop. stack push: (stack top importedEntities at: 3). self assert: self topEntity sourceCode equals: 'pi'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('pi') + self assert: self topEntity segments asArray equals: #('pi') asArray ] { #category : 'tests - imports' } @@ -23759,7 +23760,7 @@ FASTPythonImporterTest >> testFromImportMultipleWithParenthesis [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'math'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('math'). + self assert: self topEntity segments asArray equals: #('math') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23768,19 +23769,19 @@ FASTPythonImporterTest >> testFromImportMultipleWithParenthesis [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'count'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('count'). + self assert: self topEntity segments asArray equals: #('count') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'cycle'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('cycle'). + self assert: self topEntity segments asArray equals: #('cycle') asArray. stack pop. stack push: (stack top importedEntities at: 3). self assert: self topEntity sourceCode equals: 'repeat'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('repeat') + self assert: self topEntity segments asArray equals: #('repeat') asArray ] { #category : 'tests - imports' } @@ -23806,7 +23807,7 @@ FASTPythonImporterTest >> testFromImportMultipleWithParenthesisAndAlias [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'math'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('math'). + self assert: self topEntity segments asArray equals: #('math') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23815,20 +23816,20 @@ FASTPythonImporterTest >> testFromImportMultipleWithParenthesisAndAlias [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'count'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('count'). + self assert: self topEntity segments asArray equals: #('count') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'cycle as c'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'c'. - self assert: self topEntity segments equals: #('cycle'). + self assert: self topEntity segments asArray equals: #('cycle') asArray. stack pop. stack push: (stack top importedEntities at: 3). self assert: self topEntity sourceCode equals: 'repeat'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('repeat') + self assert: self topEntity segments asArray equals: #('repeat') asArray ] { #category : 'tests - imports' } @@ -23854,7 +23855,7 @@ FASTPythonImporterTest >> testFromImportRelative [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: '..'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('..' 'utils' 'extra'). + self assert: self topEntity segments asArray equals: #('..' 'utils' 'extra') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23863,7 +23864,7 @@ FASTPythonImporterTest >> testFromImportRelative [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'module'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('module') + self assert: self topEntity segments asArray equals: #('module') asArray ] { #category : 'tests - imports' } @@ -23889,7 +23890,7 @@ FASTPythonImporterTest >> testFromImportRelativeWithAlias [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: '..'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('..' 'utils'). + self assert: self topEntity segments asArray equals: #('..' 'utils') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23899,7 +23900,7 @@ FASTPythonImporterTest >> testFromImportRelativeWithAlias [ self assert: self topEntity sourceCode equals: 'module as mod'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'mod'. - self assert: self topEntity segments equals: #('module') + self assert: self topEntity segments asArray equals: #('module') asArray ] { #category : 'tests - imports' } @@ -23925,7 +23926,7 @@ FASTPythonImporterTest >> testFromImportRelativeWithDoubleDot [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: '..'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('..'). + self assert: self topEntity segments asArray equals: #('..') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23934,7 +23935,7 @@ FASTPythonImporterTest >> testFromImportRelativeWithDoubleDot [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'module'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('module') + self assert: self topEntity segments asArray equals: #('module') asArray ] { #category : 'tests - imports' } @@ -23960,7 +23961,7 @@ FASTPythonImporterTest >> testFromImportRelativeWithOnlyOneDot [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: '.'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('.'). + self assert: self topEntity segments asArray equals: #('.') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -23969,7 +23970,7 @@ FASTPythonImporterTest >> testFromImportRelativeWithOnlyOneDot [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'module'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('module') + self assert: self topEntity segments asArray equals: #('module') asArray ] { #category : 'tests - imports' } @@ -23995,7 +23996,7 @@ FASTPythonImporterTest >> testFromImportWithAlias [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'datetime'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('datetime'). + self assert: self topEntity segments asArray equals: #('datetime') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -24005,7 +24006,7 @@ FASTPythonImporterTest >> testFromImportWithAlias [ self assert: self topEntity sourceCode equals: 'date as d'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'd'. - self assert: self topEntity segments equals: #('date') + self assert: self topEntity segments asArray equals: #('date') asArray ] { #category : 'tests - imports' } @@ -24031,7 +24032,7 @@ FASTPythonImporterTest >> testFromImportWithWildcard [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'math'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('math'). + self assert: self topEntity segments asArray equals: #('math') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -24040,7 +24041,7 @@ FASTPythonImporterTest >> testFromImportWithWildcard [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: '*'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('*') + self assert: self topEntity segments asArray equals: #('*') asArray ] { #category : 'tests - function definitions' } @@ -24158,7 +24159,7 @@ FASTPythonImporterTest >> testFutureImport [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'from __future__ import annotiations as ann, division'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('__future__'). + self assert: self topEntity segments asArray equals: #('__future__') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -24168,13 +24169,13 @@ FASTPythonImporterTest >> testFutureImport [ self assert: self topEntity sourceCode equals: 'annotiations as ann'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'ann'. - self assert: self topEntity segments equals: #('annotiations'). + self assert: self topEntity segments asArray equals: #('annotiations') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'division'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('division') + self assert: self topEntity segments asArray equals: #('division') asArray ] { #category : 'tests - comprehensions' } @@ -24739,7 +24740,7 @@ FASTPythonImporterTest >> testGeneratorExpressionWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'str'. stack pop. - self assert: self topEntity operators equals: #('in'). + self assert: self topEntity operators asArray equals: #('in') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -25531,7 +25532,7 @@ FASTPythonImporterTest >> testGeneratorExpressionWithIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -26109,7 +26110,7 @@ FASTPythonImporterTest >> testGeneratorExpressionWithMultipleIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. stack push: (stack top conditions at: 2). @@ -26151,7 +26152,7 @@ FASTPythonImporterTest >> testGeneratorExpressionWithMultipleIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -27349,7 +27350,7 @@ FASTPythonImporterTest >> testIf [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation thenClause" @@ -27422,7 +27423,7 @@ else: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation elseClause" @@ -27514,7 +27515,7 @@ elif x < 10: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of multivalued relation elifClauses" @@ -27550,7 +27551,7 @@ elif x < 10: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('<'). + self assert: self topEntity operators asArray equals: #('<') asArray. stack pop. "Testing value of multivalued relation statements" @@ -27638,7 +27639,7 @@ elif x == 60: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of multivalued relation elifClauses" @@ -27674,7 +27675,7 @@ elif x == 60: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('<'). + self assert: self topEntity operators asArray equals: #('<') asArray. stack pop. "Testing value of multivalued relation statements" @@ -27718,7 +27719,7 @@ elif x == 60: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of multivalued relation statements" @@ -27811,7 +27812,7 @@ else: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of multivalued relation elifClauses" @@ -27847,7 +27848,7 @@ else: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('<'). + self assert: self topEntity operators asArray equals: #('<') asArray. stack pop. "Testing value of multivalued relation statements" @@ -27891,7 +27892,7 @@ else: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of multivalued relation statements" @@ -27987,7 +27988,7 @@ FASTPythonImporterTest >> testIfStatementWithABreak [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation thenClause" @@ -28051,7 +28052,7 @@ FASTPythonImporterTest >> testIfStatementWithAContinue [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation thenClause" @@ -28092,7 +28093,7 @@ FASTPythonImporterTest >> testImport [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'random'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('random') + self assert: self topEntity segments asArray equals: #('random') asArray ] { #category : 'tests - imports' } @@ -28117,7 +28118,7 @@ FASTPythonImporterTest >> testImportDottedImport [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'xml.etree.ElementTree'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('xml' 'etree' 'ElementTree') + self assert: self topEntity segments asArray equals: #('xml' 'etree' 'ElementTree') asArray ] { #category : 'tests - imports' } @@ -28143,7 +28144,7 @@ FASTPythonImporterTest >> testImportDottedImportAndAlias [ self assert: self topEntity sourceCode equals: 'xml.etree.ElementTree as ET'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'ET'. - self assert: self topEntity segments equals: #('xml' 'etree' 'ElementTree') + self assert: self topEntity segments asArray equals: #('xml' 'etree' 'ElementTree') asArray ] { #category : 'tests - imports' } @@ -28171,7 +28172,7 @@ FASTPythonImporterTest >> testImportFromWithLineContinuation [ stack push: self topEntity fromModule. self assert: self topEntity sourceCode equals: 'distutils.ccompiler'. self assert: (self topEntity isOfType: FASTPyFromModule). - self assert: self topEntity segments equals: #('distutils' 'ccompiler'). + self assert: self topEntity segments asArray equals: #('distutils' 'ccompiler') asArray. stack pop. "Testing value of multivalued relation importedEntities" @@ -28180,13 +28181,13 @@ FASTPythonImporterTest >> testImportFromWithLineContinuation [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'CCompiler'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('CCompiler'). + self assert: self topEntity segments asArray equals: #('CCompiler') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'gen_preprocess_options'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('gen_preprocess_options') + self assert: self topEntity segments asArray equals: #('gen_preprocess_options') asArray ] { #category : 'tests - imports' } @@ -28231,7 +28232,7 @@ FASTPythonImporterTest >> testImportInFunction [ self assert: self topEntity sourceCode equals: 'numpy as np'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'np'. - self assert: self topEntity segments equals: #('numpy'). + self assert: self topEntity segments asArray equals: #('numpy') asArray. stack pop. stack pop. @@ -28280,13 +28281,13 @@ FASTPythonImporterTest >> testImportMultiple [ stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'random'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('random'). + self assert: self topEntity segments asArray equals: #('random') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'collections'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('collections') + self assert: self topEntity segments asArray equals: #('collections') asArray ] { #category : 'tests - imports' } @@ -28312,13 +28313,13 @@ FASTPythonImporterTest >> testImportMultipleAndAliases [ self assert: self topEntity sourceCode equals: 'random as rand'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'rand'. - self assert: self topEntity segments equals: #('random'). + self assert: self topEntity segments asArray equals: #('random') asArray. stack pop. stack push: (stack top importedEntities at: 2). self assert: self topEntity sourceCode equals: 'collections'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('collections') + self assert: self topEntity segments asArray equals: #('collections') asArray ] { #category : 'tests - imports' } @@ -28344,7 +28345,7 @@ FASTPythonImporterTest >> testImportWithAlias [ self assert: self topEntity sourceCode equals: 'random as rand'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'rand'. - self assert: self topEntity segments equals: #('random') + self assert: self topEntity segments asArray equals: #('random') asArray ] { #category : 'tests - imports' } @@ -28381,7 +28382,7 @@ mathplotlib' withPlatformLineEndings. stack push: (stack top importedEntities at: 1). self assert: self topEntity sourceCode equals: 'mathplotlib'. self assert: (self topEntity isOfType: FASTPyImportedEntity). - self assert: self topEntity segments equals: #('mathplotlib') + self assert: self topEntity segments asArray equals: #('mathplotlib') asArray ] { #category : 'tests - literals' } @@ -28705,7 +28706,7 @@ FASTPythonImporterTest >> testInterpolationWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('==') + self assert: self topEntity operators asArray equals: #('==') asArray ] { #category : 'tests - interpolations' } @@ -29393,7 +29394,7 @@ FASTPythonImporterTest >> testKeywordArgumentToComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. stack pop. @@ -31890,7 +31891,7 @@ FASTPythonImporterTest >> testListComprehensionWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'str'. stack pop. - self assert: self topEntity operators equals: #('in'). + self assert: self topEntity operators asArray equals: #('in') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -32682,7 +32683,7 @@ FASTPythonImporterTest >> testListComprehensionWithIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -33259,7 +33260,7 @@ FASTPythonImporterTest >> testListComprehensionWithMultipleIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. stack push: (stack top conditions at: 2). @@ -33301,7 +33302,7 @@ FASTPythonImporterTest >> testListComprehensionWithMultipleIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -35148,7 +35149,7 @@ FASTPythonImporterTest >> testListWithComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - collections' } @@ -36852,7 +36853,7 @@ FASTPythonImporterTest >> testMatchPatternDictionaryWithDictionary [ stack push: self topEntity value. self assert: self topEntity sourceCode equals: 'name'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('name'). + self assert: self topEntity identifiers asArray equals: #('name') asArray. stack pop. stack pop. stack pop. @@ -37132,7 +37133,7 @@ FASTPythonImporterTest >> testMatchPatternDictionaryWithVariables [ stack push: self topEntity value. self assert: self topEntity sourceCode equals: 'host'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('host'). + self assert: self topEntity identifiers asArray equals: #('host') asArray. stack pop. stack pop. @@ -37156,7 +37157,7 @@ FASTPythonImporterTest >> testMatchPatternDictionaryWithVariables [ stack push: self topEntity value. self assert: self topEntity sourceCode equals: 'port'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('port'). + self assert: self topEntity identifiers asArray equals: #('port') asArray. stack pop. stack pop. stack pop. @@ -37215,7 +37216,7 @@ FASTPythonImporterTest >> testMatchPatternDottedName [ stack push: self topEntity pattern. self assert: self topEntity sourceCode equals: 'Status.OK'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('Status' 'OK'). + self assert: self topEntity identifiers asArray equals: #('Status' 'OK') asArray. stack pop. "Testing value of multivalued relation statements" @@ -37531,7 +37532,7 @@ FASTPythonImporterTest >> testMatchPatternKeywordWithClass [ stack push: (stack top elements at: 1). self assert: self topEntity sourceCode equals: 'AClass'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('AClass'). + self assert: self topEntity identifiers asArray equals: #('AClass') asArray. stack pop. stack pop. stack pop. @@ -37689,7 +37690,7 @@ FASTPythonImporterTest >> testMatchPatternKeywordWithDottedName [ stack push: self topEntity value. self assert: self topEntity sourceCode equals: 'x.y'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('x' 'y'). + self assert: self topEntity identifiers asArray equals: #('x' 'y') asArray. stack pop. stack pop. @@ -37756,7 +37757,7 @@ FASTPythonImporterTest >> testMatchPatternKeywordWithIdentifier [ stack push: self topEntity value. self assert: self topEntity sourceCode equals: 'x'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('x'). + self assert: self topEntity identifiers asArray equals: #('x') asArray. stack pop. stack pop. @@ -38914,7 +38915,7 @@ FASTPythonImporterTest >> testMatchPatternUnionClassPattern [ stack push: (stack top elements at: 1). self assert: self topEntity sourceCode equals: 'AClass'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('AClass'). + self assert: self topEntity identifiers asArray equals: #('AClass') asArray. stack pop. stack pop. @@ -39091,7 +39092,7 @@ FASTPythonImporterTest >> testMatchPatternUnionDottedName [ stack push: (stack top members at: 1). self assert: self topEntity sourceCode equals: 'x.y'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('x' 'y'). + self assert: self topEntity identifiers asArray equals: #('x' 'y') asArray. stack pop. stack push: (stack top members at: 2). @@ -39323,7 +39324,7 @@ FASTPythonImporterTest >> testMatchPatternWithAlias [ stack push: self topEntity pattern. self assert: self topEntity sourceCode equals: 'x'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('x'). + self assert: self topEntity identifiers asArray equals: #('x') asArray. stack pop. "Testing value of multivalued relation statements" @@ -39398,7 +39399,7 @@ FASTPythonImporterTest >> testMatchPatternWithGuard [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation pattern" @@ -39407,7 +39408,7 @@ FASTPythonImporterTest >> testMatchPatternWithGuard [ stack push: self topEntity pattern. self assert: self topEntity sourceCode equals: 'n'. self assert: (self topEntity isOfType: FASTPyDottedName). - self assert: self topEntity identifiers equals: #('n'). + self assert: self topEntity identifiers asArray equals: #('n') asArray. stack pop. "Testing value of multivalued relation statements" @@ -39829,7 +39830,7 @@ else: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of monovalue relation elseClause" @@ -39897,7 +39898,7 @@ else: self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('<'). + self assert: self topEntity operators asArray equals: #('<') asArray. stack pop. "Testing value of monovalue relation elseClause" @@ -40322,7 +40323,7 @@ FASTPythonImporterTest >> testNotOperatorWithComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - operators' } @@ -41476,7 +41477,7 @@ FASTPythonImporterTest >> testReturnOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - collections' } @@ -42059,7 +42060,7 @@ FASTPythonImporterTest >> testSetComprehensionWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'str'. stack pop. - self assert: self topEntity operators equals: #('in'). + self assert: self topEntity operators asArray equals: #('in') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -42852,7 +42853,7 @@ FASTPythonImporterTest >> testSetComprehensionWithIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -43428,7 +43429,7 @@ FASTPythonImporterTest >> testSetComprehensionWithMultipleIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. stack push: (stack top conditions at: 2). @@ -43470,7 +43471,7 @@ FASTPythonImporterTest >> testSetComprehensionWithMultipleIfClause [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('=='). + self assert: self topEntity operators asArray equals: #('==') asArray. stack pop. "Testing value of multivalued relation forClauses" @@ -44502,7 +44503,7 @@ FASTPythonImporterTest >> testSetWithComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - collections' } @@ -48521,7 +48522,7 @@ FASTPythonImporterTest >> testTupleWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - collections' } @@ -49514,7 +49515,7 @@ import mathplotlib as mpl' withPlatformLineEndings. self assert: self topEntity sourceCode equals: 'numpy as np'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'np'. - self assert: self topEntity segments equals: #('numpy'). + self assert: self topEntity segments asArray equals: #('numpy') asArray. stack pop. stack pop. @@ -49529,7 +49530,7 @@ import mathplotlib as mpl' withPlatformLineEndings. self assert: self topEntity sourceCode equals: 'mathplotlib as mpl'. self assert: (self topEntity isOfType: FASTPyImportedEntity). self assert: self topEntity alias equals: 'mpl'. - self assert: self topEntity segments equals: #('mathplotlib') + self assert: self topEntity segments asArray equals: #('mathplotlib') asArray ] { #category : 'tests - statements' } @@ -49879,7 +49880,7 @@ FASTPythonImporterTest >> testTypeComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. stack pop. @@ -51310,7 +51311,7 @@ FASTPythonImporterTest >> testUnaryOperatorWithComparisonOperator [ self assert: (self topEntity isOfType: FASTPyIdentifier). self assert: self topEntity name equals: 'y'. stack pop. - self assert: self topEntity operators equals: #('>'). + self assert: self topEntity operators asArray equals: #('>') asArray. stack pop. self assert: self topEntity operator equals: '~(' ] @@ -52081,7 +52082,7 @@ FASTPythonImporterTest >> testWalrusComparisonOperator [ self assert: (self topEntity isOfType: FASTTLiteral). self assert: (self topEntity isOfType: FASTTNumericalLiteral). stack pop. - self assert: self topEntity operators equals: #('>') + self assert: self topEntity operators asArray equals: #('>') asArray ] { #category : 'tests - assignments' } From b9c5d822ee78c161cac7b4f582cc54e309b9d82d Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Wed, 23 Sep 2026 16:50:44 +0200 Subject: [PATCH 04/15] Swap derived side for relations --- src/FAST-Python-Model/FASTPyAssertStatement.class.st | 1 - src/FAST-Python-Model/FASTPyCaseClause.class.st | 1 + src/FAST-Python-Model/FASTPyClassDefinition.class.st | 2 -- src/FAST-Python-Model/FASTPyClassPattern.class.st | 1 - .../FASTPyCollectionInitializer.class.st | 1 - src/FAST-Python-Model/FASTPyComparisonOperator.class.st | 1 - src/FAST-Python-Model/FASTPyComprehension.class.st | 2 -- src/FAST-Python-Model/FASTPyConcatenatedString.class.st | 1 - src/FAST-Python-Model/FASTPyDecorator.class.st | 1 + src/FAST-Python-Model/FASTPyElifClause.class.st | 1 + src/FAST-Python-Model/FASTPyExceptClause.class.st | 1 + src/FAST-Python-Model/FASTPyExecStatement.class.st | 1 - src/FAST-Python-Model/FASTPyExpression.class.st | 8 ++++++++ src/FAST-Python-Model/FASTPyGenericType.class.st | 1 - src/FAST-Python-Model/FASTPyGlobalStatement.class.st | 1 - src/FAST-Python-Model/FASTPyIfStatement.class.st | 1 - src/FAST-Python-Model/FASTPyImport.class.st | 1 - src/FAST-Python-Model/FASTPyImportedEntity.class.st | 1 + src/FAST-Python-Model/FASTPyInterpolation.class.st | 1 + src/FAST-Python-Model/FASTPyKeywordArgument.class.st | 1 + src/FAST-Python-Model/FASTPyMatchStatement.class.st | 1 - src/FAST-Python-Model/FASTPyNonlocalStatement.class.st | 1 - src/FAST-Python-Model/FASTPyPrintStatement.class.st | 1 - src/FAST-Python-Model/FASTPySlice.class.st | 1 - src/FAST-Python-Model/FASTPyString.class.st | 2 +- src/FAST-Python-Model/FASTPySubscript.class.st | 1 - src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st | 1 + src/FAST-Python-Model/FASTPyTDefinition.trait.st | 1 - src/FAST-Python-Model/FASTPyTPattern.trait.st | 1 + src/FAST-Python-Model/FASTPyTSliceIndex.trait.st | 1 + src/FAST-Python-Model/FASTPyTSuperclass.trait.st | 1 + src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st | 1 + src/FAST-Python-Model/FASTPyTWithTypeParameters.trait.st | 1 - src/FAST-Python-Model/FASTPyTryStatement.class.st | 1 - src/FAST-Python-Model/FASTPyType.class.st | 3 +++ src/FAST-Python-Model/FASTPyUnionPattern.class.st | 1 - src/FAST-Python-Model/FASTPyUnionType.class.st | 1 - src/FAST-Python-Model/FASTPyVariable.class.st | 2 ++ src/FAST-Python-Model/FASTPyWithStatement.class.st | 1 - 39 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/FAST-Python-Model/FASTPyAssertStatement.class.st b/src/FAST-Python-Model/FASTPyAssertStatement.class.st index b60f224..24cfe6c 100644 --- a/src/FAST-Python-Model/FASTPyAssertStatement.class.st +++ b/src/FAST-Python-Model/FASTPyAssertStatement.class.st @@ -47,7 +47,6 @@ FASTPyAssertStatement >> expressions [ - ^ expressions ] diff --git a/src/FAST-Python-Model/FASTPyCaseClause.class.st b/src/FAST-Python-Model/FASTPyCaseClause.class.st index 43572aa..83ed0dc 100644 --- a/src/FAST-Python-Model/FASTPyCaseClause.class.st +++ b/src/FAST-Python-Model/FASTPyCaseClause.class.st @@ -78,6 +78,7 @@ FASTPyCaseClause >> parentMatchStatement [ + ^ parentMatchStatement ] diff --git a/src/FAST-Python-Model/FASTPyClassDefinition.class.st b/src/FAST-Python-Model/FASTPyClassDefinition.class.st index f68afad..24caf4d 100644 --- a/src/FAST-Python-Model/FASTPyClassDefinition.class.st +++ b/src/FAST-Python-Model/FASTPyClassDefinition.class.st @@ -85,7 +85,6 @@ FASTPyClassDefinition >> keywords [ - ^ keywords ] @@ -103,7 +102,6 @@ FASTPyClassDefinition >> superclasses [ - ^ superclasses ] diff --git a/src/FAST-Python-Model/FASTPyClassPattern.class.st b/src/FAST-Python-Model/FASTPyClassPattern.class.st index 8bea2a1..f45859f 100644 --- a/src/FAST-Python-Model/FASTPyClassPattern.class.st +++ b/src/FAST-Python-Model/FASTPyClassPattern.class.st @@ -55,7 +55,6 @@ FASTPyClassPattern >> elements [ - ^ elements ] diff --git a/src/FAST-Python-Model/FASTPyCollectionInitializer.class.st b/src/FAST-Python-Model/FASTPyCollectionInitializer.class.st index ac48d8c..af5fab0 100644 --- a/src/FAST-Python-Model/FASTPyCollectionInitializer.class.st +++ b/src/FAST-Python-Model/FASTPyCollectionInitializer.class.st @@ -57,7 +57,6 @@ FASTPyCollectionInitializer >> initializers [ - ^ initializers ] diff --git a/src/FAST-Python-Model/FASTPyComparisonOperator.class.st b/src/FAST-Python-Model/FASTPyComparisonOperator.class.st index 6788d8d..8f79296 100644 --- a/src/FAST-Python-Model/FASTPyComparisonOperator.class.st +++ b/src/FAST-Python-Model/FASTPyComparisonOperator.class.st @@ -52,7 +52,6 @@ FASTPyComparisonOperator >> operands [ - ^ operands ] diff --git a/src/FAST-Python-Model/FASTPyComprehension.class.st b/src/FAST-Python-Model/FASTPyComprehension.class.st index 7b78ccd..9b37448 100644 --- a/src/FAST-Python-Model/FASTPyComprehension.class.st +++ b/src/FAST-Python-Model/FASTPyComprehension.class.st @@ -91,7 +91,6 @@ FASTPyComprehension >> conditions [ - ^ conditions ] @@ -109,7 +108,6 @@ FASTPyComprehension >> forClauses [ - ^ forClauses ] diff --git a/src/FAST-Python-Model/FASTPyConcatenatedString.class.st b/src/FAST-Python-Model/FASTPyConcatenatedString.class.st index 880fcf3..cd89e51 100644 --- a/src/FAST-Python-Model/FASTPyConcatenatedString.class.st +++ b/src/FAST-Python-Model/FASTPyConcatenatedString.class.st @@ -44,7 +44,6 @@ FASTPyConcatenatedString >> strings [ - ^ strings ] diff --git a/src/FAST-Python-Model/FASTPyDecorator.class.st b/src/FAST-Python-Model/FASTPyDecorator.class.st index 5c3f605..dfaa092 100644 --- a/src/FAST-Python-Model/FASTPyDecorator.class.st +++ b/src/FAST-Python-Model/FASTPyDecorator.class.st @@ -62,6 +62,7 @@ FASTPyDecorator >> parentDefinition [ + ^ parentDefinition ] diff --git a/src/FAST-Python-Model/FASTPyElifClause.class.st b/src/FAST-Python-Model/FASTPyElifClause.class.st index a4e23ea..ed5662d 100644 --- a/src/FAST-Python-Model/FASTPyElifClause.class.st +++ b/src/FAST-Python-Model/FASTPyElifClause.class.st @@ -55,6 +55,7 @@ FASTPyElifClause >> parentIfStatement [ + ^ parentIfStatement ] diff --git a/src/FAST-Python-Model/FASTPyExceptClause.class.st b/src/FAST-Python-Model/FASTPyExceptClause.class.st index e2b3189..ce96c89 100644 --- a/src/FAST-Python-Model/FASTPyExceptClause.class.st +++ b/src/FAST-Python-Model/FASTPyExceptClause.class.st @@ -92,6 +92,7 @@ FASTPyExceptClause >> parentTryStatement [ + ^ parentTryStatement ] diff --git a/src/FAST-Python-Model/FASTPyExecStatement.class.st b/src/FAST-Python-Model/FASTPyExecStatement.class.st index b0110c3..3f7658a 100644 --- a/src/FAST-Python-Model/FASTPyExecStatement.class.st +++ b/src/FAST-Python-Model/FASTPyExecStatement.class.st @@ -63,7 +63,6 @@ FASTPyExecStatement >> scopes [ - ^ scopes ] diff --git a/src/FAST-Python-Model/FASTPyExpression.class.st b/src/FAST-Python-Model/FASTPyExpression.class.st index a3f7074..7b3e41a 100644 --- a/src/FAST-Python-Model/FASTPyExpression.class.st +++ b/src/FAST-Python-Model/FASTPyExpression.class.st @@ -146,6 +146,7 @@ FASTPyExpression >> collectionInitializer [ + ^ collectionInitializer ] @@ -183,6 +184,7 @@ FASTPyExpression >> parentAssertStatement [ + ^ parentAssertStatement ] @@ -260,6 +262,7 @@ FASTPyExpression >> parentComparisonOperator [ + ^ parentComparisonOperator ] @@ -297,6 +300,7 @@ FASTPyExpression >> parentComprehensionCondition [ + ^ parentComprehensionCondition ] @@ -315,6 +319,7 @@ FASTPyExpression >> parentComprehensionForClause [ + ^ parentComprehensionForClause ] @@ -409,6 +414,7 @@ FASTPyExpression >> parentExecStatementScopes [ + ^ parentExecStatementScopes ] @@ -640,6 +646,7 @@ FASTPyExpression >> parentSlice [ + ^ parentSlice ] @@ -736,6 +743,7 @@ FASTPyExpression >> prarentPrintStatement [ + ^ prarentPrintStatement ] diff --git a/src/FAST-Python-Model/FASTPyGenericType.class.st b/src/FAST-Python-Model/FASTPyGenericType.class.st index f09be7a..57ddb4b 100644 --- a/src/FAST-Python-Model/FASTPyGenericType.class.st +++ b/src/FAST-Python-Model/FASTPyGenericType.class.st @@ -61,7 +61,6 @@ FASTPyGenericType >> arguments [ - ^ arguments ] diff --git a/src/FAST-Python-Model/FASTPyGlobalStatement.class.st b/src/FAST-Python-Model/FASTPyGlobalStatement.class.st index fa55db0..2d7f4b7 100644 --- a/src/FAST-Python-Model/FASTPyGlobalStatement.class.st +++ b/src/FAST-Python-Model/FASTPyGlobalStatement.class.st @@ -45,7 +45,6 @@ FASTPyGlobalStatement >> variables [ - ^ variables ] diff --git a/src/FAST-Python-Model/FASTPyIfStatement.class.st b/src/FAST-Python-Model/FASTPyIfStatement.class.st index 6e9e42c..f4599fa 100644 --- a/src/FAST-Python-Model/FASTPyIfStatement.class.st +++ b/src/FAST-Python-Model/FASTPyIfStatement.class.st @@ -63,7 +63,6 @@ FASTPyIfStatement >> elifClauses [ - ^ elifClauses ] diff --git a/src/FAST-Python-Model/FASTPyImport.class.st b/src/FAST-Python-Model/FASTPyImport.class.st index 988f198..234bcb0 100644 --- a/src/FAST-Python-Model/FASTPyImport.class.st +++ b/src/FAST-Python-Model/FASTPyImport.class.st @@ -45,7 +45,6 @@ FASTPyImport >> importedEntities [ - ^ importedEntities ] diff --git a/src/FAST-Python-Model/FASTPyImportedEntity.class.st b/src/FAST-Python-Model/FASTPyImportedEntity.class.st index 1b5f046..37ba8d8 100644 --- a/src/FAST-Python-Model/FASTPyImportedEntity.class.st +++ b/src/FAST-Python-Model/FASTPyImportedEntity.class.st @@ -70,6 +70,7 @@ FASTPyImportedEntity >> import [ + ^ import ] diff --git a/src/FAST-Python-Model/FASTPyInterpolation.class.st b/src/FAST-Python-Model/FASTPyInterpolation.class.st index e6227d4..14c9c0a 100644 --- a/src/FAST-Python-Model/FASTPyInterpolation.class.st +++ b/src/FAST-Python-Model/FASTPyInterpolation.class.st @@ -86,6 +86,7 @@ FASTPyInterpolation >> parentString [ + ^ parentString ] diff --git a/src/FAST-Python-Model/FASTPyKeywordArgument.class.st b/src/FAST-Python-Model/FASTPyKeywordArgument.class.st index 45ca6de..90d696e 100644 --- a/src/FAST-Python-Model/FASTPyKeywordArgument.class.st +++ b/src/FAST-Python-Model/FASTPyKeywordArgument.class.st @@ -54,6 +54,7 @@ FASTPyKeywordArgument >> parentClassDefinition [ + ^ parentClassDefinition ] diff --git a/src/FAST-Python-Model/FASTPyMatchStatement.class.st b/src/FAST-Python-Model/FASTPyMatchStatement.class.st index 111176d..75b239c 100644 --- a/src/FAST-Python-Model/FASTPyMatchStatement.class.st +++ b/src/FAST-Python-Model/FASTPyMatchStatement.class.st @@ -46,7 +46,6 @@ FASTPyMatchStatement >> cases [ - ^ cases ] diff --git a/src/FAST-Python-Model/FASTPyNonlocalStatement.class.st b/src/FAST-Python-Model/FASTPyNonlocalStatement.class.st index 15b53f6..00eafde 100644 --- a/src/FAST-Python-Model/FASTPyNonlocalStatement.class.st +++ b/src/FAST-Python-Model/FASTPyNonlocalStatement.class.st @@ -45,7 +45,6 @@ FASTPyNonlocalStatement >> variables [ - ^ variables ] diff --git a/src/FAST-Python-Model/FASTPyPrintStatement.class.st b/src/FAST-Python-Model/FASTPyPrintStatement.class.st index 4432467..24eb3a1 100644 --- a/src/FAST-Python-Model/FASTPyPrintStatement.class.st +++ b/src/FAST-Python-Model/FASTPyPrintStatement.class.st @@ -46,7 +46,6 @@ FASTPyPrintStatement >> expressions [ - ^ expressions ] diff --git a/src/FAST-Python-Model/FASTPySlice.class.st b/src/FAST-Python-Model/FASTPySlice.class.st index d792f4d..31ae80d 100644 --- a/src/FAST-Python-Model/FASTPySlice.class.st +++ b/src/FAST-Python-Model/FASTPySlice.class.st @@ -52,7 +52,6 @@ FASTPySlice >> components [ - ^ components ] diff --git a/src/FAST-Python-Model/FASTPyString.class.st b/src/FAST-Python-Model/FASTPyString.class.st index 813659f..a440ed3 100644 --- a/src/FAST-Python-Model/FASTPyString.class.st +++ b/src/FAST-Python-Model/FASTPyString.class.st @@ -70,7 +70,6 @@ FASTPyString >> interpolations [ - ^ interpolations ] @@ -89,6 +88,7 @@ FASTPyString >> parentConcatenatedString [ + ^ parentConcatenatedString ] diff --git a/src/FAST-Python-Model/FASTPySubscript.class.st b/src/FAST-Python-Model/FASTPySubscript.class.st index cad8877..1fdda1f 100644 --- a/src/FAST-Python-Model/FASTPySubscript.class.st +++ b/src/FAST-Python-Model/FASTPySubscript.class.st @@ -64,7 +64,6 @@ FASTPySubscript >> indices [ - ^ indices ] diff --git a/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st b/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st index 1edde42..7d0fa12 100644 --- a/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st +++ b/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st @@ -38,6 +38,7 @@ FASTPyTClassPatternElement >> parentClassPattern [ + ^ parentClassPattern ] diff --git a/src/FAST-Python-Model/FASTPyTDefinition.trait.st b/src/FAST-Python-Model/FASTPyTDefinition.trait.st index 11a9693..1a16054 100644 --- a/src/FAST-Python-Model/FASTPyTDefinition.trait.st +++ b/src/FAST-Python-Model/FASTPyTDefinition.trait.st @@ -62,7 +62,6 @@ FASTPyTDefinition >> decorators [ - ^ decorators ] diff --git a/src/FAST-Python-Model/FASTPyTPattern.trait.st b/src/FAST-Python-Model/FASTPyTPattern.trait.st index 9484594..a37a28e 100644 --- a/src/FAST-Python-Model/FASTPyTPattern.trait.st +++ b/src/FAST-Python-Model/FASTPyTPattern.trait.st @@ -80,6 +80,7 @@ FASTPyTPattern >> parentUnionPattern [ + ^ parentUnionPattern ] diff --git a/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st b/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st index 993cfe2..15acdde 100644 --- a/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st +++ b/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st @@ -39,6 +39,7 @@ FASTPyTSliceIndex >> parentSubscriptIndex [ + ^ parentSubscriptIndex ] diff --git a/src/FAST-Python-Model/FASTPyTSuperclass.trait.st b/src/FAST-Python-Model/FASTPyTSuperclass.trait.st index 7b14d62..7b1ddb0 100644 --- a/src/FAST-Python-Model/FASTPyTSuperclass.trait.st +++ b/src/FAST-Python-Model/FASTPyTSuperclass.trait.st @@ -38,6 +38,7 @@ FASTPyTSuperclass >> parentClassDefinition [ + ^ parentClassDefinition ] diff --git a/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st b/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st index 8b3132f..8b45bef 100644 --- a/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st +++ b/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st @@ -38,6 +38,7 @@ FASTPyTWithStatementItem >> parentWithStatementItem [ + ^ parentWithStatementItem ] diff --git a/src/FAST-Python-Model/FASTPyTWithTypeParameters.trait.st b/src/FAST-Python-Model/FASTPyTWithTypeParameters.trait.st index 7b76ab3..fcb8efa 100644 --- a/src/FAST-Python-Model/FASTPyTWithTypeParameters.trait.st +++ b/src/FAST-Python-Model/FASTPyTWithTypeParameters.trait.st @@ -45,7 +45,6 @@ FASTPyTWithTypeParameters >> typeParameters [ - ^ typeParameters ] diff --git a/src/FAST-Python-Model/FASTPyTryStatement.class.st b/src/FAST-Python-Model/FASTPyTryStatement.class.st index 21cf2ce..beed60c 100644 --- a/src/FAST-Python-Model/FASTPyTryStatement.class.st +++ b/src/FAST-Python-Model/FASTPyTryStatement.class.st @@ -64,7 +64,6 @@ FASTPyTryStatement >> excepts [ - ^ excepts ] diff --git a/src/FAST-Python-Model/FASTPyType.class.st b/src/FAST-Python-Model/FASTPyType.class.st index 8a449f6..93c067b 100644 --- a/src/FAST-Python-Model/FASTPyType.class.st +++ b/src/FAST-Python-Model/FASTPyType.class.st @@ -156,6 +156,7 @@ FASTPyType >> parentGenericTypeArgument [ + ^ parentGenericTypeArgument ] @@ -212,6 +213,7 @@ FASTPyType >> parentUnionType [ + ^ parentUnionType ] @@ -230,6 +232,7 @@ FASTPyType >> parentWithTypeParameters [ + ^ parentWithTypeParameters ] diff --git a/src/FAST-Python-Model/FASTPyUnionPattern.class.st b/src/FAST-Python-Model/FASTPyUnionPattern.class.st index 7b92408..271e2ee 100644 --- a/src/FAST-Python-Model/FASTPyUnionPattern.class.st +++ b/src/FAST-Python-Model/FASTPyUnionPattern.class.st @@ -53,7 +53,6 @@ FASTPyUnionPattern >> members [ - ^ members ] diff --git a/src/FAST-Python-Model/FASTPyUnionType.class.st b/src/FAST-Python-Model/FASTPyUnionType.class.st index 9bcaa11..0ede2ff 100644 --- a/src/FAST-Python-Model/FASTPyUnionType.class.st +++ b/src/FAST-Python-Model/FASTPyUnionType.class.st @@ -51,7 +51,6 @@ FASTPyUnionType >> types [ - ^ types ] diff --git a/src/FAST-Python-Model/FASTPyVariable.class.st b/src/FAST-Python-Model/FASTPyVariable.class.st index 4549cf7..8bce9f3 100644 --- a/src/FAST-Python-Model/FASTPyVariable.class.st +++ b/src/FAST-Python-Model/FASTPyVariable.class.st @@ -54,6 +54,7 @@ FASTPyVariable >> parentGlobalStatement [ + ^ parentGlobalStatement ] @@ -73,6 +74,7 @@ FASTPyVariable >> parentNonlocalStatement [ + ^ parentNonlocalStatement ] diff --git a/src/FAST-Python-Model/FASTPyWithStatement.class.st b/src/FAST-Python-Model/FASTPyWithStatement.class.st index 68f6233..18ef2b2 100644 --- a/src/FAST-Python-Model/FASTPyWithStatement.class.st +++ b/src/FAST-Python-Model/FASTPyWithStatement.class.st @@ -61,7 +61,6 @@ FASTPyWithStatement >> items [ - ^ items ] From 634d366d846c3c0102f908637ce0c469f6e8920d Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Fri, 25 Sep 2026 16:05:56 +0200 Subject: [PATCH 05/15] FIx two exporter tests that were flacky (used the order of elements in a set..) --- .../FASTPythonImporterTest.class.st | 101 +++++++++++++----- 1 file changed, 76 insertions(+), 25 deletions(-) diff --git a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st index b91869e..9842055 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st @@ -4657,47 +4657,98 @@ FASTPythonImporterTest >> testAwaitSubscript [ { #category : 'tests - operators' } FASTPythonImporterTest >> testBinaryOperator [ + + "Generated as regression test by TSFASTImporterTestGenerator>>#generateTestNamed:fromCode:protocol: + Regenerate executing: self regenerateTest: #testBinaryOperator " - | operator | self parse: '40 + 2'. - self assert: (fast allWithType: FASTPyModule) size equals: 1. self assert: (fast allWithType: FASTPyBinaryOperator) size equals: 1. + self assert: (fast allWithType: FASTPyInteger) size equals: 2. + self assert: (fast allWithType: FASTPyModule) size equals: 1. - operator := (fast allWithType: FASTPyBinaryOperator) anyOne. - self assert: operator sourceCode equals: '40 + 2'. - self assert: (operator isOfType: FASTTBinaryExpression). - self assert: operator leftOperand sourceCode equals: '40'. - self assert: (operator leftOperand isOfType: FASTPyInteger). - self assert: operator rightOperand sourceCode equals: '2'. - self assert: (operator rightOperand isOfType: FASTPyInteger). - self assert: operator operator equals: '+' + stack push: fast rootEntities anyOne containedEntities first. + self assert: self topEntity sourceCode equals: '40 + 2'. + self assert: (self topEntity isOfType: FASTPyBinaryOperator). + self assert: (self topEntity isOfType: FASTTBinaryExpression). + + "Testing value of monovalue relation leftOperand" + self assert: self topEntity leftOperand isNotNil. + + stack push: self topEntity leftOperand. + self assert: self topEntity sourceCode equals: '40'. + self assert: (self topEntity isOfType: FASTPyInteger). + self assert: (self topEntity isOfType: FASTTLiteral). + self assert: (self topEntity isOfType: FASTTNumericalLiteral). + stack pop. + self assert: self topEntity operator equals: '+'. + + "Testing value of monovalue relation rightOperand" + self assert: self topEntity rightOperand isNotNil. + + stack push: self topEntity rightOperand. + self assert: self topEntity sourceCode equals: '2'. + self assert: (self topEntity isOfType: FASTPyInteger). + self assert: (self topEntity isOfType: FASTTLiteral). + self assert: (self topEntity isOfType: FASTTNumericalLiteral) ] { #category : 'tests - operators' } FASTPythonImporterTest >> testBinaryOperatorInBinaryOperator [ + + "Generated as regression test by TSFASTImporterTestGenerator>>#generateTestNamed:fromCode:protocol: + Regenerate executing: self regenerateTest: #testBinaryOperatorInBinaryOperator " - | operator left | self parse: '40 + 2 - 0'. - self assert: (fast allWithType: FASTPyModule) size equals: 1. self assert: (fast allWithType: FASTPyBinaryOperator) size equals: 2. + self assert: (fast allWithType: FASTPyInteger) size equals: 3. + self assert: (fast allWithType: FASTPyModule) size equals: 1. - operator := (fast allWithType: FASTPyBinaryOperator) anyOne. - self assert: operator sourceCode equals: '40 + 2 - 0'. - self assert: (operator isOfType: FASTTBinaryExpression). + stack push: fast rootEntities anyOne containedEntities first. + self assert: self topEntity sourceCode equals: '40 + 2 - 0'. + self assert: (self topEntity isOfType: FASTPyBinaryOperator). + self assert: (self topEntity isOfType: FASTTBinaryExpression). + + "Testing value of monovalue relation leftOperand" + self assert: self topEntity leftOperand isNotNil. - self assert: operator operator equals: '-'. - self assert: operator rightOperand sourceCode equals: '0'. - self assert: (operator rightOperand isOfType: FASTPyInteger). + stack push: self topEntity leftOperand. + self assert: self topEntity sourceCode equals: '40 + 2'. + self assert: (self topEntity isOfType: FASTPyBinaryOperator). + self assert: (self topEntity isOfType: FASTTBinaryExpression). + + "Testing value of monovalue relation leftOperand" + self assert: self topEntity leftOperand isNotNil. - left := operator leftOperand. - self assert: left sourceCode equals: '40 + 2'. - self assert: (left isOfType: FASTPyBinaryOperator). - self assert: (left leftOperand isOfType: FASTPyInteger). - self assert: (left leftOperand sourceCode) equals: '40'. - self assert: (left rightOperand sourceCode) equals: '2'. - self assert: left operator equals: '+' + stack push: self topEntity leftOperand. + self assert: self topEntity sourceCode equals: '40'. + self assert: (self topEntity isOfType: FASTPyInteger). + self assert: (self topEntity isOfType: FASTTLiteral). + self assert: (self topEntity isOfType: FASTTNumericalLiteral). + stack pop. + self assert: self topEntity operator equals: '+'. + + "Testing value of monovalue relation rightOperand" + self assert: self topEntity rightOperand isNotNil. + + stack push: self topEntity rightOperand. + self assert: self topEntity sourceCode equals: '2'. + self assert: (self topEntity isOfType: FASTPyInteger). + self assert: (self topEntity isOfType: FASTTLiteral). + self assert: (self topEntity isOfType: FASTTNumericalLiteral). + stack pop. + stack pop. + self assert: self topEntity operator equals: '-'. + + "Testing value of monovalue relation rightOperand" + self assert: self topEntity rightOperand isNotNil. + + stack push: self topEntity rightOperand. + self assert: self topEntity sourceCode equals: '0'. + self assert: (self topEntity isOfType: FASTPyInteger). + self assert: (self topEntity isOfType: FASTTLiteral). + self assert: (self topEntity isOfType: FASTTNumericalLiteral) ] { #category : 'tests - operators' } From 18f6d53f2174a1290924e8772d46d03b8950c975 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Sat, 26 Sep 2026 13:28:37 +0200 Subject: [PATCH 06/15] Some fixes related to export/import - Move #ensureLocalUses to FASTTCanBeLocalDeclaration - Add the non local declarations to the model - Enable parametric tests for all FAST-Python tests --- .../FASTPythonAbstractTestCase.class.st | 8 +++----- .../FASTPythonLocalResolverVisitor.class.st | 7 ++++--- .../FASTTCanBeLocalDeclaration.extension.st | 7 +++++++ src/FAST-Python-Tools/FASTTEntity.extension.st | 6 ------ 4 files changed, 14 insertions(+), 14 deletions(-) create mode 100644 src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st diff --git a/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st b/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st index f885e51..af7e422 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st @@ -19,9 +19,7 @@ FASTPythonAbstractTestCase class >> isAbstract [ { #category : 'building suites' } FASTPythonAbstractTestCase class >> testParameters [ - self flag: #todo. "enable once the tests of FASTPythonImporterTest will all be green with the parametric tests." - "^ ParametrizedTestMatrix new forSelector: #persist addOptions: { false. true }" - ^ super testParameters + ^ ParametrizedTestMatrix new forSelector: #persist addOptions: { false. true } ] { #category : 'running' } @@ -31,7 +29,7 @@ FASTPythonAbstractTestCase >> exportAndImportModelIfNeeded [ self persist ifFalse: [ ^ self ]. json := model asJSONString. - self halt. + model := json readStreamDo: [ :stream | FASTPyModel new importFromJSONStream: stream ] ] @@ -47,7 +45,7 @@ FASTPythonAbstractTestCase >> parse: aString [ { #category : 'accessing' } FASTPythonAbstractTestCase >> persist [ - ^ persist + ^ persist ifNil: [ ^ false ] ] { #category : 'accessing' } diff --git a/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st b/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st index 8463c54..35593b8 100644 --- a/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st +++ b/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st @@ -40,7 +40,7 @@ FASTPythonLocalResolverVisitor class >> resolve: aPythonEntity [ { #category : 'declarations' } FASTPythonLocalResolverVisitor >> bind: aFASTNode toDeclarationNamed: aName [ - ^ self bind: aFASTNode toDeclarationNamed: aName ifAbsentUse: [ self ensureNonlocalDeclarationNamed: aName ] + ^ self bind: aFASTNode toDeclarationNamed: aName ifAbsentUse: [ self ensureNonlocalDeclarationNamed: aName model: aFASTNode mooseModel ] ] { #category : 'declarations' } @@ -62,7 +62,7 @@ FASTPythonLocalResolverVisitor >> declarationForUndeclaredNode: aNode named: aNa localDeclarationifPresent: [ ^ self ensureDeclarationOf: aName declaration: aNode in: namesContext top ] ifAbsent: [ "Nothing, just let the non local declaration." ] ]. - ^ self ensureNonlocalDeclarationNamed: aName + ^ self ensureNonlocalDeclarationNamed: aName model: aNode mooseModel ] { #category : 'declarations' } @@ -104,12 +104,13 @@ FASTPythonLocalResolverVisitor >> ensureDeclarationOf: anEntity named: aName dec ] { #category : 'declarations' } -FASTPythonLocalResolverVisitor >> ensureNonlocalDeclarationNamed: aName [ +FASTPythonLocalResolverVisitor >> ensureNonlocalDeclarationNamed: aName model: mooseModel [ ^ self ensureDeclarationOf: aName declaration: (FASTNonLocalDeclaration new name: aName; + in: [ :declaration | mooseModel add: declaration ]; yourself) in: namesContext first ] diff --git a/src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st b/src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st new file mode 100644 index 0000000..5692b65 --- /dev/null +++ b/src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st @@ -0,0 +1,7 @@ +Extension { #name : 'FASTTCanBeLocalDeclaration' } + +{ #category : '*FAST-Python-Tools' } +FASTTCanBeLocalDeclaration >> ensureLocalUses [ + + self attributeAt: #localUses ifAbsentPut: OrderedCollection new +] diff --git a/src/FAST-Python-Tools/FASTTEntity.extension.st b/src/FAST-Python-Tools/FASTTEntity.extension.st index 622a8a4..d4f286d 100644 --- a/src/FAST-Python-Tools/FASTTEntity.extension.st +++ b/src/FAST-Python-Tools/FASTTEntity.extension.st @@ -1,11 +1,5 @@ Extension { #name : 'FASTTEntity' } -{ #category : '*FAST-Python-Tools' } -FASTTEntity >> ensureLocalUses [ - - self attributeAt: #localUses ifAbsentPut: OrderedCollection new -] - { #category : '*FAST-Python-Tools' } FASTTEntity >> resetLocalResolution [ From ea6e3b10f8ac1595d042f6a4653836f787d50cd0 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Sat, 26 Sep 2026 13:30:39 +0200 Subject: [PATCH 07/15] Make CFG tests deterministics --- AGENTS.md | 100 ++++++++++++++++++ .../FASTPythonCFGTest.class.st | 6 +- 2 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ab40be1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,100 @@ +# AGENTS.md + +Always read and follow the coding conventions in `~/.opencode/AGENTS.md` if present. + +## What This Is + +A **Pharo Smalltalk** project (not Python) that provides a Famix AST representation for Python code, built on TreeSitter. Part of the [moosetechnology/FAST](https://github.com/moosetechnology/FAST) ecosystem. + +Source code format: **Tonel** (all source in `src/`). + +## Build & Test + +This is a Pharo Smalltalk project. There are no npm/pip/make commands. + +**Install dependencies in a Pharo image:** +```smalltalk +Metacello new + githubUser: 'moosetechnology' project: 'FAST-Python' commitish: 'main' path: 'src'; + baseline: 'FASTPython'; + load +``` + +**CI command (what actually runs):** +```bash +smalltalkci -s Pharo64-13 # or Pharo64-14 +``` +CI is defined in `.github/workflows/tests.yml`. Tests run via `smalltalkci` using the `smalltalk.ston` spec. Coverage is collected in lcov format for `FAST-Python.*` packages. + +There is no local test runner script outside of `smalltalkci`. You need a Pharo image with the project loaded to run tests interactively. + +## Package Structure + +``` +src/ + BaselineOfFASTPython/ -- Metacello baseline (dependency & group definitions) + FAST-Python-Model-Generator/ -- Metamodel generator (Famix code generation) + FAST-Python-Model/ -- Generated model classes (FASTPy*), do NOT edit by hand + FAST-Python-Tools/ -- Importer, CFG, local resolver, SSA, TreeSitter visitor, variable-analysis extensions + FAST-Python-Tools-Tests/ -- All tests (tags: Core = abstract test case, Model = model tests, Analysis = variable-analysis tests) +``` + +**Baseline groups:** +- `Core` = Model + Tools +- `Generator` = Model-Generator only +- `Tests` = Tools-Tests only (the former Model-Tests package was merged into Tools-Tests) + +**Dependencies** (from baseline): +- `FAST` v3: `github://moosetechnology/FAST:v3/src` (loads `'All'` group) +- `TreeSitter` v2.0.0: `github://Evref-BL/Pharo-Tree-Sitter:v.2.0.0/src` + +## Critical: Model Files Are Generated + +`FAST-Python-Model/` contains ~130 generated class files (`FASTPy*`). These are produced by `FASTPythonMetamodelGenerator` in `FAST-Python-Model-Generator/`. **Do not edit model files directly** -- edit the generator and re-run it. The generator also produces a visitor trait (`FASTPyTVisitor`). + +## Key Entry Points + +| Class | Role | +|-------|------| +| `FASTPythonImporter` | Parse Python source string or file → FAST model. Extends `TSFASTAbstractImporter`. | +| `FASTPythonTreeSitterVisitor` | Walks TreeSitter CST → builds FAST model. 1100+ lines, the core import logic. | +| `FASTPythonCFGVisitor` | Builds control flow graph. Uses `FASTTCFGUtility` trait from FAST. | +| `FASTPythonLocalResolverVisitor` | Links entity usages to their local declarations (scope-aware). | +| `FASTPythonSSAVisitor` | SSA transform. Uses `FASTCFGTVisitor` trait from FAST. Requires local resolution first. | +| `FASTPythonMetamodelGenerator` | Generates the Famix metamodel. Run via `FASTPythonMetamodelGenerator new generate`. | + +**Typical analysis pipeline:** +```smalltalk +model := FASTPythonImporter parseFile: aFile. +FASTPythonLocalResolverVisitor resolve: model module. +model allFunctionDefinitions first cfg. "CFG" +FASTPythonSSAVisitor resolve: model allFunctionDefinitions first. "SSA (after resolution)" +``` + +### Variable-analysis API + +- Python-specific variable APIs (`usedVariables`, `isResolvedVariable`, `transitiveAssignedExpressions`, `transitiveAssignedExpressionsMap`, `internalAccesses`, `allNodesUsingMe`, `statementsUsingMe`, `allNodesUsingMyVersion`, `statementsUsingMyVersion`, `callsOnVariable`, `callsOnVariableVersion`) are single implementations on `FASTPyEntity` in `src/FAST-Python-Tools/FASTPyEntity.extension.st` (protocol `*FAST-Python-Tools`). The transitive ones require SSA resolution; the others require local resolution. The `*MyVersion` and `*VariableVersion` variants also require SSA. +- Contrast: FAST-level helpers (`versionWriteAccesses`, `assignedExpressionsMap`, `versionAccesses`, ...) follow a mass-extension convention -- one identical copy per FAST class in protocol `*FAST-Core-Tools`, living in the FAST dependency repo, not here. + +## Testing + +- **Base test class**: `FASTPythonAbstractTestCase` (in Tools-Tests, tag `Core`) -- provides a `parse:` helper that wraps `FASTPythonImporter` with error reporting. The `model` instance variable has no accessor. +- **Variable-analysis tests**: `FASTPythonVariablesAnalysisTest` is a slim base providing `parseAndResolve:` (parse + local resolution + SSA). Four subclasses in tag `Analysis`: `FASTPythonAssignedExpressionsInVariablesTest`, `FASTPythonIsResolvedVariablesTest`, `FASTPythonUsedVariablesTest`, `FASTPythonInternalAccessesTest`. Since each class tests a single concept, test methods use the plain `tests` protocol -- no specialized protocols. +- **Documentation**: `resources/doc/analysis.md` documents the local resolver, SSA, shadowing and variable-query APIs. Convention: questions are written as bold questions without new TOC entries, and only implemented API is documented. +- **Importer tests**: `FASTPythonImporterTest` extends `TSFASTAbstractImporterTest` (from TreeSitter). The test file is ~53k lines -- generated tests for every AST node type. Test generation snippet is in the class comment. +- **CFG/Resolver/SSA tests**: `FASTPythonCFGTest`, `FASTPythonLocalResolverTest`, `FASTPythonSSATest`. + +## Gotchas + +- **TreeSitter python grammar version matters**: After v0.25, expression statements were removed from the tree. If tests fail unexpectedly, check your `tree-sitter-python` version first (see README). +- **Pharo 13 is the primary target**; Pharo 14 is also tested. The baseline references `FAST:v3` which requires Moose 13. +- **The importer uses the master branch** of `TSLibrariesPython` (hardcoded in `FASTPythonTreeSitterVisitor class >> initialize`). +- **`expression --|> statement`**: In Python, expressions can be expression statements. This is reflected in the model hierarchy and affects how the visitor processes nodes. +- **CFG uses `FASTTCFGUtility`** from FAST (the parent project). SSA uses `FASTCFGTVisitor`. These traits define the core graph traversal protocol. +- **Local resolver scope management**: The resolver maintains a `scopes` stack. Shadowing is handled by checking entity kind consistency (same kind = shared declaration, different kind = new declaration). +- **Python 3 only for resolver**: The local resolver is Python 3 scoped. Python 2 comprehension scoping (no scope) is not supported (issue #26). +- **Non-local declarations are not deduplicated**: Each access to an unknown field creates a separate `FASTNonLocalDeclaration` (issue #26 in the repo). +- **In-image method installation**: the MCP `pharo_method_compile` can be blocked by critiques (e.g. `ReDeadBlockRule`). Fallback: `Behavior>>compile:classified:` with method source **without** the outer `[ ]` brackets -- with brackets the body parses as an inner block and a silent no-op wrapper method gets installed. Use CR line returns (see global conventions). +- **The importer cannot parse CR line endings**: pass the string through `withPlatformLineEndings` before parsing to avoid errors. +- **`assertCollection:hasSameElements:` is multiplicity-insensitive** in current images (`#(a a)` vs `#(a)` passes) -- add explicit `size` assertions to catch duplicates. +- **`model` ivar of `FASTPythonAbstractTestCase` has no accessor** -- in DoIt/evaluate code use `instVarNamed: #model`. diff --git a/src/FAST-Python-Tools-Tests/FASTPythonCFGTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonCFGTest.class.st index bb88754..77d63e5 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonCFGTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonCFGTest.class.st @@ -13,7 +13,7 @@ Class { FASTPythonCFGTest >> buildCFGForFunction: aString [ self parse: aString. - startBlock := FASTPythonCFGVisitor buildCFGOf: model allFunctionDefinitions first + startBlock := FASTPythonCFGVisitor buildCFGOf: (model allFunctionDefinitions sorted: [ :a :b | a startPos < b startPos ]) first ] { #category : 'tests' } @@ -39,7 +39,7 @@ FASTPythonCFGTest >> testCFGOfClass [ { #category : 'tests' } FASTPythonCFGTest >> testCFGOfFunction [ - startBlock := FASTPythonCFGVisitor buildCFGOf: (self parse: 'def funct(): + startBlock := FASTPythonCFGVisitor buildCFGOf: ((self parse: 'def funct(): i = 0 def funct2(i): @@ -48,7 +48,7 @@ FASTPythonCFGTest >> testCFGOfFunction [ i = funct2(i) print(i) - return i') allFunctionDefinitions first. + return i') allFunctionDefinitions sorted: [ :a :b | a startPos < b startPos ]) first. self assert: startBlock isStart. self assert: startBlock isFinal. From c3d9f0fc063d82c5f49cce4c9d9c920b9383fbc1 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Mon, 28 Sep 2026 15:46:45 +0200 Subject: [PATCH 08/15] Regenerate MM --- .../FASTPyCaseClause.class.st | 1 - src/FAST-Python-Model/FASTPyChevron.class.st | 1 - .../FASTPyDecorator.class.st | 1 - .../FASTPyElifClause.class.st | 1 - .../FASTPyElseClause.class.st | 1 - .../FASTPyExceptClause.class.st | 1 - .../FASTPyExpression.class.st | 31 ------------------- .../FASTPyFinallyClause.class.st | 1 - .../FASTPyFromModule.class.st | 1 - .../FASTPyImportedEntity.class.st | 1 - .../FASTPyInterpolation.class.st | 1 - .../FASTPyKeywordArgument.class.st | 1 - src/FAST-Python-Model/FASTPyString.class.st | 1 - .../FASTPyTAsPatternSource.trait.st | 1 - .../FASTPyTAsPatternTarget.trait.st | 1 - .../FASTPyTAssignable.trait.st | 1 - .../FASTPyTAwaitable.trait.st | 1 - .../FASTPyTCallable.trait.st | 1 - .../FASTPyTClassPatternElement.trait.st | 1 - .../FASTPyTDecoratorExpression.trait.st | 1 - .../FASTPyTDeletable.trait.st | 1 - .../FASTPyTExecutable.trait.st | 1 - src/FAST-Python-Model/FASTPyTPattern.trait.st | 3 -- src/FAST-Python-Model/FASTPyTRaised.trait.st | 1 - .../FASTPyTSliceIndex.trait.st | 1 - .../FASTPyTSplatExpression.trait.st | 1 - .../FASTPyTSplatParameterTarget.trait.st | 1 - .../FASTPyTSuperclass.trait.st | 1 - .../FASTPyTTypeContent.trait.st | 1 - src/FAST-Python-Model/FASTPyTVisitor.trait.st | 9 ++++++ .../FASTPyTWithStatementItem.trait.st | 1 - .../FASTPyThenClause.class.st | 1 - src/FAST-Python-Model/FASTPyType.class.st | 11 ------- src/FAST-Python-Model/FASTPyVariable.class.st | 2 -- 34 files changed, 9 insertions(+), 76 deletions(-) diff --git a/src/FAST-Python-Model/FASTPyCaseClause.class.st b/src/FAST-Python-Model/FASTPyCaseClause.class.st index 83ed0dc..43572aa 100644 --- a/src/FAST-Python-Model/FASTPyCaseClause.class.st +++ b/src/FAST-Python-Model/FASTPyCaseClause.class.st @@ -78,7 +78,6 @@ FASTPyCaseClause >> parentMatchStatement [ - ^ parentMatchStatement ] diff --git a/src/FAST-Python-Model/FASTPyChevron.class.st b/src/FAST-Python-Model/FASTPyChevron.class.st index 1a317a4..57bb51c 100644 --- a/src/FAST-Python-Model/FASTPyChevron.class.st +++ b/src/FAST-Python-Model/FASTPyChevron.class.st @@ -62,7 +62,6 @@ FASTPyChevron >> parentPrintStatement [ - ^ parentPrintStatement ] diff --git a/src/FAST-Python-Model/FASTPyDecorator.class.st b/src/FAST-Python-Model/FASTPyDecorator.class.st index dfaa092..5c3f605 100644 --- a/src/FAST-Python-Model/FASTPyDecorator.class.st +++ b/src/FAST-Python-Model/FASTPyDecorator.class.st @@ -62,7 +62,6 @@ FASTPyDecorator >> parentDefinition [ - ^ parentDefinition ] diff --git a/src/FAST-Python-Model/FASTPyElifClause.class.st b/src/FAST-Python-Model/FASTPyElifClause.class.st index ed5662d..a4e23ea 100644 --- a/src/FAST-Python-Model/FASTPyElifClause.class.st +++ b/src/FAST-Python-Model/FASTPyElifClause.class.st @@ -55,7 +55,6 @@ FASTPyElifClause >> parentIfStatement [ - ^ parentIfStatement ] diff --git a/src/FAST-Python-Model/FASTPyElseClause.class.st b/src/FAST-Python-Model/FASTPyElseClause.class.st index 3ce1d98..9a8180a 100644 --- a/src/FAST-Python-Model/FASTPyElseClause.class.st +++ b/src/FAST-Python-Model/FASTPyElseClause.class.st @@ -54,7 +54,6 @@ FASTPyElseClause >> parentIfStatement [ - ^ parentIfStatement ] diff --git a/src/FAST-Python-Model/FASTPyExceptClause.class.st b/src/FAST-Python-Model/FASTPyExceptClause.class.st index ce96c89..e2b3189 100644 --- a/src/FAST-Python-Model/FASTPyExceptClause.class.st +++ b/src/FAST-Python-Model/FASTPyExceptClause.class.st @@ -92,7 +92,6 @@ FASTPyExceptClause >> parentTryStatement [ - ^ parentTryStatement ] diff --git a/src/FAST-Python-Model/FASTPyExpression.class.st b/src/FAST-Python-Model/FASTPyExpression.class.st index 7b3e41a..563c688 100644 --- a/src/FAST-Python-Model/FASTPyExpression.class.st +++ b/src/FAST-Python-Model/FASTPyExpression.class.st @@ -146,7 +146,6 @@ FASTPyExpression >> collectionInitializer [ - ^ collectionInitializer ] @@ -184,7 +183,6 @@ FASTPyExpression >> parentAssertStatement [ - ^ parentAssertStatement ] @@ -203,7 +201,6 @@ FASTPyExpression >> parentAssignmentRight [ - ^ parentAssignmentRight ] @@ -223,7 +220,6 @@ FASTPyExpression >> parentAttributeObject [ - ^ parentAttributeObject ] @@ -242,7 +238,6 @@ FASTPyExpression >> parentChevron [ - ^ parentChevron ] @@ -262,7 +257,6 @@ FASTPyExpression >> parentComparisonOperator [ - ^ parentComparisonOperator ] @@ -281,7 +275,6 @@ FASTPyExpression >> parentComprehensionBody [ - ^ parentComprehensionBody ] @@ -300,7 +293,6 @@ FASTPyExpression >> parentComprehensionCondition [ - ^ parentComprehensionCondition ] @@ -319,7 +311,6 @@ FASTPyExpression >> parentComprehensionForClause [ - ^ parentComprehensionForClause ] @@ -338,7 +329,6 @@ FASTPyExpression >> parentConditionalExpressionElse [ - ^ parentConditionalExpressionElse ] @@ -357,7 +347,6 @@ FASTPyExpression >> parentConditionalExpressionThen [ - ^ parentConditionalExpressionThen ] @@ -376,7 +365,6 @@ FASTPyExpression >> parentDefaultParameterValue [ - ^ parentDefaultParameterValue ] @@ -395,7 +383,6 @@ FASTPyExpression >> parentExceptClause [ - ^ parentExceptClause ] @@ -414,7 +401,6 @@ FASTPyExpression >> parentExecStatementScopes [ - ^ parentExecStatementScopes ] @@ -433,7 +419,6 @@ FASTPyExpression >> parentForInClauseLeft [ - ^ parentForInClauseLeft ] @@ -452,7 +437,6 @@ FASTPyExpression >> parentForInClauseRight [ - ^ parentForInClauseRight ] @@ -472,7 +456,6 @@ FASTPyExpression >> parentForStatementLeft [ - ^ parentForStatementLeft ] @@ -492,7 +475,6 @@ FASTPyExpression >> parentForStatementRight [ - ^ parentForStatementRight ] @@ -511,7 +493,6 @@ FASTPyExpression >> parentIfClause [ - ^ parentIfClause ] @@ -530,7 +511,6 @@ FASTPyExpression >> parentInterpolation [ - ^ parentInterpolation ] @@ -550,7 +530,6 @@ FASTPyExpression >> parentKeywordArgument [ - ^ parentKeywordArgument ] @@ -569,7 +548,6 @@ FASTPyExpression >> parentLambda [ - ^ parentLambda ] @@ -588,7 +566,6 @@ FASTPyExpression >> parentMatchStatement [ - ^ parentMatchStatement ] @@ -607,7 +584,6 @@ FASTPyExpression >> parentPairKey [ - ^ parentPairKey ] @@ -626,7 +602,6 @@ FASTPyExpression >> parentPairValuer [ - ^ parentPairValuer ] @@ -646,7 +621,6 @@ FASTPyExpression >> parentSlice [ - ^ parentSlice ] @@ -666,7 +640,6 @@ FASTPyExpression >> parentSubscriptValue [ - ^ parentSubscriptValue ] @@ -686,7 +659,6 @@ FASTPyExpression >> parentUnaryOperator [ - ^ parentUnaryOperator ] @@ -705,7 +677,6 @@ FASTPyExpression >> parentWalrus [ - ^ parentWalrus ] @@ -724,7 +695,6 @@ FASTPyExpression >> parentYield [ - ^ parentYield ] @@ -743,7 +713,6 @@ FASTPyExpression >> prarentPrintStatement [ - ^ prarentPrintStatement ] diff --git a/src/FAST-Python-Model/FASTPyFinallyClause.class.st b/src/FAST-Python-Model/FASTPyFinallyClause.class.st index 194c932..8759055 100644 --- a/src/FAST-Python-Model/FASTPyFinallyClause.class.st +++ b/src/FAST-Python-Model/FASTPyFinallyClause.class.st @@ -54,7 +54,6 @@ FASTPyFinallyClause >> parentTryStatement [ - ^ parentTryStatement ] diff --git a/src/FAST-Python-Model/FASTPyFromModule.class.st b/src/FAST-Python-Model/FASTPyFromModule.class.st index 8593371..054d07b 100644 --- a/src/FAST-Python-Model/FASTPyFromModule.class.st +++ b/src/FAST-Python-Model/FASTPyFromModule.class.st @@ -51,7 +51,6 @@ FASTPyFromModule >> import [ - ^ import ] diff --git a/src/FAST-Python-Model/FASTPyImportedEntity.class.st b/src/FAST-Python-Model/FASTPyImportedEntity.class.st index 37ba8d8..1b5f046 100644 --- a/src/FAST-Python-Model/FASTPyImportedEntity.class.st +++ b/src/FAST-Python-Model/FASTPyImportedEntity.class.st @@ -70,7 +70,6 @@ FASTPyImportedEntity >> import [ - ^ import ] diff --git a/src/FAST-Python-Model/FASTPyInterpolation.class.st b/src/FAST-Python-Model/FASTPyInterpolation.class.st index 14c9c0a..e6227d4 100644 --- a/src/FAST-Python-Model/FASTPyInterpolation.class.st +++ b/src/FAST-Python-Model/FASTPyInterpolation.class.st @@ -86,7 +86,6 @@ FASTPyInterpolation >> parentString [ - ^ parentString ] diff --git a/src/FAST-Python-Model/FASTPyKeywordArgument.class.st b/src/FAST-Python-Model/FASTPyKeywordArgument.class.st index 90d696e..45ca6de 100644 --- a/src/FAST-Python-Model/FASTPyKeywordArgument.class.st +++ b/src/FAST-Python-Model/FASTPyKeywordArgument.class.st @@ -54,7 +54,6 @@ FASTPyKeywordArgument >> parentClassDefinition [ - ^ parentClassDefinition ] diff --git a/src/FAST-Python-Model/FASTPyString.class.st b/src/FAST-Python-Model/FASTPyString.class.st index a440ed3..868c25b 100644 --- a/src/FAST-Python-Model/FASTPyString.class.st +++ b/src/FAST-Python-Model/FASTPyString.class.st @@ -88,7 +88,6 @@ FASTPyString >> parentConcatenatedString [ - ^ parentConcatenatedString ] diff --git a/src/FAST-Python-Model/FASTPyTAsPatternSource.trait.st b/src/FAST-Python-Model/FASTPyTAsPatternSource.trait.st index fcdaea8..8a2fe46 100644 --- a/src/FAST-Python-Model/FASTPyTAsPatternSource.trait.st +++ b/src/FAST-Python-Model/FASTPyTAsPatternSource.trait.st @@ -38,7 +38,6 @@ FASTPyTAsPatternSource >> parentAsPatternSource [ - ^ parentAsPatternSource ] diff --git a/src/FAST-Python-Model/FASTPyTAsPatternTarget.trait.st b/src/FAST-Python-Model/FASTPyTAsPatternTarget.trait.st index c72fdb2..e79ac1c 100644 --- a/src/FAST-Python-Model/FASTPyTAsPatternTarget.trait.st +++ b/src/FAST-Python-Model/FASTPyTAsPatternTarget.trait.st @@ -41,7 +41,6 @@ FASTPyTAsPatternTarget >> parentAsPatternTarget [ - ^ parentAsPatternTarget ] diff --git a/src/FAST-Python-Model/FASTPyTAssignable.trait.st b/src/FAST-Python-Model/FASTPyTAssignable.trait.st index 45ca01b..db0d4b1 100644 --- a/src/FAST-Python-Model/FASTPyTAssignable.trait.st +++ b/src/FAST-Python-Model/FASTPyTAssignable.trait.st @@ -38,7 +38,6 @@ FASTPyTAssignable >> parentAssignmentLeft [ - ^ parentAssignmentLeft ] diff --git a/src/FAST-Python-Model/FASTPyTAwaitable.trait.st b/src/FAST-Python-Model/FASTPyTAwaitable.trait.st index 35c93a8..cd04ad1 100644 --- a/src/FAST-Python-Model/FASTPyTAwaitable.trait.st +++ b/src/FAST-Python-Model/FASTPyTAwaitable.trait.st @@ -38,7 +38,6 @@ FASTPyTAwaitable >> parentAwait [ - ^ parentAwait ] diff --git a/src/FAST-Python-Model/FASTPyTCallable.trait.st b/src/FAST-Python-Model/FASTPyTCallable.trait.st index a794017..11e12fb 100644 --- a/src/FAST-Python-Model/FASTPyTCallable.trait.st +++ b/src/FAST-Python-Model/FASTPyTCallable.trait.st @@ -47,7 +47,6 @@ FASTPyTCallable >> caller [ - ^ caller ] diff --git a/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st b/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st index 7d0fa12..1edde42 100644 --- a/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st +++ b/src/FAST-Python-Model/FASTPyTClassPatternElement.trait.st @@ -38,7 +38,6 @@ FASTPyTClassPatternElement >> parentClassPattern [ - ^ parentClassPattern ] diff --git a/src/FAST-Python-Model/FASTPyTDecoratorExpression.trait.st b/src/FAST-Python-Model/FASTPyTDecoratorExpression.trait.st index 87f6a00..339dc47 100644 --- a/src/FAST-Python-Model/FASTPyTDecoratorExpression.trait.st +++ b/src/FAST-Python-Model/FASTPyTDecoratorExpression.trait.st @@ -38,7 +38,6 @@ FASTPyTDecoratorExpression >> parentDeclarator [ - ^ parentDeclarator ] diff --git a/src/FAST-Python-Model/FASTPyTDeletable.trait.st b/src/FAST-Python-Model/FASTPyTDeletable.trait.st index 386543c..d7f8390 100644 --- a/src/FAST-Python-Model/FASTPyTDeletable.trait.st +++ b/src/FAST-Python-Model/FASTPyTDeletable.trait.st @@ -39,7 +39,6 @@ FASTPyTDeletable >> parentDeleteStatement [ - ^ parentDeleteStatement ] diff --git a/src/FAST-Python-Model/FASTPyTExecutable.trait.st b/src/FAST-Python-Model/FASTPyTExecutable.trait.st index ec0e73f..91b3570 100644 --- a/src/FAST-Python-Model/FASTPyTExecutable.trait.st +++ b/src/FAST-Python-Model/FASTPyTExecutable.trait.st @@ -38,7 +38,6 @@ FASTPyTExecutable >> parentExecStatement [ - ^ parentExecStatement ] diff --git a/src/FAST-Python-Model/FASTPyTPattern.trait.st b/src/FAST-Python-Model/FASTPyTPattern.trait.st index a37a28e..3b02934 100644 --- a/src/FAST-Python-Model/FASTPyTPattern.trait.st +++ b/src/FAST-Python-Model/FASTPyTPattern.trait.st @@ -42,7 +42,6 @@ FASTPyTPattern >> parentCaseClause [ - ^ parentCaseClause ] @@ -61,7 +60,6 @@ FASTPyTPattern >> parentKeywordPatternValue [ - ^ parentKeywordPatternValue ] @@ -80,7 +78,6 @@ FASTPyTPattern >> parentUnionPattern [ - ^ parentUnionPattern ] diff --git a/src/FAST-Python-Model/FASTPyTRaised.trait.st b/src/FAST-Python-Model/FASTPyTRaised.trait.st index db86105..c685b1c 100644 --- a/src/FAST-Python-Model/FASTPyTRaised.trait.st +++ b/src/FAST-Python-Model/FASTPyTRaised.trait.st @@ -38,7 +38,6 @@ FASTPyTRaised >> parentRaiseStatement [ - ^ parentRaiseStatement ] diff --git a/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st b/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st index 15acdde..993cfe2 100644 --- a/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st +++ b/src/FAST-Python-Model/FASTPyTSliceIndex.trait.st @@ -39,7 +39,6 @@ FASTPyTSliceIndex >> parentSubscriptIndex [ - ^ parentSubscriptIndex ] diff --git a/src/FAST-Python-Model/FASTPyTSplatExpression.trait.st b/src/FAST-Python-Model/FASTPyTSplatExpression.trait.st index 496ef83..9ffe4fa 100644 --- a/src/FAST-Python-Model/FASTPyTSplatExpression.trait.st +++ b/src/FAST-Python-Model/FASTPyTSplatExpression.trait.st @@ -38,7 +38,6 @@ FASTPyTSplatExpression >> parentSplat [ - ^ parentSplat ] diff --git a/src/FAST-Python-Model/FASTPyTSplatParameterTarget.trait.st b/src/FAST-Python-Model/FASTPyTSplatParameterTarget.trait.st index 547e8ae..5634f41 100644 --- a/src/FAST-Python-Model/FASTPyTSplatParameterTarget.trait.st +++ b/src/FAST-Python-Model/FASTPyTSplatParameterTarget.trait.st @@ -38,7 +38,6 @@ FASTPyTSplatParameterTarget >> parentSplatParameter [ - ^ parentSplatParameter ] diff --git a/src/FAST-Python-Model/FASTPyTSuperclass.trait.st b/src/FAST-Python-Model/FASTPyTSuperclass.trait.st index 7b1ddb0..7b14d62 100644 --- a/src/FAST-Python-Model/FASTPyTSuperclass.trait.st +++ b/src/FAST-Python-Model/FASTPyTSuperclass.trait.st @@ -38,7 +38,6 @@ FASTPyTSuperclass >> parentClassDefinition [ - ^ parentClassDefinition ] diff --git a/src/FAST-Python-Model/FASTPyTTypeContent.trait.st b/src/FAST-Python-Model/FASTPyTTypeContent.trait.st index d467139..b96be60 100644 --- a/src/FAST-Python-Model/FASTPyTTypeContent.trait.st +++ b/src/FAST-Python-Model/FASTPyTTypeContent.trait.st @@ -38,7 +38,6 @@ FASTPyTTypeContent >> parentType [ - ^ parentType ] diff --git a/src/FAST-Python-Model/FASTPyTVisitor.trait.st b/src/FAST-Python-Model/FASTPyTVisitor.trait.st index 5f22eb9..27dd6c9 100644 --- a/src/FAST-Python-Model/FASTPyTVisitor.trait.st +++ b/src/FAST-Python-Model/FASTPyTVisitor.trait.st @@ -1321,6 +1321,14 @@ FASTPyTVisitor >> visitFASTTBreakStatement: aTBreakStatement [ "We should visit FASTTStatement but all its users in this language already visit it in their superclasses so we skip the call here." ] +{ #category : 'visiting' } +FASTPyTVisitor >> visitFASTTCanBeLocalDeclaration: aTCanBeLocalDeclaration [ + + + + +] + { #category : 'visiting' } FASTPyTVisitor >> visitFASTTCanBeVariable: aTCanBeVariable [ @@ -1361,6 +1369,7 @@ FASTPyTVisitor >> visitFASTTEntity: aTEntity [ + "We should visit FASTTCanBeLocalDeclaration but all its users in this language already visit it in their superclasses so we skip the call here.". "We should visit TEntityMetaLevelDependency but all its users in this language already visit it in their superclasses so we skip the call here." ] diff --git a/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st b/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st index 8b45bef..8b3132f 100644 --- a/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st +++ b/src/FAST-Python-Model/FASTPyTWithStatementItem.trait.st @@ -38,7 +38,6 @@ FASTPyTWithStatementItem >> parentWithStatementItem [ - ^ parentWithStatementItem ] diff --git a/src/FAST-Python-Model/FASTPyThenClause.class.st b/src/FAST-Python-Model/FASTPyThenClause.class.st index 12f05ed..98e3f11 100644 --- a/src/FAST-Python-Model/FASTPyThenClause.class.st +++ b/src/FAST-Python-Model/FASTPyThenClause.class.st @@ -54,7 +54,6 @@ FASTPyThenClause >> parentIfStatement [ - ^ parentIfStatement ] diff --git a/src/FAST-Python-Model/FASTPyType.class.st b/src/FAST-Python-Model/FASTPyType.class.st index 93c067b..2b28ec2 100644 --- a/src/FAST-Python-Model/FASTPyType.class.st +++ b/src/FAST-Python-Model/FASTPyType.class.st @@ -80,7 +80,6 @@ FASTPyType >> parentAssignment [ - ^ parentAssignment ] @@ -99,7 +98,6 @@ FASTPyType >> parentContrainedType [ - ^ parentContrainedType ] @@ -118,7 +116,6 @@ FASTPyType >> parentContrainedTypeBound [ - ^ parentContrainedTypeBound ] @@ -137,7 +134,6 @@ FASTPyType >> parentFunctionDefinition [ - ^ parentFunctionDefinition ] @@ -156,7 +152,6 @@ FASTPyType >> parentGenericTypeArgument [ - ^ parentGenericTypeArgument ] @@ -175,7 +170,6 @@ FASTPyType >> parentMethodDefinition [ - ^ parentMethodDefinition ] @@ -194,7 +188,6 @@ FASTPyType >> parentParameter [ - ^ parentParameter ] @@ -213,7 +206,6 @@ FASTPyType >> parentUnionType [ - ^ parentUnionType ] @@ -232,7 +224,6 @@ FASTPyType >> parentWithTypeParameters [ - ^ parentWithTypeParameters ] @@ -251,7 +242,6 @@ FASTPyType >> parentyTypeAliasStatementAlias [ - ^ parentyTypeAliasStatementAlias ] @@ -270,7 +260,6 @@ FASTPyType >> parentyTypeAliasStatementType [ - ^ parentyTypeAliasStatementType ] diff --git a/src/FAST-Python-Model/FASTPyVariable.class.st b/src/FAST-Python-Model/FASTPyVariable.class.st index 8bce9f3..4549cf7 100644 --- a/src/FAST-Python-Model/FASTPyVariable.class.st +++ b/src/FAST-Python-Model/FASTPyVariable.class.st @@ -54,7 +54,6 @@ FASTPyVariable >> parentGlobalStatement [ - ^ parentGlobalStatement ] @@ -74,7 +73,6 @@ FASTPyVariable >> parentNonlocalStatement [ - ^ parentNonlocalStatement ] From 3a8af68ad6ae2702acf9e8f320732d487c6986c2 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Mon, 28 Sep 2026 16:23:54 +0200 Subject: [PATCH 09/15] Add the SSA versions to the model --- src/FAST-Python-Tools/FASTPythonSSAVisitor.class.st | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FAST-Python-Tools/FASTPythonSSAVisitor.class.st b/src/FAST-Python-Tools/FASTPythonSSAVisitor.class.st index 84800cc..c66ccce 100644 --- a/src/FAST-Python-Tools/FASTPythonSSAVisitor.class.st +++ b/src/FAST-Python-Tools/FASTPythonSSAVisitor.class.st @@ -47,6 +47,7 @@ FASTPythonSSAVisitor >> createPhiVersionFor: localDeclaration versions: allVersi allVersions size < 2 ifTrue: [ ^ self ]. "No need to create a phi version if we don't have at least 2 versions" phiVersion := FASTVariablePhiVersionSSA for: allVersions. + allVersions anyOne mooseModel add: phiVersion. localDeclaration activeVersion: phiVersion. ^ phiVersion ] @@ -56,6 +57,7 @@ FASTPythonSSAVisitor >> createVariableVersionFor: aFASTEntity [ | newSSA | newSSA := FASTVariableVersionSSA for: aFASTEntity. + aFASTEntity mooseModel add: newSSA. aFASTEntity lastSSAVersion ifNotNil: [ :lastSSA | newSSA version: lastSSA version ]. aFASTEntity localDeclaration activeVersion: newSSA. From c90f85cb26c0635a2a1c729d1eb3b7fdfe286b42 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Mon, 28 Sep 2026 18:30:12 +0200 Subject: [PATCH 10/15] Fix last tests on export/import --- .../FASTPythonImporterTest.class.st | 62 ++++++++++++++----- .../FASTPythonSSATest.class.st | 2 - 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st index 9842055..4a3f5a3 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st @@ -6368,28 +6368,60 @@ FASTPythonImporterTest >> testBooleanOperator [ { #category : 'tests - operators' } FASTPythonImporterTest >> testBooleanOperatorInBooleanOperator [ + + "Generated as regression test by TSFASTImporterTestGenerator>>#generateTestNamed:fromCode:protocol: + Regenerate executing: self regenerateTest: #testBooleanOperatorInBooleanOperator " - | operator left | self parse: 'True and True or False'. - self assert: (fast allWithType: FASTPyModule) size equals: 1. + self assert: (fast allWithType: FASTPyBoolean) size equals: 3. self assert: (fast allWithType: FASTPyBooleanOperator) size equals: 2. + self assert: (fast allWithType: FASTPyModule) size equals: 1. - operator := (fast allWithType: FASTPyBooleanOperator) anyOne. - self assert: operator sourceCode equals: 'True and True or False'. - self assert: (operator isOfType: FASTTBinaryExpression). + stack push: fast rootEntities anyOne containedEntities first. + self assert: self topEntity sourceCode equals: 'True and True or False'. + self assert: (self topEntity isOfType: FASTPyBooleanOperator). + self assert: (self topEntity isOfType: FASTTBinaryExpression). + + "Testing value of monovalue relation leftOperand" + self assert: self topEntity leftOperand isNotNil. - self assert: operator operator equals: 'or'. - self assert: operator rightOperand sourceCode equals: 'False'. - self assert: (operator rightOperand isOfType: FASTPyBoolean). + stack push: self topEntity leftOperand. + self assert: self topEntity sourceCode equals: 'True and True'. + self assert: (self topEntity isOfType: FASTPyBooleanOperator). + self assert: (self topEntity isOfType: FASTTBinaryExpression). + + "Testing value of monovalue relation leftOperand" + self assert: self topEntity leftOperand isNotNil. - left := operator leftOperand. - self assert: left sourceCode equals: 'True and True'. - self assert: (left isOfType: FASTPyBooleanOperator). - self assert: (left leftOperand isOfType: FASTPyBoolean). - self assert: (left leftOperand sourceCode) equals: 'True'. - self assert: (left rightOperand sourceCode) equals: 'True'. - self assert: left operator equals: 'and' + stack push: self topEntity leftOperand. + self assert: self topEntity sourceCode equals: 'True'. + self assert: (self topEntity isOfType: FASTPyBoolean). + self assert: (self topEntity isOfType: FASTTBooleanLiteral). + self assert: (self topEntity isOfType: FASTTLiteral). + stack pop. + self assert: self topEntity operator equals: 'and'. + + "Testing value of monovalue relation rightOperand" + self assert: self topEntity rightOperand isNotNil. + + stack push: self topEntity rightOperand. + self assert: self topEntity sourceCode equals: 'True'. + self assert: (self topEntity isOfType: FASTPyBoolean). + self assert: (self topEntity isOfType: FASTTBooleanLiteral). + self assert: (self topEntity isOfType: FASTTLiteral). + stack pop. + stack pop. + self assert: self topEntity operator equals: 'or'. + + "Testing value of monovalue relation rightOperand" + self assert: self topEntity rightOperand isNotNil. + + stack push: self topEntity rightOperand. + self assert: self topEntity sourceCode equals: 'False'. + self assert: (self topEntity isOfType: FASTPyBoolean). + self assert: (self topEntity isOfType: FASTTBooleanLiteral). + self assert: (self topEntity isOfType: FASTTLiteral) ] { #category : 'tests - operators' } diff --git a/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st index 6c04f54..afdad22 100644 --- a/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st +++ b/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st @@ -1881,7 +1881,6 @@ FASTPythonSSATest >> testSingleAssignement [ self assert: assignedVar ssaVersion version equals: 1. self assert: assignedVar ssaName equals: 'x_1'. - self assert: assignedVar localDeclaration newVersionNumber equals: 2. self assert: assignedVar ssaVersion localDeclaration equals: assignedVar localDeclaration. self assert: assignedVar ssaVersion localUses size equals: 1 ] @@ -1914,7 +1913,6 @@ FASTPythonSSATest >> testSubscriptAssignement [ self assert: assignedVar ssaVersion version equals: 1. self assert: assignedVar ssaName equals: 'x[3]_1'. - self assert: assignedVar localDeclaration newVersionNumber equals: 2. self assert: assignedVar ssaVersion localDeclaration equals: assignedVar localDeclaration. self assert: assignedVar ssaVersion localUses size equals: 1 ] From c8210caf07dee861887e8ba2417f19572f9f243b Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Mon, 28 Sep 2026 18:30:37 +0200 Subject: [PATCH 11/15] Add new package to baseline with export of derived properties --- src/BaselineOfFASTPython/BaselineOfFASTPython.class.st | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/BaselineOfFASTPython/BaselineOfFASTPython.class.st b/src/BaselineOfFASTPython/BaselineOfFASTPython.class.st index 1a22810..ed8803c 100644 --- a/src/BaselineOfFASTPython/BaselineOfFASTPython.class.st +++ b/src/BaselineOfFASTPython/BaselineOfFASTPython.class.st @@ -12,9 +12,9 @@ Class { BaselineOfFASTPython >> baseline: spec [ - spec for: #common do: [ - spec preLoadDoIt: #'preload:package:'. - + spec for: #common do: [ + spec preLoadDoIt: #preload:package:. + "Dependencies" self fast: spec; @@ -25,11 +25,13 @@ BaselineOfFASTPython >> baseline: spec [ package: 'FAST-Python-Model' with: [ spec requires: #( 'FAST' 'TreeSitter' ) ]; package: 'FAST-Python-Model-Generator'; package: 'FAST-Python-Tools' with: [ spec requires: #( 'FAST-Python-Model' ) ]; + package: 'FAST-Python-ExtraTools' with: [ spec requires: #( 'FAST-Python-Tools' ) ]; package: 'FAST-Python-Tools-Tests' with: [ spec requires: #( 'FAST-Python-Tools' ) ]. "Groups" spec group: 'Core' with: #( 'FAST-Python-Model' 'FAST-Python-Tools' ); + group: 'Profile' with: #( 'FAST-Python-ExtraTools' ); group: 'Generator' with: #( 'FAST-Python-Model-Generator' ); group: 'Tests' with: #( 'FAST-Python-Tools-Tests' ) ] ] From 207ff43af98b77faa6e10eddebed14dff5a04e6c Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Mon, 28 Sep 2026 18:42:40 +0200 Subject: [PATCH 12/15] Add UUID and finish export of derived properties --- .../FASTPyEntity.extension.st | 9 +++ .../FASTPyModel.extension.st | 21 +++++++ .../FMModelExporterWithDerived.class.st | 60 +++++++++++++++++++ .../ManifestFASTPythonExtraTools.class.st | 17 ++++++ src/FAST-Python-ExtraTools/package.st | 1 + 5 files changed, 108 insertions(+) create mode 100644 src/FAST-Python-ExtraTools/FASTPyEntity.extension.st create mode 100644 src/FAST-Python-ExtraTools/FASTPyModel.extension.st create mode 100644 src/FAST-Python-ExtraTools/FMModelExporterWithDerived.class.st create mode 100644 src/FAST-Python-ExtraTools/ManifestFASTPythonExtraTools.class.st create mode 100644 src/FAST-Python-ExtraTools/package.st diff --git a/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st b/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st new file mode 100644 index 0000000..db9507d --- /dev/null +++ b/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st @@ -0,0 +1,9 @@ +Extension { #name : 'FASTPyEntity' } + +{ #category : '*FAST-Python-ExtraTools' } +FASTPyEntity >> uniqueIdentifier [ + + + + ^ self attributeAt: #uniqueIdentifier ifAbsentPut: [ UUID new asString ] +] diff --git a/src/FAST-Python-ExtraTools/FASTPyModel.extension.st b/src/FAST-Python-ExtraTools/FASTPyModel.extension.st new file mode 100644 index 0000000..a2c3a16 --- /dev/null +++ b/src/FAST-Python-ExtraTools/FASTPyModel.extension.st @@ -0,0 +1,21 @@ +Extension { #name : 'FASTPyModel' } + +{ #category : '*FAST-Python-ExtraTools' } +FASTPyModel >> exportAsJSONWithDerived [ + + ^ self exportAsJSONWithDerivedBlacklist: #( ) +] + +{ #category : '*FAST-Python-ExtraTools' } +FASTPyModel >> exportAsJSONWithDerivedBlacklist: aCollection [ + "The blacklist should be a collection of properties to exclude such as `TEntityMetalevelDependency>>fanIn`." + + ^ '' writeStreamDo: [ :stream | + FMModelExporterWithDerived new + blacklist: aCollection; + model: ((FMModel withMetamodel: self metamodel) + addAll: self entities; + yourself); + printer: (FMJSONPrinter on: stream); + run ] +] diff --git a/src/FAST-Python-ExtraTools/FMModelExporterWithDerived.class.st b/src/FAST-Python-ExtraTools/FMModelExporterWithDerived.class.st new file mode 100644 index 0000000..f6a42fb --- /dev/null +++ b/src/FAST-Python-ExtraTools/FMModelExporterWithDerived.class.st @@ -0,0 +1,60 @@ +" +I am a special exporter that exports also derived properties. This is useful when we want to provide a model to people not using Moose. + +I also allow to give a blacklist of properties to exclude. It should contain identifier of properties to exclude in this form: `TEntityMetaLevelDependency>>#fanIn` for example. + +If a property fails to be computed, it is not exported. + +Example + +```smalltalk +model exportAsJSONWithDerivedBlacklist: #('TEntityMetaLevelDependency>>#isDead' 'TEntityMetaLevelDependency>>#fanIn' 'TEntityMetaLevelDependency>>#fanOut' 'TEntityMetaLevelDependency>>#numberOfDeadChildren' 'TEntityMetaLevelDependency>>#numberOfExternalClients' 'TEntityMetaLevelDependency>>#numberOfExternalProviders' 'TEntityMetaLevelDependency>>#numberOfInternalProviders' 'TEntityMetaLevelDependency>>#numberOfInternalClients') +``` + +" +Class { + #name : 'FMModelExporterWithDerived', + #superclass : 'FMModelExporter', + #instVars : [ + 'blacklist' + ], + #category : 'FAST-Python-ExtraTools', + #package : 'FAST-Python-ExtraTools' +} + +{ #category : 'accessing' } +FMModelExporterWithDerived >> blacklist [ + ^ blacklist +] + +{ #category : 'accessing' } +FMModelExporterWithDerived >> blacklist: anObject [ + blacklist := anObject +] + +{ #category : 'initialization' } +FMModelExporterWithDerived >> initialize [ + + super initialize. + blacklist := OrderedCollection new +] + +{ #category : 'exporting' } +FMModelExporterWithDerived >> shouldExportProperty: property for: anEntity [ + + (self blacklist includes: property compiledMethod name) ifTrue: [ ^ false ]. + + ^ [ super shouldExportProperty: property for: anEntity ] + on: Error + do: [ + property traceCr. + false ] +] + +{ #category : 'exporting' } +FMModelExporterWithDerived >> shouldIgnoreProperty: property [ + + (model metamodel includes: property) ifFalse: [ ^ true ]. + + ^ false +] diff --git a/src/FAST-Python-ExtraTools/ManifestFASTPythonExtraTools.class.st b/src/FAST-Python-ExtraTools/ManifestFASTPythonExtraTools.class.st new file mode 100644 index 0000000..f739e2d --- /dev/null +++ b/src/FAST-Python-ExtraTools/ManifestFASTPythonExtraTools.class.st @@ -0,0 +1,17 @@ +" +I am a package containing extra tools. Originally for Profile contract. +" +Class { + #name : 'ManifestFASTPythonExtraTools', + #superclass : 'PackageManifest', + #category : 'FAST-Python-ExtraTools-Manifest', + #package : 'FAST-Python-ExtraTools', + #tag : 'Manifest' +} + +{ #category : 'asserting' } +ManifestFASTPythonExtraTools class >> shouldBeIncludedByDefaultInMetamodelsWith: aCollectionOfPackages [ + "Includes in MM that are based on FAST" + + ^ aCollectionOfPackages anySatisfy: [ :package | package definedClasses anySatisfy: [ :class | class = FASTPyEntity ] ] +] diff --git a/src/FAST-Python-ExtraTools/package.st b/src/FAST-Python-ExtraTools/package.st new file mode 100644 index 0000000..9afe88c --- /dev/null +++ b/src/FAST-Python-ExtraTools/package.st @@ -0,0 +1 @@ +Package { #name : 'FAST-Python-ExtraTools' } From eadf221f1ded95a8a780515f618dde5bd249481b Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Mon, 28 Sep 2026 18:44:28 +0200 Subject: [PATCH 13/15] Fix export --- src/FAST-Python-ExtraTools/FASTPyModel.extension.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FAST-Python-ExtraTools/FASTPyModel.extension.st b/src/FAST-Python-ExtraTools/FASTPyModel.extension.st index a2c3a16..125a8c3 100644 --- a/src/FAST-Python-ExtraTools/FASTPyModel.extension.st +++ b/src/FAST-Python-ExtraTools/FASTPyModel.extension.st @@ -10,7 +10,7 @@ FASTPyModel >> exportAsJSONWithDerived [ FASTPyModel >> exportAsJSONWithDerivedBlacklist: aCollection [ "The blacklist should be a collection of properties to exclude such as `TEntityMetalevelDependency>>fanIn`." - ^ '' writeStreamDo: [ :stream | + ^ String streamContents: [ :stream | FMModelExporterWithDerived new blacklist: aCollection; model: ((FMModel withMetamodel: self metamodel) From 4e93fc74be8c4d9d14014ab7e265c6a6a26be76e Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Tue, 29 Sep 2026 15:12:35 +0200 Subject: [PATCH 14/15] Add setter to unique identifier --- src/FAST-Python-ExtraTools/FASTPyEntity.extension.st | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st b/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st index db9507d..337610b 100644 --- a/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st +++ b/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st @@ -7,3 +7,9 @@ FASTPyEntity >> uniqueIdentifier [ ^ self attributeAt: #uniqueIdentifier ifAbsentPut: [ UUID new asString ] ] + +{ #category : '*FAST-Python-ExtraTools' } +FASTPyEntity >> uniqueIdentifier: aString [ + + ^ self attributeAt: #uniqueIdentifier put: aString +] From 232f446fee95f67c772acf8978d9f2bbd0783243 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Tue, 29 Sep 2026 15:26:20 +0200 Subject: [PATCH 15/15] Adapt to new FAST --- src/FAST-Python-Tools/FASTPyEntity.extension.st | 8 ++------ .../FASTPythonLocalResolverVisitor.class.st | 9 ++------- .../FASTTCanBeLocalDeclaration.extension.st | 7 ------- src/FAST-Python-Tools/FASTTEntity.extension.st | 1 + 4 files changed, 5 insertions(+), 20 deletions(-) delete mode 100644 src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st diff --git a/src/FAST-Python-Tools/FASTPyEntity.extension.st b/src/FAST-Python-Tools/FASTPyEntity.extension.st index cfbeca7..17eee5b 100644 --- a/src/FAST-Python-Tools/FASTPyEntity.extension.st +++ b/src/FAST-Python-Tools/FASTPyEntity.extension.st @@ -72,9 +72,7 @@ FASTPyEntity >> allSSABasicVersions [ Requires SSA resolution." - ^ (self localDeclaration allAccesses - collect: #ssaVersion - thenReject: #isPhi) asSet + ^ ((self localDeclaration allAccesses collect: #ssaVersion) reject: #isPhi) asSet ] { #category : '*FAST-Python-Tools' } @@ -164,9 +162,7 @@ FASTPyEntity >> internalAccesses [ - subscript `x[3]` - attribute `x.y`" - ^ self allAccesses - collect: #internalAccess - thenReject: #isNil + ^ (self allAccesses collect: #internalAccess) reject: #isNil ] { #category : '*FAST-Python-Tools' } diff --git a/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st b/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st index 35593b8..c86c527 100644 --- a/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st +++ b/src/FAST-Python-Tools/FASTPythonLocalResolverVisitor.class.st @@ -49,8 +49,7 @@ FASTPythonLocalResolverVisitor >> bind: aFASTNode toDeclarationNamed: aName ifAb | declaration | declaration := (self declarationNamed: aName) ifNil: [ aBlock cull: aFASTNode cull: aName ]. - aFASTNode localDeclaration: declaration. - declaration addLocalUse: aFASTNode + aFASTNode localDeclaration: declaration ] { #category : 'declarations' } @@ -88,12 +87,8 @@ FASTPythonLocalResolverVisitor >> ensureDeclarationOf: aName declaration: aFASTN declaration shadowedBy: aFASTNode. "If the kind is different, we save a new declaration." - aFASTNode ensureLocalUses. scope at: aName put: aFASTNode ] ] - ifAbsentPut: [ - aFASTNode - ensureLocalUses; - yourself ] + ifAbsentPut: [ aFASTNode ] ] { #category : 'declarations' } diff --git a/src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st b/src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st deleted file mode 100644 index 5692b65..0000000 --- a/src/FAST-Python-Tools/FASTTCanBeLocalDeclaration.extension.st +++ /dev/null @@ -1,7 +0,0 @@ -Extension { #name : 'FASTTCanBeLocalDeclaration' } - -{ #category : '*FAST-Python-Tools' } -FASTTCanBeLocalDeclaration >> ensureLocalUses [ - - self attributeAt: #localUses ifAbsentPut: OrderedCollection new -] diff --git a/src/FAST-Python-Tools/FASTTEntity.extension.st b/src/FAST-Python-Tools/FASTTEntity.extension.st index d4f286d..6e3bd17 100644 --- a/src/FAST-Python-Tools/FASTTEntity.extension.st +++ b/src/FAST-Python-Tools/FASTTEntity.extension.st @@ -3,6 +3,7 @@ Extension { #name : 'FASTTEntity' } { #category : '*FAST-Python-Tools' } FASTTEntity >> resetLocalResolution [ + (self attributeAt: #localUses ifAbsent: [ nil ]) ifNotNil: [ :uses | uses removeAll ]. self removeAttribute: #localDeclaration. self removeAttribute: #localUses ]