From cd1e7c306c58e03ebe677a29f9954e9cf8e4cc87 Mon Sep 17 00:00:00 2001 From: CyrilFerlicot Date: Thu, 24 Sep 2026 19:01:50 +0200 Subject: [PATCH] Introduce FASTTCanBeLocalDeclaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently FASTNonLocalDeclaration is using FASTTEntity to got the LR and SSA API. But this is wrong because it should not be a FASTTEntity. I extracted this API to a FASTTCanBeLocalDeclaration trait used by FASTTEntity and FASTNonLocalDeclaration. This is a first step to: - Include LR/SSA entities in the meta description - Export LR/SSA data in JSON/MSE --- .../FASTTCanBeLocalDeclaration.trait.st | 20 ++ src/FAST-Core-Model/FASTTEntity.trait.st | 8 +- .../FASTNonLocalDeclaration.class.st | 4 +- .../FASTTCanBeLocalDeclaration.extension.st | 195 ++++++++++++++++++ src/FAST-Core-Tools/FASTTEntity.extension.st | 194 ----------------- .../FASTMetamodelGenerator.class.st | 5 +- 6 files changed, 225 insertions(+), 201 deletions(-) create mode 100644 src/FAST-Core-Model/FASTTCanBeLocalDeclaration.trait.st create mode 100644 src/FAST-Core-Tools/FASTTCanBeLocalDeclaration.extension.st diff --git a/src/FAST-Core-Model/FASTTCanBeLocalDeclaration.trait.st b/src/FAST-Core-Model/FASTTCanBeLocalDeclaration.trait.st new file mode 100644 index 0000000..3ad932c --- /dev/null +++ b/src/FAST-Core-Model/FASTTCanBeLocalDeclaration.trait.st @@ -0,0 +1,20 @@ +" +This trait is here to add API used for the local resolution. + + +" +Trait { + #name : 'FASTTCanBeLocalDeclaration', + #category : 'FAST-Core-Model-Traits', + #package : 'FAST-Core-Model', + #tag : 'Traits' +} + +{ #category : 'meta' } +FASTTCanBeLocalDeclaration classSide >> annotation [ + + + + + +] diff --git a/src/FAST-Core-Model/FASTTEntity.trait.st b/src/FAST-Core-Model/FASTTEntity.trait.st index 74b5528..04a5c4c 100644 --- a/src/FAST-Core-Model/FASTTEntity.trait.st +++ b/src/FAST-Core-Model/FASTTEntity.trait.st @@ -13,11 +13,11 @@ any entity Trait { #name : 'FASTTEntity', #instVars : [ - '#startPos => FMProperty', - '#endPos => FMProperty' + '#endPos => FMProperty', + '#startPos => FMProperty' ], - #traits : 'TEntityMetaLevelDependency', - #classTraits : 'TEntityMetaLevelDependency classTrait', + #traits : 'FASTTCanBeLocalDeclaration + TEntityMetaLevelDependency', + #classTraits : 'FASTTCanBeLocalDeclaration classTrait + TEntityMetaLevelDependency classTrait', #category : 'FAST-Core-Model-Traits', #package : 'FAST-Core-Model', #tag : 'Traits' diff --git a/src/FAST-Core-Tools/FASTNonLocalDeclaration.class.st b/src/FAST-Core-Tools/FASTNonLocalDeclaration.class.st index 847497d..150d792 100644 --- a/src/FAST-Core-Tools/FASTNonLocalDeclaration.class.st +++ b/src/FAST-Core-Tools/FASTNonLocalDeclaration.class.st @@ -4,8 +4,8 @@ A ""null-object"" signaling the declaration of a 'name' was not found Class { #name : 'FASTNonLocalDeclaration', #superclass : 'FASTEntity', - #traits : 'FASTTEntity', - #classTraits : 'FASTTEntity classTrait', + #traits : 'FASTTCanBeLocalDeclaration', + #classTraits : 'FASTTCanBeLocalDeclaration classTrait', #instVars : [ 'name' ], diff --git a/src/FAST-Core-Tools/FASTTCanBeLocalDeclaration.extension.st b/src/FAST-Core-Tools/FASTTCanBeLocalDeclaration.extension.st new file mode 100644 index 0000000..494014a --- /dev/null +++ b/src/FAST-Core-Tools/FASTTCanBeLocalDeclaration.extension.st @@ -0,0 +1,195 @@ +Extension { #name : 'FASTTCanBeLocalDeclaration' } + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> activeVersion [ + "Used for SSA" + + ^ self attributeAt: #activeVersion ifAbsent: [ nil ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> activeVersion: aSSAVersion [ + "Used for SSA" + + ^ self attributeAt: #activeVersion put: aSSAVersion +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> addLocalUse: aFASTNode [ + "Used for LocalResolver" + + (self attributeAt: #localUses ifAbsent: [ Error signal: 'missing #localUses attribute in ' , self asString ]) add: aFASTNode +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> allAccesses [ + "For a specific variable, I return all the read and write accesses to the variable. + + Note that the receiver should be a node representing a variable for it to work." + + ^ self localDeclaration localUses +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> allReadAccesses [ + "For a specific variable, I return all the read accesses to the variable. + + Note that the receiver should be a node representing a variable for it to work." + + ^ self localDeclaration localUses reject: [ :access | access isVariableWriteAccess ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> allWriteAccesses [ + "For a specific variable, I return all the write accesses to the variable. + + Note that the receiver should be a node representing a variable for it to work." + + ^ self localDeclaration localUses select: [ :access | access isVariableWriteAccess ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> assignedExpressions [ + "If I am a node representing an assignment (can be a for each for example), return the expressions used for the assignment. Else return an empty collection" + + ^ self explicitRequirement +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> assignedExpressionsMap [ + + | result | + result := Dictionary new. + + self versionWriteAccesses do: [ :access | result at: access put: access variableDeclaration assignedExpressions ]. + ^ result +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> clearLocalUses [ + "Used for LocalResolver" + + self attributeAt: #localUses put: OrderedCollection new +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> hasLocalDeclaration [ + "Used for LocalResolver" + + ^ self localDeclarationifPresent: [ true ] ifAbsent: [ false ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> localDeclaration [ + "Used for LocalResolver" + + ^ self localDeclarationIfAbsent: [ + self error: 'Missing #localDeclaration attribute in ' , self asString , '. It can have multiple sources: +- The local resolution was not done (launch the local resolver visitor or the SSA visitor on your top module) +- The entity is not an entity with a definition +- There is a bug in the local resolver' ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> localDeclaration: aDeclarationNode [ + "Used for LocalResolver" + + self attributeAt: #localDeclaration put: aDeclarationNode +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> localDeclarationIfAbsent: aBlock [ + "Used for LocalResolver" + + ^ self attributeAt: #localDeclaration ifAbsent: aBlock +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> localDeclarationifPresent: aBlock ifAbsent: anotherBlock [ + "Used for LocalResolver" + + ^ aBlock cull: (self attributeAt: #localDeclaration ifAbsent: anotherBlock) +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> localUses [ + "Used for LocalResolver" + + ^ self attributeAt: #localUses ifAbsent: [ Error signal: 'missing #localUses attribute in ' , self asString ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> localUses: aCollection [ + "Used for LocalResolver" + + self attributeAt: #localUses put: aCollection +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> newVersionNumber [ + "Used for SSA" + + ^ self activeVersion + ifNil: [ 0 ] + ifNotNil: [ :active | active version + 1 ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> ssaName [ + "Used for SSA" + + ^ self ssaVersion name +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> ssaVersion [ + "If I represent a variable and we resolved the SSA of my FAST model, I'll return the SSA version I'm linked to." + + ^ self attributeAt: #ssaVersion ifAbsent: [ nil ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> ssaVersion: aSSAVersion [ + "Used for SSA" + + self attributeAt: #ssaVersion put: aSSAVersion +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> versionAccesses [ + "For a specific variable, I return all the read and write accesses to the current version of the variable. + + The current version match the current SSA version of the variable. It means that it ill ignore all read and write accesses that cannot impact the currently assigned variable (in case of assignemnts in a conditional, takes all possible versions). + + Note that the receiver should be a node representing a variable for it to work." + + ^ self ssaVersion + ifNil: [ + self error: 'No SSA version available. Possible sources: + - You did not run the SSA resolver + - Your node is not representing a variable + - There is a bug in the SSA or Local resolver' ] + ifNotNil: [ :version | version localUses ] +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> versionReadAccesses [ + "For a specific variable, I return all the read accesses to the current version of the variable. + + The current version match the current SSA version of the variable. It means that it ill ignore all read and write accesses that cannot impact the currently assigned variable (in case of assignemnts in a conditional, takes all possible versions). + + Note that the receiver should be a node representing a variable for it to work." + + ^ self versionAccesses reject: #isVariableWriteAccess +] + +{ #category : '*FAST-Core-Tools' } +FASTTCanBeLocalDeclaration >> versionWriteAccesses [ + "For a specific variable, I return all the write accesses to the current version of the variable. + + The current version match the current SSA version of the variable. It means that it ill ignore all read and write accesses that cannot impact the currently assigned variable (in case of assignemnts in a conditional, takes all possible versions). + + Note that the receiver should be a node representing a variable for it to work." + + ^ self versionAccesses select: #isVariableWriteAccess +] diff --git a/src/FAST-Core-Tools/FASTTEntity.extension.st b/src/FAST-Core-Tools/FASTTEntity.extension.st index b08d92d..ab85c36 100644 --- a/src/FAST-Core-Tools/FASTTEntity.extension.st +++ b/src/FAST-Core-Tools/FASTTEntity.extension.st @@ -1,77 +1,5 @@ Extension { #name : 'FASTTEntity' } -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> activeVersion [ - "Used for SSA" - - ^ self attributeAt: #activeVersion ifAbsent: [ nil ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> activeVersion: aSSAVersion [ - "Used for SSA" - - ^ self attributeAt: #activeVersion put: aSSAVersion -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> addLocalUse: aFASTNode [ - "Used for LocalResolver" - - (self attributeAt: #localUses ifAbsent: [ Error signal: 'missing #localUses attribute in ' , self asString ]) add: aFASTNode -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> allAccesses [ - "For a specific variable, I return all the read and write accesses to the variable. - - Note that the receiver should be a node representing a variable for it to work." - - ^ self localDeclaration localUses -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> allReadAccesses [ - "For a specific variable, I return all the read accesses to the variable. - - Note that the receiver should be a node representing a variable for it to work." - - ^ self localDeclaration localUses reject: [ :access | access isVariableWriteAccess ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> allWriteAccesses [ - "For a specific variable, I return all the write accesses to the variable. - - Note that the receiver should be a node representing a variable for it to work." - - ^ self localDeclaration localUses select: [ :access | access isVariableWriteAccess ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> assignedExpressions [ - "If I am a node representing an assignment (can be a for each for example), return the expressions used for the assignment. Else return an empty collection" - - ^ self explicitRequirement -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> assignedExpressionsMap [ - - | result | - result := Dictionary new. - - self versionWriteAccesses do: [ :access | result at: access put: access variableDeclaration assignedExpressions ]. - ^ result -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> clearLocalUses [ - "Used for LocalResolver" - - self attributeAt: #localUses put: OrderedCollection new -] - { #category : '*FAST-Core-Tools' } FASTTEntity >> dump [ @@ -80,13 +8,6 @@ FASTTEntity >> dump [ ^ FASTDumpVisitor visit: self ] -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> hasLocalDeclaration [ - "Used for LocalResolver" - - ^ self localDeclarationifPresent: [ true ] ifAbsent: [ false ] -] - { #category : '*FAST-Core-Tools' } FASTTEntity >> inspectionFASTDump: aBuilder [ @@ -120,124 +41,9 @@ FASTTEntity >> isVariableWriteAccess [ ^ self variableDeclaration isNotNil ] -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> localDeclaration [ - "Used for LocalResolver" - - ^ self localDeclarationIfAbsent: [ - self error: 'Missing #localDeclaration attribute in ' , self asString , '. It can have multiple sources: -- The local resolution was not done (launch the local resolver visitor or the SSA visitor on your top module) -- The entity is not an entity with a definition -- There is a bug in the local resolver' ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> localDeclaration: aDeclarationNode [ - "Used for LocalResolver" - - self attributeAt: #localDeclaration put: aDeclarationNode -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> localDeclarationIfAbsent: aBlock [ - "Used for LocalResolver" - - ^ self attributeAt: #localDeclaration ifAbsent: aBlock -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> localDeclarationifPresent: aBlock ifAbsent: anotherBlock [ - "Used for LocalResolver" - - ^ aBlock cull: (self attributeAt: #localDeclaration ifAbsent: anotherBlock) -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> localUses [ - "Used for LocalResolver" - - ^ self attributeAt: #localUses ifAbsent: [ Error signal: 'missing #localUses attribute in ' , self asString ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> localUses: aCollection [ - "Used for LocalResolver" - - self attributeAt: #localUses put: aCollection -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> newVersionNumber [ - "Used for SSA" - - ^ self activeVersion - ifNil: [ 0 ] - ifNotNil: [ :active | active version + 1 ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> ssaName [ - "Used for SSA" - - ^ self ssaVersion name -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> ssaVersion [ - "If I represent a variable and we resolved the SSA of my FAST model, I'll return the SSA version I'm linked to." - - ^ self attributeAt: #ssaVersion ifAbsent: [ nil ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> ssaVersion: aSSAVersion [ - "Used for SSA" - - self attributeAt: #ssaVersion put: aSSAVersion -] - { #category : '*FAST-Core-Tools' } FASTTEntity >> variableDeclaration [ "If I am a node representing a write access, I should return the node assigning me. Else I return nil." ^ self explicitRequirement ] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> versionAccesses [ - "For a specific variable, I return all the read and write accesses to the current version of the variable. - - The current version match the current SSA version of the variable. It means that it ill ignore all read and write accesses that cannot impact the currently assigned variable (in case of assignemnts in a conditional, takes all possible versions). - - Note that the receiver should be a node representing a variable for it to work." - - ^ self ssaVersion - ifNil: [ - self error: 'No SSA version available. Possible sources: - - You did not run the SSA resolver - - Your node is not representing a variable - - There is a bug in the SSA or Local resolver' ] - ifNotNil: [ :version | version localUses ] -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> versionReadAccesses [ - "For a specific variable, I return all the read accesses to the current version of the variable. - - The current version match the current SSA version of the variable. It means that it ill ignore all read and write accesses that cannot impact the currently assigned variable (in case of assignemnts in a conditional, takes all possible versions). - - Note that the receiver should be a node representing a variable for it to work." - - ^ self versionAccesses reject: #isVariableWriteAccess -] - -{ #category : '*FAST-Core-Tools' } -FASTTEntity >> versionWriteAccesses [ - "For a specific variable, I return all the write accesses to the current version of the variable. - - The current version match the current SSA version of the variable. It means that it ill ignore all read and write accesses that cannot impact the currently assigned variable (in case of assignemnts in a conditional, takes all possible versions). - - Note that the receiver should be a node representing a variable for it to work." - - ^ self versionAccesses select: #isVariableWriteAccess -] diff --git a/src/FAST-Model-Generator/FASTMetamodelGenerator.class.st b/src/FAST-Model-Generator/FASTMetamodelGenerator.class.st index f538967..942e6c1 100644 --- a/src/FAST-Model-Generator/FASTMetamodelGenerator.class.st +++ b/src/FAST-Model-Generator/FASTMetamodelGenerator.class.st @@ -40,7 +40,8 @@ Class { 'tWithCondition', 'tBreakStatement', 'tContinueStatement', - 'tCanBeVariable' + 'tCanBeVariable', + 'tCanBeLocalDeclaration' ], #category : 'FAST-Model-Generator', #package : 'FAST-Model-Generator' @@ -221,6 +222,7 @@ FASTMetamodelGenerator >> defineClasses [ FASTMetamodelGenerator >> defineHierarchy [ super defineHierarchy. tEntity --|> #TEntityMetaLevelDependency. + tEntity --|> tCanBeLocalDeclaration. tExpression --|> tEntity. entity --|> tEntity. @@ -351,6 +353,7 @@ FASTMetamodelGenerator >> defineTraits [ tBreakStatement withTesting. tCanBeVariable := (builder newTraitNamed: #TCanBeVariable) comment: 'Represent everything that can be a variable. Useful for the LocalResolver and the SSA builder.'. tCanBeVariable testingSelector: #canBeVariable. + tCanBeLocalDeclaration := (builder newTraitNamed: #TCanBeLocalDeclaration) comment: 'This trait is here to add API used for the local resolution.'. tCharacterLiteral := builder newTraitNamed: #TCharacterLiteral comment: self commentForTCharacterLiteral. tCharacterLiteral withTesting. tComment := builder newTraitNamed: #TComment.