From 99672cd842230df4185704c0ac618b93b3ef40c9 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Mon, 8 Apr 2024 00:00:37 +1200 Subject: [PATCH] Interpreter: skeleton code. --- src/CMakeLists.txt | 3 + src/api/libcellml/interpreter.h | 75 +++++++++++++++++++ src/api/libcellml/module/libcellml | 1 + src/api/libcellml/types.h | 2 + src/bindings/interface/interpreter.i | 29 +++++++ src/bindings/interface/types.i | 1 + src/bindings/javascript/CMakeLists.txt | 1 + src/bindings/javascript/interpreter.cpp | 30 ++++++++ src/bindings/python/CMakeLists.txt | 1 + src/bindings/python/__init__.py | 1 + src/interpreter.cpp | 48 ++++++++++++ src/interpreter_p.h | 35 +++++++++ tests/bindings/javascript/CMakeLists.txt | 1 + tests/bindings/javascript/interpreter.test.js | 41 ++++++++++ tests/bindings/python/CMakeLists.txt | 1 + tests/bindings/python/test_interpreter.py | 42 +++++++++++ tests/coverage/coverage.cpp | 18 +++++ 17 files changed, 330 insertions(+) create mode 100644 src/api/libcellml/interpreter.h create mode 100644 src/bindings/interface/interpreter.i create mode 100644 src/bindings/javascript/interpreter.cpp create mode 100644 src/interpreter.cpp create mode 100644 src/interpreter_p.h create mode 100644 tests/bindings/javascript/interpreter.test.js create mode 100644 tests/bindings/python/test_interpreter.py diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2129b330ec..766ad492cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/importer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/importsource.cpp ${CMAKE_CURRENT_SOURCE_DIR}/internaltypes.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/interpreter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/issue.cpp ${CMAKE_CURRENT_SOURCE_DIR}/logger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mathmldtd.cpp @@ -94,6 +95,7 @@ set(GIT_API_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/importedentity.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/importer.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/importsource.h + ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/interpreter.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/issue.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/logger.h ${CMAKE_CURRENT_SOURCE_DIR}/api/libcellml/model.h @@ -136,6 +138,7 @@ set(GIT_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/generatorprofilesha1values.h ${CMAKE_CURRENT_SOURCE_DIR}/generatorprofiletools.h ${CMAKE_CURRENT_SOURCE_DIR}/internaltypes.h + ${CMAKE_CURRENT_SOURCE_DIR}/interpreter_p.h ${CMAKE_CURRENT_SOURCE_DIR}/issue_p.h ${CMAKE_CURRENT_SOURCE_DIR}/logger_p.h ${CMAKE_CURRENT_SOURCE_DIR}/mathmldtd.h diff --git a/src/api/libcellml/interpreter.h b/src/api/libcellml/interpreter.h new file mode 100644 index 0000000000..8d9dfa1740 --- /dev/null +++ b/src/api/libcellml/interpreter.h @@ -0,0 +1,75 @@ +/* +Copyright libCellML Contributors + +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. +*/ + +#pragma once + +#include "libcellml/exportdefinitions.h" +#include "libcellml/types.h" + +namespace libcellml { + +/** + * @brief The Interpreter class. + * + * The Interpreter class is for representing a CellML Interpreter. + */ +class LIBCELLML_EXPORT Interpreter +{ +public: + ~Interpreter(); /**< Destructor, @private. */ + Interpreter(const Interpreter &rhs) = delete; /**< Copy constructor, @private. */ + Interpreter(Interpreter &&rhs) noexcept = delete; /**< Move constructor, @private. */ + Interpreter &operator=(Interpreter rhs) = delete; /**< Assignment operator, @private. */ + + /** + * @brief Create an @ref Interpreter object. + * + * Factory method to create an @ref Interpreter. Create an interpreter with:: + * + * @code + * auto interpreter = libcellml::Interpreter::create(); + * @endcode + * + * @return A smart pointer to an @ref Interpreter object. + */ + static InterpreterPtr create() noexcept; + + /** + * @brief Get the @ref AnalyserModel. + * + * Get the @ref AnalyserModel used by this @ref Interpreter. + * + * @return The @ref AnalyserModel used. + */ + AnalyserModelPtr model(); + + /** + * @brief Set the @ref AnalyserModel. + * + * Set the @ref AnalyserModel to be used by this @ref Interpreter. + * + * @param model The @ref AnalyserModel to set. + */ + void setModel(const AnalyserModelPtr &model); + +private: + Interpreter(); /**< Constructor, @private. */ + + struct InterpreterImpl; + InterpreterImpl *mPimpl; /**< Private member to implementation pointer, @private. */ +}; + +} // namespace libcellml diff --git a/src/api/libcellml/module/libcellml b/src/api/libcellml/module/libcellml index 18940a3c27..7dfca862df 100644 --- a/src/api/libcellml/module/libcellml +++ b/src/api/libcellml/module/libcellml @@ -37,6 +37,7 @@ limitations under the License. #include "libcellml/generatorprofile.h" #include "libcellml/importer.h" #include "libcellml/importsource.h" +#include "libcellml/interpreter.h" #include "libcellml/issue.h" #include "libcellml/logger.h" #include "libcellml/model.h" diff --git a/src/api/libcellml/types.h b/src/api/libcellml/types.h index 48fb728564..73e54cf54c 100644 --- a/src/api/libcellml/types.h +++ b/src/api/libcellml/types.h @@ -50,6 +50,8 @@ class GeneratorProfile; /**< Forward declaration of GeneratorProfile class. */ using GeneratorProfilePtr = std::shared_ptr; /**< Type definition for shared generator variable pointer. */ class Importer; /**< Forward declaration of Importer class. */ using ImporterPtr = std::shared_ptr; /**< Type definition for shared importer pointer. */ +class Interpreter; /**< Forward declaration of Interpreter class. */ +using InterpreterPtr = std::shared_ptr; /**< Type definition for shared Interpreter pointer. */ class Issue; /**< Forward declaration of Issue class. */ using IssuePtr = std::shared_ptr; /**< Type definition for shared issue pointer. */ class Logger; /**< Forward declaration of Parser class. */ diff --git a/src/bindings/interface/interpreter.i b/src/bindings/interface/interpreter.i new file mode 100644 index 0000000000..8373681836 --- /dev/null +++ b/src/bindings/interface/interpreter.i @@ -0,0 +1,29 @@ +%module(package="libcellml") interpreter + +#define LIBCELLML_EXPORT + +%include + +%import "analysermodel.i" +%import "createconstructor.i" + +%feature("docstring") libcellml::Interpreter +"Creates a :class:`Interpreter` object."; + +%feature("docstring") libcellml::Interpreter::model +"Returns the model to interpret."; + +%feature("docstring") libcellml::Interpreter::setModel +"Sets the model to interpret."; + +%{ +#include "libcellml/interpreter.h" +%} + +%pythoncode %{ +# libCellML generated wrapper code starts here. +%} + +%create_constructor(Interpreter) + +%include "libcellml/interpreter.h" diff --git a/src/bindings/interface/types.i b/src/bindings/interface/types.i index 01c6b8c17a..9cad37a58c 100644 --- a/src/bindings/interface/types.i +++ b/src/bindings/interface/types.i @@ -29,6 +29,7 @@ Provides support for shared pointers declared in types.h. %shared_ptr(libcellml::Importer) %shared_ptr(libcellml::ImportSource) %shared_ptr(libcellml::ImportedEntity) +%shared_ptr(libcellml::Interpreter) %shared_ptr(libcellml::Issue) %shared_ptr(libcellml::Logger) %shared_ptr(libcellml::Model) diff --git a/src/bindings/javascript/CMakeLists.txt b/src/bindings/javascript/CMakeLists.txt index 86e79547fa..1fe2832c6b 100644 --- a/src/bindings/javascript/CMakeLists.txt +++ b/src/bindings/javascript/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/importedentity.cpp ${CMAKE_CURRENT_SOURCE_DIR}/importer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/importsource.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/interpreter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/issue.cpp ${CMAKE_CURRENT_SOURCE_DIR}/logger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/model.cpp diff --git a/src/bindings/javascript/interpreter.cpp b/src/bindings/javascript/interpreter.cpp new file mode 100644 index 0000000000..8ff8f6ebf5 --- /dev/null +++ b/src/bindings/javascript/interpreter.cpp @@ -0,0 +1,30 @@ +/* +Copyright libCellML Contributors + +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. +*/ + +#include + +#include "libcellml/interpreter.h" + +using namespace emscripten; + +EMSCRIPTEN_BINDINGS(libcellml_interpreter) +{ + class_("Interpreter") + .smart_ptr_constructor("Interpreter", &libcellml::Interpreter::create) + .function("model", &libcellml::Interpreter::model) + .function("setModel", &libcellml::Interpreter::setModel) + ; +} diff --git a/src/bindings/python/CMakeLists.txt b/src/bindings/python/CMakeLists.txt index 74d0917c42..3e31c79f07 100644 --- a/src/bindings/python/CMakeLists.txt +++ b/src/bindings/python/CMakeLists.txt @@ -31,6 +31,7 @@ set(SWIG_INTERFACE_SRCS ../interface/importer.i ../interface/importsource.i ../interface/importedentity.i + ../interface/interpreter.i ../interface/issue.i ../interface/logger.i ../interface/model.i diff --git a/src/bindings/python/__init__.py b/src/bindings/python/__init__.py index 4ae2736eb2..841e60fc9b 100644 --- a/src/bindings/python/__init__.py +++ b/src/bindings/python/__init__.py @@ -22,6 +22,7 @@ from libcellml.generatorprofile import GeneratorProfile from libcellml.importer import Importer from libcellml.importsource import ImportSource +from libcellml.interpreter import Interpreter from libcellml.issue import Issue from libcellml.model import Model from libcellml.parser import Parser diff --git a/src/interpreter.cpp b/src/interpreter.cpp new file mode 100644 index 0000000000..ba71cda7b6 --- /dev/null +++ b/src/interpreter.cpp @@ -0,0 +1,48 @@ +/* +Copyright libCellML Contributors + +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. +*/ + +#include "libcellml/interpreter.h" + +#include "interpreter_p.h" + +namespace libcellml { + +Interpreter::Interpreter() + : mPimpl(new InterpreterImpl()) +{ +} + +Interpreter::~Interpreter() +{ + delete mPimpl; +} + +InterpreterPtr Interpreter::create() noexcept +{ + return std::shared_ptr {new Interpreter {}}; +} + +AnalyserModelPtr Interpreter::model() +{ + return mPimpl->mModel; +} + +void Interpreter::setModel(const AnalyserModelPtr &model) +{ + mPimpl->mModel = model; +} + +} // namespace libcellml diff --git a/src/interpreter_p.h b/src/interpreter_p.h new file mode 100644 index 0000000000..0988fd471d --- /dev/null +++ b/src/interpreter_p.h @@ -0,0 +1,35 @@ +/* +Copyright libCellML Contributors + +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. +*/ + +#pragma once + +#include "libcellml/interpreter.h" + +namespace libcellml { + +std::string generateDoubleCode(const std::string &value); + +/** + * @brief The Interpreter::InterpreterImpl struct. + * + * The private implementation for the Interpreter class. + */ +struct Interpreter::InterpreterImpl +{ + AnalyserModelPtr mModel; +}; + +} // namespace libcellml diff --git a/tests/bindings/javascript/CMakeLists.txt b/tests/bindings/javascript/CMakeLists.txt index 87176319b0..86dc3d0990 100644 --- a/tests/bindings/javascript/CMakeLists.txt +++ b/tests/bindings/javascript/CMakeLists.txt @@ -27,6 +27,7 @@ set(TEST_SRCS generator.test.js generatorprofile.test.js importsource.test.js + interpreter.test.js model.test.js namedentity.test.js parentedentity.test.js diff --git a/tests/bindings/javascript/interpreter.test.js b/tests/bindings/javascript/interpreter.test.js new file mode 100644 index 0000000000..ce4532cca0 --- /dev/null +++ b/tests/bindings/javascript/interpreter.test.js @@ -0,0 +1,41 @@ +/* +Copyright libCellML Contributors + +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. +*/ + +const loadLibCellML = require('libcellml.js/libcellml.common') +const { basicModel } = require('./resources') + +let libcellml = null + +describe("Interpreter tests", () => { + beforeAll(async () => { + libcellml = await loadLibCellML() + }) + test('Checking Interpreter model manipulation.', () => { + const i = new libcellml.Interpreter() + const p = new libcellml.Parser(true) + + m = p.parseModel(basicModel) + a = new libcellml.Analyser() + + a.analyseModel(m) + + expect(i.model()).toBe(null) + + i.setModel(a.model()) + + expect(i.model()).toBeDefined() + }) +}) diff --git a/tests/bindings/python/CMakeLists.txt b/tests/bindings/python/CMakeLists.txt index 16d776bc9a..33de11a89d 100644 --- a/tests/bindings/python/CMakeLists.txt +++ b/tests/bindings/python/CMakeLists.txt @@ -25,6 +25,7 @@ set(TEST_SRCS test_import_requirement.py test_import_source.py test_importer.py + test_interpreter.py test_issue.py test_model.py test_parser.py diff --git a/tests/bindings/python/test_interpreter.py b/tests/bindings/python/test_interpreter.py new file mode 100644 index 0000000000..0fb8b9e10e --- /dev/null +++ b/tests/bindings/python/test_interpreter.py @@ -0,0 +1,42 @@ +# +# Tests the Interpreter class bindings +# +import unittest + + +class InterpreterTestCase(unittest.TestCase): + + def test_create_destroy(self): + from libcellml import Interpreter + + x = Interpreter() + del x + + def test_algebraic_eqn_computed_var_on_rhs(self): + from libcellml import Analyser + from libcellml import AnalyserModel + from libcellml import Interpreter + from libcellml import Parser + from test_resources import file_contents + + p = Parser() + m = p.parseModel(file_contents('generator/algebraic_eqn_computed_var_on_rhs/model.cellml')) + + a = Analyser() + a.analyseModel(m) + + am = a.model() + + self.assertEqual(AnalyserModel.Type.ALGEBRAIC, am.type()) + + i = Interpreter() + + self.assertIsNone(i.model()) + + i.setModel(am) + + self.assertIsNotNone(i.model()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/coverage/coverage.cpp b/tests/coverage/coverage.cpp index 811dd9eadc..df993d458e 100644 --- a/tests/coverage/coverage.cpp +++ b/tests/coverage/coverage.cpp @@ -840,6 +840,24 @@ TEST(Coverage, generator) libcellml::Generator::equationCode(analyser->model()->equation(0)->ast()); } +TEST(Coverage, interpreter) +{ + auto parser = libcellml::Parser::create(); + auto model = parser->parseModel(fileContents("coverage/generator/model.cellml")); + auto analyser = libcellml::Analyser::create(); + + analyser->analyseModel(model); + + auto analyserModel = analyser->model(); + auto interpreter = libcellml::Interpreter::create(); + + EXPECT_EQ(nullptr, interpreter->model()); + + interpreter->setModel(analyserModel); + + EXPECT_EQ(analyserModel, interpreter->model()); +} + TEST(CoverageValidator, degreeElementWithOneSibling) { const std::string math =