├── .gitignore
├── AUTHORS
├── BUILD
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── WORKSPACE
├── statechart
├── BUILD
├── example
│ ├── BUILD
│ ├── microwave.proto
│ ├── microwave_example_main.cc
│ └── microwave_statechart.svg
├── internal
│ ├── BUILD
│ ├── datamodel.cc
│ ├── datamodel.h
│ ├── event_dispatcher.cc
│ ├── event_dispatcher.h
│ ├── event_dispatcher_test.cc
│ ├── executor.cc
│ ├── executor.h
│ ├── executor_test.cc
│ ├── function_dispatcher.h
│ ├── function_dispatcher_builtin.cc
│ ├── function_dispatcher_builtin.h
│ ├── function_dispatcher_builtin_test.cc
│ ├── function_dispatcher_impl.cc
│ ├── function_dispatcher_impl.h
│ ├── function_dispatcher_impl_test.cc
│ ├── json_value_coder.h
│ ├── json_value_coder_test.cc
│ ├── light_weight_datamodel.cc
│ ├── light_weight_datamodel.h
│ ├── light_weight_datamodel_test.cc
│ ├── model.cc
│ ├── model.h
│ ├── model
│ │ ├── BUILD
│ │ ├── assign.cc
│ │ ├── assign.h
│ │ ├── assign_test.cc
│ │ ├── data.cc
│ │ ├── data.h
│ │ ├── data_test.cc
│ │ ├── executable_block.h
│ │ ├── executable_block_test.cc
│ │ ├── executable_content.h
│ │ ├── for_each.cc
│ │ ├── for_each.h
│ │ ├── for_each_test.cc
│ │ ├── if.cc
│ │ ├── if.h
│ │ ├── if_test.cc
│ │ ├── log.cc
│ │ ├── log.h
│ │ ├── log_test.cc
│ │ ├── model.h
│ │ ├── model_element.cc
│ │ ├── model_element.h
│ │ ├── raise.cc
│ │ ├── raise.h
│ │ ├── raise_test.cc
│ │ ├── send.cc
│ │ ├── send.h
│ │ ├── send_test.cc
│ │ ├── state.cc
│ │ ├── state.h
│ │ ├── str_or_expr.cc
│ │ ├── str_or_expr.h
│ │ ├── str_or_expr_test.cc
│ │ ├── transition.cc
│ │ ├── transition.h
│ │ └── transition_test.cc
│ ├── model_builder.cc
│ ├── model_builder.h
│ ├── model_builder_test.cc
│ ├── model_impl.cc
│ ├── model_impl.h
│ ├── model_impl_test.cc
│ ├── model_test.cc
│ ├── runtime.cc
│ ├── runtime.h
│ ├── runtime_impl.cc
│ ├── runtime_impl.h
│ ├── runtime_impl_test.cc
│ ├── state_machine_impl.cc
│ ├── state_machine_impl.h
│ ├── state_machine_logger.cc
│ ├── state_machine_logger.h
│ ├── testing
│ │ ├── BUILD
│ │ ├── delegating_mock_executor.h
│ │ ├── json_value_coder_test.proto
│ │ ├── mock_datamodel.h
│ │ ├── mock_event_dispatcher.h
│ │ ├── mock_executable_content.h
│ │ ├── mock_function_dispatcher.h
│ │ ├── mock_model.h
│ │ ├── mock_runtime.h
│ │ ├── mock_state.h
│ │ ├── mock_transition.h
│ │ ├── state_chart_builder.h
│ │ └── state_chart_builder_test.cc
│ ├── utility.cc
│ ├── utility.h
│ └── utility_test.cc
├── json_utils.cc
├── json_utils.h
├── json_utils_test.cc
├── logging.h
├── logging_test.cc
├── platform
│ ├── BUILD
│ ├── logging.h
│ ├── map_util.h
│ ├── protobuf.h
│ ├── str_util.cc
│ ├── str_util.h
│ ├── test_util.h
│ └── types.h
├── proto
│ ├── BUILD
│ ├── state_chart.proto
│ └── state_machine_context.proto
├── state_machine.cc
├── state_machine.h
├── state_machine_factory.cc
├── state_machine_factory.h
├── state_machine_factory_test.cc
├── state_machine_listener.h
├── state_machine_test.cc
└── testing
│ ├── BUILD
│ ├── mock_state_machine.h
│ └── state_machine_test.proto
└── third_party
├── BUILD
└── jsoncpp.BUILD
/.gitignore:
--------------------------------------------------------------------------------
1 | bazel-*
2 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | # This is the list of [Project Name] authors for copyright purposes.
2 | #
3 | # This does not necessarily list everyone who has contributed code, since in
4 | # some cases, their employer may be the copyright holder. To see the full list
5 | # of contributors, see the revision history in source control.
6 |
7 | Google LLC.
8 | Qiangfeng Peter Lau
9 | Sudeep Gandhe
10 |
--------------------------------------------------------------------------------
/BUILD:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google/statechart/d283cefab5a051a91c21be46d97bc18407fd7628/BUILD
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
25 | ## Community Guidelines
26 |
27 | This project follows [Google's Open Source Community
28 | Guidelines](https://opensource.google.com/conduct/).
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # C++ StateChart Library
2 |
3 | StateCharts [(Harel, 1987)](ref1) is a visual formalism for declarative
4 | description of complex interactive systems.
5 | It extends the conventional state machine formalism with Hierarchy, Concurrency
6 | and Communication.
7 |
8 | [SCXML](https://www.w3.org/TR/scxml/) is a W3C standard based on StateCharts.
9 | This is a C++ library that implements the SCXML specification. Instead of XML, a
10 | StateChart is represented as a StateChart protobuf.
11 |
12 | ## Features
13 | Many features from the SCXML standard have been implemented.
14 |
15 | * Composite State
16 | * Parallel State
17 | * Datamodel
18 | * Transitions (Conditional, Eventless)
19 | * Executable Statements (Raise, Log, Assign, If, ForEach, Send)
20 | * Serialize/Deserialize the state machine
21 |
22 | ## TODO
23 |
24 | * History
25 |
26 | ## Example
27 | Here's an example of a StateChart that describes a Microwave.
28 |
29 | 
30 |
31 | You can see [//statechart/example/microwave_example_main.cc](statechart/example/microwave_example_main.cc)
32 | for details on how to specify such a StateChart as a StateChart proto and how to use it in code.
33 |
34 | ## Usage
35 |
36 | To build the library you'll need bazel. You can download and install it from [here](https://www.bazel.build/).
37 |
38 | ```
39 | # Download/Clone the repo.
40 | git clone https://github.com/google/statechart.git
41 | cd statechart
42 |
43 | # Build the library
44 | bazel build //statechart/...
45 |
46 | # Run unit tests
47 | bazel test //statechart/...
48 |
49 | # Run the Microwave example
50 | bazel run //statechart/example:microwave_example_main -- --alsologtostderr
51 | ```
52 |
53 | ## Disclaimer
54 |
55 | This is not an officially supported Google product.
56 |
57 | ## References
58 |
59 | * David Harel, 1987, Statecharts: a visual formalism for complex systems,
60 | Science of Computer Programming.
61 | [Link](https://www.sciencedirect.com/science/article/pii/0167642387900359)
62 | * State Chart XML (SCXML): State Machine Notation for Control Abstraction.
63 | [Link](https://www.w3.org/TR/scxml/)
64 |
--------------------------------------------------------------------------------
/WORKSPACE:
--------------------------------------------------------------------------------
1 | workspace(name = "com_google_statechart")
2 |
3 | # Using protobuf version 3.5.1
4 | http_archive(
5 | name = "com_google_protobuf",
6 | strip_prefix = "protobuf-3.5.1",
7 | urls = ["https://github.com/google/protobuf/archive/v3.5.1.tar.gz"],
8 | )
9 |
10 | http_archive(
11 | name = "com_google_protobuf_cc",
12 | strip_prefix = "protobuf-3.5.1",
13 | urls = ["https://github.com/google/protobuf/archive/v3.5.1.tar.gz"],
14 | )
15 |
16 | # GoogleTest/GoogleMock framework. Used by most unit-tests.
17 | http_archive(
18 | name = "com_google_googletest",
19 | urls = ["https://github.com/google/googletest/archive/master.zip"],
20 | strip_prefix = "googletest-master",
21 | )
22 |
23 | # We depend on Abseil.
24 | http_archive(
25 | name = "com_google_absl",
26 | strip_prefix = "abseil-cpp-master",
27 | urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"],
28 | )
29 |
30 | # Abseil depends on CCTZ (Time-zone framework).
31 | http_archive(
32 | name = "com_googlesource_code_cctz",
33 | strip_prefix = "cctz-master",
34 | urls = ["https://github.com/google/cctz/archive/master.zip"],
35 | )
36 |
37 | http_archive(
38 | name = "com_googlesource_code_re2",
39 | urls = ["https://github.com/google/re2/archive/master.zip"],
40 | strip_prefix = "re2-master",
41 | )
42 |
43 | new_http_archive(
44 | name = "jsoncpp_git",
45 | urls = ["https://github.com/open-source-parsers/jsoncpp/archive/1.7.6.tar.gz"],
46 | strip_prefix = "jsoncpp-1.7.6",
47 | build_file = "//third_party:jsoncpp.BUILD",
48 | )
49 |
50 | http_archive(
51 | name = "com_github_gflags_gflags",
52 | urls = [ "https://github.com/gflags/gflags/archive/master.zip" ],
53 | strip_prefix = "gflags-master"
54 | )
55 | #
56 | http_archive(
57 | name = "com_google_glog",
58 | urls = [ "https://github.com/google/glog/archive/master.zip" ],
59 | strip_prefix = "glog-master"
60 | )
61 |
62 | # gflags needed by glog
63 | # http_archive(
64 | # name = "com_github_gflags_gflags",
65 | # sha256 = "6e16c8bc91b1310a44f3965e616383dbda48f83e8c1eaa2370a215057b00cabe",
66 | # strip_prefix = "gflags-77592648e3f3be87d6c7123eb81cbad75f9aef5a",
67 | # urls = [
68 | # "https://mirror.bazel.build/github.com/gflags/gflags/archive/77592648e3f3be87d6c7123eb81cbad75f9aef5a.tar.gz",
69 | # "https://github.com/gflags/gflags/archive/77592648e3f3be87d6c7123eb81cbad75f9aef5a.tar.gz",
70 | # ],
71 | # )
72 |
73 | # glog
74 | # http_archive(
75 | # name = "com_google_glog",
76 | # sha256 = "1ee310e5d0a19b9d584a855000434bb724aa744745d5b8ab1855c85bff8a8e21",
77 | # strip_prefix = "glog-028d37889a1e80e8a07da1b8945ac706259e5fd8",
78 | # urls = [
79 | # "https://mirror.bazel.build/github.com/google/glog/archive/028d37889a1e80e8a07da1b8945ac706259e5fd8.tar.gz",
80 | # "https://github.com/google/glog/archive/028d37889a1e80e8a07da1b8945ac706259e5fd8.tar.gz",
81 | # ],
82 | # )
--------------------------------------------------------------------------------
/statechart/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2018 The StateChart Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Description:
16 | # Libraries for a generic StateChart executor based on SCXML standard.
17 |
18 | package(default_visibility = ["//visibility:public"])
19 |
20 | cc_library(
21 | name = "state_machine",
22 | srcs = ["state_machine.cc"],
23 | hdrs = ["state_machine.h"],
24 | deps = [
25 | ":logging",
26 | "//statechart/internal:datamodel",
27 | "//statechart/internal:model",
28 | "//statechart/internal:runtime",
29 | "//statechart/platform:protobuf",
30 | "//statechart/proto:state_machine_context_cc_proto",
31 | ],
32 | )
33 | # TODO(srgandhe): Fix this test.
34 | #cc_test(
35 | # name = "state_machine_test",
36 | # size = "small",
37 | # srcs = ["state_machine_test.cc"],
38 | # deps = [
39 | # ":state_machine",
40 | # "//statechart/internal/testing:mock_datamodel",
41 | # "//statechart/internal/testing:mock_runtime",
42 | # "//statechart/platform:test_util",
43 | # "//statechart/proto:state_machine_context_cc_proto",
44 | # "//statechart/testing:mock_state_machine",
45 | # "//statechart/testing:state_machine_test_cc_proto",
46 | # "@com_google_googletest//:gtest_main",
47 | # ],
48 | #)
49 |
50 | cc_library(
51 | name = "state_machine_factory",
52 | srcs = ["state_machine_factory.cc"],
53 | hdrs = ["state_machine_factory.h"],
54 | deps = [
55 | ":logging",
56 | ":state_machine",
57 | ":state_machine_listener",
58 | "//statechart/internal:datamodel",
59 | "//statechart/internal:executor",
60 | "//statechart/internal:function_dispatcher",
61 | "//statechart/internal:light_weight_datamodel",
62 | "//statechart/internal:model",
63 | "//statechart/internal:model_builder",
64 | "//statechart/internal:model_impl",
65 | "//statechart/internal:runtime",
66 | "//statechart/internal:runtime_impl",
67 | "//statechart/internal:state_machine_impl",
68 | "//statechart/internal:state_machine_logger",
69 | "//statechart/platform:map_util",
70 | "//statechart/proto:state_chart_cc_proto",
71 | "//statechart/proto:state_machine_context_cc_proto",
72 | "@com_google_absl//absl/memory",
73 | "@com_google_absl//absl/strings",
74 | ],
75 | )
76 |
77 | cc_test(
78 | name = "state_machine_factory_test",
79 | srcs = ["state_machine_factory_test.cc"],
80 | deps = [
81 | ":state_machine",
82 | ":state_machine_factory",
83 | "//statechart/internal:function_dispatcher",
84 | "//statechart/internal:model",
85 | "//statechart/internal:runtime",
86 | "//statechart/internal/model",
87 | "//statechart/internal/testing:mock_function_dispatcher",
88 | "//statechart/internal/testing:state_chart_builder",
89 | "//statechart/platform:test_util",
90 | "//statechart/proto:state_chart_cc_proto",
91 | "@com_google_googletest//:gtest_main",
92 | ],
93 | )
94 |
95 | cc_library(
96 | name = "state_machine_listener",
97 | hdrs = ["state_machine_listener.h"],
98 | deps = ["//statechart/platform:types"],
99 | )
100 |
101 | cc_library(
102 | name = "logging",
103 | hdrs = ["logging.h"],
104 | deps = [
105 | "//statechart/platform:logging",
106 | "@com_google_glog//:glog",
107 | ],
108 | )
109 |
110 | cc_test(
111 | name = "logging_test",
112 | srcs = ["logging_test.cc"],
113 | deps = [
114 | ":logging",
115 | "@com_google_googletest//:gtest_main",
116 | ],
117 | )
118 |
119 | cc_library(
120 | name = "json_utils",
121 | srcs = ["json_utils.cc"],
122 | hdrs = ["json_utils.h"],
123 | deps = [
124 | "//statechart/platform:map_util",
125 | "//statechart/platform:protobuf",
126 | "//statechart/platform:types",
127 | "//statechart/proto:state_machine_context_cc_proto",
128 | "@com_google_absl//absl/memory",
129 | "@com_google_absl//absl/strings",
130 | "@jsoncpp_git//:jsoncpp",
131 | ],
132 | )
133 |
134 | cc_test(
135 | name = "json_utils_test",
136 | srcs = ["json_utils_test.cc"],
137 | deps = [
138 | ":json_utils",
139 | "//statechart/proto:state_machine_context_cc_proto",
140 | "@com_google_googletest//:gtest_main",
141 | ],
142 | )
143 |
--------------------------------------------------------------------------------
/statechart/example/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2018 The StateChart Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | package(default_visibility = ["//visibility:public"])
16 |
17 | cc_binary(
18 | name = "microwave_example_main",
19 | srcs = ["microwave_example_main.cc"],
20 | deps = [
21 | ":microwave_cc_proto",
22 | "//statechart:state_machine",
23 | "//statechart:state_machine_factory",
24 | "//statechart/internal:function_dispatcher_impl",
25 | "//statechart/platform:protobuf",
26 | "//statechart/proto:state_chart_cc_proto",
27 | "//statechart/proto:state_machine_context_cc_proto",
28 | "@com_github_gflags_gflags//:gflags",
29 | "@com_google_absl//absl/memory",
30 | "@com_google_absl//absl/strings",
31 | "@com_google_glog//:glog",
32 | ],
33 | )
34 |
35 | proto_library(
36 | name = "microwave_proto",
37 | srcs = ["microwave.proto"],
38 | )
39 |
40 | cc_proto_library(
41 | name = "microwave_cc_proto",
42 | deps = [":microwave_proto"],
43 | )
44 |
--------------------------------------------------------------------------------
/statechart/example/microwave.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package example.microwave;
4 |
5 | message MicrowaveState {
6 | enum Light {
7 | UNKNOWN = 0;
8 | OFF = 1;
9 | ON = 2;
10 | }
11 | optional Light light = 1;
12 |
13 | // The amount of cooking time left.
14 | optional int32 cooking_duration_sec = 2;
15 | }
16 |
17 | message MicrowavePayload {
18 | optional int32 duration_sec = 1;
19 | }
20 |
--------------------------------------------------------------------------------
/statechart/internal/datamodel.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/datamodel.h"
16 |
17 | namespace state_chart {
18 | Datamodel::~Datamodel() {}
19 | } // namespace state_chart
20 |
--------------------------------------------------------------------------------
/statechart/internal/event_dispatcher.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/event_dispatcher.h"
16 |
17 | #include "statechart/internal/runtime.h"
18 | #include "statechart/state_machine_listener.h"
19 |
20 | #define FOREACH_LISTENER(what) for (const auto& listener : listeners_) { \
21 | listener->what; \
22 | }
23 |
24 | namespace state_chart {
25 |
26 | // virtual
27 | EventDispatcher::~EventDispatcher() {}
28 |
29 | void EventDispatcher::AddListener(StateMachineListener* listener) {
30 | listeners_.push_back(listener);
31 | }
32 |
33 | // virtual
34 | void EventDispatcher::NotifyStateEntered(const Runtime* runtime,
35 | const model::State* state) {
36 | FOREACH_LISTENER(OnStateEntered(runtime, state));
37 | }
38 |
39 | // virtual
40 | void EventDispatcher::NotifyStateExited(const Runtime* runtime,
41 | const model::State* state) {
42 | FOREACH_LISTENER(OnStateExited(runtime, state));
43 | }
44 |
45 | // virtual
46 | void EventDispatcher::NotifyTransitionFollowed(
47 | const Runtime* runtime, const model::Transition* transition) {
48 | FOREACH_LISTENER(OnTransitionFollowed(runtime, transition));
49 | }
50 |
51 | // virtual
52 | void EventDispatcher::NotifySendEvent(const Runtime* runtime,
53 | const string& event, const string& target,
54 | const string& type, const string& id,
55 | const string& data) {
56 | FOREACH_LISTENER(OnSendEvent(runtime, event, target, type, id, data));
57 | }
58 |
59 | } // namespace state_chart
60 |
--------------------------------------------------------------------------------
/statechart/internal/event_dispatcher.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef STATE_CHART_INTERNAL_EVENT_DISPATCHER_H_
18 | #define STATE_CHART_INTERNAL_EVENT_DISPATCHER_H_
19 |
20 | #include
21 | #include
22 |
23 | #include "statechart/platform/types.h"
24 |
25 | namespace state_chart {
26 |
27 | class Runtime;
28 | class StateMachineListener;
29 |
30 | namespace model {
31 | class State;
32 | class Transition;
33 | } // namespace model
34 |
35 | // This class is responsible for collecting listeners for a specific instance of
36 | // a state machine, and dispatching events when they occur. The state machine
37 | // system invokes the various Notify*() methods, which are in turn passed to the
38 | // equivalent On*() methods in the listeners.
39 | class EventDispatcher {
40 | public:
41 | virtual ~EventDispatcher();
42 |
43 | // Does not take ownership of 'listener'.
44 | void AddListener(StateMachineListener* listener);
45 |
46 | virtual void NotifyStateEntered(const Runtime* runtime,
47 | const model::State* state);
48 |
49 | virtual void NotifyStateExited(const Runtime* runtime,
50 | const model::State* state);
51 |
52 | virtual void NotifyTransitionFollowed(const Runtime* runtime,
53 | const model::Transition* transition);
54 |
55 | virtual void NotifySendEvent(const Runtime* runtime, const string& event,
56 | const string& target, const string& type,
57 | const string& id, const string& data);
58 |
59 | private:
60 | std::vector listeners_;
61 | };
62 |
63 | } // namespace state_chart
64 |
65 | #endif // STATE_CHART_INTERNAL_EVENT_DISPATCHER_H_
66 |
--------------------------------------------------------------------------------
/statechart/internal/event_dispatcher_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/event_dispatcher.h"
16 |
17 | #include
18 | #include
19 |
20 | #include "statechart/internal/testing/mock_runtime.h"
21 | #include "statechart/internal/testing/mock_state.h"
22 | #include "statechart/state_machine_listener.h"
23 |
24 | namespace state_chart {
25 | namespace {
26 |
27 | class MockListener : public StateMachineListener {
28 | public:
29 | MOCK_METHOD2(OnStateEntered, void(const Runtime*, const model::State*));
30 | MOCK_METHOD2(OnStateExited, void(const Runtime*, const model::State*));
31 | MOCK_METHOD2(OnTransitionFollowed,
32 | void(const Runtime*, const model::Transition*));
33 | MOCK_METHOD6(OnSendEvent, void(const Runtime*, const string&, const string&,
34 | const string&, const string&, const string&));
35 | };
36 |
37 | class EventDispatcherTest : public ::testing::Test {
38 | protected:
39 | EventDispatcherTest() { dispatcher_.AddListener(&listener_); }
40 |
41 | MockRuntime runtime_;
42 | testing::StrictMock listener_;
43 | EventDispatcher dispatcher_;
44 | };
45 |
46 | TEST_F(EventDispatcherTest, OnStateEntered) {
47 | MockState state("A");
48 | EXPECT_CALL(listener_,
49 | OnStateEntered(&runtime_, &state));
50 | dispatcher_.NotifyStateEntered(&runtime_, &state);
51 | }
52 |
53 | TEST_F(EventDispatcherTest, OnStateExited) {
54 | MockState state("A");
55 | EXPECT_CALL(listener_,
56 | OnStateExited(&runtime_, &state));
57 | dispatcher_.NotifyStateExited(&runtime_, &state);
58 | }
59 |
60 | TEST_F(EventDispatcherTest, OnSendEvent) {
61 | EXPECT_CALL(listener_,
62 | OnSendEvent(&runtime_, "event", "target", "type", "id", "data"));
63 |
64 | dispatcher_.NotifySendEvent(&runtime_, "event", "target", "type", "id",
65 | "data");
66 | }
67 |
68 | } // namespace
69 | } // namespace state_chart
70 |
--------------------------------------------------------------------------------
/statechart/internal/executor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // The Executor implements most of the SCXML interpretation pseudo-code.
18 | // See: http://www.w3.org/TR/scxml/#AlgorithmforSCXMLInterpretation
19 | #ifndef STATE_CHART_INTERNAL_EXECUTOR_H_
20 | #define STATE_CHART_INTERNAL_EXECUTOR_H_
21 |
22 | #include
23 | #include
24 |
25 | #include "statechart/platform/types.h"
26 |
27 | namespace state_chart {
28 | class Model;
29 | class Runtime;
30 | namespace model {
31 | class Transition;
32 | } // namespace model
33 | } // namespace state_chart
34 |
35 | namespace state_chart {
36 |
37 | // This class executes the StateChart with the same semantics as the algorithm
38 | // for SCXML interpretation. An Executor instance may be shared for various
39 | // instances of Model and Runtime. In general, StateMachine instances share the
40 | // same Executor instance, may (or may not) share the same Model, and will own
41 | // an instance of Runtime. The methods on Executor reflects this by allowing
42 | // different Model and Runtime instances to be passed in as parameters.
43 | // These input parameters should be non-null. If anyone of them is nullptr no
44 | // action is performed.
45 | class Executor {
46 | public:
47 | Executor() = default;
48 | Executor(const Executor&) = delete;
49 | Executor& operator=(const Executor&) = delete;
50 | virtual ~Executor() = default;
51 |
52 | // Start the execution of the machine by entering the initial state
53 | // and executing until the state machine reaches a stable state. A stable
54 | // state is one where there are no transitions and no internal events that
55 | // can be processed.
56 | virtual void Start(const Model* model, Runtime* runtime) const;
57 |
58 | // Notify the Executor of an external event. Executes transitions based on
59 | // this event until the state machine reaches a stable state.
60 | // This corresponds to a 'macro step' in the SCXML algorithm specification.
61 | // Parameter payload may be an empty string (i.e. no payload).
62 | virtual void SendEvent(const Model* model, Runtime* runtime,
63 | const string& event, const string& payload) const;
64 |
65 | protected:
66 | // Handles all internal events until the state machine reaches a stable state.
67 | // This corresponds to mainEventLoop() procedure above from lines 6 to 35.
68 | // Input params 'model' & 'runtime' must be non-null.
69 | virtual void ExecuteUntilStable(const Model* model, Runtime* runtime) const;
70 |
71 | // Handles a single external event. This corresponds to the mainEventLoop()
72 | // procedure above from lines 40 to 53.
73 | // Parameter payload may be an empty string (i.e. no payload).
74 | // Input params 'model' & 'runtime' must be non-null.
75 | virtual void ProcessExternalEvent(const Model* model, Runtime* runtime,
76 | const string& event,
77 | const string& payload) const;
78 |
79 | // Execute a microstep. This takes a list of transitions, exits all their
80 | // source states, runs their executable blocks and finally enters all the
81 | // target states.
82 | // Input params 'model' & 'runtime' must be non-null.
83 | virtual void MicroStep(
84 | const Model* model, Runtime* runtime,
85 | const std::vector& transitions) const;
86 |
87 | // Enters the target states of the transitions, calling their
88 | // executable blocks.
89 | // Input params 'model' & 'runtime' must be non-null.
90 | virtual void EnterStates(
91 | const Model* model, Runtime* runtime,
92 | const std::vector& transitions) const;
93 |
94 | // Exits the source states of the transitions, calling executable
95 | // blocks.
96 | // Input params 'model' & 'runtime' must be non-null.
97 | virtual void ExitStates(
98 | const Model* model, Runtime* runtime,
99 | const std::vector& transitions) const;
100 |
101 | // Assigns event data to the '_event' variable in the runtime's datamodel.
102 | // Parameters:
103 | // event The event name.
104 | // payload The event data.
105 | //
106 | // Input params 'model' & 'runtime' must be non-null.
107 | virtual void AssignEventData(Runtime* runtime, const string& event,
108 | const string& payload) const;
109 |
110 | // Shutdown the state machine by exiting all states in the correct order.
111 | // Input params 'model' & 'runtime' must be non-null.
112 | virtual void Shutdown(const Model* model, Runtime* runtime) const;
113 | };
114 |
115 | } // namespace state_chart
116 |
117 | #endif // STATE_CHART_INTERNAL_EXECUTOR_H_
118 |
--------------------------------------------------------------------------------
/statechart/internal/function_dispatcher.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef STATE_CHART_INTERNAL_FUNCTION_DISPATCHER_H_
18 | #define STATE_CHART_INTERNAL_FUNCTION_DISPATCHER_H_
19 |
20 | #include
21 | #include
22 |
23 | #include "statechart/platform/types.h"
24 |
25 | namespace Json { class Value; }
26 |
27 | namespace state_chart {
28 |
29 | // This base class executes C++ functions with a given function name and
30 | // arguments.
31 | class FunctionDispatcher {
32 | public:
33 | FunctionDispatcher() = default;
34 | FunctionDispatcher(const FunctionDispatcher&) = delete;
35 | FunctionDispatcher& operator=(const FunctionDispatcher&) = delete;
36 | virtual ~FunctionDispatcher() = default;
37 |
38 | // Returns whether a function identified by the 'function_name' is registered
39 | // with this function dispatcher.
40 | virtual bool HasFunction(const string& function_name) const = 0;
41 |
42 | // Executes a function identified by the 'function_name' using the 'inputs'
43 | // arguments and sets the output to '*return_value'.
44 | // Returns true on successful function execution.
45 | virtual bool Execute(const string& function_name,
46 | const std::vector& inputs,
47 | Json::Value* return_value) = 0;
48 | };
49 |
50 | } // namespace state_chart
51 |
52 | #endif // STATE_CHART_INTERNAL_FUNCTION_DISPATCHER_H_
53 |
--------------------------------------------------------------------------------
/statechart/internal/function_dispatcher_builtin.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/function_dispatcher_builtin.h"
16 |
17 | #include "include/json/json.h"
18 |
19 | namespace state_chart {
20 | namespace builtin {
21 |
22 | bool ContainsKey(const Json::Value& value, const string& field_name) {
23 | return value.isMember(field_name);
24 | }
25 |
26 | int FindFirstWithKeyValue(const Json::Value& array, const string& key,
27 | const Json::Value& value) {
28 | if (array.isArray()) {
29 | for (unsigned int i = 0; i < array.size(); ++i) {
30 | if (array[i].isMember(key) && (array[i][key] == value)) {
31 | return i;
32 | }
33 | }
34 | }
35 | return -1;
36 | }
37 |
38 | } // namespace builtin
39 | } // namespace state_chart
40 |
--------------------------------------------------------------------------------
/statechart/internal/function_dispatcher_builtin.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // A set of utility function for manipulating datamodel objects.
18 | // These are builtin into every instance of FunctionDispatcher.
19 | #ifndef STATE_CHART_INTERNAL_FUNCTION_DISPATCHER_BUILTIN_H_
20 | #define STATE_CHART_INTERNAL_FUNCTION_DISPATCHER_BUILTIN_H_
21 |
22 | #include
23 |
24 | #include "statechart/platform/types.h"
25 |
26 | namespace Json { class Value; }
27 |
28 | namespace state_chart {
29 | namespace builtin {
30 |
31 | // Checks whether a particular field_name exists in a Json value.
32 | bool ContainsKey(const Json::Value& value, const string& field_name);
33 |
34 | // Finds the index of the first object in a 'array' of objects where the
35 | // object has a specified pair.
36 | // Returns -1 if no such matching object is found.
37 | // Returns -1 if the input array is not a Json array.
38 | // E.g.,
39 | // if array = [ { "K1" : "V1" } ,
40 | // { "K2" : "V2", "foo" : "bar" },
41 | // { "K2" : "V2"} ] then,
42 | // EXPECT_EQ(0, FindFirstWithKeyValue(array, "K1", "V1"))
43 | // EXPECT_EQ(-1, FindFirstWithKeyValue(array, "K1", ""))
44 | // EXPECT_EQ(1, FindFirstWithKeyValue(array, "K2", "V2"))
45 | int FindFirstWithKeyValue(const Json::Value& array, const string& key,
46 | const Json::Value& value);
47 |
48 | } // namespace builtin
49 | } // namespace state_chart
50 |
51 | #endif // STATE_CHART_INTERNAL_FUNCTION_DISPATCHER_BUILTIN_H_
52 |
--------------------------------------------------------------------------------
/statechart/internal/function_dispatcher_builtin_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/function_dispatcher_builtin.h"
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include "statechart/platform/types.h"
22 | #include "include/json/json.h"
23 |
24 | namespace state_chart {
25 | namespace builtin {
26 | namespace {
27 |
28 | TEST(FunctionDispatcherBuiltins, ContainsKey) {
29 | Json::Reader reader;
30 | Json::Value value;
31 | CHECK(reader.parse(R"({ "K3" : { "lower" : "l" } } )", value));
32 | EXPECT_FALSE(ContainsKey(value, "K"));
33 | EXPECT_TRUE(ContainsKey(value, "K3"));
34 | // Specifying a path as key does not work.
35 | EXPECT_FALSE(ContainsKey(value, "K3.lower"));
36 | }
37 |
38 | TEST(FunctionDispatcherBuiltins, FindFirstWithKeyValue) {
39 | Json::Reader reader;
40 | Json::Value value;
41 | CHECK(reader.parse(R"([ { "K1" : "V1" } ,
42 | { "K2" : "V2", "foo" : "bar" },
43 | { "K2" : "V2"},
44 | { "K3" : { "lower" : "l" }}
45 | ])",
46 | value));
47 |
48 | EXPECT_EQ(-1, FindFirstWithKeyValue(value, "K", "V1"));
49 | EXPECT_EQ(-1, FindFirstWithKeyValue(value, "K1", ""));
50 | EXPECT_EQ(0, FindFirstWithKeyValue(value, "K1", "V1"));
51 | EXPECT_EQ(1, FindFirstWithKeyValue(value, "K2", "V2"));
52 |
53 | Json::Value lower_value;
54 | CHECK(reader.parse(R"({ "lower" : "l" })", lower_value));
55 | EXPECT_EQ(3, FindFirstWithKeyValue(value, "K3", lower_value));
56 |
57 | // Specifying a path as key does not work.
58 | EXPECT_EQ(-1, FindFirstWithKeyValue(value, "K3.lower", "l"));
59 | }
60 |
61 | } // namespace
62 | } // namespace builtin
63 | } // namespace state_chart
64 |
--------------------------------------------------------------------------------
/statechart/internal/function_dispatcher_impl.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/function_dispatcher_impl.h"
16 |
17 | #include
18 |
19 | #include "statechart/internal/function_dispatcher_builtin.h"
20 | #include "statechart/platform/map_util.h"
21 |
22 | namespace state_chart {
23 |
24 | namespace internal {
25 |
26 | std::vector JsonValuesToStrings(
27 | const std::vector& values) {
28 | std::vector json_strs;
29 | for (const auto* json_value : values) {
30 | json_strs.push_back(Json::FastWriter().write(*json_value));
31 | }
32 | return json_strs;
33 | }
34 |
35 | } // namespace internal
36 |
37 | FunctionDispatcherImpl::FunctionDispatcherImpl() {
38 | RegisterFunction("ContainsKey", &builtin::ContainsKey);
39 | RegisterFunction("FindFirstWithKeyValue", &builtin::FindFirstWithKeyValue);
40 | }
41 |
42 | FunctionDispatcherImpl::FunctionDispatcherImpl(
43 | const FunctionDispatcherImpl& other) {
44 | for (const auto& entry : other.function_map_) {
45 | function_map_.emplace(entry.first, entry.second->Clone());
46 | }
47 | }
48 |
49 | // override
50 | bool FunctionDispatcherImpl::HasFunction(const string& function_name) const {
51 | return gtl::ContainsKey(function_map_, function_name);
52 | }
53 |
54 | // override
55 | bool FunctionDispatcherImpl::Execute(
56 | const string& function_name, const std::vector& inputs,
57 | Json::Value* return_value) {
58 | if (!HasFunction(function_name)) {
59 | LOG(INFO) << "No function registered for name : " << function_name;
60 | return false;
61 | }
62 | return function_map_.at(function_name)->Execute(inputs, return_value);
63 | }
64 |
65 | } // namespace state_chart
66 |
--------------------------------------------------------------------------------
/statechart/internal/model.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model.h"
16 |
17 | #include "absl/strings/match.h"
18 |
19 | namespace state_chart {
20 |
21 | // static
22 | bool Model::EventMatches(const string& event_name,
23 | const std::vector& events) {
24 | // Search the list of event names.
25 | for (const string& transition_event : events) {
26 | // Wildcard matches all.
27 | if (transition_event == "*") {
28 | return true;
29 | }
30 | // The transition_event must be a prefix of event in the event hierarchy.
31 | // For example, the transition events, 'event_A' and 'event_A.sub_event_B',
32 | // will match the event, 'event_A.sub_event_B.something_else'.
33 | if (absl::StartsWith(event_name, transition_event) &&
34 | (event_name.size() == transition_event.size() ||
35 | event_name[transition_event.size()] == '.')) {
36 | return true;
37 | }
38 | } // for event_to_match
39 | return false;
40 | }
41 |
42 | } // namespace state_chart
43 |
--------------------------------------------------------------------------------
/statechart/internal/model/assign.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/assign.h"
16 |
17 | #include
18 |
19 | #include "absl/strings/str_cat.h"
20 | #include "absl/strings/substitute.h"
21 | #include "statechart/internal/datamodel.h"
22 | #include "statechart/internal/runtime.h"
23 | #include "statechart/internal/utility.h"
24 |
25 | namespace state_chart {
26 | namespace model {
27 |
28 | Assign::Assign(const string& location, const string& expr)
29 | : location_(location), expr_(expr) {}
30 |
31 | // override
32 | bool Assign::Execute(Runtime* runtime) const {
33 | VLOG(1) << absl::Substitute("Assign($0, $1)", location_, expr_);
34 | if (!runtime->mutable_datamodel()->AssignExpression(location_, expr_)) {
35 | runtime->EnqueueExecutionError(
36 | absl::StrCat("'Assign' failure for: ", location_, " = ", expr_));
37 | return false;
38 | }
39 | return true;
40 | }
41 |
42 | } // namespace model
43 | } // namespace state_chart
44 |
--------------------------------------------------------------------------------
/statechart/internal/model/assign.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_ASSIGN_H_
21 | #define STATE_CHART_INTERNAL_MODEL_ASSIGN_H_
22 |
23 | #include
24 |
25 | #include "statechart/platform/types.h"
26 | #include "statechart/internal/model/executable_content.h"
27 |
28 | namespace state_chart {
29 | class Runtime;
30 | }
31 |
32 | namespace state_chart {
33 | namespace model {
34 |
35 | class Assign : public ExecutableContent {
36 | public:
37 | Assign(const string& location, const string& expr);
38 | Assign(const Assign&) = delete;
39 | Assign& operator=(const Assign&) = delete;
40 |
41 | bool Execute(Runtime* runtime) const override;
42 |
43 | private:
44 | const string location_;
45 | const string expr_;
46 | };
47 |
48 | } // namespace model
49 | } // namespace state_chart
50 |
51 | #endif // STATE_CHART_INTERNAL_MODEL_ASSIGN_H_
52 |
--------------------------------------------------------------------------------
/statechart/internal/model/assign_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/assign.h"
16 |
17 | #include
18 | #include
19 |
20 | #include "statechart/internal/testing/mock_datamodel.h"
21 | #include "statechart/internal/testing/mock_runtime.h"
22 |
23 | namespace state_chart {
24 | namespace model {
25 | namespace {
26 |
27 | using ::testing::_;
28 | using ::testing::Return;
29 |
30 | TEST(AssignTest, EvaluationError) {
31 | Assign assign("location", "expression");
32 |
33 | MockRuntime runtime;
34 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(),
35 | AssignExpression("location", "expression"))
36 | .WillOnce(Return(false));
37 | EXPECT_CALL(runtime, EnqueueInternalEvent("error.execution", _));
38 | EXPECT_FALSE(assign.Execute(&runtime));
39 | }
40 |
41 | TEST(AssignTest, ValidLocation) {
42 | Assign assign("location", "expression");
43 |
44 | MockRuntime runtime;
45 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(),
46 | AssignExpression("location", "expression"))
47 | .WillOnce(Return(true));
48 | EXPECT_TRUE(assign.Execute(&runtime));
49 | }
50 |
51 | } // namespace
52 | } // namespace model
53 | } // namespace state_chart
54 |
--------------------------------------------------------------------------------
/statechart/internal/model/data.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/data.h"
16 |
17 | #include
18 |
19 | #include "absl/strings/str_cat.h"
20 | #include "absl/strings/substitute.h"
21 | #include "statechart/internal/datamodel.h"
22 | #include "statechart/internal/runtime.h"
23 | #include "statechart/internal/utility.h"
24 |
25 | namespace state_chart {
26 | namespace model {
27 |
28 | Data::Data(const string& location, const string& expr)
29 | : location_(location), expr_(expr) {}
30 |
31 | // override
32 | bool Data::Execute(Runtime* runtime) const {
33 | VLOG(1) << absl::Substitute("Data($0, $1)", location_, expr_);
34 | if (!runtime->mutable_datamodel()->Declare(location_)) {
35 | runtime->EnqueueExecutionError(
36 | absl::StrCat("'Data' declaration failure at location: ", location_));
37 | return false;
38 | }
39 | if (!expr_.empty() &&
40 | !runtime->mutable_datamodel()->AssignExpression(location_, expr_)) {
41 | runtime->EnqueueExecutionError(
42 | absl::StrCat("'Data' assign failure: ", location_, " = ",
43 | expr_.empty() ? "[empty]" : expr_));
44 | return false;
45 | }
46 | return true;
47 | }
48 |
49 | } // namespace model
50 | } // namespace state_chart
51 |
--------------------------------------------------------------------------------
/statechart/internal/model/data.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_DATA_H_
21 | #define STATE_CHART_INTERNAL_MODEL_DATA_H_
22 |
23 | #include
24 |
25 | #include "statechart/platform/types.h"
26 | #include "statechart/internal/model/executable_content.h"
27 |
28 | namespace state_chart {
29 | class Runtime;
30 | }
31 |
32 | namespace state_chart {
33 | namespace model {
34 |
35 | // The data element as an executable content. When executed, declare the
36 | // variable that this represents. Currently 'src' method for defining the value
37 | // is not supported.
38 | class Data : public ExecutableContent {
39 | public:
40 | Data(const string& location, const string& expr);
41 | Data(const Data&) = delete;
42 | Data& operator=(const Data&) = delete;
43 |
44 | bool Execute(Runtime* runtime) const override;
45 |
46 | private:
47 | string location_;
48 | string expr_;
49 | };
50 |
51 | } // namespace model
52 | } // namespace state_chart
53 |
54 | #endif // STATE_CHART_INTERNAL_MODEL_DATA_H_
55 |
--------------------------------------------------------------------------------
/statechart/internal/model/data_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/data.h"
16 |
17 | #include
18 | #include
19 |
20 | #include "statechart/internal/testing/mock_datamodel.h"
21 | #include "statechart/internal/testing/mock_runtime.h"
22 |
23 | namespace state_chart {
24 | namespace model {
25 | namespace {
26 |
27 | using ::testing::_;
28 | using ::testing::Return;
29 |
30 | TEST(DataTest, EvaluationError) {
31 | Data data("location", "expression");
32 |
33 | MockRuntime runtime;
34 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(), Declare("location"))
35 | .WillOnce(Return(false));
36 | EXPECT_CALL(runtime, EnqueueInternalEvent("error.execution", _));
37 | EXPECT_FALSE(data.Execute(&runtime));
38 |
39 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(), Declare("location"))
40 | .WillOnce(Return(true));
41 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(),
42 | AssignExpression("location", "expression"))
43 | .WillOnce(Return(false));
44 | EXPECT_CALL(runtime, EnqueueInternalEvent("error.execution", _));
45 | EXPECT_FALSE(data.Execute(&runtime));
46 | }
47 |
48 | TEST(DataTest, ValidDeclaration) {
49 | Data data("location", "expression");
50 |
51 | MockRuntime runtime;
52 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(), Declare("location"))
53 | .WillOnce(Return(true));
54 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(),
55 | AssignExpression("location", "expression"))
56 | .WillOnce(Return(true));
57 | EXPECT_TRUE(data.Execute(&runtime));
58 | }
59 |
60 | } // namespace
61 | } // namespace model
62 | } // namespace state_chart
63 |
--------------------------------------------------------------------------------
/statechart/internal/model/executable_block.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_EXECUTABLE_BLOCK_H_
21 | #define STATE_CHART_INTERNAL_MODEL_EXECUTABLE_BLOCK_H_
22 |
23 | #include
24 | #include
25 |
26 | #include
27 |
28 | #include "statechart/internal/model/executable_content.h"
29 |
30 | namespace state_chart {
31 | class Runtime;
32 | }
33 |
34 | namespace state_chart {
35 | namespace model {
36 |
37 | // A class that encapsulates a sequence of executable content.
38 | class ExecutableBlock : public ExecutableContent {
39 | public:
40 | // Skips over items in 'executables' which are nullptr.
41 | explicit ExecutableBlock(
42 | const std::vector& executables) {
43 | for (auto executable : executables) {
44 | if (executable != nullptr) {
45 | executables_.push_back(executable);
46 | } else {
47 | LOG(DFATAL) << "Not adding null executable block to executable content"
48 | << std::endl;
49 | }
50 | }
51 | }
52 |
53 | ExecutableBlock(const ExecutableBlock&) = delete;
54 | ExecutableBlock& operator=(const ExecutableBlock&) = delete;
55 |
56 | ~ExecutableBlock() override = default;
57 |
58 | // Executes all executables in sequence order. Stop execution of the block if
59 | // any executable raises an error (returns false).
60 | bool Execute(Runtime* runtime) const override {
61 | for (auto executable : executables_) {
62 | if (!executable->Execute(runtime)) {
63 | return false;
64 | }
65 | }
66 | return true;
67 | }
68 |
69 | private:
70 | std::vector executables_;
71 | };
72 |
73 | } // namespace model
74 | } // namespace state_chart
75 |
76 | #endif // STATE_CHART_INTERNAL_MODEL_EXECUTABLE_BLOCK_H_
77 |
--------------------------------------------------------------------------------
/statechart/internal/model/executable_block_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/executable_block.h"
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include "statechart/internal/testing/mock_executable_content.h"
22 | #include "statechart/internal/testing/mock_runtime.h"
23 |
24 | namespace state_chart {
25 | namespace model {
26 | namespace {
27 |
28 | using ::testing::Return;
29 |
30 | TEST(ExecutableBlock, ExecutableBlockOrderingTest) {
31 | MockExecutableContent exec1, exec2, exec3, exec4;
32 | MockRuntime runtime;
33 |
34 | testing::InSequence sequence;
35 | EXPECT_CALL(exec1, Execute(&runtime)).WillOnce(Return(true));
36 | EXPECT_CALL(exec2, Execute(&runtime)).WillOnce(Return(true));
37 | EXPECT_CALL(exec3, Execute(&runtime)).WillOnce(Return(true));
38 | EXPECT_CALL(exec4, Execute(&runtime)).WillOnce(Return(true));
39 |
40 | ExecutableBlock block({&exec1, &exec2, &exec3, &exec4});
41 | EXPECT_TRUE(block.Execute(&runtime));
42 | }
43 |
44 | TEST(ExecutableBlock, ExecutableBlockOrderingTestWithError) {
45 | MockExecutableContent exec1, exec2, exec3, exec4;
46 | MockRuntime runtime;
47 |
48 | testing::InSequence sequence;
49 | EXPECT_CALL(exec1, Execute(&runtime)).WillOnce(Return(true));
50 | EXPECT_CALL(exec2, Execute(&runtime)).WillOnce(Return(true));
51 | EXPECT_CALL(exec3, Execute(&runtime)).WillOnce(Return(false));
52 | EXPECT_CALL(exec4, Execute(&runtime)).Times(0);
53 |
54 | ExecutableBlock block({&exec1, &exec2, &exec3, &exec4});
55 | EXPECT_FALSE(block.Execute(&runtime));
56 | }
57 |
58 | } // namespace
59 | } // namespace model
60 | } // namespace state_chart
61 |
--------------------------------------------------------------------------------
/statechart/internal/model/executable_content.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_EXECUTABLE_CONTENT_H_
21 | #define STATE_CHART_INTERNAL_MODEL_EXECUTABLE_CONTENT_H_
22 |
23 | #include "statechart/internal/model/model_element.h"
24 |
25 | namespace state_chart {
26 | class Runtime;
27 | }
28 |
29 | namespace state_chart {
30 | namespace model {
31 |
32 | // This class executes operation(s) on a Runtime.
33 | class ExecutableContent : public ModelElement {
34 | public:
35 | // Returns true if there were no errors.
36 | virtual bool Execute(Runtime* runtime) const = 0;
37 | };
38 |
39 | } // namespace model
40 | } // namespace state_chart
41 |
42 | #endif // STATE_CHART_INTERNAL_MODEL_EXECUTABLE_CONTENT_H_
43 |
--------------------------------------------------------------------------------
/statechart/internal/model/for_each.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/for_each.h"
16 |
17 | #include
18 |
19 | #include "absl/strings/str_cat.h"
20 | #include "absl/strings/substitute.h"
21 | #include "statechart/internal/datamodel.h"
22 | #include "statechart/internal/model/executable_content.h"
23 | #include "statechart/internal/runtime.h"
24 | #include "statechart/internal/utility.h"
25 |
26 | namespace state_chart {
27 | namespace model {
28 |
29 | ForEach::ForEach(const string& array, const string& item, const string& index,
30 | const ExecutableContent* body)
31 | : array_(array), item_(item), index_(index), body_(body) {}
32 |
33 | // override
34 | bool ForEach::Execute(Runtime* runtime) const {
35 | VLOG(1) << absl::Substitute("ForEach(<$0, $1> : $2)", index_, item_, array_);
36 | auto* datamodel = runtime->mutable_datamodel();
37 | // Get the iterator.
38 | auto iterator = datamodel->EvaluateIterator(array_);
39 | if (iterator == nullptr) {
40 | runtime->EnqueueExecutionError(absl::StrCat(
41 | "'ForEach' unable to get iterator for collection: ", array_));
42 | return false;
43 | }
44 | // Create item variable if needed.
45 | if (!datamodel->IsDefined(item_) && !datamodel->Declare(item_)) {
46 | runtime->EnqueueExecutionError(
47 | absl::StrCat("'ForEach' unable to declare item variable at: ", item_));
48 | return false;
49 | }
50 | // Create the index variable if specified.
51 | if (!index_.empty() && !datamodel->IsDefined(index_) &&
52 | !datamodel->Declare(index_)) {
53 | runtime->EnqueueExecutionError(absl::StrCat(
54 | "'ForEach' unable to declare index variable at: ", index_));
55 | return false;
56 | }
57 |
58 | // Execute the loop.
59 | string value;
60 | string index;
61 | for (; !iterator->AtEnd(); iterator->Next()) {
62 | value = iterator->GetValue();
63 | // Assign the item.
64 | if (!datamodel->AssignExpression(item_, value)) {
65 | runtime->EnqueueExecutionError(
66 | absl::StrCat("'ForEach' unable to assign item variable '", item_,
67 | "' with value: ", value));
68 | return false;
69 | }
70 | // Assign the index if needed.
71 | if (!index_.empty()) {
72 | index = iterator->GetIndex();
73 | if (!datamodel->AssignExpression(index_, index)) {
74 | runtime->EnqueueExecutionError(
75 | absl::StrCat("'ForEach' unable to assign index variable '", index_,
76 | "' with value: ", index));
77 | return false;
78 | }
79 | }
80 | // Run the loop body, empty executable blocks are nullptr.
81 | if (body_ != nullptr && !body_->Execute(runtime)) {
82 | return false;
83 | }
84 | }
85 | return true;
86 | }
87 |
88 | } // namespace model
89 | } // namespace state_chart
90 |
--------------------------------------------------------------------------------
/statechart/internal/model/for_each.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_FOR_EACH_H_
21 | #define STATE_CHART_INTERNAL_MODEL_FOR_EACH_H_
22 |
23 | #include "statechart/platform/types.h"
24 | #include "statechart/internal/model/executable_content.h"
25 |
26 | namespace state_chart {
27 | class Runtime;
28 | }
29 |
30 | namespace state_chart {
31 | namespace model {
32 |
33 | // Encapsulates execution logic for a 'foreach' element in state charts.
34 | class ForEach : public ExecutableContent {
35 | public:
36 | // Params:
37 | // array Location expression of the iterable collection (array).
38 | // item Location expression of the item (value).
39 | // index Location expression of the index, may be empty to ignore.
40 | // body The body of the foreach, usually an ExecutableBlock. Does not take
41 | // ownership.
42 | ForEach(const string& array, const string& item, const string& index,
43 | const ExecutableContent* body);
44 |
45 | ForEach(const ForEach&) = delete;
46 | ForEach& operator=(const ForEach&) = delete;
47 |
48 |
49 | ~ForEach() override = default;
50 |
51 | // If an error occurs while running the body of the foreach, the loop is
52 | // terminated and false returned.
53 | bool Execute(Runtime* runtime) const override;
54 |
55 | private:
56 | const string array_;
57 | const string item_;
58 | const string index_;
59 | const ExecutableContent* const body_;
60 | };
61 |
62 | } // namespace model
63 | } // namespace state_chart
64 |
65 | #endif // STATE_CHART_INTERNAL_MODEL_FOR_EACH_H_
66 |
--------------------------------------------------------------------------------
/statechart/internal/model/if.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/if.h"
16 |
17 | #include "absl/strings/str_cat.h"
18 | #include "absl/strings/str_join.h"
19 | #include "statechart/internal/datamodel.h"
20 | #include "statechart/internal/runtime.h"
21 | #include "statechart/internal/utility.h"
22 | #include "statechart/logging.h"
23 |
24 | namespace state_chart {
25 | namespace model {
26 |
27 | namespace {
28 |
29 | struct KeyFormatter {
30 | template
31 | void operator()(std::string* out, Pair pair) const {
32 | out->append(pair.first);
33 | }
34 | };
35 |
36 | } // namespace
37 |
38 |
39 | If::If(const std::vector>&
40 | condition_executable)
41 | : condition_executable_(condition_executable) {}
42 |
43 | // override
44 | bool If::Execute(Runtime* runtime) const {
45 | VLOG(1) << absl::StrCat(
46 | "If conditions: ",
47 | absl::StrJoin(condition_executable_, ", ", KeyFormatter()));
48 |
49 | bool saw_empty = false;
50 | bool no_error = true;
51 | for (const auto& cond_executable : condition_executable_) {
52 | RETURN_FALSE_IF_MSG(saw_empty,
53 | "Empty conditions in executable must come last.");
54 |
55 | const string& cond = cond_executable.first;
56 | auto* executable = cond_executable.second;
57 |
58 | bool result = cond.empty(); // Empty cond evaluates to true.
59 | if (!result &&
60 | !runtime->datamodel().EvaluateBooleanExpression(cond, &result)) {
61 | runtime->EnqueueExecutionError(
62 | absl::StrCat("'If' condition failed to evaluate: ", cond));
63 | no_error = false;
64 | continue;
65 | }
66 |
67 | if (result) {
68 | // Empty executable blocks are nullptr.
69 | if (executable != nullptr) {
70 | executable->Execute(runtime);
71 | }
72 | return no_error;
73 | }
74 |
75 | saw_empty |= cond.empty();
76 | }
77 | return no_error;
78 | }
79 |
80 | } // namespace model
81 | } // namespace state_chart
82 |
--------------------------------------------------------------------------------
/statechart/internal/model/if.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_IF_H_
21 | #define STATE_CHART_INTERNAL_MODEL_IF_H_
22 |
23 | #include
24 | #include
25 |
26 | #include "statechart/platform/types.h"
27 | #include "statechart/internal/model/executable_content.h"
28 |
29 | namespace state_chart {
30 | class Runtime;
31 | } // namespace state_chart
32 |
33 | namespace state_chart {
34 | namespace model {
35 |
36 | class If : public ExecutableContent {
37 | public:
38 | // Accepts a list of pairs of condition, executable. The logic for If will
39 | // loop through the configuration, evaluate the condition and execute the
40 | // first executable for which the condition evaluates to true.
41 | explicit If(const std::vector>&
42 | condition_executable);
43 | If(const If&) = delete;
44 | If& operator=(const If&) = delete;
45 |
46 | bool Execute(Runtime* runtime) const override;
47 |
48 | private:
49 | const std::vector>
50 | condition_executable_;
51 | };
52 |
53 | } // namespace model
54 | } // namespace state_chart
55 |
56 | #endif // STATE_CHART_INTERNAL_MODEL_IF_H_
57 |
--------------------------------------------------------------------------------
/statechart/internal/model/log.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/log.h"
16 |
17 | #include
18 |
19 | #include "absl/strings/str_cat.h"
20 | #include "statechart/internal/datamodel.h"
21 | #include "statechart/internal/runtime.h"
22 | #include "statechart/internal/utility.h"
23 |
24 | namespace state_chart {
25 | namespace model {
26 |
27 | Log::Log(const string& label, const string& expr)
28 | : label_(label), expr_(expr) {}
29 |
30 | // override
31 | bool Log::Execute(Runtime* runtime) const {
32 | VLOG(1) << "Log: " << label_ << ": " << expr_;
33 | string log_string;
34 | if (!runtime->datamodel().EvaluateStringExpression(expr_, &log_string)) {
35 | runtime->EnqueueExecutionError(
36 | absl::StrCat("'Log' expression failed to evaluate to string: ", expr_));
37 | return false;
38 | }
39 | LOG(INFO) << (label_.empty() ? "" : label_ + ": ") << log_string;
40 | return true;
41 | }
42 |
43 | } // namespace model
44 | } // namespace state_chart
45 |
--------------------------------------------------------------------------------
/statechart/internal/model/log.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_LOG_H_
21 | #define STATE_CHART_INTERNAL_MODEL_LOG_H_
22 |
23 | #include
24 |
25 | #include "statechart/platform/types.h"
26 | #include "statechart/internal/model/executable_content.h"
27 |
28 | namespace state_chart {
29 | class Runtime;
30 | }
31 |
32 | namespace state_chart {
33 | namespace model {
34 |
35 | class Log : public ExecutableContent {
36 | public:
37 | Log(const string& label, const string& expr);
38 | Log(const Log&) = delete;
39 | Log& operator=(const Log&) = delete;
40 |
41 | bool Execute(Runtime* runtime) const override;
42 |
43 | private:
44 | const string label_;
45 | const string expr_;
46 | };
47 |
48 | } // namespace model
49 | } // namespace state_chart
50 |
51 | #endif // STATE_CHART_INTERNAL_MODEL_LOG_H_
52 |
--------------------------------------------------------------------------------
/statechart/internal/model/log_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/log.h"
16 |
17 | #include "statechart/platform/test_util.h"
18 | #include "statechart/internal/testing/mock_datamodel.h"
19 | #include "statechart/internal/testing/mock_runtime.h"
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | namespace state_chart {
26 | namespace model {
27 | namespace {
28 |
29 | using ::testing::_;
30 | using ::testing::kDoNotCaptureLogsYet;
31 | using ::testing::NotNull;
32 | using ::testing::ScopedMockLog;
33 |
34 | const char kLogCCPath[] = "statechart/internal/model/log.cc";
35 |
36 | TEST(LogTest, Error) {
37 | MockRuntime runtime;
38 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(),
39 | EvaluateStringExpression("expression", NotNull()))
40 | .WillOnce(ReturnEvaluationError());
41 | EXPECT_CALL(runtime, EnqueueInternalEvent("error.execution", _));
42 |
43 | ScopedMockLog mock_log(kDoNotCaptureLogsYet);
44 | EXPECT_CALL(mock_log, Log(base_logging::INFO, kLogCCPath, _)).Times(0);
45 |
46 | Log log("", "expression");
47 | mock_log.StartCapturingLogs();
48 | EXPECT_FALSE(log.Execute(&runtime));
49 | }
50 |
51 | TEST(LogTest, NoLabel) {
52 | MockRuntime runtime;
53 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(),
54 | EvaluateStringExpression("expression", NotNull()))
55 | .WillOnce(ReturnEvaluationResult("log line"));
56 |
57 | ScopedMockLog mock_log(kDoNotCaptureLogsYet);
58 | EXPECT_CALL(mock_log, Log(base_logging::INFO, kLogCCPath, "log line"));
59 |
60 | Log log("", "expression");
61 | mock_log.StartCapturingLogs();
62 | EXPECT_TRUE(log.Execute(&runtime));
63 | }
64 |
65 | TEST(LogTest, Label) {
66 | MockRuntime runtime;
67 | EXPECT_CALL(runtime.GetDefaultMockDatamodel(),
68 | EvaluateStringExpression("expression", NotNull()))
69 | .WillOnce(ReturnEvaluationResult("log line"));
70 |
71 | ScopedMockLog mock_log(kDoNotCaptureLogsYet);
72 | EXPECT_CALL(mock_log, Log(base_logging::INFO, kLogCCPath, "label: log line"));
73 |
74 | Log log("label", "expression");
75 | mock_log.StartCapturingLogs();
76 | log.Execute(&runtime);
77 | }
78 |
79 | } // namespace
80 | } // namespace model
81 | } // namespace state_chart
82 |
--------------------------------------------------------------------------------
/statechart/internal/model/model.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef STATE_CHART_INTERNAL_MODEL_MODEL_H_
18 | #define STATE_CHART_INTERNAL_MODEL_MODEL_H_
19 |
20 | #include "statechart/internal/model/assign.h" // IWYU pragma: export
21 | #include "statechart/internal/model/data.h" // IWYU pragma: export
22 | #include "statechart/internal/model/executable_block.h" // IWYU pragma: export
23 | #include "statechart/internal/model/executable_content.h" // IWYU pragma: export
24 | #include "statechart/internal/model/for_each.h" // IWYU pragma: export
25 | #include "statechart/internal/model/if.h" // IWYU pragma: export
26 | #include "statechart/internal/model/log.h" // IWYU pragma: export
27 | #include "statechart/internal/model/model_element.h" // IWYU pragma: export
28 | #include "statechart/internal/model/raise.h" // IWYU pragma: export
29 | #include "statechart/internal/model/send.h" // IWYU pragma: export
30 | #include "statechart/internal/model/state.h" // IWYU pragma: export
31 | #include "statechart/internal/model/transition.h" // IWYU pragma: export
32 |
33 | #endif // STATE_CHART_INTERNAL_MODEL_MODEL_H_
34 |
--------------------------------------------------------------------------------
/statechart/internal/model/model_element.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/model_element.h"
16 |
17 | namespace state_chart {
18 | namespace model {
19 | ModelElement::~ModelElement() {}
20 | } // namespace model
21 | } // namespace state_chart
22 |
--------------------------------------------------------------------------------
/statechart/internal/model/model_element.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_MODEL_ELEMENT_H_
21 | #define STATE_CHART_INTERNAL_MODEL_MODEL_ELEMENT_H_
22 |
23 | namespace state_chart {
24 | namespace model {
25 |
26 | // A root superclass used for memory management of all instances of model
27 | // related classes except the model itself.
28 | // It only contains a single virtual destructor.
29 | class ModelElement {
30 | public:
31 | virtual ~ModelElement();
32 | };
33 |
34 | } // namespace model
35 | } // namespace state_chart
36 |
37 | #endif // STATE_CHART_INTERNAL_MODEL_MODEL_ELEMENT_H_
38 |
--------------------------------------------------------------------------------
/statechart/internal/model/raise.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/raise.h"
16 |
17 | #include
18 |
19 | #include "statechart/internal/runtime.h"
20 |
21 | namespace state_chart {
22 | namespace model {
23 |
24 | Raise::Raise(const string& event) : event_(event) {}
25 |
26 | // override
27 | bool Raise::Execute(Runtime* runtime) const {
28 | VLOG(1) << "Raise: " << event_;
29 | runtime->EnqueueInternalEvent(event_, "");
30 | return true;
31 | }
32 |
33 | } // namespace model
34 | } // namespace state_chart
35 |
--------------------------------------------------------------------------------
/statechart/internal/model/raise.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_RAISE_H_
21 | #define STATE_CHART_INTERNAL_MODEL_RAISE_H_
22 |
23 | #include
24 |
25 | #include "statechart/platform/types.h"
26 | #include "statechart/internal/model/executable_content.h"
27 |
28 | namespace state_chart {
29 | class Runtime;
30 | }
31 |
32 | namespace state_chart {
33 | namespace model {
34 |
35 | class Raise : public ExecutableContent {
36 | public:
37 | explicit Raise(const string& event);
38 | Raise(const Raise&) = delete;
39 | Raise& operator=(const Raise&) = delete;
40 |
41 | // Enqueues an internal event by calling runtime->EnqueueInternalEvent().
42 | bool Execute(Runtime* runtime) const override;
43 |
44 | private:
45 | const string event_;
46 | };
47 |
48 | } // namespace model
49 | } // namespace state_chart
50 |
51 | #endif // STATE_CHART_INTERNAL_MODEL_RAISE_H_
52 |
--------------------------------------------------------------------------------
/statechart/internal/model/raise_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/raise.h"
16 |
17 | #include
18 | #include
19 |
20 | #include "statechart/internal/testing/mock_runtime.h"
21 |
22 | namespace state_chart {
23 | namespace model {
24 | namespace {
25 |
26 | TEST(RaiseTest, All) {
27 | Raise raise("event");
28 |
29 | MockRuntime runtime;
30 | EXPECT_CALL(runtime, EnqueueInternalEvent("event", ""));
31 | raise.Execute(&runtime);
32 | }
33 |
34 | } // namespace
35 | } // namespace model
36 | } // namespace state_chart
37 |
--------------------------------------------------------------------------------
/statechart/internal/model/send.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The StateChart Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "statechart/internal/model/send.h"
16 |
17 | #include
18 |
19 | #include "absl/strings/str_cat.h"
20 | #include "statechart/internal/datamodel.h"
21 | #include "statechart/internal/event_dispatcher.h"
22 | #include "statechart/internal/runtime.h"
23 | #include "statechart/internal/utility.h"
24 | #include "statechart/logging.h"
25 | #include "statechart/platform/map_util.h"
26 |
27 | namespace state_chart {
28 | namespace model {
29 |
30 | Send::Send(const StrOrExpr& event, const StrOrExpr& target, const StrOrExpr& id,
31 | const StrOrExpr& type)
32 | : event_(event), target_(target), id_(id), type_(type) {}
33 |
34 | // override
35 | bool Send::Execute(Runtime* runtime) const {
36 | VLOG(1) << "Send: event = " << event_.Value()
37 | << ", target = " << target_.Value();
38 | Datamodel* datamodel = runtime->mutable_datamodel();
39 |
40 | // Evaluate string expressions for send attributes.
41 | static const char* const kAttributeName[] = {"event", "target", "type", "id"};
42 | const StrOrExpr* string_attr[] = {&event_, &target_, &type_, &id_};
43 |
44 | static_assert(ABSL_ARRAYSIZE(kAttributeName) == ABSL_ARRAYSIZE(string_attr),
45 | "Array sizes must be equal.");
46 |
47 | std::vector string_attr_value(ABSL_ARRAYSIZE(string_attr), "");
48 |
49 | for (unsigned int i = 0; i < ABSL_ARRAYSIZE(string_attr); ++i) {
50 | if (!string_attr[i]->IsEmpty() &&
51 | !string_attr[i]->Evaluate(datamodel, &string_attr_value[i])) {
52 | runtime->EnqueueExecutionError(absl::StrCat(
53 | "'Send' attribute '", kAttributeName[i],
54 | "' failed to evaluate value: ", string_attr[i]->Value()));
55 | return false;
56 | }
57 | }
58 |
59 | // Evaluate expressions for send parameters.
60 | std::map evaluated_data;
61 | string result;
62 | bool no_error = true;
63 | for (const auto& data : parameters_) {
64 | result.clear();
65 | // If there is an error, the specifications say to ignore the parameter.
66 | // Hence we continue to process the rest.
67 | if (!datamodel->EvaluateExpression(data.second, &result)) {
68 | runtime->EnqueueExecutionError(
69 | absl::StrCat("'Send' parameter '", data.first,
70 | "' failed to evaluate value: ", data.second));
71 | no_error = false;
72 | } else {
73 | evaluated_data[data.first] = result;
74 | }
75 | }
76 |
77 | runtime->GetEventDispatcher()->NotifySendEvent(
78 | runtime, string_attr_value[0], string_attr_value[1], string_attr_value[2],
79 | string_attr_value[3], datamodel->EncodeParameters(evaluated_data));
80 | return no_error;
81 | }
82 |
83 | bool Send::AddParamByExpression(const string& key, const string& expr) {
84 | RETURN_FALSE_IF(expr.empty());
85 | gtl::InsertIfNotPresent(¶meters_, key, expr);
86 | return true;
87 | }
88 |
89 | } // namespace model
90 | } // namespace state_chart
91 |
--------------------------------------------------------------------------------
/statechart/internal/model/send.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The StateChart Authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // IWYU pragma: private, include "src/internal/model/model.h"
18 | // IWYU pragma: friend src/internal/model/*
19 |
20 | #ifndef STATE_CHART_INTERNAL_MODEL_SEND_H_
21 | #define STATE_CHART_INTERNAL_MODEL_SEND_H_
22 |
23 | #include