-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #534 from nasa/feature/state-machine-phase-2
State Machines Phase 2
- Loading branch information
Showing
758 changed files
with
51,762 additions
and
4,009 deletions.
There are no files selected for viewing
2,121 changes: 1,879 additions & 242 deletions
2,121
compiler/lib/src/main/resources/META-INF/native-image/reflect-config.json
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
compiler/lib/src/main/scala/analysis/Analyzers/StateMachine/SmTypedElementAnalyzer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package fpp.compiler.analysis | ||
|
||
import fpp.compiler.ast._ | ||
import fpp.compiler.util._ | ||
|
||
/** State machine typed element analyzer */ | ||
trait SmTypedElementAnalyzer | ||
extends StateMachineAnalysisVisitor | ||
with StateAnalyzer | ||
{ | ||
|
||
// ---------------------------------------------------------------------- | ||
// Interface methods to override | ||
// Each of these methods is called when a corresponding typed element | ||
// is visited | ||
// ---------------------------------------------------------------------- | ||
|
||
def initialTransitionTypedElement( | ||
sma: StateMachineAnalysis, | ||
te: StateMachineTypedElement.InitialTransition | ||
): Result = default(sma) | ||
|
||
def choiceTypedElement( | ||
sma: StateMachineAnalysis, | ||
te: StateMachineTypedElement.Choice | ||
): Result = default(sma) | ||
|
||
def stateEntryTypedElement( | ||
sma: StateMachineAnalysis, | ||
te: StateMachineTypedElement.StateEntry | ||
): Result = default(sma) | ||
|
||
def stateExitTypedElement( | ||
sma: StateMachineAnalysis, | ||
te: StateMachineTypedElement.StateExit | ||
): Result = default(sma) | ||
|
||
def stateTransitionTypedElement( | ||
sma: StateMachineAnalysis, | ||
te: StateMachineTypedElement.StateTransition | ||
): Result = default(sma) | ||
|
||
// ---------------------------------------------------------------------- | ||
// Implementation using StateMachineAnalysisVisitor | ||
// ---------------------------------------------------------------------- | ||
|
||
def visitTypedElement( | ||
sma: StateMachineAnalysis, | ||
te: StateMachineTypedElement | ||
): Result = te match { | ||
case it: StateMachineTypedElement.InitialTransition => | ||
initialTransitionTypedElement(sma, it) | ||
case c: StateMachineTypedElement.Choice => | ||
choiceTypedElement(sma, c) | ||
case se: StateMachineTypedElement.StateEntry => | ||
stateEntryTypedElement(sma, se) | ||
case se: StateMachineTypedElement.StateExit => | ||
stateExitTypedElement(sma, se) | ||
case st: StateMachineTypedElement.StateTransition => | ||
stateTransitionTypedElement(sma, st) | ||
} | ||
|
||
override def defChoiceAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.DefChoice]] | ||
) = visitTypedElement( | ||
sma, | ||
StateMachineTypedElement.Choice(aNode) | ||
) | ||
|
||
override def specStateEntryAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecStateEntry]] | ||
) = visitTypedElement( | ||
sma, | ||
StateMachineTypedElement.StateEntry(aNode) | ||
) | ||
|
||
override def specStateExitAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecStateExit]] | ||
) = visitTypedElement( | ||
sma, | ||
StateMachineTypedElement.StateExit(aNode) | ||
) | ||
|
||
override def specInitialTransitionAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecInitialTransition]] | ||
) = visitTypedElement( | ||
sma, | ||
StateMachineTypedElement.InitialTransition(aNode) | ||
) | ||
|
||
override def specStateTransitionAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecStateTransition]] | ||
) = visitTypedElement( | ||
sma, | ||
StateMachineTypedElement.StateTransition(aNode) | ||
) | ||
|
||
} |
19 changes: 19 additions & 0 deletions
19
compiler/lib/src/main/scala/analysis/Analyzers/StateMachine/StateAnalyzer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package fpp.compiler.analysis | ||
|
||
import fpp.compiler.ast._ | ||
|
||
/** Analyze state definition members */ | ||
trait StateAnalyzer extends StateMachineAnalysisVisitor { | ||
|
||
override def defStateAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.DefState]] | ||
) = { | ||
val (_, node, _) = aNode | ||
val data = node.data | ||
val sma1 = sma.copy(scopeNameList = data.name :: sma.scopeNameList) | ||
for { sma2 <- visitList(sma1, data.members, matchStateMember) } | ||
yield sma2.copy(scopeNameList = sma.scopeNameList) | ||
} | ||
|
||
} |
20 changes: 20 additions & 0 deletions
20
...iler/lib/src/main/scala/analysis/Analyzers/StateMachine/StateMachineAnalysisVisitor.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package fpp.compiler.analysis | ||
|
||
import fpp.compiler.ast._ | ||
|
||
/** A generic analysis visitor for state machine semantics */ | ||
trait StateMachineAnalysisVisitor extends AstStateVisitor { | ||
|
||
type State = StateMachineAnalysis | ||
|
||
/** Apply an analysis to an option value */ | ||
final def opt[T] (f: (StateMachineAnalysis, T) => Result) (sma: StateMachineAnalysis, o: Option[T]): Result = | ||
o.map(x => f(sma, x)).getOrElse(Right(sma)) | ||
|
||
override def defStateMachineAnnotatedNodeInternal( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.DefStateMachine]], | ||
members: List[Ast.StateMachineMember] | ||
) = visitList(sma, members, matchStateMachineMember) | ||
|
||
} |
127 changes: 127 additions & 0 deletions
127
compiler/lib/src/main/scala/analysis/Analyzers/StateMachine/StateMachineUseAnalyzer.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package fpp.compiler.analysis | ||
|
||
import fpp.compiler.ast._ | ||
import fpp.compiler.util._ | ||
|
||
/** Analyze state machine uses */ | ||
trait StateMachineUseAnalyzer | ||
extends StateMachineAnalysisVisitor | ||
with StateAnalyzer | ||
{ | ||
|
||
// ---------------------------------------------------------------------- | ||
// Interface methods to override | ||
// Each of these methods is called when a corresponding use occurs | ||
// ---------------------------------------------------------------------- | ||
|
||
/** A use of an action definition */ | ||
def actionUse( | ||
sma: StateMachineAnalysis, | ||
node: AstNode[Ast.Ident], | ||
use: Name.Unqualified | ||
): Result = default(sma) | ||
|
||
/** A use of a guard definition */ | ||
def guardUse( | ||
sma: StateMachineAnalysis, | ||
node: AstNode[Ast.Ident], | ||
use: Name.Unqualified | ||
): Result = default(sma) | ||
|
||
/** A use of a signal definition */ | ||
def signalUse( | ||
sma: StateMachineAnalysis, | ||
node: AstNode[Ast.Ident], | ||
use: Name.Unqualified | ||
): Result = default(sma) | ||
|
||
/** A use of a state definition or choice definition */ | ||
def stateOrChoiceUse( | ||
sma: StateMachineAnalysis, | ||
node: AstNode[Ast.QualIdent], | ||
use: Name.Qualified | ||
): Result = default(sma) | ||
|
||
// ---------------------------------------------------------------------- | ||
// Implementation using StateMachineAnalysisVisitor | ||
// ---------------------------------------------------------------------- | ||
|
||
override def defChoiceAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.DefChoice]] | ||
) = { | ||
val data = aNode._2.data | ||
for { | ||
sma <- identNode(guardUse)(sma, data.guard) | ||
sma <- transitionExpr(sma, data.ifTransition.data) | ||
sma <- transitionExpr(sma, data.elseTransition.data) | ||
} | ||
yield sma | ||
} | ||
|
||
override def specStateEntryAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecStateEntry]] | ||
) = actions(sma, aNode._2.data.actions) | ||
|
||
override def specStateExitAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecStateExit]] | ||
) = actions(sma, aNode._2.data.actions) | ||
|
||
override def specInitialTransitionAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecInitialTransition]] | ||
) = transitionExpr(sma, aNode._2.data.transition.data) | ||
|
||
override def specStateTransitionAnnotatedNode( | ||
sma: StateMachineAnalysis, | ||
aNode: Ast.Annotated[AstNode[Ast.SpecStateTransition]] | ||
) = { | ||
val data = aNode._2.data | ||
for { | ||
sma <- identNode(signalUse)(sma, data.signal) | ||
sma <- opt(identNode(guardUse))(sma, data.guard) | ||
sma <- transitionOrDo(sma, data.transitionOrDo) | ||
} | ||
yield sma | ||
} | ||
|
||
// ---------------------------------------------------------------------- | ||
// Private helper methods | ||
// ---------------------------------------------------------------------- | ||
|
||
private def transitionExpr( | ||
sma: StateMachineAnalysis, | ||
e: Ast.TransitionExpr | ||
): Result = | ||
for { | ||
sma <- actions(sma, e.actions) | ||
sma <- qualIdentNode(stateOrChoiceUse)(sma, e.target) | ||
} | ||
yield sma | ||
|
||
private def actions(sma: StateMachineAnalysis, actions: List[AstNode[Ast.Ident]]) = | ||
Result.foldLeft (actions) (sma) (identNode(actionUse)) | ||
|
||
private def transitionOrDo( | ||
sma: StateMachineAnalysis, | ||
tod: Ast.TransitionOrDo | ||
): Result = tod match { | ||
case Ast.TransitionOrDo.Transition(e) => transitionExpr(sma, e.data) | ||
case Ast.TransitionOrDo.Do(as) => actions(sma, as) | ||
} | ||
|
||
private def identNode | ||
(f: (StateMachineAnalysis, AstNode[Ast.Ident], Name.Unqualified) => Result) | ||
(sma: StateMachineAnalysis, ident: AstNode[Ast.Ident]): Result = | ||
f(sma, ident, ident.data) | ||
|
||
private def qualIdentNode | ||
(f: (StateMachineAnalysis, AstNode[Ast.QualIdent], Name.Qualified) => Result) | ||
(sma: StateMachineAnalysis, qualIdent: AstNode[Ast.QualIdent]): Result = { | ||
val use = Name.Qualified.fromQualIdent(qualIdent.data) | ||
f(sma, qualIdent, use) | ||
} | ||
|
||
} |
Oops, something went wrong.