-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
engine(lua): Restructure Lua integration
Up until now, we had one big cloe table that we patched from several different places. This is not very maintainable as the library grows and so another approach was needed. Hopefully, this is the last large set of breaking changes. - Tests can make use of expect_OP and assert_OP methods to provide better report generation. For example: z:expect_gt(left, right) will actually provide useful messages in the report, especially when something isn't as expected. - Tests can use `expect_OP` methods to make assertions without terminating the test when they fail. - At the end of cloe.schedule_test, it will automatically terminate the simulation with the appropriate result, depending on whether any expect / assert failed or not. If multiple tests were scheduled, the last one terminates the simulation. The results are written to the report. To disable this, set terminate = false in the schedule_test: cloe.schedule_test { id = "test", on = "start", run = function() end, terminate = false, } BREAKING CHANGES: - The Lua cloe library has been split into the pure Lua library, cloe, and the pure C++ library, cloe-engine. - The engine now exports Lua state and functions to the cloe-engine Lua library, which is not loaded into the global namespace anymore. To access them, use: - `require("cloe-engine")` - `require("cloe-engine.fs")` - `require("cloe-engine.types")` These should not be used directly by users, instead functions and mechanisms in cloe should be used. - The `cloe` global is no longer automatically set in the global namespace anymore: - This allows configuration of libraries before they are required by cloe. - The cloe library pulls in most of the cloe-engine Lua library. - The files in the `cloe` library have reorganized. Require statements may need to be rewritten, if anything other than cloe was required. - Signals table and requires is not directly accessible, instead you should use the functions provided: cloe.require_signals(table) => table cloe.require_signals_enum(table) => table cloe.signals() => table cloe.signal(string) => any For example, before and after: cloe.require_signals = {...} -> cloe.require_signals({ ... }) cloe.signals["string"] -> cloe.signal("string") or alternatively, thanks to Lua syntax goodness: cloe.require_signals = {...} -> cloe.require_signals { ... } cloe.signals["string"] -> cloe.signal "string" - The TestFixture class replaces the table previously used for the same purpose. - The methods need to be called with a colon, since this automatically passes the self to the function (which is needed): z.printf() -> z:printf() z.wait_duration() -> z:wait_duration() ... - `z:expect()` can be used to assert without terminating the simulation. - Typecheck is used to replace `cloe.validate` for most function argument validation, as this provides much better error messages. If you have used cloe.validate, you need to use the new format or use `require("cloe.luax").validate` instead. - Functions previously exported directly to the cloe table that were utility functions are now delegated to a separate namespace, in order to keep everything in cloe related. Thus, the `cloe.utils` has been renamed `cloe.luax`, since they are Lua extensions. They may be replaced in the future with a larger set of libraries, but for now they will stay. - The table `cloe.report` has been moved to `cloe.system` and is no longer automatically included in cloe. You need to require it: local sys = require("cloe.system") - The function `cloe.system` has been moved to the `system` table and renamed to `exec`. See previous point.
- Loading branch information
Showing
37 changed files
with
2,031 additions
and
1,205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", | ||
"workspace.library": ["engine/lua"], | ||
"runtime.version": "Lua 5.4", | ||
"completion.displayContext": 1, | ||
"diagnostics.globals": ["cloe"], | ||
"hint.enable": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
-- | ||
-- Copyright 2023 Robert Bosch GmbH | ||
-- | ||
-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
-- you may not use this file except in compliance with the License. | ||
-- You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, software | ||
-- distributed under the License is distributed on an "AS IS" BASIS, | ||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
-- See the License for the specific language governing permissions and | ||
-- limitations under the License. | ||
-- | ||
-- SPDX-License-Identifier: Apache-2.0 | ||
-- | ||
|
||
--- | ||
--- @meta cloe-engine | ||
--- | ||
--- This file contains the type annotations of the `cloe-engine` module, | ||
--- which are exported by the cloe-engine executable. | ||
--- | ||
--- These methods should only be used by the cloe library. | ||
--- | ||
|
||
local engine = { | ||
-- Contains data that will be processed at simulation start, | ||
-- but will not be considered afterward. | ||
initial_input = { | ||
triggers = {}, | ||
triggers_processed = 0, | ||
signal_aliases = {}, | ||
signal_requires = {}, | ||
}, | ||
|
||
-- Contains engine state for a simulation. | ||
state = { | ||
features = {}, | ||
report = {}, | ||
scheduler = nil, | ||
stack = nil, | ||
current_script_file = nil, | ||
current_script_dir = nil, | ||
scripts_loaded = {}, | ||
}, | ||
|
||
plugins = {}, | ||
|
||
signals = {}, | ||
} | ||
|
||
require("cloe-engine.types") | ||
|
||
--- Fail with an error message that cloe-engine functionality not available. | ||
--- | ||
--- @param fname string | ||
--- @param ... any Consumed but not used | ||
--- @return any | ||
local function unavailable(fname, ...) | ||
local inspect = require("inspect").inspect | ||
local buf = "cloe-engine." .. fname .. "(" | ||
for i, v in ipairs(...) do | ||
if i ~= 1 then | ||
buf = buf .. ", " | ||
end | ||
buf = buf .. inspect(v) | ||
end | ||
buf = buf .. ")" | ||
error(string.format("error: %s: implementation unavailable outside cloe-engine", buf)) | ||
end | ||
|
||
--- Return two-character string representation of log-level. | ||
--- | ||
--- @param level string | ||
--- @return string | ||
--- @nodiscard | ||
local function log_level_format(level) | ||
if level == "info" then | ||
return "II" | ||
elseif level == "debug" then | ||
return "DD" | ||
elseif level == "warn" then | ||
return "WW" | ||
elseif level == "error" then | ||
return "EE" | ||
elseif level == "critical" then | ||
return "CC" | ||
elseif level == "trace" then | ||
return "TT" | ||
else | ||
return "??" | ||
end | ||
end | ||
|
||
--- Return whether the engine is available. | ||
--- | ||
--- This is not the case when a Lua script is being run with | ||
--- another interpreter, a REPL, or a language server. | ||
--- | ||
--- @return boolean | ||
function engine.is_available() | ||
return false | ||
end | ||
|
||
--- Return path to Lua file that the engine is currently merging, | ||
--- or nil if no file is being loaded. | ||
--- | ||
--- @return string|nil | ||
function engine.get_script_file() | ||
return engine.state.current_script_file | ||
end | ||
|
||
--- Return path to directory containing the Lua file that the engine is | ||
--- currently merging, or nil if no file is being loaded. | ||
--- | ||
--- @return string|nil | ||
function engine.get_script_dir() | ||
return engine.state.current_script_dir | ||
end | ||
|
||
--- Return the global Stack instance. | ||
--- | ||
--- @return Stack | ||
function engine.get_stack() | ||
return unavailable("get_stack") | ||
end | ||
|
||
--- Return the simulation scheduler (aka. Coordinator) global instance. | ||
--- | ||
--- @return Coordinator | ||
function engine.get_scheduler() | ||
return unavailable("get_scheduler") | ||
end | ||
|
||
--- Return the simulation report. | ||
--- | ||
--- @return table | ||
function engine.get_report() | ||
return engine.state.report | ||
end | ||
|
||
--- Return a table of available features. | ||
--- | ||
--- @return table | ||
function engine.get_features() | ||
return engine.state.features | ||
end | ||
|
||
--- Log a message. | ||
--- | ||
--- @param level string | ||
--- @param prefix string | ||
--- @param message string | ||
--- @return nil | ||
function engine.log(level, prefix, message) | ||
print(string.format("%s %s [%s] %s", log_level_format(level), os.date("%T"), prefix, message)) | ||
end | ||
|
||
--- @class CommandSpecA | ||
--- @field path string name or path of executable | ||
--- @field args table list of arguments | ||
--- @field mode? string execution mode (one of "sync", "async", "detach") | ||
--- @field log_output? string output verbosity ("never", "on_error", "always") | ||
--- @field ignore_failure? boolean whether to ignore failure | ||
|
||
--- @class CommandSpecB | ||
--- @field command string command or script to run with default shell | ||
--- @field mode? string execution mode (one of "sync", "async", "detach") | ||
--- @field log_output? string output verbosity ("never", "on_error", "always") | ||
--- @field ignore_failure? boolean whether to ignore failure | ||
|
||
--- @alias CommandSpecC string command or script to run with default shell | ||
|
||
--- @alias CommandSpec (CommandSpecA | CommandSpecB | CommandSpecC) | ||
|
||
--- Run a system command with the cloe executer. | ||
--- | ||
--- @param spec CommandSpec | ||
--- @return string,number | ||
function engine.exec(spec) | ||
return unavailable("exec", spec), 1 | ||
end | ||
|
||
return engine |
Oops, something went wrong.