Documentation
¶
Overview ¶
Package lower provides AST → execution IR lowering. Converts declarative members (TransitionMember, EntryMember) to operational graphs (nodes + edges) that executors consume.
Index ¶
- Constants
- Variables
- func ActionEndpointAccepted(nodes []ast.Node, hasInitial bool, ref ast.Node, source bool) bool
- func ActionNodes(actionDecl ast.Node, scope *symbols.Scope) (nodes []ast.Node, hasInitial bool, err error)
- func BehaviorMembers(decl ast.Node) ([]ast.Node, error)
- func BodyStatementMembers(members []ast.Node) []ast.Node
- func FeaturePath(node ast.Node) string
- func Returns(stmts []Statement) bool
- func SendTarget(node ast.Node) (string, bool)
- func StatesBehaviorBody(members []ast.Node) bool
- func VertexDecls(stateMachineDecl ast.Node, scope *symbols.Scope) (map[ast.Node]bool, error)
- func VertexKind(decl ast.Node) string
- type Accept
- type ActionEdge
- type ActionGraph
- type Assign
- type AssignTarget
- type Attribute
- type Binding
- type BindingEnd
- type Block
- type ClassifierBehavior
- type ClassifierBehaviorKind
- type Connection
- type ConnectionOwner
- type Declare
- type DeclareUsage
- type Effect
- type EffectKind
- type EndpointResolver
- type If
- type Loop
- type ObjectFlow
- type Return
- type Send
- type StateBehavior
- type StateBehaviors
- type StateGraph
- type StateTypeResolver
- type Statement
- type Subflow
- type Transition
- type Unsupported
Constants ¶
const NotAVertexFormat = "transition endpoint %s names a %s that is not a vertex of this state machine"
NotAVertexFormat reports an endpoint naming an element outside the machine's vertices, shared by the check reporting it and the lowering backstopping it.
Variables ¶
var ErrRecursiveStateTyping = errors.New("recursive state typing")
ErrRecursiveStateTyping reports a state definition whose content contains a state typed by that same definition, which has no finite materialization.
var ErrStatementOutsideFlow = errors.New("has no position in the token flow")
ErrStatementOutsideFlow reports a statement written among an action's own members that no succession binds, so it holds no position in the token flow.
var ErrUnsupportedStateContent = errors.New("unsupported state machine content")
ErrUnsupportedStateContent reports content of a state machine that lowering cannot represent, rather than dropping it.
Functions ¶
func ActionEndpointAccepted ¶ added in v0.3.0
ActionEndpointAccepted reports whether an action endpoint names a lowered node or one of the implicit start/done markers.
func ActionNodes ¶ added in v0.3.0
func ActionNodes(actionDecl ast.Node, scope *symbols.Scope) (nodes []ast.Node, hasInitial bool, err error)
ActionNodes returns the nodes accepted by action lowering and whether the action has an initial node after interpreting `first <node>`.
func BehaviorMembers ¶
BehaviorMembers are the members of a behavior declaration, and an error for a node that declares no behavior.
func BodyStatementMembers ¶ added in v0.2.0
BodyStatementMembers returns the members of a node body that state work to perform, in declaration order: what a body declares (a parameter, a doc comment) is a feature of the node, not a step of the flow through it.
func FeaturePath ¶
FeaturePath renders the feature a node names as a dotted path, so a nested port keeps every segment it was written with. It returns "" for a node that names no feature.
func Returns ¶
Returns reports whether the statements return a value on some path, so a calculation whose body only computes can be told from one that has no result.
func SendTarget ¶
SendTarget renders a send's target and reports whether it is a feature chain (`alpha.inPort`) rather than a name in a namespace (`R`, `P::R`).
func StatesBehaviorBody ¶
StatesBehaviorBody reports whether members state a behavior body rather than only annotating the declaration or binding the behavior's parameters (`exhibit m { in x = y; }`, `exhibit m : M { doc /* … */ }`).
func VertexDecls ¶
VertexDecls returns every declaration a transition of this state machine may name as an endpoint, collected by the pass a lowered graph's vertices are collected by, so a checker reads the same ownership the executor does. scope is the scope the machine's body was declared in.
func VertexKind ¶
VertexKind names what an endpoint reached in modelling terms, for a message a modeller reads.
Types ¶
type Accept ¶
type Accept struct {
ParamName string
SignalType string
ViaPort string
SubsetsEvent string
Trigger ast.Node
}
Accept is a lowered accept parameter: `action r accept msg : Warning;`. SignalType is the parameter's declared type, empty when it was declared without one, in which case the node accepts a message of any type.
ViaPort is the port named by `accept msg : Warning via p`, empty when the accept named none. A port-routed message is only offered to an accept on the port it arrived at, so the two forms do not consume each other's messages.
SubsetsEvent is the event feature the payload subsets (`accept :> shutDown`), empty when it subsets none. Such an accept waits for an occurrence of that one event rather than for any occurrence of a type.
Trigger is the time or change event of `accept at t` / `accept after d` / `accept when c`, nil when the accept waits for a message instead.
type ActionEdge ¶ added in v0.3.0
ActionEdge is one succession out of a node: the target it reaches, the guard it carries, and the declaration it was written as.
type ActionGraph ¶
type ActionGraph struct {
// Scope is the scope the action's body was declared in, in which every
// expression written directly among its members resolves its names. A nested
// node or a body-local block carries its own scope instead.
Scope *symbols.Scope
// Attributes are the attribute defaults the action declares, in order.
Attributes []Attribute
// Nodes in the graph (InitialNode, FinalNode, ExecutionNode, etc.)
Nodes []ast.Node
// Edges: source node → successions in declaration order.
Edges map[ast.Node][]ActionEdge
// DataFlows: source node → list of object flows
DataFlows map[ast.Node][]ObjectFlow
// Bodies: node → the statements that node executes, in declaration order
Bodies map[ast.Node][]Statement
// Accepts: node → the message that node waits for
Accepts map[ast.Node]Accept
// Subflows: node → the flow the node's own members state, present only for a
// node that states one. Its subactions are subperformances of the node, so it
// completes only when that flow does (action_subflow.go).
Subflows map[ast.Node]*Subflow
// InitialNode (required)
Initial ast.Node
// FinalNodes (may be multiple)
Finals []ast.Node
// Connections are the connectors declared in the action body, which is how
// a `send ... via <port>` finds the ports it reaches.
Connections []Connection
// StatementRuns marks the nodes of a block's own flow that stand for a run of
// statements rather than for an action node (block_graph.go). Such a node is
// keyed by the first statement of the run, whose name names no step.
StatementRuns map[ast.Node]bool
}
ActionGraph is the execution IR for actions. Nodes represent control flow points, edges represent flow paths.
func ToActionGraph ¶
ToActionGraph converts an action AST (Usage or Definition) to an ActionGraph. scope is the scope the action's body was declared in — the scope the action itself owns — which every expression the graph carries is evaluated in. Returns error if graph is malformed (e.g., no initial node, dangling edges).
type Assign ¶
type Assign struct {
Target string
// Chain is the chained target the assignment writes through (`s.reading`),
// nil when the target was a plain name the body's host binds.
Chain *AssignTarget
Value ast.Node
Node ast.Node // the statement itself, for diagnostics
Scope *symbols.Scope // the scope the statement was declared in
}
Assign is a lowered assignment: `assign <Target> := <Value>`. Target is the feature written — the target's last segment — empty when the target names no feature.
type AssignTarget ¶ added in v0.4.0
type AssignTarget struct {
// Base is the expression the chain starts from, evaluated in the statement's
// own scope.
Base ast.Node
// Steps are the features walked from Base to the object written, in order.
Steps []string
// Text is the target as written (`a.b.c`), for diagnostics.
Text string
}
AssignTarget is a chained assignment target: `assign a.b.c := v` walks `b` from `a` and writes `c` on the object it reaches.
type Attribute ¶
type Attribute struct {
Name string
Value ast.Node
Node ast.Node // the declaration itself, for diagnostics
// Scope is the scope the declaration was written in, in which its default
// resolves; nil where the owner's own scope resolves it.
Scope *symbols.Scope
}
Attribute is a lowered attribute default written among a behavior's members (`attribute h : LengthValue = 500.0 [m];`), whose Value resolves in the graph's own scope.
type Binding ¶
type Binding struct {
Ends [2]BindingEnd
Scope *symbols.Scope
Decl *ast.Usage
}
Binding is a lowered binding connector with its two endpoint expressions and the scope in which those expressions were declared.
type BindingEnd ¶
BindingEnd is one binding endpoint. Path is the runtime lvalue path; Expr retains the lossless expression for diagnostics and calc evaluation.
type Block ¶
type Block struct {
Statements []Statement
Node ast.Node // the loop or branch the block belongs to
// Scope is the block's own scope, which its declarations, and a loop's
// condition, resolve in.
Scope *symbols.Scope
// Graph is the block's own token flow, present where a member of the block is
// an action node rather than a statement — a nested action declaration, a
// `perform` — which only a flow of its own executes with the succession
// semantics it has (block_graph.go). Statements is empty for such a block: the
// statements are the bodies of the flow's nodes.
Graph *ActionGraph
}
Block is a lowered body-local statement list: the body of a loop or of one branch of a conditional. It is a namespace of its own (symbols/builder.go), so the names its Declare statements introduce do not leak out of it.
type ClassifierBehavior ¶
type ClassifierBehavior struct {
Kind ClassifierBehaviorKind
// Name is the name the behavior answers to on the object, which is the
// effective name of the declaration binding it.
Name string
// Decl is the `exhibit`/`perform` declaration itself.
Decl *ast.Usage
// StatesBody reports whether Decl states the behavior's body. A declaration
// that states none names the element that holds one instead.
StatesBody bool
// Arguments are the values the declaration binds to the behavior's
// parameters (`exhibit m { in controller = vehicleController; }`), in
// declaration order.
Arguments []Attribute
}
ClassifierBehavior is a behavior every object of a type runs because the type exhibits or performs it: the declaration that binds it, whether that declaration states a body of its own or names an element holding one, and the values it binds to the behavior's parameters.
func ClassifierBehaviorOf ¶
func ClassifierBehaviorOf(member ast.Node) (ClassifierBehavior, bool)
ClassifierBehaviorOf reports the behavior a type's member binds to every object of that type, and false for a member that binds none: a state or action a type merely owns is not one its objects run.
func ClassifierBehaviorsOf ¶
func ClassifierBehaviorsOf(members []ast.Node) []ClassifierBehavior
ClassifierBehaviorsOf reports the behaviors the given members bind, in declaration order.
type ClassifierBehaviorKind ¶
type ClassifierBehaviorKind int
ClassifierBehaviorKind is how a type binds a behavior to its objects.
const ( // ExhibitedState is a state machine the type exhibits: `exhibit state m { … }`, // `exhibit state m : M;`, `exhibit m;` (SysML v2 §7.16.6, Part::exhibitedStates). ExhibitedState ClassifierBehaviorKind = iota // PerformedAction is an action the type performs: `perform action a { … }`, // `perform action a : A;`, `perform a;` (Part::performedActions). PerformedAction )
func (ClassifierBehaviorKind) String ¶
func (k ClassifierBehaviorKind) String() string
String names the kind in diagnostics.
type Connection ¶
type Connection struct {
Ends []string
Variation string // variation point the connection is a variant of, empty when it is not
Variant string // name of the variant declaring it, empty when it is not one
Owner ConnectionOwner // what declares it, whose selection governs a variant's connection
Scope *symbols.Scope // scope the end paths resolve in, nil when unknown
}
Connection is a lowered connector: the ends it joins, by the name each end resolves to. A `connect a to b` has two ends; a multi-end `connect` has more, and every end is reachable from every other.
A connection a `variant interface` declares joins its ends only where that variant is the one selected, so it carries the variation it belongs to, its own name, and what owns it: routing must ask what that owner bound the variation to before delivering through it (SysML v2 §7.20).
An end keeps the whole path it was written as (`sensor.out`, `p.q`), so a nested port is joined as itself and not as a same-named port elsewhere; Scope is where those paths resolve, which is what routing asks to learn the direction an end's flow features carry.
func ToObjectConnections ¶
func ToObjectConnections(decl ast.Node, scope *symbols.Scope) []Connection
ToObjectConnections lowers the connectors declared in the body of a type an object is of. A `send … via p` of a behavior an object performs routes through the object's connections as well as through the behavior's own, and it is that object's selection that realizes a variant's connection among them.
type ConnectionOwner ¶
type ConnectionOwner int
ConnectionOwner is what a lowered connection belongs to, which decides whose selection governs it when it is a variant's: a behavior activation, or the object performing the behavior.
const ( // OwnerBehavior marks a connection declared in the behavior's own body. OwnerBehavior ConnectionOwner = iota // OwnerObject marks a connection declared in the body of a type an object // performing the behavior is of. OwnerObject )
type Declare ¶
type Declare struct {
Name string
Value ast.Node
Node ast.Node // the declaration itself, for diagnostics
Scope *symbols.Scope // the scope the declaration was written in
}
Declare is a lowered declaration in a body-local block: `attribute i = 0;` written inside a loop or an `if` branch. The name it declares is a member of that block, so the executor binds it in the block's own frame and discards it when the block exits. Value is nil when the declaration carried none.
type DeclareUsage ¶
type DeclareUsage struct {
Name string
Node *ast.Usage // the declaration itself, for diagnostics
Scope *symbols.Scope // the scope the usage was declared in
}
DeclareUsage is a calc usage declared in a body-local block: `calc p : Pair { in k = h; }` written inside a loop or an `if` branch. It states no step of the computation; it declares the usage and marks where it becomes reachable, so the statements after it read its outputs from one evaluation of its body per execution of the block.
type Effect ¶
type Effect struct {
Kind EffectKind
Node ast.Node
Scope *symbols.Scope // the scope the statement was declared in
}
Effect is a statement acting on the world outside the body — perform, accept, terminate — lowered so a host rejecting it (a calculation) can say so.
type EffectKind ¶
type EffectKind int
EffectKind names a statement that acts on the world outside the body it stands in.
const ( EffectPerform EffectKind = iota EffectAccept EffectTerminate )
func (EffectKind) String ¶
func (k EffectKind) String() string
type EndpointResolver ¶ added in v0.4.1
type EndpointResolver interface {
// Endpoint returns the declaration qn names, written in scope, and whether it
// names a vertex at all.
Endpoint(scope *symbols.Scope, qn *ast.QualifiedName) (decl ast.Node, ok bool)
}
EndpointResolver resolves the vertex a transition endpoint names, implemented by the name-resolution tier (*resolve.Resolver) so lowering matches no names itself.
type If ¶
type If struct {
Condition ast.Node
Then Block
Else *Block
Node ast.Node // the conditional itself, for diagnostics
Scope *symbols.Scope // the scope the conditional, and so its condition, was declared in
}
If is a lowered conditional. The condition is evaluated in the enclosing body, outside both branches. Else is nil when the conditional declared none.
type Loop ¶
type Loop struct {
Kind ast.LoopKind
Condition ast.Node // nil for `for`, and for a `loop` written without `until`
// Until is the condition a `while` loop's `until` clause tests after each
// iteration (`while c { … } until d;`), nil when it carries none.
Until ast.Node
Variable string // `for` only: the name each element is bound to
Collection ast.Node // `for` only: the collection iterated over
Body Block
Node ast.Node // the loop itself, for diagnostics
// Scope is the scope the loop was declared in, which its collection resolves
// in; its condition resolves in Body.Scope, which the body declares into.
Scope *symbols.Scope
}
Loop is a lowered loop statement. Kind says when the condition is tested: before each iteration (`while`), after each iteration (`loop … until`), or not at all, iteration being driven by a collection (`for`).
Condition and Collection stay expressions because their values are only known at execution time. The iteration count is bounded by the executor's step budget, so a loop that never terminates fails the run rather than hanging it.
type ObjectFlow ¶
type ObjectFlow struct {
// Name is the flow's own name, when it was declared with one
// (`flow generateToAmplify from a.out to b.in;`), and "" for the anonymous
// form and for a flow the notation writes as an edge.
Name string
SourcePin string
TargetPin string
Target ast.Node
// Decl is the declaration the flow was written as, for a consumer that
// reports where it comes from.
Decl ast.Node
}
ObjectFlow represents a data flow edge between pins.
type Return ¶
type Return struct {
Value ast.Node
Node ast.Node // the return itself, for diagnostics
Scope *symbols.Scope // the scope the returned expression was written in
}
Return is a lowered `return`: the value the enclosing behavior computes, possibly from inside a block. Value is nil when it named no expression.
type Send ¶
type Send struct {
Message ast.Node
Target string
// TargetPath records that Target is a feature chain (`a.b`) reaching through
// the sender's features, rather than a name in a namespace (`R`, `P::R`).
TargetPath bool
IsVia bool
// Receiver is the name addressed by a routed send, empty when omitted.
Receiver string
ReceiverPath bool
Scope *symbols.Scope // the scope the statement was declared in
}
Send is a lowered send statement. Message stays an expression because its value is only known at execution time.
Target is the name the send addressed, empty for a broadcast. IsVia records that the name is a port of the sender rather than a receiver, in which case it is the whole path the port was written as and the message goes to whatever the graph's Connections join that port to.
type StateBehavior ¶
type StateBehavior struct {
// Node is the behavior's declaration, unwrapped of the membership the parser
// puts it in, and is what a diagnostic about it names.
Node ast.Node
// Name is the name the behavior was declared with, "" for an anonymous one.
Name string
// Body are the behavior's statements in declaration order. An inline action
// body is one block, since it is a namespace of its own; every other form
// lowers to the one statement it states.
Body []Statement
// Scope is the scope the behavior was declared in, which its own statements
// and the action name it performs resolve in.
Scope *symbols.Scope
// Owner is the state whose attributes the behavior reads and writes: the
// state it belongs to, or the source of the transition it is an effect of.
Owner *ast.StateNode
}
StateBehavior is one behavior a state machine performs: an entry, do or exit behavior of a state, or one effect of a transition. Every form it may be written in — an inline action body, an assignment, a send, a performed action — is lowered into the statements the runtime executes.
func LowerBehaviors ¶
func LowerBehaviors(actions []ast.Node, scope *symbols.Scope) []StateBehavior
LowerBehaviors lowers the actions of an entry, do or exit member, or the effects of a transition, in the scope they were declared in.
type StateBehaviors ¶
type StateBehaviors struct {
Entry []StateBehavior
Do []StateBehavior
Exit []StateBehavior
}
StateBehaviors are the lowered entry, do and exit behaviors of one state, each in declaration order.
type StateGraph ¶
type StateGraph struct {
// Scope is the scope the machine's own body was declared in, in which the
// expressions written directly among its members resolve their names.
Scope *symbols.Scope
// Attributes are the attributes the machine declares, in declaration order.
Attributes []Attribute
// StateScopes: state → the scope that state's body was declared in, which is
// what the names in its entry, do and exit behaviors resolve against.
StateScopes map[*ast.StateNode]*symbols.Scope
// Behaviors: state → its lowered entry, do and exit behaviors. The executor
// runs these rather than the state's AST members, so an inline action body is
// executable statements by the time it is reached.
Behaviors map[*ast.StateNode]*StateBehaviors
// HiddenStates are graph-only composite owners synthesized for parallel
// regions. They execute behaviors but are not user-visible state visits.
HiddenStates map[*ast.StateNode]bool
// HiddenRegionOf: graph-only owner → the region it stands for, so a walk up
// the parent chain crosses it without losing which region a state is in.
HiddenRegionOf map[*ast.StateNode]*ast.StateRegion
// Machine is the graph-only root state for a parallel machine's own entry,
// do and exit behaviors. Its regions are represented by TopRegions instead.
Machine *ast.StateNode
// States in the machine (flat list, includes nested)
States []*ast.StateNode
// Pseudostates of the machine in declaration order. Not keyed by name:
// sibling regions may declare same-named pseudostates.
Pseudostates []*ast.PseudostateNode
// PseudostateOwner: pseudostate -> the composite state that declares it,
// absent for one declared directly in the machine. A history pseudostate
// restores the configuration of its owner, so the owner must survive lowering.
PseudostateOwner map[*ast.PseudostateNode]*ast.StateNode
// Transitions: source node (StateNode or PseudostateNode) → list of transitions
Transitions map[ast.Node][]*Transition
// CompositeStates: state → regions
CompositeStates map[*ast.StateNode][]*ast.StateRegion
// CompositeStateOrder preserves declaration order for deterministic runtime
// selection of an active composite owner.
CompositeStateOrder []*ast.StateNode
// RegionInitials: region → initial state
RegionInitials map[*ast.StateRegion]*ast.StateNode
// ParentState: child → parent
ParentState map[*ast.StateNode]*ast.StateNode
// RegionOwner: region → owning composite state
RegionOwner map[*ast.StateRegion]*ast.StateNode
// Deferred: state → the triggers it defers while active, normalized the same
// way transition triggers are.
Deferred map[*ast.StateNode][]ast.Node
// TopRegions are the machine's own orthogonal regions, in declaration order.
// The order is observable: it is the order regions are entered and exited in.
TopRegions []*ast.StateRegion
// RegionOf: state → the region that declares it (fork/join need the region a
// target belongs to)
RegionOf map[*ast.StateNode]*ast.StateRegion
// InitialState (required for simple machines, nil for multi-region)
Initial *ast.StateNode
// Connections are the connectors declared in the state machine body, which
// is how a `send ... via <port>` in an entry/do/exit/effect action finds the
// ports it reaches.
Connections []Connection
// StateAttributes: state → the attributes it owns, its own and those it
// inherits from the definition typing it. Each state owns its values, so two
// usages of one definition hold two sets of them.
StateAttributes map[*ast.StateNode][]Attribute
// contains filtered or unexported fields
}
StateGraph is the execution IR for state machines.
func ToStateGraph ¶
ToStateGraph converts a state machine AST (Usage or Definition) to a StateGraph. scope is the scope the machine's body was declared in — the scope the machine itself owns — from which the scope of every state and transition it carries is derived. Its endpoints resolve against the machine's own symbols; a caller holding the name-resolution tier's uses ToStateGraphWithEndpoints instead.
func ToStateGraphWithEndpoints ¶
func ToStateGraphWithEndpoints(stateMachineDecl ast.Node, scope *symbols.Scope, endpoints EndpointResolver) (*StateGraph, error)
ToStateGraphWithEndpoints lowers a state machine, building its transitions from the endpoints the name-resolution tier already resolved.
func (*StateGraph) AttributeScope ¶ added in v0.4.0
func (g *StateGraph) AttributeScope(attr Attribute) *symbols.Scope
AttributeScope is the scope an attribute's value resolves in, which is the body declaring it rather than the machine's when the machine inherits it.
type StateTypeResolver ¶ added in v0.4.1
type StateTypeResolver interface {
TypeDecl(scope *symbols.Scope, qn *ast.QualifiedName) (ast.Node, *symbols.Scope, bool)
}
StateTypeResolver resolves the declaration a type name reaches and the scope of that declaration's body. The name-resolution tier implements it; lowering falls back to the scope tree for a machine lowered without it.
type Statement ¶
type Statement interface {
// contains filtered or unexported methods
}
Statement is one lowered statement in an action node's body. Statements are kept in declaration order so the executor never walks the node's members again to find them.
func CalcBody ¶
CalcBody lowers the computation a calculation body states, in declaration order and in the scope it was written in. A member stating no computation — an input parameter, documentation, a nested definition — is skipped. A result the body declares names the value answered with, not a step, so it runs after the steps; a `return` inside a branch or loop stops the body there.
type Subflow ¶ added in v0.4.0
type Subflow struct {
Graph *ActionGraph
Err error
}
Subflow is the flow a nested action node's own members state. Graph is nil when those members state a flow that could not be built, which Err says; the executor reports it at initialize() rather than treating the node as a leaf.
type Transition ¶
type Transition struct {
// Name is the transition's own name, when it was written with one
// (`transition maintain first idle then busy`), and "" when it was not.
Name string
// Decl is the declaration the transition was written as, for a consumer that
// reports where it comes from.
Decl ast.Node
Source ast.Node // *ast.StateNode or *ast.PseudostateNode
Target ast.Node // *ast.StateNode or *ast.PseudostateNode
Trigger ast.Node // TimeEvent, ChangeEvent, SignalEvent, CallEvent, nil = completion
Guard ast.Node // guard expression, nil = no guard
// Effect are the transition's effect behaviors, lowered the same way a state's
// entry, do and exit behaviors are.
Effect []StateBehavior
// Via is the port the accepted occurrence must arrive at
// (`accept Ping via commPort`), and "" when the trigger names no port, in
// which case an occurrence reaching the machine by any route fires it.
Via string
// Scope is the scope the transition was declared in, in which the expressions
// its trigger carries — a time event's duration, a change event's condition —
// resolve their names.
Scope *symbols.Scope
// BodyScope is the scope the transition's guard and effect resolve in. It is
// Scope, except for a call trigger, whose parameters are visible to the guard
// and effect and nowhere else (`accept setSpeed(v) if v > 0`).
BodyScope *symbols.Scope
}
Transition represents a state transition (lowered from TransitionEdge or TransitionMember).
type Unsupported ¶
type Unsupported struct {
Description string
Node ast.Node
Scope *symbols.Scope // the scope the member was declared in
}
Unsupported is a body member the lowering layer recognizes but cannot yet turn into an executable statement. It is lowered rather than dropped so that reaching it fails the execution with a diagnostic instead of silently producing a wrong answer. Description names the construct.