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/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' ) ] ] diff --git a/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st b/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st new file mode 100644 index 0000000..337610b --- /dev/null +++ b/src/FAST-Python-ExtraTools/FASTPyEntity.extension.st @@ -0,0 +1,15 @@ +Extension { #name : 'FASTPyEntity' } + +{ #category : '*FAST-Python-ExtraTools' } +FASTPyEntity >> uniqueIdentifier [ + + + + ^ self attributeAt: #uniqueIdentifier ifAbsentPut: [ UUID new asString ] +] + +{ #category : '*FAST-Python-ExtraTools' } +FASTPyEntity >> uniqueIdentifier: aString [ + + ^ self attributeAt: #uniqueIdentifier put: aString +] diff --git a/src/FAST-Python-ExtraTools/FASTPyModel.extension.st b/src/FAST-Python-ExtraTools/FASTPyModel.extension.st new file mode 100644 index 0000000..125a8c3 --- /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`." + + ^ String streamContents: [ :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' } 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/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/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/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/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..563c688 100644 --- a/src/FAST-Python-Model/FASTPyExpression.class.st +++ b/src/FAST-Python-Model/FASTPyExpression.class.st @@ -201,7 +201,6 @@ FASTPyExpression >> parentAssignmentRight [ - ^ parentAssignmentRight ] @@ -221,7 +220,6 @@ FASTPyExpression >> parentAttributeObject [ - ^ parentAttributeObject ] @@ -240,7 +238,6 @@ FASTPyExpression >> parentChevron [ - ^ parentChevron ] @@ -278,7 +275,6 @@ FASTPyExpression >> parentComprehensionBody [ - ^ parentComprehensionBody ] @@ -333,7 +329,6 @@ FASTPyExpression >> parentConditionalExpressionElse [ - ^ parentConditionalExpressionElse ] @@ -352,7 +347,6 @@ FASTPyExpression >> parentConditionalExpressionThen [ - ^ parentConditionalExpressionThen ] @@ -371,7 +365,6 @@ FASTPyExpression >> parentDefaultParameterValue [ - ^ parentDefaultParameterValue ] @@ -390,7 +383,6 @@ FASTPyExpression >> parentExceptClause [ - ^ parentExceptClause ] @@ -427,7 +419,6 @@ FASTPyExpression >> parentForInClauseLeft [ - ^ parentForInClauseLeft ] @@ -446,7 +437,6 @@ FASTPyExpression >> parentForInClauseRight [ - ^ parentForInClauseRight ] @@ -466,7 +456,6 @@ FASTPyExpression >> parentForStatementLeft [ - ^ parentForStatementLeft ] @@ -486,7 +475,6 @@ FASTPyExpression >> parentForStatementRight [ - ^ parentForStatementRight ] @@ -505,7 +493,6 @@ FASTPyExpression >> parentIfClause [ - ^ parentIfClause ] @@ -524,7 +511,6 @@ FASTPyExpression >> parentInterpolation [ - ^ parentInterpolation ] @@ -544,7 +530,6 @@ FASTPyExpression >> parentKeywordArgument [ - ^ parentKeywordArgument ] @@ -563,7 +548,6 @@ FASTPyExpression >> parentLambda [ - ^ parentLambda ] @@ -582,7 +566,6 @@ FASTPyExpression >> parentMatchStatement [ - ^ parentMatchStatement ] @@ -601,7 +584,6 @@ FASTPyExpression >> parentPairKey [ - ^ parentPairKey ] @@ -620,7 +602,6 @@ FASTPyExpression >> parentPairValuer [ - ^ parentPairValuer ] @@ -659,7 +640,6 @@ FASTPyExpression >> parentSubscriptValue [ - ^ parentSubscriptValue ] @@ -679,7 +659,6 @@ FASTPyExpression >> parentUnaryOperator [ - ^ parentUnaryOperator ] @@ -698,7 +677,6 @@ FASTPyExpression >> parentWalrus [ - ^ parentWalrus ] @@ -717,7 +695,6 @@ FASTPyExpression >> parentYield [ - ^ parentYield ] 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/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/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..868c25b 100644 --- a/src/FAST-Python-Model/FASTPyString.class.st +++ b/src/FAST-Python-Model/FASTPyString.class.st @@ -70,7 +70,6 @@ FASTPyString >> interpolations [ - ^ interpolations ] 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/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/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/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/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 9484594..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 ] 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/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/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/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/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/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..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 ] @@ -174,7 +170,6 @@ FASTPyType >> parentMethodDefinition [ - ^ parentMethodDefinition ] @@ -193,7 +188,6 @@ FASTPyType >> parentParameter [ - ^ parentParameter ] @@ -248,7 +242,6 @@ FASTPyType >> parentyTypeAliasStatementAlias [ - ^ parentyTypeAliasStatementAlias ] @@ -267,7 +260,6 @@ FASTPyType >> parentyTypeAliasStatementType [ - ^ parentyTypeAliasStatementType ] 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/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 ] diff --git a/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st b/src/FAST-Python-Tools-Tests/FASTPythonAbstractTestCase.class.st index 6bb6733..af7e422 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,47 @@ 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. + ^ model +] + +{ #category : 'accessing' } +FASTPythonAbstractTestCase >> persist [ + + ^ persist ifNil: [ ^ false ] +] + +{ #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/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. diff --git a/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonImporterTest.class.st index a35ddf7..4a3f5a3 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,37 @@ 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 ifNil: [ ^ false ] +] + +{ #category : 'accessing' } +FASTPythonImporterTest >> persist: anObject [ + persist := anObject +] + { #category : 'tests - with statements' } FASTPythonImporterTest >> testAsPatternWithAttribute [ @@ -732,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' } @@ -1405,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' } @@ -2838,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' } @@ -4617,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' } @@ -4982,7 +5073,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' } @@ -6277,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. + + 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. - 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 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' } @@ -6600,7 +6723,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'. @@ -6627,7 +6750,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' } @@ -7748,7 +7871,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" @@ -9281,7 +9404,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" @@ -9658,7 +9781,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" @@ -10825,7 +10948,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' } @@ -10881,7 +11004,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' } @@ -10934,7 +11057,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' } @@ -10979,7 +11102,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' } @@ -11014,7 +11137,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' } @@ -11068,7 +11191,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" @@ -11140,7 +11263,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' } @@ -11174,7 +11297,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' } @@ -11209,7 +11332,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' } @@ -11244,7 +11367,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' } @@ -11278,7 +11401,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' } @@ -11313,7 +11436,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' } @@ -11346,7 +11469,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' } @@ -11380,7 +11503,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' } @@ -11423,7 +11546,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' } @@ -11467,7 +11590,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' } @@ -11502,7 +11625,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' } @@ -11556,7 +11679,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' } @@ -11591,7 +11714,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' } @@ -11640,7 +11763,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' } @@ -11686,7 +11809,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' } @@ -11822,7 +11945,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" @@ -12193,7 +12316,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" @@ -12217,7 +12340,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' } @@ -12553,7 +12676,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" @@ -15930,7 +16053,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. @@ -17870,7 +17993,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'. @@ -20186,7 +20309,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" @@ -21170,7 +21293,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' } @@ -22699,7 +22822,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" @@ -23596,7 +23719,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" @@ -23605,7 +23728,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' } @@ -23631,7 +23754,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" @@ -23640,13 +23763,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' } @@ -23672,7 +23795,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" @@ -23681,20 +23804,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' } @@ -23720,7 +23843,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" @@ -23729,19 +23852,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' } @@ -23767,7 +23890,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" @@ -23776,20 +23899,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' } @@ -23815,7 +23938,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" @@ -23824,7 +23947,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' } @@ -23850,7 +23973,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" @@ -23860,7 +23983,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' } @@ -23886,7 +24009,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" @@ -23895,7 +24018,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' } @@ -23921,7 +24044,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" @@ -23930,7 +24053,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' } @@ -23956,7 +24079,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" @@ -23966,7 +24089,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' } @@ -23992,7 +24115,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" @@ -24001,7 +24124,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' } @@ -24119,7 +24242,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" @@ -24129,13 +24252,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' } @@ -24700,7 +24823,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" @@ -25492,7 +25615,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" @@ -26070,7 +26193,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). @@ -26112,7 +26235,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" @@ -27310,7 +27433,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" @@ -27383,7 +27506,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" @@ -27475,7 +27598,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" @@ -27511,7 +27634,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" @@ -27599,7 +27722,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" @@ -27635,7 +27758,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" @@ -27679,7 +27802,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" @@ -27772,7 +27895,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" @@ -27808,7 +27931,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" @@ -27852,7 +27975,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" @@ -27948,7 +28071,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" @@ -28012,7 +28135,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" @@ -28053,7 +28176,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' } @@ -28078,7 +28201,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' } @@ -28104,7 +28227,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' } @@ -28132,7 +28255,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" @@ -28141,13 +28264,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' } @@ -28192,7 +28315,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. @@ -28241,13 +28364,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' } @@ -28273,13 +28396,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' } @@ -28305,7 +28428,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' } @@ -28342,7 +28465,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' } @@ -28666,7 +28789,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' } @@ -29354,7 +29477,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. @@ -31851,7 +31974,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" @@ -32643,7 +32766,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" @@ -33220,7 +33343,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). @@ -33262,7 +33385,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" @@ -35109,7 +35232,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' } @@ -36813,7 +36936,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. @@ -37093,7 +37216,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. @@ -37117,7 +37240,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. @@ -37176,7 +37299,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" @@ -37492,7 +37615,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. @@ -37650,7 +37773,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. @@ -37717,7 +37840,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. @@ -38875,7 +38998,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. @@ -39052,7 +39175,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). @@ -39284,7 +39407,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" @@ -39359,7 +39482,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" @@ -39368,7 +39491,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" @@ -39790,7 +39913,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" @@ -39858,7 +39981,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" @@ -40283,7 +40406,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' } @@ -41437,7 +41560,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' } @@ -42020,7 +42143,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" @@ -42813,7 +42936,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" @@ -43389,7 +43512,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). @@ -43431,7 +43554,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" @@ -44463,7 +44586,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' } @@ -48482,7 +48605,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' } @@ -49475,7 +49598,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. @@ -49490,7 +49613,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' } @@ -49840,7 +49963,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. @@ -51271,7 +51394,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: '~(' ] @@ -52042,7 +52165,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' } 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/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' +} diff --git a/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st b/src/FAST-Python-Tools-Tests/FASTPythonSSATest.class.st index 0ca3c78..afdad22 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' } @@ -1880,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 ] @@ -1913,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 ] 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' } 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 8463c54..c86c527 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' } @@ -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' } @@ -62,7 +61,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' } @@ -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' } @@ -104,12 +99,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/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. diff --git a/src/FAST-Python-Tools/FASTTEntity.extension.st b/src/FAST-Python-Tools/FASTTEntity.extension.st index 622a8a4..6e3bd17 100644 --- a/src/FAST-Python-Tools/FASTTEntity.extension.st +++ b/src/FAST-Python-Tools/FASTTEntity.extension.st @@ -1,14 +1,9 @@ Extension { #name : 'FASTTEntity' } -{ #category : '*FAST-Python-Tools' } -FASTTEntity >> ensureLocalUses [ - - self attributeAt: #localUses ifAbsentPut: OrderedCollection new -] - { #category : '*FAST-Python-Tools' } FASTTEntity >> resetLocalResolution [ + (self attributeAt: #localUses ifAbsent: [ nil ]) ifNotNil: [ :uses | uses removeAll ]. self removeAttribute: #localDeclaration. self removeAttribute: #localUses ]